From 14c8620e0b08fefede6261b5ddee657694bf9314 Mon Sep 17 00:00:00 2001
From: Chris Allegretta <chrisa@asty.org>
Date: Sun, 3 Aug 2008 04:48:05 +0000
Subject: [PATCH] - Change add_undo and current_undo to only take action arg,
 as openfilestruct arg is always openfile - Add ability to undo a file/cmd
 insert, needed to add undoable flag to read_file and open_buffer as a result

git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@4291 35c25a1d-7b9e-4130-9fde-d3aeb78583b8
---
 src/cut.c    |  6 +++---
 src/files.c  | 25 +++++++++++++++++--------
 src/nano.c   |  8 ++++----
 src/nano.h   |  2 +-
 src/proto.h  |  9 +++++----
 src/search.c |  2 +-
 src/text.c   | 51 ++++++++++++++++++++++++++++++++++++---------------
 src/utils.c  | 18 ++++++++++++++++++
 8 files changed, 85 insertions(+), 36 deletions(-)

diff --git a/src/cut.c b/src/cut.c
index 6fda848c..72148e13 100644
--- a/src/cut.c
+++ b/src/cut.c
@@ -205,7 +205,7 @@ void do_cut_text(
 	if (!old_no_newlines)
 	    UNSET(NO_NEWLINES);
     } else if (!undoing)
-	update_undo(CUT, openfile);
+	update_undo(CUT);
 #endif
 	/* Leave the text in the cutbuffer, and mark the file as
 	 * modified. */
