From 27eb13f0fa35c88b460c350a45ad9105d3189440 Mon Sep 17 00:00:00 2001 From: Chris Allegretta Date: Sun, 5 Nov 2000 16:52:21 +0000 Subject: [PATCH] Rocco's spelling code git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@266 35c25a1d-7b9e-4130-9fde-d3aeb78583b8 --- ChangeLog | 5 + nano.c | 288 ++++++++++++++++++++++++++++++++++++++++-------- po/cat-id-tbl.c | 16 +-- po/nano.pot | 216 ++++++++++++++++++------------------ proto.h | 9 ++ search.c | 198 +++++++++++++++++++-------------- 6 files changed, 489 insertions(+), 243 deletions(-) diff --git a/ChangeLog b/ChangeLog index 35d94238..9c7e0c54 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14,6 +14,11 @@ CVS Code - pointers. New function not_found_msg in search.c for displaying truncated strings in satusbar when the string is not found. We disable this feature when using PICO_MSGS (-p). + - New spelling code by Rocco Corsi. New functions + do_int_speller, do_alt_speller, changes to do_spell in nano.c, + New functions search_init_globals and do_replace_loop, changes + to search_init(), do_replace, findnextstr, moved last_search and + last_replace back to nano.c (*shrug*). - files.c: do_writeout() - Change strcpy to answer to mallocstrcpy. diff --git a/nano.c b/nano.c index c1a55195..7137e678 100644 --- a/nano.c +++ b/nano.c @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include #include #include @@ -66,6 +68,10 @@ static char *help_text_init = ""; /* Initial message, not including shortcuts */ static struct sigaction act; /* For all out fun signal handlers */ +char *last_search = NULL; /* Last string we searched for */ +char *last_replace = NULL; /* Last replacement string */ +int search_last_line; /* Is this the last search line? */ + void keypad_on(int yesno) { keypad(edit, yesno); @@ -1045,6 +1051,8 @@ void wrap_reset(void) UNSET(SAMELINEWRAP); } +#ifndef NANO_SMALL + /* Stuff we want to do when we exit the spell program one of its many ways */ void exit_spell(char *tmpfilename, char *foo) { @@ -1054,65 +1062,259 @@ void exit_spell(char *tmpfilename, char *foo) statusbar(_("Error deleting tempfile, ack!")); display_main_list(); } +#endif -/* - * This is Chris' very ugly spell function. Someone please make this - * better =-) - */ -int do_spell(void) +#ifndef NANO_SMALL + +int do_int_spell_fix(char *word) { -#ifdef NANO_SMALL - nano_small_msg(); - return 1; -#else - char *temp, *foo; - int i, size; + char *prevanswer = NULL, *save_search = NULL, *save_replace = NULL; + filestruct *begin, *begin_top; + int i = 0, beginx, beginx_top; - if ((temp = tempnam(0, "nano.")) == NULL) { - statusbar(_("Could not create a temporary filename: %s"), - strerror(errno)); - return 0; + /* save where we are */ + begin = current; + beginx = current_x + 1; + + /* save the current search/replace strings */ + search_init_globals(); + save_search = mallocstrcpy(save_search, last_search); + save_replace = mallocstrcpy(save_replace, last_replace); + + /* set search/replace strings to mis-spelt word */ + prevanswer = mallocstrcpy(prevanswer, word); + last_search = mallocstrcpy(last_search, word); + last_replace = mallocstrcpy(last_replace, word); + + /* start from the top of file */ + begin_top = current = fileage; + beginx_top = current_x = -1; + + search_last_line = FALSE; + + /* make sure word is still mis-spelt (i.e. when multi-errors) */ + if (findnextstr(TRUE, begin_top, beginx_top, prevanswer) != NULL) + { + /* start from the start of this line again */ + current = begin_top; + current_x = beginx_top; + + search_last_line = FALSE; + + /* allow replace word to be corrected */ + i = statusq(replace_list_2, REPLACE_LIST_2_LEN, last_replace, + _("Edit a replacement")); + + do_replace_loop(prevanswer, begin_top, &beginx_top, TRUE, &i); } - if (write_file(temp, 1) == -1) - return 0; - if (alt_speller) { - size = strlen(temp) + strlen(alt_speller) + 2; - foo = nmalloc(size); - snprintf(foo, size, "%s %s", alt_speller, temp); - } else { + /* restore the search/replace strings */ + last_search = mallocstrcpy(last_search, save_search); + last_replace = mallocstrcpy(last_replace, save_replace); - /* For now, we only try ispell because we're not capable of - handling the normal spell program (yet...) */ - size = strlen(temp) + 8; - foo = nmalloc(size); - snprintf(foo, size, "ispell %s", temp); + /* restore where we were */ + current = begin; + current_x = beginx - 1; + + edit_update(current, CENTER); + + if (i == -1) + return FALSE; + + return TRUE; +} +#endif + +#ifndef NANO_SMALL + +/* Integrated spell checking using 'spell' program */ +int do_int_speller(void) +{ + + filestruct *fileptr; + char read_buff[2], *read_buff_ptr; + char curr_word[132], *curr_word_ptr; + int in_fd[2], out_fd[2]; + int spell_status; + pid_t pid_spell; + ssize_t bytesread; + + /* Input from spell pipe */ + if (pipe(in_fd) == -1) + return FALSE; + + /* Output to spell pipe */ + if (pipe(out_fd) == -1) { + + close(in_fd[0]); + close(in_fd[1]); + + return FALSE; } - endwin(); - if (alt_speller) { - if ((i = system(foo)) == -1 || i == 32512) { - statusbar(_("Could not invoke spell program \"%s\""), - alt_speller); - exit_spell(temp, foo); - return 0; + if ( (pid_spell = fork()) == 0) { + + /* Child continues, (i.e. future spell process) */ + + close(in_fd[1]); + close(out_fd[0]); + + /* setup spell standard in */ + if (dup2(in_fd[0], STDIN_FILENO) != STDIN_FILENO) + { + close(in_fd[0]); + close(out_fd[1]); + return FALSE; } - } else if ((i = system(foo)) == -1 || i == 32512) { /* Why 32512? I dont know! */ - statusbar(_("Could not invoke \"ispell\"")); - exit_spell(temp, foo); - return 0; + close(in_fd[0]); + + /* setup spell standard out */ + if (dup2(out_fd[1], STDOUT_FILENO) != STDOUT_FILENO) + { + close(out_fd[1]); + return FALSE; + } + close(out_fd[1]); + + /* Start spell program */ + execlp("spell", "spell", NULL); + + /* Should not be reached, if spell is available!!! */ + + exit(-1); } -/* initscr(); */ + + /* Parent continues here */ + + close(in_fd[0]); /* close child's input pipe */ + close(out_fd[1]); /* close child's output pipe */ + + if (pid_spell < 0) { + + /* Child process was not forked successfully */ + + close(in_fd[1]); /* close parent's output pipe */ + close(out_fd[0]); /* close parent's input pipe */ + + return FALSE; + } + + /* Send out the file content to spell program */ + + fileptr = fileage; + + while ( fileptr != NULL ) + { + write(in_fd[1], fileptr->data, strlen(fileptr->data)); + write(in_fd[1], "\n", 1); + fileptr = fileptr->next; + } + close(in_fd[1]); + + /* Let spell process the file */ + + wait(&spell_status); + if (spell_status != 0) + return FALSE; + + /* Read spelling errors from spell */ + + curr_word_ptr = curr_word; + + while ( (bytesread = read(out_fd[0], read_buff, sizeof(read_buff) - 1)) > 0) + { + read_buff[bytesread]=(char) NULL; + read_buff_ptr = read_buff; + + while (*read_buff_ptr != (char) NULL) + { + if (*read_buff_ptr == '\n') { + *curr_word_ptr = (char) NULL; + if (do_int_spell_fix(curr_word) == FALSE) + { + close(out_fd[0]); + return TRUE; + } + curr_word_ptr = curr_word; + } + else { + *curr_word_ptr = *read_buff_ptr; + curr_word_ptr++; + } + + read_buff_ptr++; + } + } + close(out_fd[0]); + replace_abort(); + + return TRUE; +} +#endif + +#ifndef NANO_SMALL + +/* External spell checking */ +int do_alt_speller(char *command_line, char *file_name) +{ + int i; + + endwin(); + + if ( (i = system(command_line) == -1) || (i == 32512)) + return FALSE; + refresh(); free_filestruct(fileage); global_init(); - open_file(temp, 0, 1); + open_file(file_name, 0, 1); edit_update(fileage, CENTER); set_modified(); - exit_spell(temp, foo); - statusbar(_("Finished checking spelling")); - return 1; + + return TRUE; +} +#endif + +int do_spell(void) +{ + +#ifdef NANO_SMALL + nano_small_msg(); + return (TRUE); +#else + char *temp, *foo; + int size, spell_res; + + if (alt_speller) { + + if ((temp = tempnam(0, "nano.")) == NULL) { + statusbar(_("Could not create a temporary filename: %s"), + strerror(errno)); + return 0; + } + + if (write_file(temp, 1) == -1) + return 0; + + size = strlen(temp) + strlen(alt_speller) + 2; + foo = nmalloc(size); + snprintf(foo, size, "%s %s", alt_speller, temp); + + spell_res = do_alt_speller(foo, temp); + + exit_spell(temp, foo); + + } else + spell_res = do_int_speller(); + + if (spell_res) + statusbar(_("Finished checking spelling")); + else + statusbar(_("Spell checking failed")); + + return spell_res; + #endif } diff --git a/po/cat-id-tbl.c b/po/cat-id-tbl.c index 2500810a..2a1e64ec 100644 --- a/po/cat-id-tbl.c +++ b/po/cat-id-tbl.c @@ -175,10 +175,10 @@ Usage: nano [option] +LINE \n\ {"current->data now = \"%s\"\n", 142}, {"After, data = \"%s\"\n", 143}, {"Error deleting tempfile, ack!", 144}, - {"Could not create a temporary filename: %s", 145}, - {"Could not invoke spell program \"%s\"", 146}, - {"Could not invoke \"ispell\"", 147}, - {"Finished checking spelling", 148}, + {"Edit a replacement", 145}, + {"Could not create a temporary filename: %s", 146}, + {"Finished checking spelling", 147}, + {"Spell checking failed", 148}, {"Save modified buffer (ANSWERING \"No\" WILL DESTROY CHANGES) ? ", 149}, {"Cannot resize top win", 150}, {"Cannot move top win", 151}, @@ -209,10 +209,10 @@ Usage: nano [option] +LINE \n\ {"Replaced %d occurences", 176}, {"Replaced 1 occurence", 177}, {"Replace Cancelled", 178}, - {"Replace with [%s]", 179}, - {"Replace with", 180}, - {"Replace this instance?", 181}, - {"Replace failed: unknown subexpression!", 182}, + {"Replace this instance?", 179}, + {"Replace failed: unknown subexpression!", 180}, + {"Replace with [%s]", 181}, + {"Replace with", 182}, {"Enter line number", 183}, {"Aborted", 184}, {"Come on, be reasonable", 185}, diff --git a/po/nano.pot b/po/nano.pot index cd708201..914d7545 100644 --- a/po/nano.pot +++ b/po/nano.pot @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" -"POT-Creation-Date: 2000-11-03 09:21-0500\n" +"POT-Creation-Date: 2000-11-05 11:52-0500\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -32,7 +32,7 @@ msgstr "" msgid "Read %d lines" msgstr "" -#: files.c:217 search.c:163 +#: files.c:217 search.c:164 #, c-format msgid "\"%s\" not found" msgstr "" @@ -55,7 +55,7 @@ msgstr "" msgid "File to insert [from ./] " msgstr "" -#: files.c:274 files.c:298 files.c:486 nano.c:1145 +#: files.c:274 files.c:298 files.c:486 nano.c:1347 msgid "Cancelled" msgstr "" @@ -388,17 +388,17 @@ msgstr "" msgid "No Replace" msgstr "" -#: nano.c:125 +#: nano.c:131 msgid "" "\n" "Buffer written to 'nano.save'\n" msgstr "" -#: nano.c:132 +#: nano.c:138 msgid "Key illegal in VIEW mode" msgstr "" -#: nano.c:169 +#: nano.c:175 msgid "" " nano help text\n" "\n" @@ -419,397 +419,395 @@ msgid "" "\n" msgstr "" -#: nano.c:272 +#: nano.c:278 msgid "free_node(): free'd a node, YAY!\n" msgstr "" -#: nano.c:277 +#: nano.c:283 msgid "free_node(): free'd last node.\n" msgstr "" -#: nano.c:329 +#: nano.c:335 msgid "" "Usage: nano [GNU long option] [option] +LINE \n" "\n" msgstr "" -#: nano.c:330 +#: nano.c:336 msgid "Option\t\tLong option\t\tMeaning\n" msgstr "" -#: nano.c:332 +#: nano.c:338 msgid " -T \t\t--tabsize=[num]\t\tSet width of a tab to num\n" msgstr "" -#: nano.c:335 +#: nano.c:341 msgid " -R\t\t--regexp\t\tUse regular expressions for search\n" msgstr "" -#: nano.c:339 +#: nano.c:345 msgid " -V \t\t--version\t\tPrint version information and exit\n" msgstr "" -#: nano.c:341 +#: nano.c:347 msgid " -c \t\t--const\t\t\tConstantly show cursor position\n" msgstr "" -#: nano.c:343 +#: nano.c:349 msgid " -h \t\t--help\t\t\tShow this message\n" msgstr "" -#: nano.c:346 +#: nano.c:352 msgid " -k \t\t--cut\t\t\tLet ^K cut from cursor to end of line\n" msgstr "" -#: nano.c:349 +#: nano.c:355 msgid " -i \t\t--autoindent\t\tAutomatically indent new lines\n" msgstr "" -#: nano.c:351 +#: nano.c:357 msgid " -l \t\t--nofollow\t\tDon't follow symbolic links, overwrite\n" msgstr "" -#: nano.c:354 +#: nano.c:360 msgid " -m \t\t--mouse\t\t\tEnable mouse\n" msgstr "" -#: nano.c:359 +#: nano.c:365 msgid "" " -r [#cols] \t--fill=[#cols]\t\tSet fill cols to (wrap lines at) #cols\n" msgstr "" -#: nano.c:361 +#: nano.c:367 msgid " -p\t \t--pico\t\t\tMake bottom 2 lines more Pico-like\n" msgstr "" -#: nano.c:363 +#: nano.c:369 msgid " -s [prog] \t--speller=[prog]\tEnable alternate speller\n" msgstr "" -#: nano.c:365 +#: nano.c:371 msgid " -t \t\t--tempfile\t\tAuto save on exit, don't prompt\n" msgstr "" -#: nano.c:367 +#: nano.c:373 msgid " -v \t\t--view\t\t\tView (read only) mode\n" msgstr "" -#: nano.c:369 +#: nano.c:375 msgid " -w \t\t--nowrap\t\tDon't wrap long lines\n" msgstr "" -#: nano.c:371 +#: nano.c:377 msgid " -x \t\t--nohelp\t\tDon't show help window\n" msgstr "" -#: nano.c:373 +#: nano.c:379 msgid " -z \t\t--suspend\t\tEnable suspend\n" msgstr "" -#: nano.c:375 +#: nano.c:381 msgid " +LINE\t\t\t\t\tStart at line number LINE\n" msgstr "" -#: nano.c:377 +#: nano.c:383 msgid "" "Usage: nano [option] +LINE \n" "\n" msgstr "" -#: nano.c:378 +#: nano.c:384 msgid "Option\t\tMeaning\n" msgstr "" -#: nano.c:379 +#: nano.c:385 msgid " -T [num]\tSet width of a tab to num\n" msgstr "" -#: nano.c:380 +#: nano.c:386 msgid " -R\t\tUse regular expressions for search\n" msgstr "" -#: nano.c:381 +#: nano.c:387 msgid " -V \t\tPrint version information and exit\n" msgstr "" -#: nano.c:382 +#: nano.c:388 msgid " -c \t\tConstantly show cursor position\n" msgstr "" -#: nano.c:383 +#: nano.c:389 msgid " -h \t\tShow this message\n" msgstr "" -#: nano.c:385 +#: nano.c:391 msgid " -k \t\tLet ^K cut from cursor to end of line\n" msgstr "" -#: nano.c:387 +#: nano.c:393 msgid " -i \t\tAutomatically indent new lines\n" msgstr "" -#: nano.c:389 +#: nano.c:395 msgid " -l \t\tDon't follow symbolic links, overwrite\n" msgstr "" -#: nano.c:392 +#: nano.c:398 msgid " -m \t\tEnable mouse\n" msgstr "" -#: nano.c:396 +#: nano.c:402 msgid " -r [#cols] \tSet fill cols to (wrap lines at) #cols\n" msgstr "" -#: nano.c:397 +#: nano.c:403 msgid " -s [prog] \tEnable alternate speller\n" msgstr "" -#: nano.c:398 +#: nano.c:404 msgid " -p \t\tMake bottom 2 lines more Pico-like\n" msgstr "" -#: nano.c:399 +#: nano.c:405 msgid " -t \t\tAuto save on exit, don't prompt\n" msgstr "" -#: nano.c:400 +#: nano.c:406 msgid " -v \t\tView (read only) mode\n" msgstr "" -#: nano.c:401 +#: nano.c:407 msgid " -w \t\tDon't wrap long lines\n" msgstr "" -#: nano.c:402 +#: nano.c:408 msgid " -x \t\tDon't show help window\n" msgstr "" -#: nano.c:403 +#: nano.c:409 msgid " -z \t\tEnable suspend\n" msgstr "" -#: nano.c:404 +#: nano.c:410 msgid " +LINE\t\tStart at line number LINE\n" msgstr "" -#: nano.c:411 +#: nano.c:417 #, c-format msgid " nano version %s by Chris Allegretta (compiled %s, %s)\n" msgstr "" -#: nano.c:414 +#: nano.c:420 msgid " Email: nano@nano-editor.org\tWeb: http://www.nano-editor.org\n" msgstr "" -#: nano.c:449 +#: nano.c:455 msgid "Mark Set" msgstr "" -#: nano.c:454 +#: nano.c:460 msgid "Mark UNset" msgstr "" -#: nano.c:881 +#: nano.c:887 #, c-format msgid "check_wrap called with inptr->data=\"%s\"\n" msgstr "" -#: nano.c:932 +#: nano.c:938 #, c-format msgid "current->data now = \"%s\"\n" msgstr "" -#: nano.c:985 +#: nano.c:991 #, c-format msgid "After, data = \"%s\"\n" msgstr "" -#: nano.c:1054 +#: nano.c:1062 msgid "Error deleting tempfile, ack!" msgstr "" -#: nano.c:1072 -#, c-format -msgid "Could not create a temporary filename: %s" +#: nano.c:1106 +msgid "Edit a replacement" msgstr "" -#: nano.c:1095 +#: nano.c:1292 #, c-format -msgid "Could not invoke spell program \"%s\"" +msgid "Could not create a temporary filename: %s" msgstr "" -#. Why 32512? I dont know! -#: nano.c:1101 -msgid "Could not invoke \"ispell\"" +#: nano.c:1312 +msgid "Finished checking spelling" msgstr "" -#: nano.c:1114 -msgid "Finished checking spelling" +#: nano.c:1314 +msgid "Spell checking failed" msgstr "" -#: nano.c:1132 +#: nano.c:1334 msgid "Save modified buffer (ANSWERING \"No\" WILL DESTROY CHANGES) ? " msgstr "" -#: nano.c:1295 +#: nano.c:1497 msgid "Cannot resize top win" msgstr "" -#: nano.c:1297 +#: nano.c:1499 msgid "Cannot move top win" msgstr "" -#: nano.c:1299 +#: nano.c:1501 msgid "Cannot resize edit win" msgstr "" -#: nano.c:1301 +#: nano.c:1503 msgid "Cannot move edit win" msgstr "" -#: nano.c:1303 +#: nano.c:1505 msgid "Cannot resize bottom win" msgstr "" -#: nano.c:1305 +#: nano.c:1507 msgid "Cannot move bottom win" msgstr "" -#: nano.c:1576 +#: nano.c:1778 msgid "Justify Complete" msgstr "" -#: nano.c:1644 +#: nano.c:1846 #, c-format msgid "%s enable/disable" msgstr "" -#: nano.c:1656 +#: nano.c:1858 msgid "enabled" msgstr "" -#: nano.c:1657 +#: nano.c:1859 msgid "disabled" msgstr "" -#: nano.c:1887 +#: nano.c:2089 msgid "Main: set up windows\n" msgstr "" -#: nano.c:1900 +#: nano.c:2102 msgid "Main: bottom win\n" msgstr "" -#: nano.c:1906 +#: nano.c:2108 msgid "Main: open file\n" msgstr "" -#: nano.c:1940 +#: nano.c:2142 #, c-format msgid "I got Alt-O-%c! (%d)\n" msgstr "" -#: nano.c:1962 +#: nano.c:2164 #, c-format msgid "I got Alt-[-1-%c! (%d)\n" msgstr "" -#: nano.c:1995 +#: nano.c:2197 #, c-format msgid "I got Alt-[-2-%c! (%d)\n" msgstr "" -#: nano.c:2043 +#: nano.c:2245 #, c-format msgid "I got Alt-[-%c! (%d)\n" msgstr "" -#: nano.c:2069 +#: nano.c:2271 #, c-format msgid "I got Alt-%c! (%d)\n" msgstr "" -#: search.c:98 +#: search.c:99 #, c-format msgid "Case Sensitive Regexp Search%s%s" msgstr "" -#: search.c:100 +#: search.c:101 #, c-format msgid "Regexp Search%s%s" msgstr "" -#: search.c:102 +#: search.c:103 #, c-format msgid "Case Sensitive Search%s%s" msgstr "" -#: search.c:104 +#: search.c:105 #, c-format msgid "Search%s%s" msgstr "" -#: search.c:107 +#: search.c:108 msgid " (to replace)" msgstr "" -#: search.c:120 search.c:289 +#: search.c:121 search.c:290 msgid "Search Cancelled" msgstr "" -#: search.c:167 +#: search.c:168 #, c-format msgid "\"%s...\" not found" msgstr "" -#: search.c:214 +#: search.c:215 msgid "Search Wrapped" msgstr "" -#: search.c:303 +#: search.c:304 #, c-format msgid "Replaced %d occurences" msgstr "" -#: search.c:305 +#: search.c:306 msgid "Replaced 1 occurence" msgstr "" -#: search.c:441 search.c:457 search.c:488 +#: search.c:443 search.c:536 search.c:552 msgid "Replace Cancelled" msgstr "" -#: search.c:474 -#, c-format -msgid "Replace with [%s]" +#: search.c:486 +msgid "Replace this instance?" msgstr "" -#: search.c:478 search.c:482 -msgid "Replace with" +#: search.c:494 +msgid "Replace failed: unknown subexpression!" msgstr "" -#: search.c:519 -msgid "Replace this instance?" +#: search.c:569 +#, c-format +msgid "Replace with [%s]" msgstr "" -#: search.c:527 -msgid "Replace failed: unknown subexpression!" +#: search.c:573 search.c:577 +msgid "Replace with" msgstr "" #. Ask for it -#: search.c:580 +#: search.c:612 msgid "Enter line number" msgstr "" -#: search.c:582 +#: search.c:614 msgid "Aborted" msgstr "" -#: search.c:602 +#: search.c:634 msgid "Come on, be reasonable" msgstr "" -#: search.c:607 +#: search.c:639 #, c-format msgid "Only %d lines available, skipping to last line" msgstr "" diff --git a/proto.h b/proto.h index 6fe76aa3..be689f0e 100644 --- a/proto.h +++ b/proto.h @@ -35,11 +35,14 @@ extern int placewewant; extern int mark_beginx, samelinewrap; extern int totsize, temp_opt; extern int fill, flags,tabsize; +extern int search_last_line; extern WINDOW *edit, *topwin, *bottomwin; extern char filename[PATH_MAX]; extern char *answer; extern char *hblank, *help_text; +extern char *last_search; +extern char *last_replace; extern struct stat fileinfo; extern filestruct *current, *fileage, *edittop, *editbot, *filebot; extern filestruct *cutbuffer, *mark_beginbuf; @@ -77,6 +80,8 @@ int renumber_all(void); int open_file(char *filename, int insert, int quiet); int do_writeout(int exiting); int do_gotoline(long defline); +int do_replace_loop(char *prevanswer, filestruct *begin, int *beginx, + int wholewords, int *i); /* Now in move.c */ int do_up(void); int do_down(void); @@ -120,6 +125,8 @@ void new_magicline(void); void splice_node(filestruct *begin, filestruct *new, filestruct *end); void null_at(char *data, int index); void page_up_center(void); +void search_init_globals(void); +void replace_abort(void); int do_writeout_void(void), do_exit(void), do_gotoline_void(void); int do_insertfile(void), do_search(void), page_up(void), page_down(void); @@ -133,3 +140,5 @@ int do_replace(void), do_help(void), do_enter_void(void); filestruct *copy_node(filestruct * src); filestruct *copy_filestruct(filestruct * src); filestruct *make_new_node(filestruct * prevnode); +filestruct *findnextstr(int quiet, filestruct * begin, + int beginx, char *needle); diff --git a/search.c b/search.c index 501900f2..9f1ddb02 100644 --- a/search.c +++ b/search.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "config.h" #include "proto.h" #include "nano.h" @@ -34,11 +35,6 @@ #define _(string) (string) #endif -static char *last_search = NULL; /* Last string we searched for */ -static char *last_replace = NULL; /* Last replacement string */ -static int search_last_line; - - /* Regular expression helper functions */ #ifdef HAVE_REGEX_H @@ -55,6 +51,18 @@ void regexp_cleanup() } #endif +void search_init_globals(void) +{ + if (last_search == NULL) { + last_search = nmalloc(1); + last_search[0] = 0; + } + if (last_replace == NULL) { + last_replace = nmalloc(1); + last_replace[0] = 0; + } +} + /* Set up the system variables for a search or replace. Returns -1 on abort, 0 on success, and 1 on rerun calling program Return -2 to run opposite program (searchg -> replace, replace -> search) @@ -67,20 +75,13 @@ int search_init(int replacing) char *buf; char *prompt, *reprompt = ""; - if (last_search == NULL) { - last_search = nmalloc(1); - last_search[0] = 0; - } - if (last_replace == NULL) { - last_replace = nmalloc(1); - last_replace[0] = 0; - } + search_init_globals(); - buf = nmalloc(strlen(last_search) + 5); - buf[0] = 0; + buf = nmalloc(strlen(last_search) + 5); + buf[0] = 0; - /* If using Pico messages, we do things the old fashioned way... */ - if (ISSET(PICO_MSGS)) { + /* If using Pico messages, we do things the old fashioned way... */ + if (ISSET(PICO_MSGS)) { if (last_search[0]) { /* We use COLS / 3 here because we need to see more on the line */ @@ -428,60 +429,14 @@ char *replace_line(void) return copy; } -/* Replace a string */ -int do_replace(void) +int do_replace_loop(char *prevanswer, filestruct *begin, int *beginx, + int wholewords, int *i) { - int i, replaceall = 0, numreplaced = 0, beginx; - filestruct *fileptr, *begin; - char *copy, *prevanswer = NULL, *buf = NULL; - - i = search_init(1); - switch (i) { - case -1: - statusbar(_("Replace Cancelled")); - replace_abort(); - return 0; - case 1: - do_replace(); - return 1; - case -2: - do_search(); - return 0; - case -3: - replace_abort(); - return 0; - } - - /* Again, there was a previous string but they deleted it and hit enter */ - if (!strcmp(answer, "")) { - statusbar(_("Replace Cancelled")); - replace_abort(); - return 0; - } - - prevanswer = mallocstrcpy(prevanswer, answer); - - if (ISSET(PICO_MSGS)) { - buf = nmalloc(strlen(last_replace) + 5); - if (strcmp(last_replace, "")) { - if (strlen(last_replace) > (COLS / 3)) { - strncpy(buf, last_replace, COLS / 3); - sprintf(&buf[COLS / 3 - 1], "..."); - } else - sprintf(buf, "%s", last_replace); - - i = statusq(replace_list_2, REPLACE_LIST_2_LEN, "", - _("Replace with [%s]"), buf); - } - else - i = statusq(replace_list_2, REPLACE_LIST_2_LEN, "", - _("Replace with")); - } - else - i = statusq(replace_list_2, REPLACE_LIST_2_LEN, last_replace, - _("Replace with")); + int replaceall = 0, numreplaced = 0; + filestruct *fileptr; + char *copy; - switch (i) { + switch (*i) { case -1: /* Aborted enter */ if (strcmp(last_replace, "")) answer = mallocstrcpy(answer, last_replace); @@ -492,7 +447,7 @@ int do_replace(void) last_replace = mallocstrcpy(last_replace, answer); break; default: - if (i != -2) { /* First page, last page, for example + if (*i != -2) { /* First page, last page, for example could get here */ do_early_abort(); replace_abort(); @@ -500,26 +455,38 @@ int do_replace(void) } } - /* save where we are */ - begin = current; - beginx = current_x + 1; - search_last_line = 0; - while (1) { /* Sweet optimization by Rocco here */ - fileptr = findnextstr(replaceall, begin, beginx, prevanswer); + fileptr = findnextstr(replaceall, begin, *beginx, prevanswer); /* No more matches. Done! */ if (!fileptr) break; + /* Make sure only wholewords are found */ + if (wholewords) + { + /* start of line or previous character not a letter */ + if ((current_x == 0) || (!isalpha(fileptr->data[current_x-1]))) + { + /* end of line or next character not a letter */ + if (((current_x + strlen(prevanswer)) == strlen(fileptr->data)) + || (!isalpha(fileptr->data[current_x + strlen(prevanswer)]))) + ; + else + continue; + } + else + continue; + } + /* If we're here, we've found the search string */ if (!replaceall) - i = do_yesno(1, 1, _("Replace this instance?")); + *i = do_yesno(1, 1, _("Replace this instance?")); - if (i > 0 || replaceall) { /* Yes, replace it!!!! */ - if (i == 2) + if (*i > 0 || replaceall) { /* Yes, replace it!!!! */ + if (*i == 2) replaceall = 1; copy = replace_line(); @@ -538,21 +505,86 @@ int do_replace(void) /* Adjust the original cursor position - COULD BE IMPROVED */ if (search_last_line) { - beginx += strlen(last_replace) - strlen(last_search); + *beginx += strlen(last_replace) - strlen(last_search); /* For strings that cross the search start/end boundary */ /* Don't go outside of allocated memory */ - if (beginx < 1) - beginx = 1; + if (*beginx < 1) + *beginx = 1; } edit_refresh(); set_modified(); numreplaced++; - } else if (i == -1) /* Abort, else do nothing and continue loop */ + } else if (*i == -1) /* Abort, else do nothing and continue loop */ break; } + return numreplaced; +} + +/* Replace a string */ +int do_replace(void) +{ + int i, numreplaced, beginx; + filestruct *begin; + char *prevanswer = NULL, *buf = NULL; + + i = search_init(1); + switch (i) { + case -1: + statusbar(_("Replace Cancelled")); + replace_abort(); + return 0; + case 1: + do_replace(); + return 1; + case -2: + do_search(); + return 0; + case -3: + replace_abort(); + return 0; + } + + /* Again, there was a previous string but they deleted it and hit enter */ + if (!strcmp(answer, "")) { + statusbar(_("Replace Cancelled")); + replace_abort(); + return 0; + } + + prevanswer = mallocstrcpy(prevanswer, answer); + + if (ISSET(PICO_MSGS)) { + buf = nmalloc(strlen(last_replace) + 5); + if (strcmp(last_replace, "")) { + if (strlen(last_replace) > (COLS / 3)) { + strncpy(buf, last_replace, COLS / 3); + sprintf(&buf[COLS / 3 - 1], "..."); + } else + sprintf(buf, "%s", last_replace); + + i = statusq(replace_list_2, REPLACE_LIST_2_LEN, "", + _("Replace with [%s]"), buf); + } + else + i = statusq(replace_list_2, REPLACE_LIST_2_LEN, "", + _("Replace with")); + } + else + i = statusq(replace_list_2, REPLACE_LIST_2_LEN, last_replace, + _("Replace with")); + + /* save where we are */ + begin = current; + beginx = current_x + 1; + + search_last_line = 0; + + numreplaced = do_replace_loop(prevanswer, begin, &beginx, FALSE, &i); + + /* restore where we were */ current = begin; current_x = beginx - 1; renumber_all(); -- 2.39.5