From 234bd9c9beda9a979c84a8f878c57593bd30026c Mon Sep 17 00:00:00 2001
From: David Lawrence Ramsey <pooka109@gmail.com>
Date: Thu, 9 Feb 2017 19:04:14 -0600
Subject: [PATCH] speller: fix replacing marked text in the alternate spell
 checker

With read_file() revamped, it now uses partition_filestruct() indirectly
via ingraft_buffer(), so we can't use partition_filestruct() to replace
marked text in the alternate spell checker anymore without segfaulting.

Add the new function replace_marked_buffer() to accomplish this instead.
Based on replace_buffer(), it uses extract_buffer() to throw away the
marked un-spell-checked text, and then uses read_file() to insert the
spell-checked text at the position where the mark was.

Accordingly, remove unneeded partitioning and related stuff from
do_alt_speller().  Besides pasting the file into the buffer at
current[current_x], ingraft_buffer() also deals with renumbering,
updating totsize, and handling a magicline, so do_alt_speller()
doesn't need to do those anymore.
---
 src/files.c | 33 ++++++++++++++++++++++++
 src/proto.h |  4 +++
 src/text.c  | 72 ++++++++++-------------------------------------------
 3 files changed, 50 insertions(+), 59 deletions(-)

diff --git a/src/files.c b/src/files.c
index b34836eb..ddba84fc 100644
--- a/src/files.c
+++ b/src/files.c
@@ -545,6 +545,39 @@ void replace_buffer(const char *filename)
     /* Put current at a place that is certain to exist. */
     openfile->current = openfile->fileage;
 }
+
+#ifndef NANO_TINY
+/* Open the specified file, and if that succeeds, blow away the text of
+ * the current buffer at the given coordinates and read the file
+ * contents into its place. */
+void replace_marked_buffer(const char *filename, filestruct *top, size_t top_x,
+	filestruct *bot, size_t bot_x)
+{
+    FILE *f;
+    int descriptor;
+    bool old_no_newlines = ISSET(NO_NEWLINES);
+    filestruct *trash_top = NULL;
+    filestruct *trash_bot = NULL;
+
+    descriptor = open_file(filename, FALSE, TRUE, &f);
+
+    if (descriptor < 0)
+	return;
+
+    /* Don't add a magicline when replacing text in the buffer. */
+    SET(NO_NEWLINES);
+
+    /* Throw away the text under the mark, and insert the processed file
+     * where the marked text was. */
+    extract_buffer(&trash_top, &trash_bot, top, top_x, bot, bot_x);
+    free_filestruct(trash_top);
+    read_file(f, descriptor, filename, FALSE, TRUE);
+
+    /* Restore the magicline behavior now that we're done fiddling. */
+    if (!old_no_newlines)
+	UNSET(NO_NEWLINES);
+}
+#endif /* !ENABLE_TINY */
 #endif /* !DISABLE_SPELLER */
 
 /* Update the screen to account for the current buffer. */
diff --git a/src/proto.h b/src/proto.h
index 0a5dc513..291f6c06 100644
--- a/src/proto.h
+++ b/src/proto.h
@@ -294,6 +294,10 @@ void initialize_buffer_text(void);
 bool open_buffer(const char *filename, bool undoable);
 #ifndef DISABLE_SPELLER
 void replace_buffer(const char *filename);
+#ifndef NANO_TINY
+void replace_marked_buffer(const char *filename, filestruct *top, size_t top_x,
+	filestruct *bot, size_t bot_x);
+#endif
 #endif
 void display_buffer(void);
 #ifndef DISABLE_MULTIBUFFER
diff --git a/src/text.c b/src/text.c
index 1cbaf768..b6335340 100644
--- a/src/text.c
+++ b/src/text.c
@@ -2880,19 +2880,11 @@ const char *do_alt_speller(char *tempfile_name)
     static int arglen = 3;
     static char **spellargs = NULL;
 #ifndef NANO_TINY
-    bool old_mark_set = openfile->mark_set;
-    bool added_magicline = FALSE;
-	/* Whether we added a magicline after filebot. */
     filestruct *top, *bot;
-    size_t top_x, bot_x, was_x, new_x;
+    size_t top_x, bot_x;
     bool right_side_up = FALSE;
+    bool old_mark_set = openfile->mark_set;
     ssize_t mb_lineno_save = 0;
-	/* We're going to close the current file, and open the output of
-	 * the alternate spell command.  The line that mark_begin points
-	 * to will be freed, so we save the line number and restore it
-	 * afterwards. */
-    size_t size_of_surrounding = 0;
-	/* The size of the text outside of a marked region. */
 #endif
 
     /* Get the timestamp and the size of the temporary file. */
@@ -2904,9 +2896,8 @@ const char *do_alt_speller(char *tempfile_name)
 	return NULL;
 
 #ifndef NANO_TINY
+    /* Save the mark's position and turn it off. */
     if (old_mark_set) {
-	/* If the mark is on, save the number of the line it starts on,
-	 * and then turn the mark off. */
 	mb_lineno_save = openfile->mark_begin->lineno;
 	openfile->mark_set = FALSE;
     }
@@ -2965,65 +2956,28 @@ const char *do_alt_speller(char *tempfile_name)
     }
 
 #ifndef NANO_TINY
+    /* Replace the text (or just the marked text) of the current buffer
+     * with the spell-checked text. */
     if (old_mark_set) {
-	/* Trim the filestruct so that it contains only the marked text. */
 	mark_order((const filestruct **)&top, &top_x,
 			(const filestruct **)&bot, &bot_x, &right_side_up);
-	filepart = partition_filestruct(top, top_x, bot, bot_x);
 
-	/* Foresay whether a magicline will be added when the
-	 * spell-checked text is read back in. */
-	if (!ISSET(NO_NEWLINES))
-	    added_magicline = (openfile->filebot->data[0] != '\0');
-
-	/* Compute the size of the text outside of the marked region. */
-	size_of_surrounding = openfile->totsize - get_totsize(top, bot);
-    }
-#endif
-
-    /* Replace the text of the current buffer with the spell-checked text. */
-    replace_buffer(tempfile_name);
-
-#ifndef NANO_TINY
-    if (old_mark_set) {
-	filestruct *top_save = openfile->fileage;
-
-	/* If a magicline was added, remove it again. */
-	if (added_magicline)
-	    remove_magicline();
+	replace_marked_buffer(tempfile_name, top, top_x, bot, bot_x);
 
 	/* Adjust the end point of the marked region for any change in
 	 * length of the region's last line. */
 	if (right_side_up)
-	    was_x = current_x_save;
-	else
-	    was_x = openfile->mark_begin_x;
-	if (top == bot)
-	    new_x = was_x - bot_x + top_x + strlen(openfile->filebot->data);
+	    current_x_save = openfile->current_x;
 	else
-	    new_x = strlen(openfile->filebot->data);
-	if (right_side_up)
-	    current_x_save = new_x;
-	else
-	    openfile->mark_begin_x = new_x;
-
-	/* Unpartition the filestruct so that it contains all the text
-	 * again.  Note that we've replaced the marked text originally
-	 * in the partition with the spell-checked marked text in the
-	 * temp file. */
-	unpartition_filestruct(&filepart);
-
-	/* Renumber, starting with the beginning line of the old partition. */
-	renumber(top_save);
+	    openfile->mark_begin_x = openfile->current_x;
 
-	/* Add back the size of the text surrounding the marked region. */
-	openfile->totsize += size_of_surrounding;
-
-	/* Restore the position of the mark, and turn it back on. */
+	/* Restore the mark's position and turn it on. */
 	openfile->mark_begin = fsfromline(mb_lineno_save);
 	openfile->mark_set = TRUE;
-    }
-#endif /* !NANO_TINY */
+    } else
+#endif
+	replace_buffer(tempfile_name);
+
 
     /* Go back to the old position. */
     goto_line_posx(lineno_save, current_x_save);
-- 
GitLab