efl/src/lib/elementary/elm_code_widget_undo.c

168 lines
5.0 KiB
C

#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 = 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);
}