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.
Этот коммит содержится в:
родитель
9d6d5b679a
Коммит
433c7e5dc6
@ -281,6 +281,9 @@ int findnextstr(
|
|||||||
|
|
||||||
enable_nodelay();
|
enable_nodelay();
|
||||||
|
|
||||||
|
if (begin == NULL)
|
||||||
|
came_full_circle = FALSE;
|
||||||
|
|
||||||
/* Start searching through the lines, looking for the needle. */
|
/* Start searching through the lines, looking for the needle. */
|
||||||
while (TRUE) {
|
while (TRUE) {
|
||||||
/* Glance at the keyboard once every second. */
|
/* 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 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);
|
not_found_msg(needle);
|
||||||
disable_nodelay();
|
disable_nodelay();
|
||||||
return 0;
|
return 0;
|
||||||
|
68
src/text.c
68
src/text.c
@ -2364,8 +2364,6 @@ bool do_int_spell_fix(const char *word)
|
|||||||
/* A storage place for the current flag settings. */
|
/* A storage place for the current flag settings. */
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
bool old_mark_set = openfile->mark_set;
|
bool old_mark_set = openfile->mark_set;
|
||||||
bool added_magicline = FALSE;
|
|
||||||
/* Whether we added a magicline after filebot. */
|
|
||||||
bool right_side_up = FALSE;
|
bool right_side_up = FALSE;
|
||||||
/* TRUE if (mark_begin, mark_begin_x) is the top of the mark,
|
/* TRUE if (mark_begin, mark_begin_x) is the top of the mark,
|
||||||
* FALSE if (current, current_x) is. */
|
* FALSE if (current, current_x) is. */
|
||||||
@ -2393,25 +2391,27 @@ bool do_int_spell_fix(const char *word)
|
|||||||
last_search = mallocstrcpy(NULL, word);
|
last_search = mallocstrcpy(NULL, word);
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
|
/* If the mark is on, start at the beginning of the marked region. */
|
||||||
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);
|
/* If the region is marked normally, swap the end points, so that
|
||||||
|
* (current, current_x) (where searching starts) is at the top. */
|
||||||
/* Foresay whether spell correction will add a magicline. */
|
if (right_side_up) {
|
||||||
if (!ISSET(NO_NEWLINES))
|
openfile->current = top;
|
||||||
added_magicline = (openfile->filebot->data[0] != '\0');
|
openfile->current_x = (size_t)(top_x - 1);
|
||||||
|
openfile->mark_begin = bot;
|
||||||
/* Turn the mark off. */
|
openfile->mark_begin_x = bot_x;
|
||||||
|
}
|
||||||
openfile->mark_set = FALSE;
|
openfile->mark_set = FALSE;
|
||||||
}
|
} else
|
||||||
#endif
|
#endif
|
||||||
|
/* Otherwise, start from the top of the file. */
|
||||||
/* Start from the top of the file. */
|
{
|
||||||
openfile->edittop = openfile->fileage;
|
openfile->edittop = openfile->fileage;
|
||||||
openfile->current = openfile->fileage;
|
openfile->current = openfile->fileage;
|
||||||
openfile->current_x = (size_t)-1;
|
openfile->current_x = (size_t)-1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Find the first whole occurrence of word. */
|
/* Find the first whole occurrence of word. */
|
||||||
result = findnextstr(TRUE, NULL, 0, word, NULL);
|
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 a replacement was given, go through all occurrences. */
|
||||||
if (proceed && strcmp(word, answer) != 0) {
|
if (proceed && strcmp(word, answer) != 0) {
|
||||||
openfile->current_x--;
|
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);
|
do_replace_loop(TRUE, current_save, ¤t_x_save, word);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
if (old_mark_set) {
|
if (old_mark_set) {
|
||||||
/* If a magicline was added, remove it again. */
|
/* Restore the (compensated) end points of the marked region. */
|
||||||
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;
|
|
||||||
if (right_side_up) {
|
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;
|
openfile->mark_begin_x = top_x;
|
||||||
current_x_save = bot_x;
|
|
||||||
} else {
|
} else {
|
||||||
current_x_save = top_x;
|
openfile->current = top;
|
||||||
openfile->mark_begin_x = bot_x;
|
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;
|
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. */
|
/* Restore the string that was last searched for. */
|
||||||
free(last_search);
|
free(last_search);
|
||||||
last_search = save_search;
|
last_search = save_search;
|
||||||
|
|
||||||
/* Restore where we were. */
|
/* Restore the viewport to where it was. */
|
||||||
openfile->edittop = edittop_save;
|
openfile->edittop = edittop_save;
|
||||||
openfile->current = current_save;
|
|
||||||
openfile->current_x = current_x_save;
|
|
||||||
|
|
||||||
/* Restore the settings of the global flags. */
|
/* Restore the settings of the global flags. */
|
||||||
memcpy(flags, stash, sizeof(flags));
|
memcpy(flags, stash, sizeof(flags));
|
||||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user