From 433c7e5dc6be9274a2fc1cac8be93bc2d44844d9 Mon Sep 17 00:00:00 2001 From: Benno Schulenberg Date: Wed, 4 May 2016 17:49:37 +0200 Subject: [PATCH] spelling: don't partition the file for replacements in a marked region Partitioning the file makes the undo system lose track, so that undoing things has a good chance of losing data. Instead, just make sure that the region is marked "backwards", with current at the top and the mark at the bottom, and then let the replace loop take care of not going outside of the marked region. This also has the effect that if the marked region fits entirely on the screen, or all the misspellings are onscreen, then the screen will not be scrolled at all. Which makes for a smooth experience. This fixes https://savannah.gnu.org/bugs/?47836, and fixes https://savannah.gnu.org/bugs/?45573. --- src/search.c | 5 +++- src/text.c | 68 +++++++++++++++++++++++++--------------------------- 2 files changed, 37 insertions(+), 36 deletions(-) diff --git a/src/search.c b/src/search.c index 54c11859..a7f19a7f 100644 --- a/src/search.c +++ b/src/search.c @@ -281,6 +281,9 @@ int findnextstr( enable_nodelay(); + if (begin == NULL) + came_full_circle = FALSE; + /* Start searching through the lines, looking for the needle. */ while (TRUE) { /* Glance at the keyboard once every second. */ @@ -323,7 +326,7 @@ int findnextstr( } /* If we're back at the beginning, then there is no needle. */ - if (came_full_circle && begin != NULL) { + if (came_full_circle) { not_found_msg(needle); disable_nodelay(); return 0; diff --git a/src/text.c b/src/text.c index 571e04b6..7240f608 100644 --- a/src/text.c +++ b/src/text.c @@ -2364,8 +2364,6 @@ bool do_int_spell_fix(const char *word) /* A storage place for the current flag settings. */ #ifndef NANO_TINY bool old_mark_set = openfile->mark_set; - bool added_magicline = FALSE; - /* Whether we added a magicline after filebot. */ bool right_side_up = FALSE; /* TRUE if (mark_begin, mark_begin_x) is the top of the mark, * FALSE if (current, current_x) is. */ @@ -2393,25 +2391,27 @@ bool do_int_spell_fix(const char *word) last_search = mallocstrcpy(NULL, word); #ifndef NANO_TINY + /* If the mark is on, start at the beginning of the marked region. */ 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 spell correction will add a magicline. */ - if (!ISSET(NO_NEWLINES)) - added_magicline = (openfile->filebot->data[0] != '\0'); - - /* Turn the mark off. */ + /* If the region is marked normally, swap the end points, so that + * (current, current_x) (where searching starts) is at the top. */ + if (right_side_up) { + openfile->current = top; + openfile->current_x = (size_t)(top_x - 1); + openfile->mark_begin = bot; + openfile->mark_begin_x = bot_x; + } openfile->mark_set = FALSE; - } + } else #endif - - /* Start from the top of the file. */ - openfile->edittop = openfile->fileage; - openfile->current = openfile->fileage; - openfile->current_x = (size_t)-1; + /* Otherwise, start from the top of the file. */ + { + openfile->edittop = openfile->fileage; + openfile->current = openfile->fileage; + openfile->current_x = (size_t)-1; + } /* Find the first whole occurrence of word. */ result = findnextstr(TRUE, NULL, 0, word, NULL); @@ -2445,43 +2445,41 @@ bool do_int_spell_fix(const char *word) /* If a replacement was given, go through all occurrences. */ if (proceed && strcmp(word, answer) != 0) { openfile->current_x--; +#ifndef NANO_TINY + /* Replacements should happen only in the marked region. */ + openfile->mark_set = old_mark_set; +#endif do_replace_loop(TRUE, current_save, ¤t_x_save, word); } } #ifndef NANO_TINY if (old_mark_set) { - /* If a magicline was added, remove it again. */ - if (added_magicline) - remove_magicline(); - - /* Put the beginning and the end of the mark at the beginning - * and the end of the spell-checked text. */ - if (openfile->fileage == openfile->filebot) - bot_x += top_x; + /* Restore the (compensated) end points of the marked region. */ if (right_side_up) { + openfile->current = openfile->mark_begin; + openfile->current_x = openfile->mark_begin_x; + openfile->mark_begin = top; openfile->mark_begin_x = top_x; - current_x_save = bot_x; } else { - current_x_save = top_x; - openfile->mark_begin_x = bot_x; + openfile->current = top; + openfile->current_x = top_x; } - - /* Unpartition the filestruct so that it contains all the text - * again, and turn the mark back on. */ - unpartition_filestruct(&filepart); openfile->mark_set = TRUE; + } else +#endif + { + /* Restore the (compensated) cursor position. */ + openfile->current = current_save; + openfile->current_x = current_x_save; } -#endif /* !NANO_TINY */ /* Restore the string that was last searched for. */ free(last_search); last_search = save_search; - /* Restore where we were. */ + /* Restore the viewport to where it was. */ openfile->edittop = edittop_save; - openfile->current = current_save; - openfile->current_x = current_x_save; /* Restore the settings of the global flags. */ memcpy(flags, stash, sizeof(flags));