diff options
Diffstat (limited to 'source/blender/editors/space_text')
-rw-r--r-- | source/blender/editors/space_text/space_text.c | 9 | ||||
-rw-r--r-- | source/blender/editors/space_text/text_draw.c | 6 | ||||
-rw-r--r-- | source/blender/editors/space_text/text_intern.h | 3 | ||||
-rw-r--r-- | source/blender/editors/space_text/text_ops.c | 326 | ||||
-rw-r--r-- | source/blender/editors/space_text/text_undo.c | 184 |
5 files changed, 365 insertions, 163 deletions
diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c index 24f282ff920..8bfb6c87625 100644 --- a/source/blender/editors/space_text/space_text.c +++ b/source/blender/editors/space_text/space_text.c @@ -82,7 +82,7 @@ static SpaceLink *text_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scen BLI_addtail(&stext->regionbase, ar); ar->regiontype = RGN_TYPE_UI; - ar->alignment = RGN_ALIGN_LEFT; + ar->alignment = RGN_ALIGN_RIGHT; ar->flag = RGN_FLAG_HIDDEN; /* main region */ @@ -197,8 +197,7 @@ static void text_operatortypes(void) WM_operatortype_append(TEXT_OT_duplicate_line); WM_operatortype_append(TEXT_OT_convert_whitespace); - WM_operatortype_append(TEXT_OT_uncomment); - WM_operatortype_append(TEXT_OT_comment); + WM_operatortype_append(TEXT_OT_comment_toggle); WM_operatortype_append(TEXT_OT_unindent); WM_operatortype_append(TEXT_OT_indent); @@ -254,7 +253,9 @@ static int text_context(const bContext *C, const char *member, bContextDataResul return 1; } else if (CTX_data_equals(member, "edit_text")) { - CTX_data_id_pointer_set(result, &st->text->id); + if (st->text != NULL) { + CTX_data_id_pointer_set(result, &st->text->id); + } return 1; } diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c index c03b804aa2c..9dc8dfa93b6 100644 --- a/source/blender/editors/space_text/text_draw.c +++ b/source/blender/editors/space_text/text_draw.c @@ -240,7 +240,7 @@ void wrap_offset( } max = wrap_width(st, ar); - cursin = txt_utf8_offset_to_column(linein->line, cursin); + cursin = BLI_str_utf8_offset_to_column(linein->line, cursin); while (linep) { start = 0; @@ -323,7 +323,7 @@ void wrap_offset_in_line( end = max; chop = 1; *offc = 0; - cursin = txt_utf8_offset_to_column(linein->line, cursin); + cursin = BLI_str_utf8_offset_to_column(linein->line, cursin); for (i = 0, j = 0; linein->line[j]; j += BLI_str_utf8_size_safe(linein->line + j)) { int columns = BLI_str_utf8_char_width_safe(linein->line + j); /* = 1 for tab */ @@ -1400,7 +1400,7 @@ static void draw_brackets(const SpaceText *st, const TextDrawContext *tdc, ARegi linep = startl; c = startc; - fc = txt_utf8_offset_to_index(linep->line, startc); + fc = BLI_str_utf8_offset_to_index(linep->line, startc); endl = NULL; endc = -1; find = -b; diff --git a/source/blender/editors/space_text/text_intern.h b/source/blender/editors/space_text/text_intern.h index aab5069f919..7a1dd312d02 100644 --- a/source/blender/editors/space_text/text_intern.h +++ b/source/blender/editors/space_text/text_intern.h @@ -119,8 +119,7 @@ void TEXT_OT_cut(struct wmOperatorType *ot); void TEXT_OT_duplicate_line(struct wmOperatorType *ot); void TEXT_OT_convert_whitespace(struct wmOperatorType *ot); -void TEXT_OT_uncomment(struct wmOperatorType *ot); -void TEXT_OT_comment(struct wmOperatorType *ot); +void TEXT_OT_comment_toggle(struct wmOperatorType *ot); void TEXT_OT_unindent(struct wmOperatorType *ot); void TEXT_OT_indent(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index 8f7bd83cbf4..a8af9c73bf2 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -61,7 +61,9 @@ static void txt_screen_clamp(SpaceText *st, ARegion *ar); -/************************ util ***************************/ +/* -------------------------------------------------------------------- */ +/** \name Util + * \{ */ /** * Tests if the given character represents a start of a new line or the @@ -138,14 +140,18 @@ static char *buf_tabs_to_spaces(const char *in_buf, const int tab_size) return out_buf; } -/************************ poll ***************************/ - BLI_INLINE int text_pixel_x_to_column(SpaceText *st, const int x) { /* add half the char width so mouse cursor selection is inbetween letters */ return (x + (st->cwidth / 2)) / st->cwidth; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Operator Poll + * \{ */ + static bool text_new_poll(bContext *UNUSED(C)) { return 1; @@ -206,7 +212,11 @@ static bool text_region_edit_poll(bContext *C) return 1; } -/********************** updates *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Updates + * \{ */ void text_update_line_edited(TextLine *line) { @@ -230,7 +240,11 @@ void text_update_edited(Text *text) } } -/******************* new operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name New Operator + * \{ */ static int text_new_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -281,7 +295,11 @@ void TEXT_OT_new(wmOperatorType *ot) ot->flag = OPTYPE_UNDO; } -/******************* open operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Open Operator + * \{ */ static void text_open_init(bContext *C, wmOperator *op) { @@ -392,7 +410,11 @@ void TEXT_OT_open(wmOperatorType *ot) ot->srna, "internal", 0, "Make internal", "Make text file internal after loading"); } -/******************* reload operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Reload Operator + * \{ */ static int text_reload_exec(bContext *C, wmOperator *op) { @@ -443,7 +465,11 @@ void TEXT_OT_reload(wmOperatorType *ot) ot->poll = text_edit_poll; } -/******************* delete operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Delete Operator + * \{ */ static bool text_unlink_poll(bContext *C) { @@ -495,7 +521,11 @@ void TEXT_OT_unlink(wmOperatorType *ot) ot->flag = OPTYPE_UNDO; } -/******************* make internal operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Make Internal Operator + * \{ */ static int text_make_internal_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -529,7 +559,11 @@ void TEXT_OT_make_internal(wmOperatorType *ot) ot->flag = OPTYPE_UNDO; } -/******************* save operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Save Operator + * \{ */ static bool text_save_poll(bContext *C) { @@ -614,7 +648,11 @@ void TEXT_OT_save(wmOperatorType *ot) ot->poll = text_save_poll; } -/******************* save as operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Save As Operator + * \{ */ static int text_save_as_exec(bContext *C, wmOperator *op) { @@ -690,7 +728,11 @@ void TEXT_OT_save_as(wmOperatorType *ot) FILE_SORT_ALPHA); // XXX TODO, relative_path } -/******************* run script operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Run Script Operator + * \{ */ static bool text_run_script_poll(bContext *C) { @@ -765,7 +807,11 @@ void TEXT_OT_run_script(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/******************* refresh pyconstraints operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Refresh Pyconstraints Operator + * \{ */ static int text_refresh_pyconstraints_exec(bContext *UNUSED(C), wmOperator *UNUSED(op)) { @@ -825,7 +871,11 @@ void TEXT_OT_refresh_pyconstraints(wmOperatorType *ot) ot->poll = text_edit_poll; } -/******************* paste operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Paste Operator + * \{ */ static int text_paste_exec(bContext *C, wmOperator *op) { @@ -889,7 +939,11 @@ void TEXT_OT_paste(wmOperatorType *ot) "Paste text selected elsewhere rather than copied (X11 only)"); } -/**************** duplicate operator *******************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Duplicate Operator + * \{ */ static int text_duplicate_line_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -924,7 +978,11 @@ void TEXT_OT_duplicate_line(wmOperatorType *ot) ot->flag = OPTYPE_UNDO; } -/******************* copy operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Copy Operator + * \{ */ static void txt_copy_clipboard(Text *text) { @@ -963,7 +1021,11 @@ void TEXT_OT_copy(wmOperatorType *ot) ot->poll = text_edit_poll; } -/******************* cut operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Cut Operator + * \{ */ static int text_cut_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -1002,7 +1064,11 @@ void TEXT_OT_cut(wmOperatorType *ot) ot->flag = OPTYPE_UNDO; } -/******************* indent operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Indent Operator + * \{ */ static int text_indent_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -1043,7 +1109,11 @@ void TEXT_OT_indent(wmOperatorType *ot) ot->flag = OPTYPE_UNDO; } -/******************* unindent operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Unindent Operator + * \{ */ static int text_unindent_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -1079,7 +1149,11 @@ void TEXT_OT_unindent(wmOperatorType *ot) ot->flag = OPTYPE_UNDO; } -/******************* line break operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Line Break Operator + * \{ */ static int text_line_break_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -1132,11 +1206,16 @@ void TEXT_OT_line_break(wmOperatorType *ot) ot->flag = OPTYPE_UNDO; } -/******************* comment operator *********************/ +/** \} */ -static int text_comment_exec(bContext *C, wmOperator *UNUSED(op)) +/* -------------------------------------------------------------------- */ +/** \name Toggle-Comment Operator + * \{ */ + +static int text_comment_exec(bContext *C, wmOperator *op) { Text *text = CTX_data_edit_text(C); + int type = RNA_enum_get(op->ptr, "type"); if (txt_has_sel(text)) { text_drawcache_tag_update(CTX_wm_space_text(C), 0); @@ -1144,45 +1223,21 @@ static int text_comment_exec(bContext *C, wmOperator *UNUSED(op)) ED_text_undo_push_init(C); txt_order_cursors(text, false); - txt_comment(text); - text_update_edited(text); - - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); - return OPERATOR_FINISHED; - } - - return OPERATOR_CANCELLED; -} - -void TEXT_OT_comment(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Comment"; - ot->idname = "TEXT_OT_comment"; - ot->description = "Convert selected text to comment"; - - /* api callbacks */ - ot->exec = text_comment_exec; - ot->poll = text_edit_poll; - - /* flags */ - ot->flag = OPTYPE_UNDO; -} - -/******************* uncomment operator *********************/ -static int text_uncomment_exec(bContext *C, wmOperator *UNUSED(op)) -{ - Text *text = CTX_data_edit_text(C); - - if (txt_has_sel(text)) { - text_drawcache_tag_update(CTX_wm_space_text(C), 0); - - ED_text_undo_push_init(C); + switch (type) { + case 1: + txt_comment(text); + break; + case -1: + txt_uncomment(text); + break; + default: + if (txt_uncomment(text) == false) { + txt_comment(text); + } + break; + } - txt_order_cursors(text, false); - txt_uncomment(text); text_update_edited(text); text_update_cursor_moved(C); @@ -1194,22 +1249,37 @@ static int text_uncomment_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_CANCELLED; } -void TEXT_OT_uncomment(wmOperatorType *ot) +void TEXT_OT_comment_toggle(wmOperatorType *ot) { + static const EnumPropertyItem comment_items[] = { + {0, "TOGGLE", 0, "Toggle Comments", NULL}, + {1, "COMMENT", 0, "Comment", NULL}, + {-1, "UNCOMMENT", 0, "Un-Comment", NULL}, + {0, NULL, 0, NULL, NULL}, + }; + /* identifiers */ - ot->name = "Uncomment"; - ot->idname = "TEXT_OT_uncomment"; - ot->description = "Convert selected comment to text"; + ot->name = "Toggle Comments"; + ot->idname = "TEXT_OT_comment_toggle"; /* api callbacks */ - ot->exec = text_uncomment_exec; + ot->exec = text_comment_exec; ot->poll = text_edit_poll; /* flags */ ot->flag = OPTYPE_UNDO; + + /* properties */ + PropertyRNA *prop; + prop = RNA_def_enum(ot->srna, "type", comment_items, 0, "Type", "Add or remove comments"); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } -/******************* convert whitespace operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Convert Whitespace Operator + * \{ */ enum { TO_SPACES, TO_TABS }; static const EnumPropertyItem whitespace_type_items[] = { @@ -1360,7 +1430,11 @@ void TEXT_OT_convert_whitespace(wmOperatorType *ot) "Type of whitespace to convert to"); } -/******************* select all operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select All Operator + * \{ */ static int text_select_all_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -1386,7 +1460,11 @@ void TEXT_OT_select_all(wmOperatorType *ot) ot->poll = text_edit_poll; } -/******************* select line operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Line Operator + * \{ */ static int text_select_line_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -1412,7 +1490,11 @@ void TEXT_OT_select_line(wmOperatorType *ot) ot->poll = text_edit_poll; } -/******************* select word operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Word Operator + * \{ */ static int text_select_word_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -1441,7 +1523,11 @@ void TEXT_OT_select_word(wmOperatorType *ot) ot->poll = text_edit_poll; } -/********************* move lines operators ***********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Move Lines Operators + * \{ */ static int move_lines_exec(bContext *C, wmOperator *op) { @@ -1487,7 +1573,11 @@ void TEXT_OT_move_lines(wmOperatorType *ot) RNA_def_enum(ot->srna, "direction", direction_items, 1, "Direction", ""); } -/************************ move operator ************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Move Operator + * \{ */ static const EnumPropertyItem move_type_items[] = { {LINE_BEGIN, "LINE_BEGIN", 0, "Line Begin", ""}, @@ -1737,7 +1827,7 @@ static void txt_wrap_move_bol(SpaceText *st, ARegion *ar, const bool sel) if (j >= oldc) { if (ch == '\0') { - *charp = txt_utf8_column_to_offset((*linep)->line, start); + *charp = BLI_str_utf8_offset_from_column((*linep)->line, start); } loop = 0; break; @@ -1753,7 +1843,7 @@ static void txt_wrap_move_bol(SpaceText *st, ARegion *ar, const bool sel) } else if (ch == ' ' || ch == '-' || ch == '\0') { if (j >= oldc) { - *charp = txt_utf8_column_to_offset((*linep)->line, start); + *charp = BLI_str_utf8_offset_from_column((*linep)->line, start); loop = 0; break; } @@ -2126,7 +2216,11 @@ void TEXT_OT_move(wmOperatorType *ot) RNA_def_enum(ot->srna, "type", move_type_items, LINE_BEGIN, "Type", "Where to move cursor to"); } -/******************* move select operator ********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Move Select Operator + * \{ */ static int text_move_select_exec(bContext *C, wmOperator *op) { @@ -2155,7 +2249,11 @@ void TEXT_OT_move_select(wmOperatorType *ot) "Where to move cursor to, to make a selection"); } -/******************* jump operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Jump Operator + * \{ */ static int text_jump_exec(bContext *C, wmOperator *op) { @@ -2203,7 +2301,11 @@ void TEXT_OT_jump(wmOperatorType *ot) RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_TEXT); } -/******************* delete operator **********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Delete Operator + * \{ */ static const EnumPropertyItem delete_type_items[] = { {DEL_NEXT_CHAR, "NEXT_CHARACTER", 0, "Next Character", ""}, @@ -2317,7 +2419,11 @@ void TEXT_OT_delete(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } -/******************* toggle overwrite operator **********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Toggle Overwrite Operator + * \{ */ static int text_toggle_overwrite_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -2342,7 +2448,11 @@ void TEXT_OT_overwrite_toggle(wmOperatorType *ot) ot->poll = text_space_edit_poll; } -/******************* scroll operator **********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Scroll Operator + * \{ */ static void txt_screen_clamp(SpaceText *st, ARegion *ar) { @@ -2571,7 +2681,11 @@ void TEXT_OT_scroll(wmOperatorType *ot) ot->srna, "lines", 1, INT_MIN, INT_MAX, "Lines", "Number of lines to scroll", -100, 100); } -/******************** scroll bar operator *******************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Scroll Bar Operator + * \{ */ static bool text_region_scroll_poll(bContext *C) { @@ -3073,7 +3187,11 @@ void TEXT_OT_selection_set(wmOperatorType *ot) RNA_def_boolean(ot->srna, "select", 0, "Select", "Set selection end rather than cursor"); } -/******************* set cursor operator **********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Set Cursor Operator + * \{ */ static int text_cursor_set_exec(bContext *C, wmOperator *op) { @@ -3121,7 +3239,11 @@ void TEXT_OT_cursor_set(wmOperatorType *ot) RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX); } -/******************* line number operator **********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Line Number Operator + * \{ */ static int text_line_number_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { @@ -3177,7 +3299,11 @@ void TEXT_OT_line_number(wmOperatorType *ot) ot->poll = text_region_edit_poll; } -/******************* insert operator **********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Insert Operator + * \{ */ static int text_insert_exec(bContext *C, wmOperator *op) { @@ -3284,7 +3410,11 @@ void TEXT_OT_insert(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } -/******************* find operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Find Operator + * \{ */ /* mode */ #define TEXT_FIND 0 @@ -3378,7 +3508,11 @@ void TEXT_OT_find(wmOperatorType *ot) ot->poll = text_space_edit_poll; } -/******************* replace operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Replace Operator + * \{ */ static int text_replace_exec(bContext *C, wmOperator *op) { @@ -3400,7 +3534,11 @@ void TEXT_OT_replace(wmOperatorType *ot) ot->flag = OPTYPE_UNDO; } -/******************* find set selected *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Find Set Selected + * \{ */ static int text_find_set_selected_exec(bContext *C, wmOperator *op) { @@ -3431,7 +3569,11 @@ void TEXT_OT_find_set_selected(wmOperatorType *ot) ot->poll = text_space_edit_poll; } -/******************* replace set selected *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Replace Set Selected + * \{ */ static int text_replace_set_selected_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -3461,7 +3603,11 @@ void TEXT_OT_replace_set_selected(wmOperatorType *ot) ot->flag = OPTYPE_UNDO; } -/****************** resolve conflict operator ******************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Resolve Conflict Operator + * \{ */ enum { RESOLVE_IGNORE, RESOLVE_RELOAD, RESOLVE_SAVE, RESOLVE_MAKE_INTERNAL }; static const EnumPropertyItem resolution_items[] = { @@ -3574,7 +3720,11 @@ void TEXT_OT_resolve_conflict(wmOperatorType *ot) "How to solve conflict due to differences in internal and external text"); } -/********************** to 3d object operator *****************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name To 3D Object Operator + * \{ */ static int text_to_3d_object_exec(bContext *C, wmOperator *op) { @@ -3604,3 +3754,5 @@ void TEXT_OT_to_3d_object(wmOperatorType *ot) RNA_def_boolean( ot->srna, "split_lines", 0, "Split Lines", "Create one object per line in the text"); } + +/** \} */ diff --git a/source/blender/editors/space_text/text_undo.c b/source/blender/editors/space_text/text_undo.c index 6ecb2b731b0..a6393291f9a 100644 --- a/source/blender/editors/space_text/text_undo.c +++ b/source/blender/editors/space_text/text_undo.c @@ -61,19 +61,69 @@ #define ARRAY_CHUNK_SIZE 128 +/** + * Only stores the state of a text buffer. + */ +typedef struct TextState { + BArrayState *buf_array_state; + + int cursor_line, cursor_line_select; + int cursor_column, cursor_column_select; +} TextState; + +static void text_state_encode(TextState *state, Text *text, BArrayStore *buffer_store) +{ + int buf_len = 0; + uchar *buf = (uchar *)txt_to_buf_for_undo(text, &buf_len); + state->buf_array_state = BLI_array_store_state_add(buffer_store, buf, buf_len, NULL); + MEM_freeN(buf); + + state->cursor_line = txt_get_span(text->lines.first, text->curl); + state->cursor_column = text->curc; + + if (txt_has_sel(text)) { + state->cursor_line_select = (text->curl == text->sell) ? + state->cursor_line : + txt_get_span(text->lines.first, text->sell); + state->cursor_column_select = text->selc; + } + else { + state->cursor_line_select = state->cursor_line; + state->cursor_column_select = state->cursor_column; + } +} + +static void text_state_decode(TextState *state, Text *text) +{ + size_t buf_len; + { + const uchar *buf = BLI_array_store_state_data_get_alloc(state->buf_array_state, &buf_len); + txt_from_buf_for_undo(text, (const char *)buf, buf_len); + MEM_freeN((void *)buf); + } + + const bool has_select = ((state->cursor_line != state->cursor_line_select) || + (state->cursor_column != state->cursor_column_select)); + if (has_select) { + txt_move_to(text, state->cursor_line_select, state->cursor_column_select, false); + } + txt_move_to(text, state->cursor_line, state->cursor_column, has_select); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Implements ED Undo System + * \{ */ + typedef struct TextUndoStep { UndoStep step; UndoRefID_Text text_ref; - struct { - BArrayState *state; - int buf_len; - } data; - - struct { - int line, line_select; - int column, column_select; - } cursor; - + /** + * First state is optional (initial state), + * the second is the state after the operation is done. + */ + TextState states[2]; } TextUndoStep; static struct { @@ -81,6 +131,21 @@ static struct { int users; } g_text_buffers = {NULL}; +static size_t text_undosys_step_encode_to_state(TextState *state, Text *text) +{ + BLI_assert(BLI_array_is_zeroed(state, 1)); + if (g_text_buffers.buffer_store == NULL) { + g_text_buffers.buffer_store = BLI_array_store_create(1, ARRAY_CHUNK_SIZE); + } + g_text_buffers.users += 1; + const size_t total_size_prev = BLI_array_store_calc_size_compacted_get( + g_text_buffers.buffer_store); + + text_state_encode(state, text, g_text_buffers.buffer_store); + + return BLI_array_store_calc_size_compacted_get(g_text_buffers.buffer_store) - total_size_prev; +} + static bool text_undosys_poll(bContext *UNUSED(C)) { /* Only use when operators initialized. */ @@ -91,10 +156,27 @@ static bool text_undosys_poll(bContext *UNUSED(C)) static void text_undosys_step_encode_init(struct bContext *C, UndoStep *us_p) { TextUndoStep *us = (TextUndoStep *)us_p; - BLI_assert(BLI_array_is_zeroed(&us->data, 1)); + BLI_assert(BLI_array_is_zeroed(us->states, ARRAY_SIZE(us->states))); - UNUSED_VARS(C, us); - /* XXX, use to set the undo type only. */ + Text *text = CTX_data_edit_text(C); + + /* Avoid writing the initial state where possible, + * failing to do this won't cause bugs, it's just inefficient. */ + bool write_init = true; + UndoStack *ustack = ED_undo_stack_get(); + if (ustack->step_active) { + if (ustack->step_active->type == BKE_UNDOSYS_TYPE_TEXT) { + TextUndoStep *us_active = (TextUndoStep *)ustack->step_active; + if (STREQ(text->id.name, us_active->text_ref.name)) { + write_init = false; + } + } + } + + if (write_init) { + us->step.data_size = text_undosys_step_encode_to_state(&us->states[0], text); + } + us->text_ref.ptr = text; } static bool text_undosys_step_encode(struct bContext *C, @@ -103,67 +185,31 @@ static bool text_undosys_step_encode(struct bContext *C, { TextUndoStep *us = (TextUndoStep *)us_p; - Text *text = CTX_data_edit_text(C); - - int buf_len = 0; - - uchar *buf = (uchar *)txt_to_buf_for_undo(text, &buf_len); - if (g_text_buffers.buffer_store == NULL) { - g_text_buffers.buffer_store = BLI_array_store_create(1, ARRAY_CHUNK_SIZE); - } - g_text_buffers.users += 1; - const size_t total_size_prev = BLI_array_store_calc_size_compacted_get( - g_text_buffers.buffer_store); - - us->data.state = BLI_array_store_state_add(g_text_buffers.buffer_store, buf, buf_len, NULL); - MEM_freeN(buf); + Text *text = us->text_ref.ptr; + BLI_assert(text == CTX_data_edit_text(C)); - us->cursor.line = txt_get_span(text->lines.first, text->curl); - us->cursor.column = text->curc; - - if (txt_has_sel(text)) { - us->cursor.line_select = (text->curl == text->sell) ? - us->cursor.line : - txt_get_span(text->lines.first, text->sell); - us->cursor.column_select = text->selc; - } - else { - us->cursor.line_select = us->cursor.line; - us->cursor.column_select = us->cursor.column; - } + us->step.data_size += text_undosys_step_encode_to_state(&us->states[1], text); us_p->is_applied = true; - us->text_ref.ptr = text; - - us->step.data_size = BLI_array_store_calc_size_compacted_get(g_text_buffers.buffer_store) - - total_size_prev; - return true; } -static void text_undosys_step_decode(struct bContext *C, - struct Main *UNUSED(bmain), - UndoStep *us_p, - int UNUSED(dir), - bool UNUSED(is_final)) +static void text_undosys_step_decode( + struct bContext *C, struct Main *UNUSED(bmain), UndoStep *us_p, int dir, bool is_final) { TextUndoStep *us = (TextUndoStep *)us_p; Text *text = us->text_ref.ptr; - size_t buf_len; - { - const uchar *buf = BLI_array_store_state_data_get_alloc(us->data.state, &buf_len); - txt_from_buf_for_undo(text, (const char *)buf, buf_len); - MEM_freeN((void *)buf); + TextState *state; + if ((us->states[0].buf_array_state != NULL) && (dir == -1) && !is_final) { + state = &us->states[0]; } - - const bool has_select = ((us->cursor.line != us->cursor.line_select) || - (us->cursor.column != us->cursor.column_select)); - if (has_select) { - txt_move_to(text, us->cursor.line_select, us->cursor.column_select, false); + else { + state = &us->states[1]; } - txt_move_to(text, us->cursor.line, us->cursor.column, has_select); + + text_state_decode(state, text); SpaceText *st = CTX_wm_space_text(C); if (st) { @@ -179,12 +225,16 @@ static void text_undosys_step_free(UndoStep *us_p) { TextUndoStep *us = (TextUndoStep *)us_p; - BLI_array_store_state_remove(g_text_buffers.buffer_store, us->data.state); - - g_text_buffers.users -= 1; - if (g_text_buffers.users == 0) { - BLI_array_store_destroy(g_text_buffers.buffer_store); - g_text_buffers.buffer_store = NULL; + for (int i = 0; i < ARRAY_SIZE(us->states); i++) { + TextState *state = &us->states[i]; + if (state->buf_array_state) { + BLI_array_store_state_remove(g_text_buffers.buffer_store, state->buf_array_state); + g_text_buffers.users -= 1; + if (g_text_buffers.users == 0) { + BLI_array_store_destroy(g_text_buffers.buffer_store); + g_text_buffers.buffer_store = NULL; + } + } } } |