Fix T44381: Text Editor: Un-indent undo fails

D1284 by @mikidep
This commit is contained in:
Campbell Barton 2015-05-07 04:43:33 +10:00
parent 4487358da7
commit c740027e30
Notes: blender-bot 2023-02-14 09:14:26 +01:00
Referenced by issue #44381, Text Editor: Un-indent undo doesn't work properly
Referenced by issue #44381, Text Editor: Un-indent undo doesn't work properly
1 changed files with 116 additions and 9 deletions

View File

@ -1896,6 +1896,47 @@ static void txt_undo_add_charop(Text *text, int op_start, unsigned int c)
text->undo_buf[text->undo_pos + 1] = 0;
}
/* extends Link */
struct LinkInt {
struct LinkInt *next, *prev;
int value;
};
/* unindentLines points to a ListBase composed of LinkInt elements, listing the numbers
* of the lines that should not be indented back. */
static void txt_undo_add_unindent_op(Text *text, const ListBase *line_index_mask, const int line_index_mask_len)
{
struct LinkInt *idata;
BLI_assert(BLI_listbase_count(line_index_mask) == line_index_mask_len);
/* OP byte + UInt32 count + counted UInt32 line numbers + UInt32 count + 12-bytes selection + OP byte */
if (!max_undo_test(text, 1 + 4 + (line_index_mask_len * 4) + 4 + 12 + 1)) {
return;
}
/* Opening buffer sequence with OP */
text->undo_pos++;
text->undo_buf[text->undo_pos] = UNDO_UNINDENT;
text->undo_pos++;
/* Adding number of line numbers to read */
txt_undo_store_uint32(text->undo_buf, &text->undo_pos, line_index_mask_len);
/* Adding linenumbers of lines that shall not be indented if undoing */
for (idata = line_index_mask->first; idata; idata = idata->next) {
txt_undo_store_uint32(text->undo_buf, &text->undo_pos, idata->value);
}
/* Adding number of line numbers to read again */
txt_undo_store_uint32(text->undo_buf, &text->undo_pos, line_index_mask_len);
/* Adding current selection */
txt_undo_store_cursors(text);
/* Closing with OP (same as above) */
text->undo_buf[text->undo_pos] = UNDO_UNINDENT;
/* Marking as last undo operation */
text->undo_buf[text->undo_pos + 1] = 0;
}
static unsigned short txt_undo_read_uint16(const char *undo_buf, int *undo_pos)
{
unsigned short val;
@ -2190,7 +2231,6 @@ void txt_do_undo(Text *text)
text->undo_pos--;
break;
case UNDO_INDENT:
case UNDO_UNINDENT:
case UNDO_COMMENT:
case UNDO_UNCOMMENT:
case UNDO_DUPLICATE:
@ -2204,9 +2244,6 @@ void txt_do_undo(Text *text)
if (op == UNDO_INDENT) {
txt_unindent(text);
}
else if (op == UNDO_UNINDENT) {
txt_indent(text);
}
else if (op == UNDO_COMMENT) {
txt_uncomment(text);
}
@ -2225,6 +2262,37 @@ void txt_do_undo(Text *text)
text->undo_pos--;
break;
case UNDO_UNINDENT:
{
int count;
int i;
/* Get and restore the cursors */
txt_undo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc);
txt_move_to(text, curln, curc, 0);
txt_move_to(text, selln, selc, 1);
/* Un-unindent */
txt_indent(text);
/* Get the count */
count = txt_undo_read_uint32(text->undo_buf, &text->undo_pos);
/* Iterate! */
txt_pop_sel(text);
for (i = 0; i < count; i++) {
txt_move_to(text, txt_undo_read_uint32(text->undo_buf, &text->undo_pos), 0, 0);
/* Un-un-unindent */
txt_unindent(text);
}
/* Restore selection */
txt_move_to(text, curln, curc, 0);
txt_move_to(text, selln, selc, 1);
/* Jumo over count */
txt_undo_read_uint32(text->undo_buf, &text->undo_pos);
/* Jump over closing OP byte */
text->undo_pos--;
break;
}
default:
//XXX error("Undo buffer error - resetting");
text->undo_pos = -1;
@ -2354,7 +2422,6 @@ void txt_do_redo(Text *text)
break;
case UNDO_INDENT:
case UNDO_UNINDENT:
case UNDO_COMMENT:
case UNDO_UNCOMMENT:
case UNDO_DUPLICATE:
@ -2370,9 +2437,6 @@ void txt_do_redo(Text *text)
if (op == UNDO_INDENT) {
txt_indent(text);
}
else if (op == UNDO_UNINDENT) {
txt_unindent(text);
}
else if (op == UNDO_COMMENT) {
txt_comment(text);
}
@ -2402,6 +2466,26 @@ void txt_do_redo(Text *text)
txt_move_to(text, selln, selc, 1);
break;
case UNDO_UNINDENT:
{
int count;
int i;
text->undo_pos++;
/* Scan all the stuff described in txt_undo_add_unindent_op */
count = txt_redo_read_uint32(text->undo_buf, &text->undo_pos);
for (i = 0; i < count; i++) {
txt_redo_read_uint32(text->undo_buf, &text->undo_pos);
}
/* Count again */
txt_redo_read_uint32(text->undo_buf, &text->undo_pos);
/* Get the selection and re-unindent */
txt_redo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc);
txt_move_to(text, curln, curc, 0);
txt_move_to(text, selln, selc, 1);
txt_unindent(text);
break;
}
default:
//XXX error("Undo buffer error - resetting");
text->undo_pos = -1;
@ -2802,6 +2886,12 @@ void txt_unindent(Text *text)
int indentlen = 1;
bool unindented_first = false;
/* List of lines that are already at indent level 0, to store them later into the undo buffer */
ListBase line_index_mask = {NULL, NULL};
int line_index_mask_len = 0;
int curl_span_init = 0;
/* hardcoded: TXT_TABSIZE = 4 spaces: */
int spaceslen = TXT_TABSIZE;
@ -2815,6 +2905,10 @@ void txt_unindent(Text *text)
indentlen = spaceslen;
}
if (!undoing) {
curl_span_init = txt_get_span(text->lines.first, text->curl);
}
while (true) {
bool changed = false;
if (STREQLEN(text->curl->line, remove, indentlen)) {
@ -2824,6 +2918,16 @@ void txt_unindent(Text *text)
memmove(text->curl->line, text->curl->line + indentlen, text->curl->len + 1);
changed = true;
}
else {
if (!undoing) {
/* Create list element for 0 indent line */
struct LinkInt *idata = MEM_mallocN(sizeof(struct LinkInt), __func__);
idata->value = curl_span_init + num;
BLI_assert(idata->value == txt_get_span(text->lines.first, text->curl));
BLI_addtail(&line_index_mask, idata);
line_index_mask_len += 1;
}
}
txt_make_dirty(text);
txt_clean_text(text);
@ -2836,6 +2940,7 @@ void txt_unindent(Text *text)
else {
text->curl = text->curl->next;
num++;
}
}
@ -2849,8 +2954,10 @@ void txt_unindent(Text *text)
}
if (!undoing) {
txt_undo_add_op(text, UNDO_UNINDENT);
txt_undo_add_unindent_op(text, &line_index_mask, line_index_mask_len);
}
BLI_freelistN(&line_index_mask);
}
void txt_comment(Text *text)