Skip to content

Commit 8b3abed

Browse files
committed
[feature] added clipboard functions
1 parent 6438457 commit 8b3abed

File tree

5 files changed

+165
-13
lines changed

5 files changed

+165
-13
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ target_compile_options(
6666
target_compile_definitions(
6767
ekg PRIVATE
6868
EKG_VERSION="${EKG_VERSION}"
69+
EKG_EOF_SYSTEM="${PLATFORM_EOF_SYSTEM}"
6970
)
7071

7172
set_target_properties(

cmake/properties.cmake

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,18 +38,18 @@ endif()
3838
if(WIN32 OR EKG_FORCE_WINDOWS)
3939
set(LIBRARY_OUTPUT_PATH "../lib/windows/")
4040
set(PLATFORM "windows")
41-
add_compile_definitions(EKG_EOF_SYSTEM="\r\n")
41+
set(PLATFORM_EOF_SYSTEM "\\r\\n")
4242
elseif(ANDROID OR EKG_FORCE_ANDROID)
4343
set(LIBRARY_OUTPUT_PATH "${ANDROID_ABI}/")
4444
set(PLATFORM "${ANDROID_ABI}")
45-
add_compile_definitions(EKG_EOF_SYSTEM="\n")
45+
set(PLATFORM_EOF_SYSTEM "\\n")
4646
elseif(EKG_EMSCRIPTEN_BUILD_TYPE)
4747
set(LIBRARY_OUTPUT_PATH "../lib/linux-wasm/")
4848
set(PLATFORM "linux-wasm")
49-
add_compile_definitions(EKG_EOF_SYSTEM="\n")
49+
set(PLATFORM_EOF_SYSTEM "\\n")
5050
elseif(LINUX OR EKG_FORCE_LINUX)
5151
# WSL is not detected as Linux-kernel based OS; force is necessary ><
5252
set(LIBRARY_OUTPUT_PATH "../lib/linux/")
5353
set(PLATFORM "linux")
54-
add_compile_definitions(EKG_EOF_SYSTEM="\n")
54+
set(PLATFORM_EOF_SYSTEM "\\n")
5555
endif()

include/ekg/io/utf.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,11 @@ namespace ekg {
247247
void push_back(std::string_view line);
248248
void set(size_t index, std::string_view line);
249249

250+
std::string read(
251+
ekg::vec2_t<size_t> &begin,
252+
ekg::vec2_t<size_t> &end
253+
);
254+
250255
void insert(
251256
size_t index,
252257
const ekg::io::chunk_t &to_insert_chunk

src/io/utf.cpp

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -568,7 +568,8 @@ void ekg::text::insert(
568568
ekg::utf8_split_endings(lines, splitted);
569569
}
570570

571-
for (size_t it {}; it < this->loaded_chunks.size(); it++) {
571+
size_t total_of_chunks {this->loaded_chunks.size()};
572+
for (size_t it {}; it < total_of_chunks; it++) {
572573
ekg::io::chunk_t &chunk {this->loaded_chunks.at(it)};
573574

574575
previous_lines = current_lines;
@@ -599,6 +600,78 @@ void ekg::text::insert(
599600
this->insert(index, chunk);
600601
}
601602

603+
std::string ekg::text::read(
604+
ekg::vec2_t<size_t> &begin,
605+
ekg::vec2_t<size_t> &end
606+
) {
607+
size_t previous_lines {};
608+
size_t chunk_size {};
609+
size_t current_lines {};
610+
size_t total_of_chunks {this->loaded_chunks.size()};
611+
size_t line_index {};
612+
size_t cut_length {end.y - begin.y};
613+
size_t cut_count {};
614+
size_t lines {};
615+
616+
size_t i {};
617+
bool oka_begin {};
618+
bool oka_end {};
619+
620+
std::string builder {};
621+
for (size_t it {}; it < total_of_chunks; it++) {
622+
ekg::io::chunk_t &chunk {this->loaded_chunks.at(it)};
623+
624+
previous_lines = current_lines;
625+
current_lines += (chunk_size = chunk.size());
626+
627+
if (
628+
begin.y > current_lines
629+
) {
630+
continue;
631+
}
632+
633+
i = 0;
634+
if (!oka_begin) {
635+
i = begin.y - previous_lines;
636+
oka_begin = true;
637+
}
638+
639+
if (end.y < previous_lines) {
640+
return builder;
641+
}
642+
643+
previous_lines += i;
644+
645+
for (; i < chunk_size; i++) {
646+
std::string &line {chunk.at(i)};
647+
648+
if (
649+
previous_lines == begin.y
650+
&&
651+
previous_lines == end.y
652+
) {
653+
builder += ekg::utf8_substr(line, begin.x, end.x - begin.x);
654+
return builder;
655+
}
656+
657+
if (
658+
previous_lines == begin.y
659+
) {
660+
builder += ekg::utf8_substr(line, begin.x, UINT32_MAX) + EKG_EOF_SYSTEM;
661+
} else if (
662+
previous_lines == end.y
663+
) {
664+
builder += ekg::utf8_substr(line, 0, end.x);
665+
return builder;
666+
} else {
667+
builder += line + EKG_EOF_SYSTEM;
668+
}
669+
670+
previous_lines++;
671+
}
672+
}
673+
}
674+
602675
void ekg::text::erase(
603676
size_t begin,
604677
size_t end

src/ui/textbox/widget.cpp

Lines changed: 81 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,10 @@ void ekg::ui::handle_erase(
296296
ekg::textbox_t &textbox,
297297
ekg::textbox_t::cursor_t &cursor
298298
) {
299+
if (cursor.a == cursor.b) {
300+
return;
301+
}
302+
299303
if (cursor.a.y == cursor.b.y) {
300304
std::string line {textbox.text.at(cursor.a.y)};
301305
std::string concated {};
@@ -314,6 +318,7 @@ void ekg::ui::handle_erase(
314318

315319
cursor.b = cursor.a;
316320
cursor.delta = cursor.a;
321+
cursor.highest_char_index = cursor.a.x;
317322

318323
return;
319324
}
@@ -338,6 +343,7 @@ void ekg::ui::handle_erase(
338343

339344
cursor.b = cursor.a;
340345
cursor.delta = cursor.a;
346+
cursor.highest_char_index = cursor.a.x;
341347
}
342348

343349
void ekg::ui::handle_insert(
@@ -358,6 +364,7 @@ void ekg::ui::handle_insert(
358364
cursor.a.y++;
359365
cursor.a.x = 0;
360366
cursor.b = cursor.a;
367+
cursor.highest_char_index = cursor.a.x;
361368
return;
362369
}
363370

@@ -375,6 +382,7 @@ void ekg::ui::handle_insert(
375382

376383
cursor.a.x += ekg::utf8_length(typed);
377384
cursor.b = cursor.a;
385+
cursor.highest_char_index = cursor.a.x;
378386
}
379387

380388
void ekg::ui::reload(
@@ -451,7 +459,7 @@ void ekg::ui::event(
451459

452460
switch (stage) {
453461
default: {
454-
ekg::input_info_t &input {ekg::p_core->handler_input.input};
462+
ekg::input_info_t input {ekg::p_core->handler_input.input};
455463
ekg::vec2_t<float> interact {static_cast<ekg::vec2_t<float>>(input.interact)};
456464

457465
/* focus part */
@@ -567,13 +575,40 @@ void ekg::ui::event(
567575
return;
568576
}
569577

570-
/* logic of cursors, for handling lot of curosrs we will use only one loop for improve performance */
578+
/**
579+
* logic of cursors:
580+
* for handling lot of cursors we will
581+
* use only one loop for improve performance
582+
**/
583+
584+
bool is_action_selected_all_fired {ekg::fired("textbox-action-select-all")};
585+
if (is_action_selected_all_fired) {
586+
size_t lines {textbox.text.length_of_lines()};
587+
if (lines > 0) {
588+
lines -= 1;
589+
std::string last_line {textbox.text.at(lines)};
590+
textbox.widget.cursors.clear();
591+
textbox.widget.cursors.push_back(
592+
{
593+
.a = {0, 0},
594+
.b = {ekg::utf8_length(last_line), lines}
595+
}
596+
);
597+
}
598+
599+
return;
600+
}
601+
602+
bool is_action_copy {ekg::fired("clipboard-copy")};
603+
bool is_action_paste {ekg::fired("clipboard-paste")};
604+
bool is_action_cut {ekg::fired("clipboard-cut")};
571605

572606
bool is_action_erase_right_fired {ekg::fired("textbox-action-erase-right")};
573607
bool is_action_erase_left_fired {ekg::fired("textbox-action-erase-left")};
574608
bool is_action_erase_fired {is_action_erase_left_fired || is_action_erase_right_fired};
575609
bool is_action_selected_keybind_fired {ekg::fired("textbox-action-select")};
576610
bool is_action_selected_fired {};
611+
bool is_action_break_line_fired {ekg::fired("textbox-action-break-line")};
577612

578613
bool is_modifier_fired {ekg::fired("textbox-action-modifier")};
579614
bool is_left_fired {ekg::fired("textbox-action-left")};
@@ -586,9 +621,31 @@ void ekg::ui::event(
586621
bool is_modifier_down_fired {is_down_fired && is_modifier_fired};
587622
bool is_arrows_fired {is_left_fired || is_right_fired || is_up_fired || is_down_fired};
588623

589-
bool is_textbox_action_break_line_fired {ekg::fired("textbox-action-break-line")};
624+
if (is_action_paste) {
625+
input.was_typed = true;
626+
input.typed = ekg::p_core->p_platform_base->get_clipboard_text();
627+
}
628+
629+
std::string clipboard_builder {};
630+
if (is_action_cut) {
631+
input.was_typed = false;
632+
}
590633

591-
if (is_arrows_fired || is_action_erase_fired || input.was_typed || is_textbox_action_break_line_fired) {
634+
if (
635+
is_arrows_fired
636+
||
637+
is_action_erase_fired
638+
||
639+
input.was_typed
640+
||
641+
is_action_break_line_fired
642+
||
643+
is_action_copy
644+
||
645+
is_action_cut
646+
||
647+
is_action_paste
648+
) {
592649
textbox.widget.set_cursor_static = true;
593650
}
594651

@@ -605,8 +662,11 @@ void ekg::ui::event(
605662
ekg::vec2_t<float> cursor_pos {};
606663
std::string line {};
607664

665+
size_t cursors_size {textbox.widget.cursors.size()};
666+
size_t cursor_count {};
608667

609668
for (ekg::textbox_t::cursor_t &cursor : textbox.widget.cursors) {
669+
cursor_count++;
610670
is_ab_equals = cursor.a == cursor.b;
611671

612672
is_action_selected_fired = (is_arrows_fired && is_action_selected_keybind_fired) || (is_action_erase_fired && is_ab_equals);
@@ -810,15 +870,24 @@ void ekg::ui::event(
810870
}
811871
}
812872

813-
if (is_action_erase_fired) {
873+
if (is_action_cut || is_action_copy) {
874+
clipboard_builder += textbox.text.read(
875+
cursor.a,
876+
cursor.b
877+
)
878+
+
879+
(((cursors_size > 1) && !is_ab_equals && cursor_count != cursors_size) ? EKG_EOF_SYSTEM : "");
880+
}
881+
882+
if (is_action_erase_fired || is_action_cut) {
814883
ekg::ui::handle_erase(textbox, cursor);
815884
}
816885

817-
if (input.was_typed || is_textbox_action_break_line_fired) {
886+
if (input.was_typed || is_action_break_line_fired) {
818887
ekg::ui::handle_insert(
819888
textbox,
820889
cursor,
821-
is_textbox_action_break_line_fired
890+
is_action_break_line_fired
822891
? EKG_EOF_SYSTEM : input.typed
823892
);
824893
}
@@ -839,7 +908,11 @@ void ekg::ui::event(
839908
}
840909
}
841910

842-
if (is_action_erase_fired || input.was_typed || is_textbox_action_break_line_fired) {
911+
if (is_action_cut || is_action_copy) {
912+
ekg::p_core->p_platform_base->set_clipboard_text(clipboard_builder.c_str());
913+
}
914+
915+
if (is_action_erase_fired || input.was_typed || is_action_break_line_fired) {
843916
ekg::ui::refresh_scroll_sizes(textbox);
844917
}
845918

0 commit comments

Comments
 (0)