diff --git a/ChangeLog b/ChangeLog index 8db2083..aefc025 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2014-05-15 ajwillia.ms (Andy Williams) + + * Add basic undo support + 2014-04-27 ajwillia.ms (Andy Williams) * Add simple build functions diff --git a/src/bin/editor/edi_editor.c b/src/bin/editor/edi_editor.c index 02eea6c..2c32187 100644 --- a/src/bin/editor/edi_editor.c +++ b/src/bin/editor/edi_editor.c @@ -5,7 +5,7 @@ #include #include -#include +#include #include "edi_editor.h" @@ -14,6 +14,86 @@ #include "edi_private.h" +static void +_undo_do(Edi_Editor *editor, Elm_Entry_Change_Info *inf) +{ + if (inf->insert) + { + const Evas_Object *tb = elm_entry_textblock_get(editor->entry); + Evas_Textblock_Cursor *mcur, *end; + mcur = (Evas_Textblock_Cursor *) evas_object_textblock_cursor_get(tb); + end = evas_object_textblock_cursor_new(tb); + + if (inf->insert) + { + elm_entry_cursor_pos_set(editor->entry, inf->change.insert.pos); + evas_textblock_cursor_pos_set(end, inf->change.insert.pos + + inf->change.insert.plain_length); + } + else + { + elm_entry_cursor_pos_set(editor->entry, inf->change.del.start); + evas_textblock_cursor_pos_set(end, inf->change.del.end); + } + + evas_textblock_cursor_range_delete(mcur, end); + evas_textblock_cursor_free(end); + elm_entry_calc_force(editor->entry); + } + else + { + if (inf->insert) + { + elm_entry_cursor_pos_set(editor->entry, inf->change.insert.pos); + elm_entry_entry_insert(editor->entry, inf->change.insert.content); + } + else + { + size_t start; + start = (inf->change.del.start < inf->change.del.end) ? + inf->change.del.start : inf->change.del.end; + + elm_entry_cursor_pos_set(editor->entry, start); + elm_entry_entry_insert(editor->entry, inf->change.insert.content); + elm_entry_cursor_pos_set(editor->entry, inf->change.del.end); + } + } +} + +static void +_undo_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Elm_Entry_Change_Info *change; + Edi_Editor *editor = data; + + if (!eina_list_next(editor->undo_stack)) + return; + + change = eina_list_data_get(editor->undo_stack); + _undo_do(editor, change); + editor->undo_stack = eina_list_next(editor->undo_stack); +} + +static void +_changed_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info) +{ + Elm_Entry_Change_Info *change; + Edi_Editor *editor = data; + + change = calloc(1, sizeof(*change)); + memcpy(change, event_info, sizeof(*change)); + if (change->insert) + { + eina_stringshare_ref(change->change.insert.content); + } + else + { + eina_stringshare_ref(change->change.del.content); + } + + editor->undo_stack = eina_list_prepend(editor->undo_stack, change); +} + static void _smart_cb_key_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event) @@ -43,6 +123,10 @@ _smart_cb_key_down(void *data, Evas *e EINA_UNUSED, { edi_mainview_search(); } + else if (!strcmp(ev->key, "z")) + { + _undo_cb(data, obj, event); + } } } @@ -51,6 +135,7 @@ EAPI Evas_Object *edi_editor_add(Evas_Object *parent, const char *path) Evas_Object *txt; Evas_Modifier_Mask ctrl, shift, alt; Evas *e; + Edi_Editor *editor; txt = elm_entry_add(parent); elm_entry_editable_set(txt, EINA_TRUE); @@ -63,8 +148,12 @@ EAPI Evas_Object *edi_editor_add(Evas_Object *parent, const char *path) evas_object_size_hint_align_set(txt, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_show(txt); + editor = calloc(1, sizeof(*editor)); + editor->entry = txt; evas_object_event_callback_add(txt, EVAS_CALLBACK_KEY_DOWN, - _smart_cb_key_down, txt); + _smart_cb_key_down, editor); + evas_object_smart_callback_add(txt, "changed,user", _changed_cb, editor); + evas_object_smart_callback_add(txt, "undo,request", _undo_cb, editor); e = evas_object_evas_get(txt); ctrl = evas_key_modifier_mask_get(e, "Control"); @@ -75,6 +164,7 @@ EAPI Evas_Object *edi_editor_add(Evas_Object *parent, const char *path) evas_object_key_grab(txt, "Next", ctrl, shift | alt, 1); evas_object_key_grab(txt, "s", ctrl, shift | alt, 1); evas_object_key_grab(txt, "f", ctrl, shift | alt, 1); + evas_object_key_grab(txt, "z", ctrl, shift | alt, 1); return txt; } diff --git a/src/bin/editor/edi_editor.h b/src/bin/editor/edi_editor.h index 313f2b8..04897b8 100644 --- a/src/bin/editor/edi_editor.h +++ b/src/bin/editor/edi_editor.h @@ -12,6 +12,26 @@ extern "C" { * @brief These routines are used for interacting with the main Edi editor view. */ +/** + * @typedef Edi_Editor + * An instance of an editor view. + */ +typedef struct _Edi_Editor Edi_Editor; + +/** + * @struct _Edi_Editor + * An instance of an editor view. + */ +struct _Edi_Editor +{ + Evas_Object *entry; /**< The main text entry widget for the editor */ + Eina_List *undo_stack; /**< The list of operations that can be undone */ + + /* Private */ + + /* Add new members here. */ +}; + /** * @brief Editor. * @defgroup Editor The main text editor functions