[nano/f20] Resolves: #1166666 - fix intermittent crashes with undo/redo
Kamil Dudka
kdudka at fedoraproject.org
Fri Nov 21 16:29:55 UTC 2014
commit ffaa1a2a594dc4330dc311d91c99b3a84907d6c8
Author: Kamil Dudka <kdudka at redhat.com>
Date: Fri Nov 21 16:51:42 2014 +0100
Resolves: #1166666 - fix intermittent crashes with undo/redo
...e-correct-positions-for-undoing-and-redoi.patch | 658 ++++++++++++++++++++
nano.spec | 9 +-
2 files changed, 666 insertions(+), 1 deletions(-)
---
diff --git a/0004-Going-to-the-correct-positions-for-undoing-and-redoi.patch b/0004-Going-to-the-correct-positions-for-undoing-and-redoi.patch
new file mode 100644
index 0000000..3a93635
--- /dev/null
+++ b/0004-Going-to-the-correct-positions-for-undoing-and-redoi.patch
@@ -0,0 +1,658 @@
+From b6965b6e07ae42b1bae33948a42f3ce90fd1074e Mon Sep 17 00:00:00 2001
+From: bens <bens at ac9c2fa3-95a5-41e5-9206-2167041ecc6c>
+Date: Thu, 15 May 2014 20:00:46 +0000
+Subject: [PATCH] Going to the correct positions for undoing and redoing cuts
+ and pastes. This fixes many undo problems and Savannah bug #25585. *Patch by
+ Mark Majeres.*
+
+git-svn-id: file:///home/kdudka/git/nano-svn/nano@4893 ac9c2fa3-95a5-41e5-9206-2167041ecc6c
+Signed-off-by: Kamil Dudka <kdudka at redhat.com>
+---
+ src/cut.c | 9 ++-
+ src/move.c | 2 +-
+ src/nano.c | 6 +-
+ src/nano.h | 2 +-
+ src/proto.h | 1 +
+ src/search.c | 14 ++++
+ src/text.c | 215 +++++++++++++++++++++++++++++++++--------------------------
+ src/utils.c | 5 +-
+ 8 files changed, 152 insertions(+), 102 deletions(-)
+
+diff --git a/src/cut.c b/src/cut.c
+index 8c21c8e..9739751 100644
+--- a/src/cut.c
++++ b/src/cut.c
+@@ -44,6 +44,9 @@ void cutbuffer_reset(void)
+ * current line. */
+ void cut_line(void)
+ {
++ if(!openfile->mark_begin)
++ openfile->mark_begin = openfile->current;
++
+ if (openfile->current != openfile->filebot)
+ move_to_filestruct(&cutbuffer, &cutbottom, openfile->current, 0,
+ openfile->current->next, 0);
+@@ -205,7 +208,7 @@ void do_cut_text(
+ if (!old_no_newlines)
+ UNSET(NO_NEWLINES);
+ } else if (!undoing)
+- update_undo(CUT);
++ update_undo(cut_till_end ? CUT_EOF : CUT);
+ #endif
+ /* Leave the text in the cutbuffer, and mark the file as
+ * modified. */
+@@ -248,7 +251,7 @@ void do_copy_text(void)
+ void do_cut_till_end(void)
+ {
+ #ifndef NANO_TINY
+- add_undo(CUT);
++ add_undo(CUT_EOF);
+ #endif
+ do_cut_text(FALSE, TRUE, FALSE);
+ }
+@@ -264,7 +267,7 @@ void do_uncut_text(void)
+ return;
+
+ #ifndef NANO_TINY
+- update_undo(UNCUT);
++ add_undo(PASTE);
+ #endif
+
+ /* Add a copy of the text in the cutbuffer to the current filestruct
+diff --git a/src/move.c b/src/move.c
+index b5bd082..e82f5f1 100644
+--- a/src/move.c
++++ b/src/move.c
+@@ -566,7 +566,7 @@ void do_down(
+ bool onlastline = FALSE;
+
+ /* If we're at the bottom of the file, get out. */
+- if (openfile->current == openfile->filebot)
++ if (openfile->current == openfile->filebot || !openfile->current->next)
+ return;
+
+
+diff --git a/src/nano.c b/src/nano.c
+index c315768..ebce05b 100644
+--- a/src/nano.c
++++ b/src/nano.c
+@@ -1993,7 +1993,7 @@ void do_output(char *output, size_t output_len, bool allow_cntrls)
+ set_modified();
+
+ #ifndef NANO_TINY
+- update_undo(ADD);
++ add_undo(ADD);
+
+ /* Note that current_x has not yet been incremented. */
+ if (openfile->mark_set && openfile->current ==
+@@ -2004,6 +2004,10 @@ void do_output(char *output, size_t output_len, bool allow_cntrls)
+
+ openfile->current_x += char_buf_len;
+
++#ifndef NANO_TINY
++ update_undo(ADD);
++#endif
++
+ #ifndef DISABLE_WRAPPING
+ /* If we're wrapping text, we need to call edit_refresh(). */
+ if (!ISSET(NO_WRAP))
+diff --git a/src/nano.h b/src/nano.h
+index bbe9532..0d64e86 100644
+--- a/src/nano.h
++++ b/src/nano.h
+@@ -188,7 +188,7 @@ typedef enum {
+ } function_type;
+
+ typedef enum {
+- ADD, DEL, REPLACE, SPLIT, UNSPLIT, CUT, UNCUT, ENTER, INSERT, OTHER
++ ADD, DEL, REPLACE, SPLIT, UNSPLIT, CUT, CUT_EOF, PASTE, ENTER, INSERT, OTHER
+ } undo_type;
+
+ #ifdef ENABLE_COLOR
+diff --git a/src/proto.h b/src/proto.h
+index a041d42..e752c96 100644
+--- a/src/proto.h
++++ b/src/proto.h
+@@ -611,6 +611,7 @@ void do_gotolinecolumn_void(void);
+ void do_gotopos(ssize_t pos_line, size_t pos_x, ssize_t pos_y, size_t
+ pos_pww);
+ #endif
++void goto_line_posx(ssize_t line, size_t pos_x);
+ #ifndef NANO_TINY
+ bool find_bracket_match(bool reverse, const char *bracket_set);
+ void do_find_bracket(void);
+diff --git a/src/search.c b/src/search.c
+index 77b2097..8c040a8 100644
+--- a/src/search.c
++++ b/src/search.c
+@@ -1008,6 +1008,20 @@ void do_replace(void)
+ search_replace_abort();
+ }
+
++/* Go to the specified line and x position. */
++void goto_line_posx(ssize_t line, size_t pos_x)
++{
++ for (openfile->current = openfile->fileage; openfile->current != openfile->filebot &&
++ openfile->current->next != NULL && line > 1; line--)
++ openfile->current = openfile->current->next;
++
++ openfile->current_x = pos_x;
++ openfile->placewewant = xplustabs();
++
++ edit_refresh_needed = TRUE;
++ edit_refresh();
++}
++
+ /* Go to the specified line and column, or ask for them if interactive
+ * is TRUE. Save the x-coordinate and y-coordinate if save_pos is TRUE.
+ * Update the screen afterwards if allow_update is TRUE. Note that both
+diff --git a/src/text.c b/src/text.c
+index cdd1159..9e91bbb 100644
+--- a/src/text.c
++++ b/src/text.c
+@@ -112,9 +112,8 @@ void do_delete(void)
+ edit_refresh_needed = TRUE;
+
+ openfile->current->data = charealloc(openfile->current->data,
+- openfile->current_x + strlen(foo->data) + 1);
+- strcpy(openfile->current->data + openfile->current_x,
+- foo->data);
++ strlen(openfile->current->data) + strlen(foo->data) + 1);
++ strcat(openfile->current->data, foo->data);
+ #ifndef NANO_TINY
+ if (openfile->mark_set && openfile->mark_begin ==
+ openfile->current->next) {
+@@ -360,6 +359,9 @@ void do_unindent(void)
+ do_indent(-tabsize);
+ }
+
++#define redo_paste undo_cut
++#define undo_paste redo_cut
++
+ /* undo a cut, or re-do an uncut */
+ void undo_cut(undo *u)
+ {
+@@ -374,10 +376,7 @@ void undo_cut(undo *u)
+ ;
+
+ /* Get to where we need to uncut from */
+- if (u->mark_set && u->mark_begin_lineno < u->lineno)
+- do_gotolinecolumn(u->mark_begin_lineno, u->mark_begin_x+1, FALSE, FALSE, FALSE, FALSE);
+- else
+- do_gotolinecolumn(u->lineno, u->begin+1, FALSE, FALSE, FALSE, FALSE);
++ goto_line_posx(u->mark_begin_lineno, u->mark_begin_x);
+
+ copy_from_filestruct(cutbuffer, cutbottom);
+ free_filestruct(cutbuffer);
+@@ -387,40 +386,26 @@ void undo_cut(undo *u)
+
+ /* Re-do a cut, or undo an uncut */
+ void redo_cut(undo *u) {
+- int i;
+- filestruct *t, *c;
+-
+ /* If we cut the magicline may was well not crash :/ */
+ if (!u->cutbuffer)
+ return;
+
+- do_gotolinecolumn(u->lineno, u->begin+1, FALSE, FALSE, FALSE, FALSE);
++ goto_line_posx(u->lineno, u->begin);
++
++ if (ISSET(NO_NEWLINES) && openfile->current->lineno != u->lineno) {
++ openfile->current_x = strlen(openfile->current->data);
++ openfile->placewewant = xplustabs();
++ }
++
+ openfile->mark_set = u->mark_set;
+ if (cutbuffer)
+ free(cutbuffer);
+ cutbuffer = NULL;
+
+- /* Move ahead the same # lines we had if a marked cut */
+- if (u->mark_set) {
+- for (i = 1, t = openfile->fileage; i != u->mark_begin_lineno; i++)
+- t = t->next;
+- openfile->mark_begin = t;
+- } else if (!u->to_end) {
+- /* Here we have a regular old potentially multi-line ^K cut. We'll
+- need to trick nano into thinking it's a marked cut to cut more
+- than one line again */
+- for (c = u->cutbuffer, t = openfile->current; c->next != NULL && t->next != NULL; ) {
++ openfile->mark_begin = fsfromline(u->mark_begin_lineno);
+
+-#ifdef DEBUG
+- fprintf(stderr, "Advancing, lineno = %lu, data = \"%s\"\n", (unsigned long) t->lineno, t->data);
+-#endif
+- c = c->next;
+- t = t->next;
+- }
+- openfile->mark_begin = t;
+- openfile->mark_begin_x = 0;
++ if (!ISSET(CUT_TO_END))
+ openfile->mark_set = TRUE;
+- }
+
+ openfile->mark_begin_x = u->mark_begin_x;
+ do_cut_text(FALSE, u->to_end, TRUE);
+@@ -433,8 +418,9 @@ void redo_cut(undo *u) {
+ /* Undo the last thing(s) we did */
+ void do_undo(void)
+ {
++ bool gotolinecolumn = FALSE;
+ undo *u = openfile->current_undo;
+- filestruct *f = openfile->current, *t;
++ filestruct *t = NULL;
+ int len = 0;
+ char *undidmsg, *data;
+ filestruct *oldcutbuffer = cutbuffer, *oldcutbottom = cutbottom;
+@@ -445,14 +431,9 @@ void do_undo(void)
+ }
+
+
+- if (u->lineno <= f->lineno)
+- for (; f->prev != NULL && f->lineno != u->lineno; f = f->prev)
+- ;
+- else
+- for (; f->next != NULL && f->lineno != u->lineno; f = f->next)
+- ;
+- if (f->lineno != u->lineno) {
+- statusbar(_("Internal error: can't match line %d. Please save your work"), u->lineno);
++ filestruct *f = fsfromline(u->mark_begin_lineno);
++ if (!f) {
++ statusbar(_("Internal error: can't match line %d. Please save your work."), u->mark_begin_lineno);
+ return;
+ }
+ #ifdef DEBUG
+@@ -470,6 +451,7 @@ void do_undo(void)
+ strcpy(&data[u->begin], &f->data[u->begin + strlen(u->strdata)]);
+ free(f->data);
+ f->data = data;
++ goto_line_posx(u->lineno, u->begin);
+ break;
+ case DEL:
+ undidmsg = _("text delete");
+@@ -483,6 +465,7 @@ void do_undo(void)
+ f->data = data;
+ if (u->xflags == UNdel_backspace)
+ openfile->current_x += strlen(u->strdata);
++ goto_line_posx(u->mark_begin_lineno, u->mark_begin_x + 1);
+ break;
+ #ifndef DISABLE_WRAPPING
+ case SPLIT:
+@@ -497,26 +480,28 @@ void do_undo(void)
+ delete_node(foo);
+ }
+ renumber(f);
++ gotolinecolumn = TRUE;
+ break;
+ #endif /* DISABLE_WRAPPING */
+ case UNSPLIT:
+ undidmsg = _("line join");
+ t = make_new_node(f);
+ t->data = mallocstrcpy(NULL, u->strdata);
+- data = mallocstrncpy(NULL, f->data, u->begin);
++ data = mallocstrncpy(NULL, f->data, u->begin + 1);
+ data[u->begin] = '\0';
+ free(f->data);
+ f->data = data;
+ splice_node(f, t, f->next);
+- renumber(f);
++ gotolinecolumn = TRUE;
+ break;
++ case CUT_EOF:
+ case CUT:
+ undidmsg = _("text cut");
+ undo_cut(u);
+ break;
+- case UNCUT:
++ case PASTE:
+ undidmsg = _("text uncut");
+- redo_cut(u);
++ undo_paste(u);
+ break;
+ case ENTER:
+ undidmsg = _("line break");
+@@ -527,6 +512,7 @@ void do_undo(void)
+ unlink_node(foo);
+ delete_node(foo);
+ }
++ goto_line_posx(u->lineno, u->begin);
+ break;
+ case INSERT:
+ undidmsg = _("text insert");
+@@ -538,7 +524,7 @@ void do_undo(void)
+ openfile->mark_begin = fsfromline(u->lineno + u->mark_begin_lineno - 1);
+ openfile->mark_begin_x = 0;
+ openfile->mark_set = TRUE;
+- do_gotolinecolumn(u->lineno, u->begin+1, FALSE, FALSE, FALSE, FALSE);
++ goto_line_posx(u->lineno, u->begin);
+ cut_marked();
+ u->cutbuffer = cutbuffer;
+ u->cutbottom = cutbottom;
+@@ -548,6 +534,7 @@ void do_undo(void)
+ break;
+ case REPLACE:
+ undidmsg = _("text replace");
++ goto_line_posx(u->lineno, u->begin);
+ data = u->strdata;
+ u->strdata = f->data;
+ f->data = data;
+@@ -559,16 +546,18 @@ void do_undo(void)
+
+ }
+ renumber(f);
+- do_gotolinecolumn(u->lineno, u->begin, FALSE, FALSE, FALSE, TRUE);
++ if (gotolinecolumn)
++ do_gotolinecolumn(u->lineno, u->begin, FALSE, FALSE, FALSE, TRUE);
+ statusbar(_("Undid action (%s)"), undidmsg);
+ openfile->current_undo = openfile->current_undo->next;
+ openfile->last_action = OTHER;
++ set_modified();
+ }
+
+ void do_redo(void)
+ {
++ bool gotolinecolumn = FALSE;
+ undo *u = openfile->undotop;
+- filestruct *f = openfile->current;
+ int len = 0;
+ char *undidmsg, *data;
+
+@@ -583,14 +572,9 @@ void do_redo(void)
+ return;
+ }
+
+- if (u->lineno <= f->lineno)
+- for (; f->prev != NULL && f->lineno != u->lineno; f = f->prev)
+- ;
+- else
+- for (; f->next != NULL && f->lineno != u->lineno; f = f->next)
+- ;
+- if (f->lineno != u->lineno) {
+- statusbar(_("Internal error: can't match line %d. Please save your work"), u->lineno);
++ filestruct *f = fsfromline(u->mark_begin_lineno);
++ if (!f) {
++ statusbar(_("Internal error: can't match line %d. Please save your work."), u->mark_begin_lineno);
+ return;
+ }
+ #ifdef DEBUG
+@@ -608,6 +592,7 @@ void do_redo(void)
+ strcpy(&data[u->begin + strlen(u->strdata)], &f->data[u->begin]);
+ free(f->data);
+ f->data = data;
++ goto_line_posx(u->mark_begin_lineno, u->mark_begin_x);
+ break;
+ case DEL:
+ undidmsg = _("text delete");
+@@ -617,10 +602,13 @@ void do_redo(void)
+ strcpy(&data[u->begin], &f->data[u->begin + strlen(u->strdata)]);
+ free(f->data);
+ f->data = data;
++ openfile->current_x = u->begin;
++ openfile->placewewant = xplustabs();
++ goto_line_posx(u->lineno, u->begin);
+ break;
+ case ENTER:
+ undidmsg = _("line break");
+- do_gotolinecolumn(u->lineno, u->begin+1, FALSE, FALSE, FALSE, FALSE);
++ goto_line_posx(u->lineno, u->begin);
+ do_enter(TRUE);
+ break;
+ #ifndef DISABLE_WRAPPING
+@@ -630,54 +618,56 @@ void do_redo(void)
+ prepend_wrap = TRUE;
+ do_wrap(f, TRUE);
+ renumber(f);
++ gotolinecolumn = TRUE;
+ break;
+ #endif /* DISABLE_WRAPPING */
+ case UNSPLIT:
+ undidmsg = _("line join");
+- len = strlen(f->data) + strlen(u->strdata + 1);
+- data = charalloc(len);
+- strcpy(data, f->data);
+- strcat(data, u->strdata);
+- free(f->data);
+- f->data = data;
++ len = strlen(f->data) + strlen(u->strdata) + 1;
++ f->data = charealloc(f->data, len);
++ strcat(f->data, u->strdata);
+ if (f->next != NULL) {
+ filestruct *tmp = f->next;
+ unlink_node(tmp);
+ delete_node(tmp);
+ }
+ renumber(f);
++ gotolinecolumn = TRUE;
+ break;
++ case CUT_EOF:
+ case CUT:
+ undidmsg = _("text cut");
+ redo_cut(u);
+ break;
+- case UNCUT:
++ case PASTE:
+ undidmsg = _("text uncut");
+- undo_cut(u);
++ redo_paste(u);
+ break;
+ case REPLACE:
+ undidmsg = _("text replace");
+ data = u->strdata;
+ u->strdata = f->data;
+ f->data = data;
++ goto_line_posx(u->lineno, u->begin);
+ break;
+ case INSERT:
+ undidmsg = _("text insert");
+- do_gotolinecolumn(u->lineno, u->begin+1, FALSE, FALSE, FALSE, FALSE);
++ goto_line_posx(u->lineno, u->begin);
+ copy_from_filestruct(u->cutbuffer, u->cutbottom);
+- openfile->placewewant = xplustabs();
+ break;
+ default:
+ undidmsg = _("Internal error: unknown type. Please save your work");
+ break;
+-
+ }
+- do_gotolinecolumn(u->lineno, u->begin, FALSE, FALSE, FALSE, TRUE);
++
++ if (gotolinecolumn)
++ do_gotolinecolumn(u->lineno, u->begin, FALSE, FALSE, FALSE, TRUE);
+ statusbar(_("Redid action (%s)"), undidmsg);
+
+ openfile->current_undo = u;
+ openfile->last_action = OTHER;
+
++ set_modified();
+ }
+ #endif /* !NANO_TINY */
+
+@@ -846,7 +836,6 @@ void add_undo(undo_type current_action)
+ undo *u;
+ char *data;
+ openfilestruct *fs = openfile;
+- static undo *last_cutu = NULL; /* Last thing we cut to set up the undo for uncut */
+ ssize_t wrap_loc; /* For calculating split beginning */
+
+ if (!ISSET(UNDOABLE))
+@@ -855,9 +844,10 @@ void add_undo(undo_type current_action)
+ /* Ugh, if we were called while cutting not-to-end, non-marked and on the same lineno,
+ we need to abort here */
+ u = fs->current_undo;
+- if (current_action == CUT && u && u->type == CUT
+- && !u->mark_set && u->lineno == fs->current->lineno)
+- return;
++ if (u && u->mark_begin_lineno == fs->current->lineno &&
++ ((current_action == CUT && u->type == CUT && !u->mark_set) ||
++ (current_action == ADD && u->type == ADD && u->mark_begin_x == fs->current_x)))
++ return;
+
+ /* Blow away the old undo stack if we are starting from the middle */
+ while (fs->undotop != NULL && fs->undotop != fs->current_undo) {
+@@ -883,8 +873,8 @@ void add_undo(undo_type current_action)
+ u->cutbuffer = NULL;
+ u->cutbottom = NULL;
+ u->mark_set = 0;
+- u->mark_begin_lineno = 0;
+- u->mark_begin_x = 0;
++ u->mark_begin_lineno = fs->current->lineno;
++ u->mark_begin_x = fs->current_x;
+ u->xflags = 0;
+ u->to_end = FALSE;
+
+@@ -893,8 +883,7 @@ void add_undo(undo_type current_action)
+ to restore it later */
+ case ADD:
+ data = charalloc(2);
+- data[0] = fs->current->data[fs->current_x];
+- data[1] = '\0';
++ data[0] = '\0';
+ u->strdata = data;
+ break;
+ case DEL:
+@@ -932,21 +921,43 @@ void add_undo(undo_type current_action)
+ data = mallocstrcpy(NULL, fs->current->data);
+ u->strdata = data;
+ break;
++ case CUT_EOF:
++ u->to_end = TRUE;
+ case CUT:
+ u->mark_set = openfile->mark_set;
+ if (u->mark_set) {
+ u->mark_begin_lineno = openfile->mark_begin->lineno;
+ u->mark_begin_x = openfile->mark_begin_x;
+ }
+- u->to_end = (ISSET(CUT_TO_END)) ? TRUE : FALSE;
+- last_cutu = u;
++ else if (!ISSET(CUT_TO_END) && !u->to_end) {
++ /* The entire line is being cut regardless of the cursor position. */
++ u->begin = 0;
++ u->mark_begin_x = 0;
++ }
+ break;
+- case UNCUT:
+- if (!last_cutu)
++ case PASTE:
++ if (!cutbuffer)
+ statusbar(_("Internal error: can't setup uncut. Please save your work."));
+- else if (last_cutu->type == CUT) {
+- u->cutbuffer = last_cutu->cutbuffer;
+- u->cutbottom = last_cutu->cutbottom;
++ else {
++ if (u->cutbuffer)
++ free(u->cutbuffer);
++ u->cutbuffer = copy_filestruct(cutbuffer);
++ u->mark_begin_lineno = fs->current->lineno;
++ u->mark_begin_x = fs->current_x;
++ u->lineno = fs->current->lineno + cutbottom->lineno - cutbuffer->lineno;
++
++ filestruct *fs_buff = cutbuffer;
++ if (fs_buff->lineno == cutbottom->lineno)
++ u->begin = fs->current_x + get_totsize(fs_buff,cutbottom);
++ else {
++ /* Advance fs_buff to the last line in the cutbuffer. */
++ while (fs_buff->lineno != cutbottom->lineno && fs_buff->next != NULL)
++ fs_buff = fs_buff->next;
++ assert(fs_buff->next != NULL);
++ u->begin = get_totsize(fs_buff,cutbottom);
++ }
++
++ u->mark_set = TRUE;
+ }
+ break;
+ case ENTER:
+@@ -1008,12 +1019,14 @@ void update_undo(undo_type action)
+ #endif
+ len = strlen(u->strdata) + 2;
+ data = (char *) nrealloc((void *) u->strdata, len * sizeof(char *));
+- data[len-2] = fs->current->data[fs->current_x];
++ data[len-2] = fs->current->data[fs->current_x - 1];
+ data[len-1] = '\0';
+ u->strdata = (char *) data;
+ #ifdef DEBUG
+ fprintf(stderr, "current undo data now \"%s\"\n", u->strdata);
+ #endif
++ u->mark_begin_lineno = fs->current->lineno;
++ u->mark_begin_x = fs->current_x;
+ break;
+ case DEL:
+ len = strlen(u->strdata) + 2;
+@@ -1055,18 +1068,37 @@ void update_undo(undo_type action)
+ fprintf(stderr, "current undo data now \"%s\"\nu->begin = %d\n", u->strdata, u->begin);
+ #endif
+ break;
++ case CUT_EOF:
+ case CUT:
+ if (!cutbuffer)
+ break;
+ if (u->cutbuffer)
+ free(u->cutbuffer);
+ u->cutbuffer = copy_filestruct(cutbuffer);
+- /* Compute cutbottom for the uncut using out copy */
+- for (u->cutbottom = u->cutbuffer; u->cutbottom->next != NULL; u->cutbottom = u->cutbottom->next)
+- ;
++ if (u->mark_set) {
++ /* If the "marking" operation was from right-->left or
++ * bottom-->top, then swap the mark points. */
++ if ((u->lineno == u->mark_begin_lineno && u->begin < u->mark_begin_x)
++ || u->lineno < u->mark_begin_lineno) {
++ size_t x_loc = u->begin;
++ u->begin = u->mark_begin_x;
++ u->mark_begin_x = x_loc;
++
++ ssize_t line = u->lineno;
++ u->lineno = u->mark_begin_lineno;
++ u->mark_begin_lineno = line;
++ }
++ } else if (!ISSET(CUT_TO_END)) {
++ /* Compute cutbottom for the uncut using our copy. */
++ u->cutbottom = u->cutbuffer;
++ while (u->cutbottom->next != NULL)
++ u->cutbottom = u->cutbottom->next;
++ if (!u->to_end)
++ u->lineno++;
++ }
+ break;
+ case REPLACE:
+- case UNCUT:
++ case PASTE:
+ add_undo(action);
+ break;
+ case INSERT:
+@@ -1087,15 +1119,8 @@ void update_undo(undo_type action)
+ }
+
+ #ifdef DEBUG
+- fprintf(stderr, "Done in udpate_undo (type was %d)\n", action);
++ fprintf(stderr, "Done in update_undo (type was %d)\n", action);
+ #endif
+- if (fs->last_action != action) {
+-#ifdef DEBUG
+- fprintf(stderr, "Starting add_undo for new action as it does not match last_action\n");
+-#endif
+- add_undo(action);
+- }
+- fs->last_action = action;
+ }
+
+ #endif /* !NANO_TINY */
+diff --git a/src/utils.c b/src/utils.c
+index 675a70a..cb02328 100644
+--- a/src/utils.c
++++ b/src/utils.c
+@@ -476,7 +476,10 @@ size_t get_page_start(size_t column)
+ * current_x. */
+ size_t xplustabs(void)
+ {
+- return strnlenpt(openfile->current->data, openfile->current_x);
++ if (openfile->current)
++ return strnlenpt(openfile->current->data, openfile->current_x);
++ else
++ return 0;
+ }
+
+ /* Return the index in s of the character displayed at the given column,
+--
+2.1.0
+
diff --git a/nano.spec b/nano.spec
index 167a0c9..96c5cc6 100644
--- a/nano.spec
+++ b/nano.spec
@@ -1,7 +1,7 @@
Summary: A small text editor
Name: nano
Version: 2.3.2
-Release: 4%{?dist}
+Release: 5%{?dist}
License: GPLv3+
Group: Applications/Editors
URL: http://www.nano-editor.org
@@ -18,6 +18,9 @@ Patch2: 0002-use-futimens-if-available-instead-of-utime.patch
# http://thread.gmane.org/gmane.editors.nano.devel/3081
Patch3: 0003-Document-the-poslog-P-option-in-nano.1-man-page.patch
+# fix intermittent crashes with undo/redo (#1166666)
+Patch4: 0004-Going-to-the-correct-positions-for-undoing-and-redoi.patch
+
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
BuildRequires: autoconf
BuildRequires: file-devel
@@ -38,6 +41,7 @@ GNU nano is a small and friendly text editor.
%patch1 -p1
%patch2 -p1
%patch3 -p1
+%patch4 -p1
for f in doc/man/fr/{nano.1,nanorc.5,rnano.1} ; do
iconv -f iso-8859-1 -t utf-8 -o $f.tmp $f && mv $f.tmp $f
@@ -93,6 +97,9 @@ exit 0
%{_datadir}/nano
%changelog
+* Fri Nov 21 2014 Kamil Dudka <kdudka at redhat.com> - 2.3.2-5
+- fix intermittent crashes with undo/redo (#1166666)
+
* Fri Aug 09 2013 Kamil Dudka <kdudka at redhat.com> - 2.3.2-4
- document the --poslog (-P) option in nano.1 man page
More information about the scm-commits
mailing list