hermet pushed a commit to branch master. http://git.enlightenment.org/tools/enventor.git/commit/?id=950d2943a1f24d8e044c4a2a11ee7da832c428e5
commit 950d2943a1f24d8e044c4a2a11ee7da832c428e5 Author: ChunEon Park <[email protected]> Date: Sat Aug 2 16:41:24 2014 +0900 revise redo/undo code --- README | 2 + src/bin/auto_comp.c | 18 +- src/bin/edc_editor.c | 62 +++++-- src/bin/indent.c | 5 +- src/bin/main.c | 12 -- src/bin/menu.c | 2 - src/bin/redoundo.c | 463 ++++++++++++++++++++++++------------------------- src/include/common.h | 2 +- src/include/redoundo.h | 91 +--------- 9 files changed, 294 insertions(+), 363 deletions(-) diff --git a/README b/README index aad958b..fb24f86 100644 --- a/README +++ b/README @@ -57,6 +57,8 @@ Ctrl+Shift+W = Insert Part Template Code: Swallow Ctrl+A = Select Text All Ctrl+Double Click = Select a word +Ctrl+Z = Undo Text +Ctrl+R = Redo Text Ctrl+C = Copy Selected Text Ctrl+V = Paste Copied Text Ctrl+X = Cut Selected Text diff --git a/src/bin/auto_comp.c b/src/bin/auto_comp.c index 6a728b0..9157c39 100644 --- a/src/bin/auto_comp.c +++ b/src/bin/auto_comp.c @@ -198,7 +198,6 @@ static void insert_completed_text(autocomp_data *ad) { if (!ad->compset_list) return; - int redoundo_cursor = 0; Elm_Object_Item *it = elm_list_selected_item_get(ad->list); comp_set *compset = elm_object_item_data_get(it); @@ -206,7 +205,7 @@ insert_completed_text(autocomp_data *ad) Evas_Object *entry = edit_entry_get(ad->ed); int space = edit_cur_indent_depth_get(ad->ed); - redoundo_cursor = elm_entry_cursor_pos_get(entry); + int cursor_pos = elm_entry_cursor_pos_get(entry); //Insert the first line. elm_entry_entry_insert(entry, txt[0]+ (ad->queue_pos + 1)); @@ -229,17 +228,12 @@ insert_completed_text(autocomp_data *ad) elm_entry_entry_insert(entry, txt[i]); } - int cursor_pos = elm_entry_cursor_pos_get(entry); - - /* undo/redo feture connection */ - elm_entry_select_region_set(entry, redoundo_cursor, cursor_pos); - redoundo_node_add(elm_entry_selection_get(entry), redoundo_cursor, - cursor_pos - redoundo_cursor, EINA_TRUE); - elm_entry_select_none(entry); - /*--------------------------------------------------------------*/ + int cursor_pos2 = elm_entry_cursor_pos_get(entry); + redoundo_data *rd = evas_object_data_get(entry, "redoundo"); + redoundo_entry_region_push(rd, cursor_pos, cursor_pos2); - cursor_pos -= (compset->cursor_offset + (compset->line_back * space)); - elm_entry_cursor_pos_set(entry, cursor_pos); + cursor_pos2 -= (compset->cursor_offset + (compset->line_back * space)); + elm_entry_cursor_pos_set(entry, cursor_pos2); edit_line_increase(ad->ed, (compset->line_cnt - 1)); } diff --git a/src/bin/edc_editor.c b/src/bin/edc_editor.c index 0818eae..9886d5e 100644 --- a/src/bin/edc_editor.c +++ b/src/bin/edc_editor.c @@ -25,6 +25,7 @@ struct editor_s syntax_helper *sh; parser_data *pd; + redoundo_data *rd; int cur_line; int line_max; @@ -334,7 +335,7 @@ ctxpopup_candidate_selected_cb(void *data, Evas_Object *obj, void *event_info) { edit_data *ed = data; const char *text = event_info; - redoundo_candidate_add(text, elm_entry_cursor_pos_get(ed->en_edit)); + redoundo_text_relative_push(ed->rd, text); elm_entry_entry_insert(ed->en_edit, text); elm_ctxpopup_dismiss(obj); edit_changed_set(ed, EINA_TRUE); @@ -445,6 +446,9 @@ edit_template_insert(edit_data *ed) elm_entry_entry_insert(ed->en_edit, p); elm_entry_entry_insert(ed->en_edit, t[i]); + int cursor_pos2 = elm_entry_cursor_pos_get(ed->en_edit); + redoundo_entry_region_push(ed->rd, cursor_pos, cursor_pos2); + elm_entry_cursor_pos_set(ed->en_edit, cursor_pos); syntax_color_partial_update(ed, 0); @@ -519,7 +523,6 @@ edit_template_part_insert(edit_data *ed, Edje_Part_Type type) break; } - int redoundo_cursor = 0; int i; for (i = 0; i < (line_cnt - 1); i++) { @@ -532,11 +535,8 @@ edit_template_part_insert(edit_data *ed, Edje_Part_Type type) elm_entry_entry_insert(ed->en_edit, p); elm_entry_entry_insert(ed->en_edit, t[i]); - redoundo_cursor = elm_entry_cursor_pos_get(ed->en_edit); - elm_entry_select_region_set(ed->en_edit, cursor_pos, redoundo_cursor); - redoundo_node_add(elm_entry_selection_get(ed->en_edit), cursor_pos, - redoundo_cursor - cursor_pos, EINA_TRUE); - elm_entry_select_none(ed->en_edit); + int cursor_pos2 = elm_entry_cursor_pos_get(ed->en_edit); + redoundo_entry_region_push(ed->rd, cursor_pos, cursor_pos2); elm_entry_cursor_pos_set(ed->en_edit, cursor_pos); @@ -834,7 +834,8 @@ edit_line_delete(edit_data *ed) //only one line remain. clear it. if (ed->line_max == 1) { - redoundo_node_add(elm_entry_entry_get(ed->en_edit), 0, 0, EINA_FALSE); + redoundo_text_push(ed->rd, elm_entry_entry_get(ed->en_edit), 0, 0, + EINA_FALSE); elm_entry_entry_set(ed->en_edit, ""); line_init(ed); return; @@ -857,15 +858,31 @@ edit_line_delete(edit_data *ed) evas_textblock_cursor_range_delete(cur1, cur2); evas_textblock_cursor_free(cur1); evas_textblock_cursor_free(cur2); - redoundo_node_add(content, cur1_pos, abs(cur2_pos - cur1_pos), EINA_FALSE); + redoundo_text_push(ed->rd, content, cur1_pos, abs(cur2_pos - cur1_pos), + EINA_FALSE); elm_entry_calc_force(ed->en_edit); edit_line_decrease(ed, 1); cur_line_pos_set(ed, EINA_TRUE); edit_changed_set(ed, EINA_TRUE); +} +static void +edit_redoundo(edit_data *ed, Eina_Bool undo) +{ + int lines; + Eina_Bool changed; + if (undo) lines = redoundo_undo(ed->rd, &changed); + else lines = redoundo_redo(ed->rd, &changed); + if (!changed) return; + + if (lines > 0) edit_line_increase(ed, lines); + else edit_line_decrease(ed, abs(lines)); + + edit_changed_set(ed, EINA_TRUE); + syntax_color_full_update(ed, EINA_TRUE); } static Eina_Bool @@ -876,7 +893,26 @@ key_down_cb(void *data, int type EINA_UNUSED, void *ev) //Control Key if (!strcmp("Control_L", event->key)) - ed->ctrl_pressed = EINA_TRUE; + { + ed->ctrl_pressed = EINA_TRUE; + return ECORE_CALLBACK_PASS_ON; + } + + if (ed->ctrl_pressed) + { + //Undo + if (!strcmp(event->key, "z") || !strcmp(event->key, "Z")) + { + edit_redoundo(ed, EINA_TRUE); + return ECORE_CALLBACK_DONE; + } + //Redo + if (!strcmp(event->key, "r") || !strcmp(event->key, "R")) + { + edit_redoundo(ed, EINA_FALSE); + return ECORE_CALLBACK_DONE; + } + } return ECORE_CALLBACK_PASS_ON; } @@ -1019,7 +1055,8 @@ edit_init(Evas_Object *parent) edit_line_number_toggle(ed); edit_font_size_update(ed, EINA_FALSE, EINA_FALSE); - redoundo_init(en_edit); + ed->rd = redoundo_init(en_edit); + evas_object_data_set(ed->en_edit, "redoundo", ed->rd); return ed; } @@ -1044,13 +1081,13 @@ edit_term(edit_data *ed) syntax_helper *sh = ed->sh; parser_data *pd = ed->pd; + redoundo_term(ed->rd); ecore_thread_cancel(ed->syntax_color_thread); ecore_timer_del(ed->syntax_color_timer); free(ed); syntax_term(sh); parser_term(pd); - redoundo_term(); } void @@ -1202,6 +1239,7 @@ edit_edc_reload(edit_data *ed, const char *edc_path) edit_new(ed); edj_mgr_reload_need_set(EINA_TRUE); config_apply(); + redoundo_clear(ed->rd); } Eina_Stringshare * diff --git a/src/bin/indent.c b/src/bin/indent.c index 08879f4..247bc72 100644 --- a/src/bin/indent.c +++ b/src/bin/indent.c @@ -95,9 +95,10 @@ indent_insert_br_case(indent_data *id, Evas_Object *entry) memset(p, ' ', space); p[space] = '\0'; - redoundo_node_add(p, elm_entry_cursor_pos_get(entry), 0, EINA_TRUE); - elm_entry_entry_insert(entry, p); + redoundo_data *rd = evas_object_data_get(entry, "redoundo"); + redoundo_text_push(rd, p, elm_entry_cursor_pos_get(entry), 0, EINA_TRUE); + elm_entry_entry_insert(entry, p); } static void diff --git a/src/bin/main.c b/src/bin/main.c index 4cce725..0a0df11 100644 --- a/src/bin/main.c +++ b/src/bin/main.c @@ -177,18 +177,6 @@ ctrl_func(app_data *ad, const char *key) autocomp_toggle(); return ECORE_CALLBACK_DONE; } - //Undo - if (!strcmp(key, "z") || !strcmp(key, "Z")) - { - undo(ad->ed); - return ECORE_CALLBACK_DONE; - } - //Redo - if (!strcmp(key, "y") || !strcmp(key, "Y")) - { - redo(ad->ed); - return ECORE_CALLBACK_DONE; - } return ECORE_CALLBACK_PASS_ON; } diff --git a/src/bin/menu.c b/src/bin/menu.c index c031f00..c1ca7d9 100644 --- a/src/bin/menu.c +++ b/src/bin/menu.c @@ -171,7 +171,6 @@ newfile_open(menu_data *md) md->newfile_layout = layout; menu_activate_request(); - redoundo_clear(); } static void @@ -580,7 +579,6 @@ edc_file_load(menu_data *md) elm_object_focus_set(fs, EINA_TRUE); md->fileselector_layout = layout; - redoundo_clear(); } static void diff --git a/src/bin/redoundo.c b/src/bin/redoundo.c index 7b40557..9aef9eb 100644 --- a/src/bin/redoundo.c +++ b/src/bin/redoundo.c @@ -1,93 +1,63 @@ #include <Elementary.h> #include "common.h" - -/** - * @struct _Diff - * The structure, that store one step of changes. - */ -struct _Diff +typedef struct diff_s { - Eina_Stringshare *diff; /**< The text, that was changed.*/ - unsigned int length; /**< Length of changed text. */ - unsigned int position; /**< Entry cursor position from that was changed text */ - Eina_Bool action; /**< Type of action: EINA_TRUE - text insert, - EINA_FALSE - text delete */ - Eina_Bool relative; /**< If this change relative to prevision or next step - this flag will EINA_TRUE*/ -}; -typedef struct _Diff Diff; - - -/** - * @struct _redoundo_queue. - * The main structure of Redo/Undo module. Here stored queue of changes and - * support fields to manage this queue. - */ -struct _redoundo_queue + Eina_Stringshare *text; + unsigned int length; + unsigned int cursor_pos; + Eina_Bool action : 1; //EINA_TRUE: insert, EINA_FALSE, delete + Eina_Bool relative : 1; //If this change relative to prevision or next step +} diff_data; + +struct redoundo_s { - Evas_Object *entry; /**< The elm_entry object, that will changed */ - Evas_Object *textblock; /**< Textblock from entry, needed for apply changes */ - Evas_Textblock_Cursor *cursor; /**< Support cursor, that provide fast access - to navigate in textblock. */ - Eina_List *queue; /**< Queue of changes. Here stored - @c _Diff structures.*/ - Eina_List *current_node; /**< Support list pointer, that provide - fast management with queue. Pointed to - current change list node*/ - Diff *last_diff; /**< @c _Diff pointer to current changes. - Provide quick acces to changes data*/ - Eina_Bool internal_change; /**< The flag, that indicates that change in - entry was initiated by Redo/Undo module. */ + Evas_Object *entry; + Evas_Object *textblock; + Evas_Textblock_Cursor *cursor; + Eina_List *queue; + Eina_List *current_node; + diff_data *last_diff; + Eina_Bool internal_change : 1; //Entry change by redoundo }; -static queue *g_queue = NULL; - static void -_free_untracked_changes(void) +untracked_diff_free(redoundo_data *rd) { - if (!g_queue) return; - if (!g_queue->last_diff) + if (!rd->last_diff) { - redoundo_clear(); + redoundo_clear(rd); return; } - Eina_List *l = NULL; - Diff *data = NULL; + Eina_List *l; + diff_data *diff; - EINA_LIST_REVERSE_FOREACH(g_queue->queue, l, data) + EINA_LIST_REVERSE_FOREACH(rd->queue, l, diff) { - if (data == g_queue->last_diff) break; - eina_stringshare_del(data->diff); - free(data); - g_queue->queue = eina_list_remove_list(g_queue->queue, l); + if (diff == rd->last_diff) break; + eina_stringshare_del(diff->text); + free(diff); + rd->queue = eina_list_remove_list(rd->queue, l); } - - return; } static void -_changed_user_cb(void *data EINA_UNUSED, - Evas_Object *obj EINA_UNUSED, - const char *emission EINA_UNUSED, - const char *source EINA_UNUSED) +entry_changed_user_cb(void *data, Evas_Object *obj EINA_UNUSED, + const char *emission EINA_UNUSED, + const char *source EINA_UNUSED) { - Edje_Entry_Change_Info *info = (Edje_Entry_Change_Info *) - edje_object_signal_callback_extra_data_get(); + redoundo_data *rd = data; + Edje_Entry_Change_Info *info = edje_object_signal_callback_extra_data_get(); - if (!info) return; - Diff *change = NULL; - int length = 0; - - if (g_queue->internal_change) + if (rd->internal_change) { - g_queue->internal_change = EINA_FALSE; + rd->internal_change = EINA_FALSE; return; } - change = (Diff *)calloc(1, sizeof(Diff)); - if (!change) + diff_data *diff = calloc(1, sizeof(diff_data)); + if (!diff) { EINA_LOG_ERR("Failed to allocate Memory!"); return; @@ -95,271 +65,286 @@ _changed_user_cb(void *data EINA_UNUSED, if (info->insert) { - if (!info->change.insert.plain_length) goto end; - - change->diff = eina_stringshare_add(info->change.insert.content); - change->length = strlen(evas_textblock_text_markup_to_utf8( - g_queue->textblock, change->diff)); - change->position = info->change.insert.pos; - change->action = EINA_TRUE; + if (info->change.insert.plain_length == 0) goto nochange; + diff->text = eina_stringshare_add(info->change.insert.content); + char *utf8 = evas_textblock_text_markup_to_utf8(NULL, diff->text); + diff->length = strlen(utf8); + diff->cursor_pos = info->change.insert.pos; + diff->action = EINA_TRUE; + free(utf8); } else { - change->diff = eina_stringshare_add(info->change.del.content); - length = info->change.del.end - info->change.del.start; - if (!length) goto end; - - if (length > 0) change->position = info->change.del.start; - else change->position = info->change.del.end; - - change->length = abs(length); - change->action = EINA_FALSE; + int length = (info->change.del.end - info->change.del.start); + if (length == 0) goto nochange; + + diff->text = eina_stringshare_add(info->change.del.content); + if (length > 0) diff->cursor_pos = info->change.del.start; + else diff->cursor_pos = info->change.del.end; + diff->length = abs(length); + diff->action = EINA_FALSE; } - change->relative = EINA_FALSE; + diff->relative = EINA_FALSE; - _free_untracked_changes(); - g_queue->queue = eina_list_append(g_queue->queue, change); - g_queue->last_diff = change; - g_queue->current_node = eina_list_last(g_queue->queue); + untracked_diff_free(rd); + rd->queue = eina_list_append(rd->queue, diff); + rd->last_diff = diff; + rd->current_node = eina_list_last(rd->queue); return; -end: - free(change); - return; +nochange: + free(diff); } -Eina_Bool -undo(edit_data *ed) +int +redoundo_undo(redoundo_data *rd, Eina_Bool *changed) { - if ((!g_queue) || (!g_queue->last_diff)) - return EINA_FALSE; + *changed = EINA_FALSE; + + if (!rd->last_diff) return 0; - int lines = 0; + elm_entry_cursor_pos_set(rd->entry, rd->last_diff->cursor_pos); + rd->internal_change = EINA_TRUE; - elm_entry_cursor_pos_set(g_queue->entry, g_queue->last_diff->position); - g_queue->internal_change = EINA_TRUE; - if (g_queue->last_diff->action) - { /* Last change was adding new symbol(s), that mean here need delete it */ - stats_line_num_update(0, elm_entry_cursor_pos_get(g_queue->entry)); - if (g_queue->last_diff->length == 1) + int lines; + + if (rd->last_diff->action) + { + //Last change was adding new symbol(s), that mean here need delete it + //FIXME: cur_line is 0? + stats_line_num_update(0, elm_entry_cursor_pos_get(rd->entry)); + + //Undo one character + if (rd->last_diff->length == 1) { - evas_textblock_cursor_pos_set(g_queue->cursor, - g_queue->last_diff->position); - evas_textblock_cursor_char_delete(g_queue->cursor); + evas_textblock_cursor_pos_set(rd->cursor, + rd->last_diff->cursor_pos); + evas_textblock_cursor_char_delete(rd->cursor); } + //Undo String else { - Evas_Textblock_Cursor *range = evas_object_textblock_cursor_new( - g_queue->textblock); - evas_textblock_cursor_pos_set(g_queue->cursor, - g_queue->last_diff->position); - evas_textblock_cursor_pos_set(range, g_queue->last_diff->position + - g_queue->last_diff->length); - evas_textblock_cursor_range_delete(g_queue->cursor, range); - evas_textblock_cursor_free(range); + Evas_Textblock_Cursor *cursor = + evas_object_textblock_cursor_new( rd->textblock); + evas_textblock_cursor_pos_set(rd->cursor, + rd->last_diff->cursor_pos); + evas_textblock_cursor_pos_set(cursor, + (rd->last_diff->cursor_pos + + rd->last_diff->length)); + evas_textblock_cursor_range_delete(rd->cursor, cursor); + evas_textblock_cursor_free(cursor); } - lines = parser_line_cnt_get(NULL, g_queue->last_diff->diff); - edit_line_decrease(ed, lines); + lines = -parser_line_cnt_get(NULL, rd->last_diff->text); } else { - evas_textblock_cursor_pos_set(g_queue->cursor, - g_queue->last_diff->position); - evas_object_textblock_text_markup_prepend(g_queue->cursor, - g_queue->last_diff->diff); + evas_textblock_cursor_pos_set(rd->cursor, + rd->last_diff->cursor_pos); + evas_object_textblock_text_markup_prepend(rd->cursor, + rd->last_diff->text); - lines = parser_line_cnt_get(NULL, g_queue->last_diff->diff); - edit_line_increase(ed, lines); + lines = parser_line_cnt_get(NULL, rd->last_diff->text); } - g_queue->internal_change = EINA_FALSE; - g_queue->current_node = eina_list_prev(g_queue->current_node); - g_queue->last_diff = eina_list_data_get(g_queue->current_node); + rd->internal_change = EINA_FALSE; + rd->current_node = eina_list_prev(rd->current_node); + rd->last_diff = eina_list_data_get(rd->current_node); - if ((g_queue->last_diff) && (g_queue->last_diff->relative)) undo(ed); - edit_changed_set(ed, EINA_TRUE); - edit_syntax_color_full_apply(ed, EINA_TRUE); - return EINA_TRUE; + if (rd->last_diff && rd->last_diff->relative) + lines += redoundo_undo(rd, changed); + + *changed = EINA_TRUE; + + return lines; } -Eina_Bool -redo(edit_data *ed) +int +redoundo_redo(redoundo_data *rd, Eina_Bool *changed) { - if ((!g_queue) || (!g_queue->queue)) - return EINA_FALSE; + *changed = EINA_FALSE; - Eina_List *next = NULL; - Diff *change = NULL; + if (!rd->queue) return 0; + + Eina_List *next; + diff_data *diff; int lines; - next = eina_list_next(g_queue->current_node); - change = eina_list_data_get(next); + next = eina_list_next(rd->current_node); + diff = eina_list_data_get(next); - if ((!next) && (!g_queue->last_diff)) + if ((!next) && (!rd->last_diff)) { - next = g_queue->queue; - change = eina_list_data_get(next); + next = rd->queue; + diff = eina_list_data_get(next); } - if ((!next) || (!change)) + if (!next || !diff) { - g_queue->internal_change = EINA_FALSE; - return EINA_FALSE; + rd->internal_change = EINA_FALSE; + return 0; } - g_queue->internal_change = EINA_TRUE; - if (change->action) + rd->internal_change = EINA_TRUE; + + //Insert + if (diff->action) { - evas_textblock_cursor_pos_set(g_queue->cursor, change->position); - evas_object_textblock_text_markup_prepend(g_queue->cursor, change->diff); + evas_textblock_cursor_pos_set(rd->cursor, diff->cursor_pos); + evas_object_textblock_text_markup_prepend(rd->cursor, diff->text); - lines = parser_line_cnt_get(NULL, change->diff); - edit_line_increase(ed, lines); + lines = parser_line_cnt_get(NULL, diff->text); } + //Remove else { - if (change->length == 1) + //One Character + if (diff->length == 1) { - evas_textblock_cursor_pos_set(g_queue->cursor, change->position); - evas_textblock_cursor_char_delete(g_queue->cursor); + evas_textblock_cursor_pos_set(rd->cursor, diff->cursor_pos); + evas_textblock_cursor_char_delete(rd->cursor); } + //String else { - Evas_Textblock_Cursor *range = evas_object_textblock_cursor_new( - g_queue->textblock); - evas_textblock_cursor_pos_set(g_queue->cursor, change->position); - evas_textblock_cursor_pos_set(range, change->position + change->length); - evas_textblock_cursor_range_delete(g_queue->cursor, range); - evas_textblock_cursor_free(range); + Evas_Textblock_Cursor *cursor = + evas_object_textblock_cursor_new(rd->textblock); + evas_textblock_cursor_pos_set(rd->cursor, diff->cursor_pos); + evas_textblock_cursor_pos_set(cursor, + (diff->cursor_pos + diff->length)); + evas_textblock_cursor_range_delete(rd->cursor, cursor); + evas_textblock_cursor_free(cursor); } - lines = parser_line_cnt_get(NULL, change->diff); - edit_line_decrease(ed, lines); + lines = -parser_line_cnt_get(NULL, diff->text); } - g_queue->internal_change = EINA_FALSE; - elm_entry_cursor_pos_set(g_queue->entry, change->position + change->length); - - g_queue->last_diff = change; - g_queue->current_node = next; - - if (change->relative) redo(ed); - edit_changed_set(ed, EINA_TRUE); - edit_syntax_color_full_apply(ed, EINA_TRUE); - return EINA_TRUE; -} -Eina_Bool -redoundo_candidate_add(const char *content, int pos) -{ - if ((!g_queue) || (!content) || (!pos)) return EINA_FALSE; - Diff *change = NULL; + rd->internal_change = EINA_FALSE; + elm_entry_cursor_pos_set(rd->entry, (diff->cursor_pos + diff->length)); - change = (Diff *)calloc(1, sizeof(Diff)); - if (!change) - { - EINA_LOG_ERR("Failed to allocate Memory!"); - return EINA_FALSE; - } + rd->last_diff = diff; + rd->current_node = next; - change->diff = eina_stringshare_add(content); - change->length = strlen(evas_textblock_text_markup_to_utf8( - g_queue->textblock, change->diff)); - change->position = pos; - change->action = EINA_TRUE; - change->relative = EINA_TRUE; + if (diff->relative) + lines += redoundo_redo(rd, changed); - _free_untracked_changes(); - g_queue->queue = eina_list_append(g_queue->queue, change); - g_queue->last_diff = change; - g_queue->current_node = eina_list_last(g_queue->queue); + *changed = EINA_TRUE; return EINA_TRUE; } -Eina_Bool -redoundo_node_add(const char *content, int pos, int length, Eina_Bool insert) +void +redoundo_text_push(redoundo_data *rd, const char *text, int pos, int length, + Eina_Bool insert) { - if ((!g_queue) || (!content)) return EINA_FALSE; - Diff *change = NULL; + if (!text) return; - change = (Diff *)calloc(1, sizeof(Diff)); - if (!change) + diff_data *diff = calloc(1, sizeof(diff_data)); + if (!diff) { EINA_LOG_ERR("Failed to allocate Memory!"); return; } - change->diff = eina_stringshare_add(content); - if (length) change->length = length; - else change->length = strlen(evas_textblock_text_markup_to_utf8( - g_queue->textblock, change->diff)); - if (!change->length) + if (length) diff->length = length; + else { - eina_stringshare_del(change->diff); - free(change); - return; + char *utf8 = evas_textblock_text_markup_to_utf8(NULL, text); + diff->length = strlen(utf8); + free(utf8); + if (!diff->length) + { + free(diff); + return; + } } - change->position = pos; - change->action = insert; - change->relative = EINA_FALSE; - _free_untracked_changes(); - g_queue->queue = eina_list_append(g_queue->queue, change); - g_queue->last_diff = change; - g_queue->current_node = eina_list_last(g_queue->queue); + diff->text = eina_stringshare_add(text); + diff->cursor_pos = pos; + diff->action = insert; + diff->relative = EINA_FALSE; - return EINA_TRUE; + untracked_diff_free(rd); + rd->queue = eina_list_append(rd->queue, diff); + rd->last_diff = diff; + rd->current_node = eina_list_last(rd->queue); } -queue * +redoundo_data * redoundo_init(Evas_Object *entry) { if (!entry) return NULL; - g_queue = (queue *)calloc(1, sizeof(queue)); - if (!g_queue) + redoundo_data *rd = calloc(1, sizeof(redoundo_data)); + if (!rd) { EINA_LOG_ERR("Failed to allocate Memory!"); return NULL; } - g_queue->entry = entry; - g_queue->textblock = elm_entry_textblock_get(entry); - g_queue->cursor = evas_object_textblock_cursor_new(g_queue->textblock); - g_queue->internal_change = EINA_FALSE; + rd->entry = entry; + rd->textblock = elm_entry_textblock_get(entry); + rd->cursor = evas_object_textblock_cursor_new(rd->textblock); + //FIXME: Why signal callback? not smart callback? elm_object_signal_callback_add(entry, "entry,changed,user", "*", - _changed_user_cb, NULL); - - return g_queue; + entry_changed_user_cb, rd); + return rd; } -Eina_Bool -redoundo_clear(void) +void +redoundo_clear(redoundo_data *rd) { - Diff *data = NULL; - if (!g_queue) return EINA_FALSE; + diff_data *data; - EINA_LIST_FREE(g_queue->queue, data) + EINA_LIST_FREE(rd->queue, data) { - eina_stringshare_del(data->diff); + eina_stringshare_del(data->text); free(data); } - g_queue->internal_change = EINA_FALSE; - return EINA_TRUE; + rd->internal_change = EINA_FALSE; } -Eina_Bool -redoundo_term(void) +void +redoundo_term(redoundo_data *rd) { - if (!g_queue) return EINA_FALSE; - - g_queue->entry = NULL; - g_queue->textblock = NULL; - evas_textblock_cursor_free(g_queue->cursor); + redoundo_clear(rd); + evas_textblock_cursor_free(rd->cursor); + free(rd); +} - redoundo_clear(); - free(g_queue); - return EINA_TRUE; +void +redoundo_entry_region_push(redoundo_data *rd, int cursor_pos, int cursor_pos2) +{ + elm_entry_select_region_set(rd->entry, cursor_pos, cursor_pos2); + redoundo_text_push(rd, elm_entry_selection_get(rd->entry), cursor_pos, + (cursor_pos2 - cursor_pos), EINA_TRUE); + elm_entry_select_none(rd->entry); } +void +redoundo_text_relative_push(redoundo_data *rd, const char *text) +{ + if (!text) return; + + diff_data *diff = malloc(sizeof(diff_data)); + if (!diff) + { + EINA_LOG_ERR("Failed to allocate Memory!"); + return; + } + + diff->text = eina_stringshare_add(text); + char *utf8 = evas_textblock_text_markup_to_utf8(NULL, diff->text); + diff->length = strlen(utf8); + diff->cursor_pos = elm_entry_cursor_pos_get(rd->entry); + diff->action = EINA_TRUE; + diff->relative = EINA_TRUE; + + untracked_diff_free(rd); + + rd->queue = eina_list_append(rd->queue, diff); + rd->last_diff = diff; + rd->current_node = eina_list_last(rd->queue); + + free(utf8); +} diff --git a/src/include/common.h b/src/include/common.h index 9afe159..f56a3df 100644 --- a/src/include/common.h +++ b/src/include/common.h @@ -9,7 +9,7 @@ typedef struct parser_s parser_data; typedef struct attr_value_s attr_value; typedef struct syntax_helper_s syntax_helper; typedef struct indent_s indent_data; -typedef struct _redoundo_queue queue; +typedef struct redoundo_s redoundo_data; #include "edc_editor.h" #include "menu.h" diff --git a/src/include/redoundo.h b/src/include/redoundo.h index 37397fd..35cfe6c 100644 --- a/src/include/redoundo.h +++ b/src/include/redoundo.h @@ -1,84 +1,9 @@ -#ifndef __REDOUNDO_H__ -#define __REDOUNDO_H__ +redoundo_data *redoundo_init(Evas_Object *entry); +void redoundo_term(redoundo_data *rd); +void redoundo_clear(redoundo_data *rd); +void redoundo_text_push(redoundo_data *rd, const char *text, int pos, int length, Eina_Bool insert); +void redoundo_text_relative_push(redoundo_data *rd, const char *text); +void redoundo_entry_region_push(redoundo_data *rd, int cursor_pos, int cursor_pos2); +int redoundo_undo(redoundo_data *rd, Eina_Bool *changed); +int redoundo_redo(redoundo_data *rd, Eina_Bool *changed); -/* FIXME: Change comments! */ - -/** - * This function undo the last change, that will happen in entry. If there are - * wasn't changes will returned EINA_FALSE; - * - * @param ed The pointer to the editor_s instatns; - * - * @return EINA_TRUE on success or EINA_FALSE in otherwise. - */ -Eina_Bool -undo(edit_data *ed); - -/** - * This function redo the previos change, that will happen in entry. If there are - * wasn't changes will returned EINA_FALSE; - * - * @param ed The pointer to the editor_s instatns; - * - * @return EINA_TRUE on success or EINA_FALSE in otherwise. - */ -Eina_Bool -redo(edit_data *ed); - -/** - * This function provide add new node into undo/redo stack, that shoud take - * undo or redo action with next(for redo) or prevision(for undo) node from stack. - * - * @param content The pointer to text, which need mark as changed. - * @param pos The position, where text shoud begin in editable area. - * - * @return EINA_TRUE on success or EINA_FALSE in otherwise. - * - */ -Eina_Bool -redoundo_candidate_add(const char *content, int pos); - -/** - * This function provide add new node into undo/redo stack. - * - * @param content The pointer to text, which need mark as changed. - * @param pos The position, where text shoud begin in editable area. - * @param length The length of text. If this value equal 0, then length will - * calculate with using eina_stringshare_strlen, after sharing. - * @param insert If EINA_TRUE change will mark as new text append action, - * else change will known as remove action. - * - * @return EINA_TRUE on success or EINA_FALSE in otherwise. - * - * @note This function need to resolve situations, where text is inserted by API, - * and this event doesn't emit signal "entry,changed,user" - */ -Eina_Bool -redoundo_node_add(const char *diff, int pos, int length, Eina_Bool insert); - -/** - * Initialize undo/redo module. - * - * @param entry The Evas_Object pointer to elm_entry, that contain chengable text. - * @return @queue structure if success, or NULL in otherwise. - */ -queue * -redoundo_init(Evas_Object *entry); - -/** - * Terminating undo/redo submodule; - * - * @return EINA_TRUE on success or EINA_FALSE in otherwise. - */ -Eina_Bool -redoundo_term(void); - -/** - * Clear all history of changes; - * - * @return EINA_TRUE on success or EINA_FALSE in otherwise. - */ -Eina_Bool -redoundo_clear(void); - -#endif /* __REDOUNDO_H__ */ --
