commit 19a11296982025d07a5e0ea91587347d98ca3028
parent f722c53223c9c3da1204a0b434c2d0dbc4627177
Author: David Lawrence Ramsey <pooka109@gmail.com>
Date: Thu, 13 Jul 2017 18:15:58 -0500
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.
Diffstat:
M | src/nano.h | | | 1 | + |
M | src/text.c | | | 81 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------- |
2 files changed, 73 insertions(+), 9 deletions(-)
diff --git a/src/nano.h b/src/nano.h
@@ -161,6 +161,7 @@ typedef enum {
#ifndef DISABLE_WRAPPING
SPLIT_BEGIN, SPLIT_END,
#endif
+ INDENT, UNINDENT,
#ifdef ENABLE_COMMENT
COMMENT, UNCOMMENT, PREFLIGHT,
#endif
diff --git a/src/text.c b/src/text.c
@@ -334,19 +334,19 @@ void do_indent(void)
indentation[1] = '\0';
}
+ add_undo(INDENT);
+
/* Go through each of the lines, but skip empty ones. */
for (line = top; line != bot->next; line = line->next) {
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);
+ update_multiline_undo(line->lineno, real_indent);
}
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();
refresh_needed = TRUE;
}
@@ -427,17 +427,61 @@ void do_unindent(void)
}
}
+ add_undo(UNINDENT);
+
/* Go through each of the lines and remove their leading indent. */
- for (line = top; line != bot->next; line = line->next)
- unindent_a_line(line, length_of_white(line->data));
+ for (line = top; line != bot->next; line = line->next) {
+ size_t indent_len = length_of_white(line->data);
+ char *indentation = mallocstrncpy(NULL, line->data, indent_len + 1);
+
+ indentation[indent_len] = '\0';
- /* Throw away the undo stack, to prevent making mistakes when
- * the user tries to undo something in the unindented text. */
- discard_until(NULL, openfile);
+ /* 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();
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 */
/* Test whether the string is empty or consists of only blanks. */
@@ -771,6 +815,14 @@ void do_undo(void)
unlink_node(f->next);
goto_line_posx(u->lineno, to_x);
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
case COMMENT:
handle_comment_action(u, TRUE, TRUE);
@@ -946,6 +998,14 @@ void do_redo(void)
free_filestruct(u->cutbuffer);
u->cutbuffer = NULL;
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
case COMMENT:
handle_comment_action(u, FALSE, TRUE);
@@ -1277,6 +1337,9 @@ void add_undo(undo_type action)
break;
case ENTER:
break;
+ case INDENT:
+ case UNINDENT:
+ break;
#ifdef ENABLE_COMMENT
case COMMENT:
case UNCOMMENT: