#ifdef HAVE_CONFIG_H # include "elementary_config.h" #endif #include "Elementary.h" #include "elm_code_widget_private.h" static void _elm_code_widget_undo_prev_clear(Evas_Object *widget) { Elm_Code_Widget_Data *pd; Elm_Code_Widget_Change_Info *info; Eina_List *list; pd = efl_data_scope_get(widget, ELM_CODE_WIDGET_CLASS); if (!pd->undo_stack_ptr) return; for (list = eina_list_prev(pd->undo_stack_ptr); list; list = eina_list_prev(list)) { info = eina_list_data_get(list); free(info->content); free(info); } } Elm_Code_Widget_Change_Info * _elm_code_widget_undo_info_copy(Elm_Code_Widget_Change_Info *info) { Elm_Code_Widget_Change_Info *copy; copy = calloc(1, sizeof(*info)); if (!copy) return NULL; memcpy(copy, info, sizeof(*info)); copy->content = eina_strndup(info->content, info->length); return copy; } void _elm_code_widget_undo_change_add(Evas_Object *widget, Elm_Code_Widget_Change_Info *info) { Elm_Code_Widget_Data *pd; Elm_Code_Widget_Change_Info *info_copy; info_copy = _elm_code_widget_undo_info_copy(info); pd = efl_data_scope_get(widget, ELM_CODE_WIDGET_CLASS); _elm_code_widget_undo_prev_clear(widget); pd->undo_stack_ptr = eina_list_prepend(pd->undo_stack_ptr, info_copy); pd->undo_stack = pd->undo_stack_ptr; } static void _elm_code_widget_undo_change(Evas_Object *widget, Elm_Code_Widget_Change_Info *info) { Elm_Code_Widget_Data *pd; unsigned int textlen, position, row, col, newrow, remainlen; short nllen; char *content; Elm_Code_Line *line; pd = efl_data_scope_get(widget, ELM_CODE_WIDGET_CLASS); if (info->insert) { elm_code_widget_selection_start(widget, info->start_line, info->start_col); elm_code_widget_selection_end(widget, info->end_line, info->end_col); _elm_code_widget_selection_delete_no_undo(widget); } else { newrow = info->start_line; content = info->content; remainlen = info->length; elm_code_widget_selection_clear(widget); elm_code_widget_cursor_position_set(widget, info->start_line, info->start_col); while (newrow <= info->end_line) { line = elm_code_file_line_get(pd->code->file, newrow); if (newrow != info->end_line) { textlen = elm_code_text_newlinenpos(content, remainlen, &nllen); remainlen -= textlen + nllen; _elm_code_widget_text_at_cursor_insert_no_undo(widget, content, textlen); efl_ui_code_widget_cursor_position_get(widget, &row, &col); position = elm_code_widget_line_text_position_for_column_get(widget, line, col); elm_code_line_split_at(line, position); elm_code_widget_cursor_position_set(widget, newrow + 1, 1); content += textlen + nllen; } else { _elm_code_widget_text_at_cursor_insert_no_undo(widget, content, strlen(content)); } newrow++; } elm_code_widget_cursor_position_set(widget, info->end_line, info->end_col + 1); } efl_event_callback_legacy_call(widget, EFL_UI_CODE_WIDGET_EVENT_CHANGED_USER, NULL); } static Eina_Bool _elm_code_widget_can_undo_get(Eo *obj EINA_UNUSED, Elm_Code_Widget_Data *pd) { return !!pd->undo_stack_ptr; } static void _elm_code_widget_undo(Eo *obj EINA_UNUSED, Elm_Code_Widget_Data *pd) { Elm_Code_Widget_Change_Info *info; if (!pd->undo_stack_ptr) return; info = eina_list_data_get(pd->undo_stack_ptr); _elm_code_widget_undo_change(obj, info); pd->undo_stack_ptr = eina_list_next(pd->undo_stack_ptr); } static Eina_Bool _elm_code_widget_can_redo_get(Eo *obj EINA_UNUSED, Elm_Code_Widget_Data *pd) { if (pd->undo_stack_ptr) return !!eina_list_prev(pd->undo_stack_ptr); return !!eina_list_last(pd->undo_stack); } static void _elm_code_widget_redo(Eo *obj EINA_UNUSED, Elm_Code_Widget_Data *pd) { Elm_Code_Widget_Change_Info *info, *redo_info; Eina_List *redo_ptr; if (pd->undo_stack_ptr) redo_ptr = eina_list_prev(pd->undo_stack_ptr); else redo_ptr = eina_list_last(pd->undo_stack); if (!redo_ptr) return; info = eina_list_data_get(redo_ptr); redo_info = _elm_code_widget_undo_info_copy(info); redo_info->insert = redo_info->insert ? EINA_FALSE : EINA_TRUE; _elm_code_widget_undo_change(obj, redo_info); pd->undo_stack_ptr = redo_ptr; free(redo_info->content); free(redo_info); }