@@ -224,7 +224,7 @@ void do_cut_text(
 void do_cut_text_void(void)
 {
 #ifndef NANO_TINY
-    add_undo(CUT, openfile);
+    add_undo(CUT);
 #endif
     do_cut_text(
 #ifndef NANO_TINY
@@ -245,7 +245,7 @@ void do_copy_text(void)
 void do_cut_till_end(void)
 {
 #ifndef NANO_TINY
-    add_undo(CUTTOEND, openfile);
+    add_undo(CUTTOEND);
 #endif
     do_cut_text(FALSE, TRUE, FALSE);
 }
diff --git a/src/files.c b/src/files.c
index 10b8a3e1..a5607dd2 100644
--- a/src/files.c
+++ b/src/files.c
@@ -101,7 +101,7 @@ void initialize_buffer_text(void)
 
 /* If it's not "", filename is a file to open.  We make a new buffer, if
  * necessary, and then open and read the file, if applicable. */
-void open_buffer(const char *filename)
+void open_buffer(const char *filename, bool undoable)
 {
     bool new_buffer = (openfile == NULL
 #ifdef ENABLE_MULTIBUFFER
@@ -142,7 +142,7 @@ void open_buffer(const char *filename)
     /* If we have a non-new file, read it in.  Then, if the buffer has
      * no stat, update the stat, if applicable. */
     if (rc == 0) {
-	read_file(f, filename);
+	read_file(f, filename, undoable);
 #ifndef NANO_TINY
 	if (openfile->current_stat == NULL) {
 	    openfile->current_stat =
@@ -192,7 +192,7 @@ void replace_buffer(const char *filename)
 
     /* If we have a non-new file, read it in. */
     if (rc == 0)
-	read_file(f, filename);
+	read_file(f, filename, FALSE);
 
     /* Move back to the beginning of the first line of the buffer. */
     openfile->current = openfile->fileage;
@@ -339,8 +339,9 @@ filestruct *read_line(char *buf, filestruct *prevnode, bool
 }
 
 /* Read an open file into the current buffer.  f should be set to the
- * open file, and filename should be set to the name of the file. */
-void read_file(FILE *f, const char *filename)
+ * open file, and filename should be set to the name of the file.
+   undoable  means do we want to create undo records to try and undo this */
+void read_file(FILE *f, const char *filename, bool undoable)
 {
     size_t num_lines = 0;
 	/* The number of lines in the file. */
@@ -371,6 +372,11 @@ void read_file(FILE *f, const char *filename)
     buf = charalloc(bufx);
     buf[0] = '\0';
 
+#ifndef NANO_TINY
+    if (undoable)
+	add_undo(INSERT);
+#endif
+
     if (openfile->current == openfile->fileage)
 	first_line_ins = TRUE;
     else
@@ -489,7 +495,7 @@ void read_file(FILE *f, const char *filename)
     /* If we didn't get a file and we don't already have one, open a
      * blank buffer. */
     if (fileptr == NULL)
-	open_buffer("");
+	open_buffer("", FALSE);
 
     /* Attach the file we got to the filestruct.  If we got a file of
      * zero bytes, don't do anything. */
@@ -561,6 +567,9 @@ void read_file(FILE *f, const char *filename)
     openfile->placewewant = xplustabs();
 
 #ifndef NANO_TINY
+    if (undoable)
+	update_undo(INSERT);
+
     if (format == 3)
 	statusbar(
 		P_("Read %lu line (Converted from DOS and Mac format)",
@@ -853,7 +862,7 @@ void do_insertfile(
 #ifdef ENABLE_MULTIBUFFER
 		if (ISSET(MULTIBUFFER))
 		    /* Open a blank buffer. */
-		    open_buffer("");
+		    open_buffer("", FALSE);
 #endif
 
 		/* Save the command's output in the current buffer. */
@@ -877,7 +886,7 @@ void do_insertfile(
 
 		/* Save the file specified in answer in the current
 		 * buffer. */
-		open_buffer(answer);
+		open_buffer(answer, TRUE);
 #ifndef NANO_TINY
 	    }
 #endif
diff --git a/src/nano.c b/src/nano.c
index 14be3388..eb8678a1 100644
--- a/src/nano.c
+++ b/src/nano.c
@@ -1647,7 +1647,7 @@ void do_output(char *output, size_t output_len, bool allow_cntrls)
 	set_modified();
 
 #ifndef NANO_TINY
-	update_undo(ADD, openfile);
+	update_undo(ADD);
 
 
 	/* Note that current_x has not yet been incremented. */
@@ -2232,7 +2232,7 @@ int main(int argc, char **argv)
 		icol == 1)
 		parse_line_column(&argv[i][1], &iline, &icol);
 	    else {
-		open_buffer(argv[i]);
+		open_buffer(argv[i], FALSE);
 
 		if (iline > 1 || icol > 1) {
 		    do_gotolinecolumn(iline, icol, FALSE, FALSE, FALSE,
@@ -2249,14 +2249,14 @@ int main(int argc, char **argv)
      * buffer or a new buffer, depending on whether multibuffer mode is
      * enabled. */
     if (optind < argc)
-	open_buffer(argv[optind]);
+	open_buffer(argv[optind], FALSE);
 
     /* We didn't open any files if all the command line arguments were
      * invalid files like directories or if there were no command line
      * arguments given.  In this case, we have to load a blank buffer.
      * Also, we unset view mode to allow editing. */
     if (openfile == NULL) {
-	open_buffer("");
+	open_buffer("", FALSE);
 	UNSET(VIEW_MODE);
     }
 
diff --git a/src/nano.h b/src/nano.h
index a1bb6720..b286f0d0 100644
--- a/src/nano.h
+++ b/src/nano.h
@@ -170,7 +170,7 @@ typedef enum {
 }  function_type;
 
 typedef enum {
-    ADD, DEL, REPLACE, SPLIT, UNSPLIT, CUT, CUTTOEND, UNCUT, OTHER
+    ADD, DEL, REPLACE, SPLIT, UNSPLIT, CUT, CUTTOEND, UNCUT, INSERT, OTHER
 } undo_type;
 
 /* Structure types. */
diff --git a/src/proto.h b/src/proto.h
index 0c8d3575..2a40dda2 100644
--- a/src/proto.h
+++ b/src/proto.h
@@ -255,7 +255,7 @@ void do_uncut_text(void);
 void make_new_buffer(void);
 void initialize_buffer(void);
 void initialize_buffer_text(void);
-void open_buffer(const char *filename);
+void open_buffer(const char *filename, bool undoable);
 #ifndef DISABLE_SPELLER
 void replace_buffer(const char *filename);
 #endif
@@ -268,7 +268,7 @@ bool close_buffer(void);
 #endif
 filestruct *read_line(char *buf, filestruct *prevnode, bool
 	*first_line_ins, size_t buf_len);
-void read_file(FILE *f, const char *filename);
+void read_file(FILE *f, const char *filename, bool undoable);
 int open_file(const char *filename, bool newfie, FILE **f);
 char *get_next_filename(const char *name, const char *suffix);
 void do_insertfile(
@@ -707,10 +707,11 @@ void new_magicline(void);
 void remove_magicline(void);
 void mark_order(const filestruct **top, size_t *top_x, const filestruct
 	**bot, size_t *bot_x, bool *right_side_up);
-void add_undo(undo_type current_action, openfilestruct *fs);
-void update_undo(undo_type action, openfilestruct *fs);
+void add_undo(undo_type current_action);
+void update_undo(undo_type action);
 #endif
 size_t get_totsize(const filestruct *begin, const filestruct *end);
+filestruct *fsfromline(ssize_t lineno);
 #ifdef DEBUG
 void dump_filestruct(const filestruct *inptr);
 void dump_filestruct_reverse(void);
diff --git a/src/search.c b/src/search.c
index 35d3d135..64ff953d 100644
--- a/src/search.c
+++ b/src/search.c
@@ -789,7 +789,7 @@ ssize_t do_replace_loop(
 	    size_t length_change;
 
 #ifndef NANO_TINY
-	    update_undo(REPLACE, openfile);
+	    update_undo(REPLACE);
 #endif
 	    if (i == 2)
 		replaceall = TRUE;
diff --git a/src/text.c b/src/text.c
index 7bd3a7db..0564cb9c 100644
--- a/src/text.c
+++ b/src/text.c
@@ -71,7 +71,7 @@ void do_delete(void)
 	 * just update_line()? */
 
 #ifndef NANO_TINY
-    update_undo(DEL, openfile);
+    update_undo(DEL);
 #endif
 
     assert(openfile->current != NULL && openfile->current->data != NULL && openfile->current_x <= strlen(openfile->current->data));
@@ -371,6 +371,7 @@ void do_undo(void)
     filestruct *f = openfile->current, *t;
     int len = 0;
     char *undidmsg, *data;
+    filestruct *oldcutbuffer = cutbuffer, *oldcutbottom = cutbottom;
 
     if (!u) {
 	statusbar(_("Nothing in undo buffer!"));
@@ -458,6 +459,24 @@ void do_undo(void)
 	free_filestruct(cutbuffer);
 	cutbuffer = NULL;
 	break;
+    case INSERT:
+	undidmsg = _("text insert");
+	cutbuffer = NULL;
+	cutbottom = NULL;
+	/* When we updated mark_begin_lineno in update_undo, it was effectively how many line
+	   were inserted due to being partitioned before read_file was called.  So we
+	   add its value here */
+	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);
+	cut_marked();
+	u->cutbuffer = cutbuffer;
+	u->cutbottom = cutbottom;
+	cutbuffer = oldcutbuffer;
+	cutbottom = oldcutbottom;
+	openfile->mark_set = FALSE;
+	break;
     case REPLACE:
 	undidmsg = _("text replace");
 	data = u->strdata;
@@ -622,7 +641,7 @@ void do_enter(void)
     assert(openfile->current != NULL && xopenfile->current->data != NULL);
 
 #ifndef NANO_TINY
-    update_undo(SPLIT, openfile);
+    update_undo(SPLIT);
 
 
     /* Do auto-indenting, like the neolithic Turbo Pascal editor. */
@@ -750,7 +769,7 @@ bool execute_command(const char *command)
     if (f == NULL)
 	nperror("fdopen");
 
-    read_file(f, "stdin");
+    read_file(f, "stdin", TRUE);
 
     if (wait(NULL) == -1)
 	nperror("wait");
@@ -767,10 +786,11 @@ bool execute_command(const char *command)
 }
 
 /* Add a new undo struct to the top of the current pile */
-void add_undo(undo_type current_action, openfilestruct *fs)
+void add_undo(undo_type current_action)
 {
     undo *u;
     char *data;
+    openfilestruct *fs = openfile;
 
     /* Ugh, if we were called while cutting not-to-end, non-marked and on the same lineno,
        we need to  abort here */
@@ -831,12 +851,11 @@ void add_undo(undo_type current_action, openfilestruct *fs)
 	    data = mallocstrcpy(NULL, fs->current->next->data);
 	    u->strdata = data;
 	}
-	u->begin = fs->current_x;
 	break;
+    case INSERT:
     case SPLIT:
     case REPLACE:
 	data = mallocstrcpy(NULL, fs->current->data);
-        u->begin = fs->current_x;
 	u->strdata = data;
 	break;
     case CUT:
@@ -868,12 +887,12 @@ void add_undo(undo_type current_action, openfilestruct *fs)
    instead.  The latter functionality just feels
    gimmicky and may just be more hassle than
    it's worth, so it should be axed if needed. */
-void update_undo(undo_type action, openfilestruct *fs)
+void update_undo(undo_type action)
 {
     undo *u;
     char *data;
     int len = 0;
-
+    openfilestruct *fs = openfile;
 
 #ifdef DEBUG
         fprintf(stderr, "action = %d, fs->last_action = %d,  openfile->current->lineno = %d",
@@ -887,9 +906,9 @@ void update_undo(undo_type action, openfilestruct *fs)
     /* Change to an add if we're not using the same undo struct
        that we should be using */
     if (action != fs->last_action
-	|| (action != CUT && action != CUTTOEND
+	|| (action != CUT && action != CUTTOEND && action != INSERT
 	    && openfile->current->lineno != fs->current_undo->lineno)) {
-        add_undo(action, fs);
+        add_undo(action);
 	return;
     }
 
@@ -919,7 +938,7 @@ void update_undo(undo_type action, openfilestruct *fs)
 	    if (!u->xflags)
 		u->xflags = UNDO_DEL_DEL;
 	    else if (u->xflags != UNDO_DEL_DEL) {
-		add_undo(action, fs);
+		add_undo(action);
 		return;
 	    }
 	    data = charalloc(len);
@@ -933,7 +952,7 @@ void update_undo(undo_type action, openfilestruct *fs)
 	    if (!u->xflags)
 		u->xflags = UNDO_DEL_BACKSPACE;
 	    else if (u->xflags != UNDO_DEL_BACKSPACE) {
-		add_undo(action, fs);
+		add_undo(action);
 		return;
 	    }
 	    data = charalloc(len);
@@ -944,7 +963,7 @@ void update_undo(undo_type action, openfilestruct *fs)
 	    u->begin--;
 	} else {
 	    /* They deleted something else on the line */
-	    add_undo(DEL, fs);
+	    add_undo(DEL);
 	    return;
 	}
 #ifdef DEBUG
@@ -961,8 +980,10 @@ void update_undo(undo_type action, openfilestruct *fs)
 	u->linescut++;
 	break;
     case REPLACE:
-	add_undo(action, fs);
+	add_undo(action);
 	break;
+    case INSERT:
+	u->mark_begin_lineno = openfile->current->lineno;
     case SPLIT:
     case UNSPLIT:
 	/* These cases are handled by the earlier check for a new line and action */
@@ -977,7 +998,7 @@ void update_undo(undo_type action, openfilestruct *fs)
 #ifdef DEBUG
 	fprintf(stderr, "Starting add_undo for new action as it does not match last_action\n");
 #endif
-	add_undo(action, openfile);
+	add_undo(action);
     }
     fs->last_action = action;
 }
diff --git a/src/utils.c b/src/utils.c
index 658e418b..d09118fa 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -603,6 +603,24 @@ void dump_filestruct(const filestruct *inptr)
     }
 }
 
+/* Get back a pointer given a line number in the current openfilestruct */
+filestruct *fsfromline(ssize_t lineno)
+{
+    filestruct *f = openfile->current;
+
+    if (lineno <= openfile->current->lineno)
+	for (; f->lineno != lineno && f != openfile->fileage; f = f->prev)
+	   ;
+    else
+        for (; f->lineno != lineno && f->next != NULL; f = f->next)
+
+    if (f->lineno != lineno)
+	return NULL;
+
+    return f;
+}
+
+
 /* Dump the current buffer's filestruct to stderr in reverse. */
 void dump_filestruct_reverse(void)
 {
-- 
GitLab