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__ */

-- 


Reply via email to