text: hook up indenting and unindenting to the undo/redo code

This is modeled after the comment/uncomment code.  Each line's
individual indent is saved in the string array of the undo
group structure.

This fixes http://savannah.gnu.org/bugs/?46860.
master
David Lawrence Ramsey 2017-07-13 18:15:58 -05:00 committed by Benno Schulenberg
parent f722c53223
commit 19a1129698
2 changed files with 74 additions and 10 deletions

View File

@ -161,6 +161,7 @@ typedef enum {
#ifndef DISABLE_WRAPPING #ifndef DISABLE_WRAPPING
SPLIT_BEGIN, SPLIT_END, SPLIT_BEGIN, SPLIT_END,
#endif #endif
INDENT, UNINDENT,
#ifdef ENABLE_COMMENT #ifdef ENABLE_COMMENT
COMMENT, UNCOMMENT, PREFLIGHT, COMMENT, UNCOMMENT, PREFLIGHT,
#endif #endif

View File

@ -334,19 +334,19 @@ void do_indent(void)
indentation[1] = '\0'; indentation[1] = '\0';
} }
add_undo(INDENT);
/* Go through each of the lines, but skip empty ones. */ /* Go through each of the lines, but skip empty ones. */
for (line = top; line != bot->next; line = line->next) { for (line = top; line != bot->next; line = line->next) {
char *real_indent = (line->data[0] == '\0') ? "" : indentation; char *real_indent = (line->data[0] == '\0') ? "" : indentation;
/* Indent a line, add undo data, and save the original indent. */
indent_a_line(line, real_indent); indent_a_line(line, real_indent);
update_multiline_undo(line->lineno, real_indent);
} }
free(indentation); free(indentation);
/* Throw away the undo stack, to prevent making mistakes when
* the user tries to undo something in the indented text. */
discard_until(NULL, openfile);
set_modified(); set_modified();
refresh_needed = TRUE; refresh_needed = TRUE;
} }
@ -427,17 +427,61 @@ void do_unindent(void)
} }
} }
/* Go through each of the lines and remove their leading indent. */ add_undo(UNINDENT);
for (line = top; line != bot->next; line = line->next)
unindent_a_line(line, length_of_white(line->data));
/* Throw away the undo stack, to prevent making mistakes when /* Go through each of the lines and remove their leading indent. */
* the user tries to undo something in the unindented text. */ for (line = top; line != bot->next; line = line->next) {
discard_until(NULL, openfile); size_t indent_len = length_of_white(line->data);
char *indentation = mallocstrncpy(NULL, line->data, indent_len + 1);
indentation[indent_len] = '\0';
/* Unindent a line, add undo data, and save the original indent. */
unindent_a_line(line, indent_len);
update_multiline_undo(line->lineno, indentation);
free(indentation);
}
set_modified(); set_modified();
refresh_needed = TRUE; refresh_needed = TRUE;
} }
/* Perform an undo or redo for an indent or unindent action. */
void handle_indent_action(undo *u, bool undoing, bool add_indent)
{
undo_group *group = u->grouping;
/* When redoing, reposition the cursor and let the indenter adjust it. */
if (!undoing)
goto_line_posx(u->lineno, u->begin);
while (group) {
filestruct *line = fsfromline(group->top_line);
/* For each line in the group, add or remove the individual indent. */
while (line && line->lineno <= group->bottom_line) {
char *indentation = mallocstrcpy(NULL,
group->indentations[line->lineno - group->top_line]);
if (undoing ^ add_indent)
indent_a_line(line, indentation);
else
unindent_a_line(line, strlen(indentation));
free(indentation);
line = line->next;
}
group = group->next;
}
/* When undoing, reposition the cursor to the recorded location. */
if (undoing)
goto_line_posx(u->lineno, u->begin);
refresh_needed = TRUE;
}
#endif /* !NANO_TINY */ #endif /* !NANO_TINY */
/* Test whether the string is empty or consists of only blanks. */ /* Test whether the string is empty or consists of only blanks. */
@ -771,6 +815,14 @@ void do_undo(void)
unlink_node(f->next); unlink_node(f->next);
goto_line_posx(u->lineno, to_x); goto_line_posx(u->lineno, to_x);
break; break;
case INDENT:
handle_indent_action(u, TRUE, TRUE);
undidmsg = _("indent");
break;
case UNINDENT:
handle_indent_action(u, TRUE, FALSE);
undidmsg = _("unindent");
break;
#ifdef ENABLE_COMMENT #ifdef ENABLE_COMMENT
case COMMENT: case COMMENT:
handle_comment_action(u, TRUE, TRUE); handle_comment_action(u, TRUE, TRUE);
@ -946,6 +998,14 @@ void do_redo(void)
free_filestruct(u->cutbuffer); free_filestruct(u->cutbuffer);
u->cutbuffer = NULL; u->cutbuffer = NULL;
break; break;
case INDENT:
handle_indent_action(u, FALSE, TRUE);
redidmsg = _("indent");
break;
case UNINDENT:
handle_indent_action(u, FALSE, FALSE);
redidmsg = _("unindent");
break;
#ifdef ENABLE_COMMENT #ifdef ENABLE_COMMENT
case COMMENT: case COMMENT:
handle_comment_action(u, FALSE, TRUE); handle_comment_action(u, FALSE, TRUE);
@ -1277,6 +1337,9 @@ void add_undo(undo_type action)
break; break;
case ENTER: case ENTER:
break; break;
case INDENT:
case UNINDENT:
break;
#ifdef ENABLE_COMMENT #ifdef ENABLE_COMMENT
case COMMENT: case COMMENT:
case UNCOMMENT: case UNCOMMENT: