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.
master
David Lawrence Ramsey 2017-02-09 19:04:14 -06:00 committed by Benno Schulenberg
parent 0d9313763d
commit 234bd9c9be
3 changed files with 50 additions and 59 deletions

View File

@ -545,6 +545,39 @@ void replace_buffer(const char *filename)
/* Put current at a place that is certain to exist. */ /* Put current at a place that is certain to exist. */
openfile->current = openfile->fileage; 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 */ #endif /* !DISABLE_SPELLER */
/* Update the screen to account for the current buffer. */ /* Update the screen to account for the current buffer. */

View File

@ -294,6 +294,10 @@ void initialize_buffer_text(void);
bool open_buffer(const char *filename, bool undoable); bool open_buffer(const char *filename, bool undoable);
#ifndef DISABLE_SPELLER #ifndef DISABLE_SPELLER
void replace_buffer(const char *filename); 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 #endif
void display_buffer(void); void display_buffer(void);
#ifndef DISABLE_MULTIBUFFER #ifndef DISABLE_MULTIBUFFER

View File

@ -2880,19 +2880,11 @@ const char *do_alt_speller(char *tempfile_name)
static int arglen = 3; static int arglen = 3;
static char **spellargs = NULL; static char **spellargs = NULL;
#ifndef NANO_TINY #ifndef NANO_TINY
bool old_mark_set = openfile->mark_set;
bool added_magicline = FALSE;
/* Whether we added a magicline after filebot. */
filestruct *top, *bot; 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 right_side_up = FALSE;
bool old_mark_set = openfile->mark_set;
ssize_t mb_lineno_save = 0; 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 #endif
/* Get the timestamp and the size of the temporary file. */ /* Get the timestamp and the size of the temporary file. */
@ -2904,9 +2896,8 @@ const char *do_alt_speller(char *tempfile_name)
return NULL; return NULL;
#ifndef NANO_TINY #ifndef NANO_TINY
/* Save the mark's position and turn it off. */
if (old_mark_set) { 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; mb_lineno_save = openfile->mark_begin->lineno;
openfile->mark_set = FALSE; openfile->mark_set = FALSE;
} }
@ -2965,65 +2956,28 @@ const char *do_alt_speller(char *tempfile_name)
} }
#ifndef NANO_TINY #ifndef NANO_TINY
/* Replace the text (or just the marked text) of the current buffer
* with the spell-checked text. */
if (old_mark_set) { if (old_mark_set) {
/* Trim the filestruct so that it contains only the marked text. */
mark_order((const filestruct **)&top, &top_x, mark_order((const filestruct **)&top, &top_x,
(const filestruct **)&bot, &bot_x, &right_side_up); (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 replace_marked_buffer(tempfile_name, top, top_x, bot, bot_x);
* 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();
/* Adjust the end point of the marked region for any change in /* Adjust the end point of the marked region for any change in
* length of the region's last line. */ * length of the region's last line. */
if (right_side_up) if (right_side_up)
was_x = current_x_save; current_x_save = openfile->current_x;
else else
was_x = openfile->mark_begin_x; openfile->mark_begin_x = openfile->current_x;
if (top == bot)
new_x = was_x - bot_x + top_x + strlen(openfile->filebot->data);
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 /* Restore the mark's position and turn it on. */
* 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);
/* 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. */
openfile->mark_begin = fsfromline(mb_lineno_save); openfile->mark_begin = fsfromline(mb_lineno_save);
openfile->mark_set = TRUE; openfile->mark_set = TRUE;
} } else
#endif /* !NANO_TINY */ #endif
replace_buffer(tempfile_name);
/* Go back to the old position. */ /* Go back to the old position. */
goto_line_posx(lineno_save, current_x_save); goto_line_posx(lineno_save, current_x_save);