Chris Allegretta | 11b0011 | 2000-08-06 21:13:45 +0000 | [diff] [blame] | 1 | /* $Id$ */ |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 2 | /************************************************************************** |
| 3 | * search.c * |
| 4 | * * |
David Lawrence Ramsey | f28f50e | 2004-01-09 23:04:55 +0000 | [diff] [blame] | 5 | * Copyright (C) 2000-2004 Chris Allegretta * |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 6 | * This program is free software; you can redistribute it and/or modify * |
| 7 | * it under the terms of the GNU General Public License as published by * |
Chris Allegretta | 3a24f3f | 2001-10-24 11:33:54 +0000 | [diff] [blame] | 8 | * the Free Software Foundation; either version 2, or (at your option) * |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 9 | * any later version. * |
| 10 | * * |
| 11 | * This program is distributed in the hope that it will be useful, * |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
| 14 | * GNU General Public License for more details. * |
| 15 | * * |
| 16 | * You should have received a copy of the GNU General Public License * |
| 17 | * along with this program; if not, write to the Free Software * |
| 18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * |
| 19 | * * |
| 20 | **************************************************************************/ |
| 21 | |
Jordi Mallach | 55381aa | 2004-11-17 23:17:05 +0000 | [diff] [blame] | 22 | #ifdef HAVE_CONFIG_H |
| 23 | #include <config.h> |
| 24 | #endif |
Chris Allegretta | 6efda54 | 2001-04-28 18:03:52 +0000 | [diff] [blame] | 25 | |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 26 | #include <stdlib.h> |
| 27 | #include <string.h> |
| 28 | #include <stdio.h> |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 29 | #include <unistd.h> |
Chris Allegretta | 27eb13f | 2000-11-05 16:52:21 +0000 | [diff] [blame] | 30 | #include <ctype.h> |
Chris Allegretta | 5beed50 | 2003-01-05 20:41:21 +0000 | [diff] [blame] | 31 | #include <errno.h> |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 32 | #include <assert.h> |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 33 | #include "proto.h" |
| 34 | #include "nano.h" |
Chris Allegretta | 4da1fc6 | 2000-06-21 03:00:43 +0000 | [diff] [blame] | 35 | |
David Lawrence Ramsey | e5e88fd | 2004-10-31 13:20:30 +0000 | [diff] [blame] | 36 | static bool search_last_line = FALSE; |
| 37 | /* Have we gone past the last line while searching? */ |
Chris Allegretta | 805c26d | 2000-09-06 13:39:17 +0000 | [diff] [blame] | 38 | #ifdef HAVE_REGEX_H |
David Lawrence Ramsey | 27fbc69 | 2004-10-19 21:09:37 +0000 | [diff] [blame] | 39 | static bool regexp_compiled = FALSE; |
| 40 | /* Have we compiled any regular expressions? */ |
David Lawrence Ramsey | 4b741b9 | 2004-04-30 19:40:03 +0000 | [diff] [blame] | 41 | |
| 42 | /* Regular expression helper functions. */ |
| 43 | |
| 44 | /* Compile the given regular expression. Return value 0 means the |
| 45 | * expression was invalid, and we wrote an error message on the status |
| 46 | * bar. Return value 1 means success. */ |
Chris Allegretta | 5d71514 | 2003-01-29 04:18:37 +0000 | [diff] [blame] | 47 | int regexp_init(const char *regexp) |
Chris Allegretta | 9fc8d43 | 2000-07-07 01:49:52 +0000 | [diff] [blame] | 48 | { |
David Lawrence Ramsey | 49d5c1b | 2004-10-11 13:55:33 +0000 | [diff] [blame] | 49 | int rc = regcomp(&search_regexp, regexp, REG_EXTENDED |
| 50 | #ifndef NANO_SMALL |
| 51 | | (ISSET(CASE_SENSITIVE) ? 0 : REG_ICASE) |
| 52 | #endif |
| 53 | ); |
Chris Allegretta | 5d71514 | 2003-01-29 04:18:37 +0000 | [diff] [blame] | 54 | |
David Lawrence Ramsey | 4b741b9 | 2004-04-30 19:40:03 +0000 | [diff] [blame] | 55 | assert(!regexp_compiled); |
| 56 | if (rc != 0) { |
| 57 | size_t len = regerror(rc, &search_regexp, NULL, 0); |
| 58 | char *str = charalloc(len); |
| 59 | |
| 60 | regerror(rc, &search_regexp, str, len); |
| 61 | statusbar(_("Bad regex \"%s\": %s"), regexp, str); |
| 62 | free(str); |
| 63 | return 0; |
| 64 | } |
| 65 | |
| 66 | regexp_compiled = TRUE; |
Chris Allegretta | 5d71514 | 2003-01-29 04:18:37 +0000 | [diff] [blame] | 67 | return 1; |
Chris Allegretta | 9fc8d43 | 2000-07-07 01:49:52 +0000 | [diff] [blame] | 68 | } |
| 69 | |
Chris Allegretta | e316773 | 2001-03-18 16:59:34 +0000 | [diff] [blame] | 70 | void regexp_cleanup(void) |
Chris Allegretta | 9fc8d43 | 2000-07-07 01:49:52 +0000 | [diff] [blame] | 71 | { |
David Lawrence Ramsey | 4b741b9 | 2004-04-30 19:40:03 +0000 | [diff] [blame] | 72 | if (regexp_compiled) { |
| 73 | regexp_compiled = FALSE; |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 74 | regfree(&search_regexp); |
| 75 | } |
Chris Allegretta | 9fc8d43 | 2000-07-07 01:49:52 +0000 | [diff] [blame] | 76 | } |
Chris Allegretta | 4780561 | 2000-07-07 02:35:34 +0000 | [diff] [blame] | 77 | #endif |
Chris Allegretta | 9fc8d43 | 2000-07-07 01:49:52 +0000 | [diff] [blame] | 78 | |
David Lawrence Ramsey | ad40fdb | 2002-09-06 20:35:28 +0000 | [diff] [blame] | 79 | void not_found_msg(const char *str) |
| 80 | { |
David Lawrence Ramsey | 483ea32 | 2004-05-29 16:25:30 +0000 | [diff] [blame] | 81 | char *disp; |
| 82 | int numchars; |
| 83 | |
David Lawrence Ramsey | a3370c4 | 2004-04-05 01:08:14 +0000 | [diff] [blame] | 84 | assert(str != NULL); |
David Lawrence Ramsey | 483ea32 | 2004-05-29 16:25:30 +0000 | [diff] [blame] | 85 | |
| 86 | disp = display_string(str, 0, (COLS / 2) + 1); |
| 87 | numchars = strnlen(disp, COLS / 2); |
| 88 | |
| 89 | statusbar(_("\"%.*s%s\" not found"), numchars, disp, |
| 90 | disp[numchars] == '\0' ? "" : "..."); |
| 91 | |
| 92 | free(disp); |
David Lawrence Ramsey | ad40fdb | 2002-09-06 20:35:28 +0000 | [diff] [blame] | 93 | } |
| 94 | |
| 95 | void search_abort(void) |
| 96 | { |
David Lawrence Ramsey | ad40fdb | 2002-09-06 20:35:28 +0000 | [diff] [blame] | 97 | display_main_list(); |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 98 | #ifndef NANO_SMALL |
David Lawrence Ramsey | ad40fdb | 2002-09-06 20:35:28 +0000 | [diff] [blame] | 99 | if (ISSET(MARK_ISSET)) |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 100 | edit_refresh(); |
| 101 | #endif |
David Lawrence Ramsey | ad40fdb | 2002-09-06 20:35:28 +0000 | [diff] [blame] | 102 | #ifdef HAVE_REGEX_H |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 103 | regexp_cleanup(); |
David Lawrence Ramsey | ad40fdb | 2002-09-06 20:35:28 +0000 | [diff] [blame] | 104 | #endif |
| 105 | } |
| 106 | |
Chris Allegretta | 27eb13f | 2000-11-05 16:52:21 +0000 | [diff] [blame] | 107 | void search_init_globals(void) |
| 108 | { |
David Lawrence Ramsey | 6be5339 | 2004-10-16 15:41:57 +0000 | [diff] [blame] | 109 | if (last_search == NULL) |
| 110 | last_search = mallocstrcpy(NULL, ""); |
| 111 | if (last_replace == NULL) |
| 112 | last_replace = mallocstrcpy(NULL, ""); |
Chris Allegretta | 27eb13f | 2000-11-05 16:52:21 +0000 | [diff] [blame] | 113 | } |
| 114 | |
David Lawrence Ramsey | d532f19 | 2004-10-04 22:37:56 +0000 | [diff] [blame] | 115 | /* Set up the system variables for a search or replace. If use_answer |
| 116 | * is TRUE, only set backupstring to answer. Return -2 to run opposite |
| 117 | * program (search -> replace, replace -> search), return -1 if the |
| 118 | * search should be canceled (due to Cancel, Go to Line, or a failed |
| 119 | * regcomp()), return 0 on success, and return 1 on rerun calling |
| 120 | * program. |
Chris Allegretta | 7662c86 | 2003-01-13 01:35:15 +0000 | [diff] [blame] | 121 | * |
David Lawrence Ramsey | d532f19 | 2004-10-04 22:37:56 +0000 | [diff] [blame] | 122 | * replacing is TRUE if we call from do_replace(), and FALSE if called |
| 123 | * from do_search(). */ |
| 124 | int search_init(bool replacing, bool use_answer) |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 125 | { |
Chris Allegretta | f372bd9 | 2001-07-15 22:24:24 +0000 | [diff] [blame] | 126 | int i = 0; |
Chris Allegretta | 71844ba | 2000-11-03 14:23:00 +0000 | [diff] [blame] | 127 | char *buf; |
Chris Allegretta | 5bf51d3 | 2000-11-16 06:01:10 +0000 | [diff] [blame] | 128 | static char *backupstring = NULL; |
David Lawrence Ramsey | d532f19 | 2004-10-04 22:37:56 +0000 | [diff] [blame] | 129 | /* The search string we'll be using. */ |
| 130 | |
| 131 | /* If backupstring doesn't exist, initialize it to "". */ |
| 132 | if (backupstring == NULL) |
| 133 | backupstring = mallocstrcpy(NULL, ""); |
| 134 | |
| 135 | /* If use_answer is TRUE, set backupstring to answer and get out. */ |
| 136 | if (use_answer) { |
| 137 | backupstring = mallocstrcpy(backupstring, answer); |
| 138 | return 0; |
| 139 | } |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 140 | |
| 141 | /* We display the search prompt below. If the user types a partial |
| 142 | * search string and then Replace or a toggle, we will return to |
| 143 | * do_search() or do_replace() and be called again. In that case, |
David Lawrence Ramsey | d532f19 | 2004-10-04 22:37:56 +0000 | [diff] [blame] | 144 | * we should put the same search string back up. */ |
Chris Allegretta | bd9e7c3 | 2000-10-26 01:44:42 +0000 | [diff] [blame] | 145 | |
Chris Allegretta | 27eb13f | 2000-11-05 16:52:21 +0000 | [diff] [blame] | 146 | search_init_globals(); |
Chris Allegretta | 31925e4 | 2000-11-02 04:40:39 +0000 | [diff] [blame] | 147 | |
Chris Allegretta | a65ba51 | 2003-01-05 20:57:07 +0000 | [diff] [blame] | 148 | #ifndef NANO_SMALL |
Chris Allegretta | 15c28f8 | 2003-01-05 21:47:06 +0000 | [diff] [blame] | 149 | search_history.current = (historytype *)&search_history.next; |
Chris Allegretta | a65ba51 | 2003-01-05 20:57:07 +0000 | [diff] [blame] | 150 | #endif |
Chris Allegretta | 15c28f8 | 2003-01-05 21:47:06 +0000 | [diff] [blame] | 151 | |
Chris Allegretta | 15c28f8 | 2003-01-05 21:47:06 +0000 | [diff] [blame] | 152 | if (last_search[0] != '\0') { |
David Lawrence Ramsey | 5ffbec5 | 2003-09-16 01:16:49 +0000 | [diff] [blame] | 153 | char *disp = display_string(last_search, 0, COLS / 3); |
| 154 | |
Chris Allegretta | cf287c8 | 2002-07-20 13:57:41 +0000 | [diff] [blame] | 155 | buf = charalloc(COLS / 3 + 7); |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 156 | /* We use COLS / 3 here because we need to see more on the |
| 157 | * line. */ |
David Lawrence Ramsey | 5ffbec5 | 2003-09-16 01:16:49 +0000 | [diff] [blame] | 158 | sprintf(buf, " [%s%s]", disp, |
| 159 | strlenpt(last_search) > COLS / 3 ? "..." : ""); |
| 160 | free(disp); |
David Lawrence Ramsey | d532f19 | 2004-10-04 22:37:56 +0000 | [diff] [blame] | 161 | } else |
| 162 | buf = mallocstrcpy(NULL, ""); |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 163 | |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 164 | /* This is now one simple call. It just does a lot. */ |
David Lawrence Ramsey | 6aec4b8 | 2004-03-15 20:26:30 +0000 | [diff] [blame] | 165 | i = statusq(FALSE, replacing ? replace_list : whereis_list, |
| 166 | backupstring, |
Chris Allegretta | 5beed50 | 2003-01-05 20:41:21 +0000 | [diff] [blame] | 167 | #ifndef NANO_SMALL |
| 168 | &search_history, |
| 169 | #endif |
David Lawrence Ramsey | 6aec4b8 | 2004-03-15 20:26:30 +0000 | [diff] [blame] | 170 | "%s%s%s%s%s%s", _("Search"), |
Chris Allegretta | 759d352 | 2001-09-27 13:04:10 +0000 | [diff] [blame] | 171 | |
David Lawrence Ramsey | 5ffbec5 | 2003-09-16 01:16:49 +0000 | [diff] [blame] | 172 | #ifndef NANO_SMALL |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 173 | /* This string is just a modifier for the search prompt; no |
| 174 | * grammar is implied. */ |
David Lawrence Ramsey | 5ffbec5 | 2003-09-16 01:16:49 +0000 | [diff] [blame] | 175 | ISSET(CASE_SENSITIVE) ? _(" [Case Sensitive]") : |
| 176 | #endif |
| 177 | "", |
Chris Allegretta | 759d352 | 2001-09-27 13:04:10 +0000 | [diff] [blame] | 178 | |
David Lawrence Ramsey | 4b741b9 | 2004-04-30 19:40:03 +0000 | [diff] [blame] | 179 | #ifdef HAVE_REGEX_H |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 180 | /* This string is just a modifier for the search prompt; no |
| 181 | * grammar is implied. */ |
David Lawrence Ramsey | 4b741b9 | 2004-04-30 19:40:03 +0000 | [diff] [blame] | 182 | ISSET(USE_REGEXP) ? _(" [Regexp]") : |
| 183 | #endif |
| 184 | "", |
Chris Allegretta | 759d352 | 2001-09-27 13:04:10 +0000 | [diff] [blame] | 185 | |
David Lawrence Ramsey | 5ffbec5 | 2003-09-16 01:16:49 +0000 | [diff] [blame] | 186 | #ifndef NANO_SMALL |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 187 | /* This string is just a modifier for the search prompt; no |
| 188 | * grammar is implied. */ |
David Lawrence Ramsey | 5ffbec5 | 2003-09-16 01:16:49 +0000 | [diff] [blame] | 189 | ISSET(REVERSE_SEARCH) ? _(" [Backwards]") : |
| 190 | #endif |
| 191 | "", |
Chris Allegretta | 759d352 | 2001-09-27 13:04:10 +0000 | [diff] [blame] | 192 | |
David Lawrence Ramsey | e1ee22f | 2004-11-03 23:05:11 +0000 | [diff] [blame] | 193 | replacing ? |
| 194 | #ifndef NANO_SMALL |
| 195 | (ISSET(MARK_ISSET) ? _(" (to replace) in selection") : |
| 196 | #endif |
| 197 | _(" (to replace)") |
| 198 | #ifndef NANO_SMALL |
| 199 | ) |
| 200 | #endif |
| 201 | : "", |
| 202 | |
Chris Allegretta | e4933a3 | 2001-06-13 02:35:44 +0000 | [diff] [blame] | 203 | buf); |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 204 | |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 205 | /* Release buf now that we don't need it anymore. */ |
Chris Allegretta | 45329a1 | 2002-03-10 01:22:21 +0000 | [diff] [blame] | 206 | free(buf); |
| 207 | |
David Lawrence Ramsey | 5ffbec5 | 2003-09-16 01:16:49 +0000 | [diff] [blame] | 208 | free(backupstring); |
| 209 | backupstring = NULL; |
| 210 | |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 211 | /* Cancel any search, or just return with no previous search. */ |
| 212 | if (i == -1 || (i < 0 && last_search[0] == '\0') || |
| 213 | (!replacing && i == 0 && answer[0] == '\0')) { |
David Lawrence Ramsey | d132210 | 2004-08-26 04:22:54 +0000 | [diff] [blame] | 214 | statusbar(_("Cancelled")); |
Chris Allegretta | 5beed50 | 2003-01-05 20:41:21 +0000 | [diff] [blame] | 215 | #ifndef NANO_SMALL |
| 216 | search_history.current = search_history.next; |
| 217 | #endif |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 218 | return -1; |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 219 | } else { |
| 220 | switch (i) { |
David Lawrence Ramsey | 6be5339 | 2004-10-16 15:41:57 +0000 | [diff] [blame] | 221 | case -2: /* It's the same string. */ |
Chris Allegretta | 805c26d | 2000-09-06 13:39:17 +0000 | [diff] [blame] | 222 | #ifdef HAVE_REGEX_H |
David Lawrence Ramsey | 6be5339 | 2004-10-16 15:41:57 +0000 | [diff] [blame] | 223 | /* Since answer is "", use last_search! */ |
| 224 | if (ISSET(USE_REGEXP) && regexp_init(last_search) == 0) |
| 225 | return -1; |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 226 | #endif |
David Lawrence Ramsey | 6be5339 | 2004-10-16 15:41:57 +0000 | [diff] [blame] | 227 | break; |
| 228 | case 0: /* They entered something new. */ |
| 229 | last_replace[0] = '\0'; |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 230 | #ifdef HAVE_REGEX_H |
David Lawrence Ramsey | 6be5339 | 2004-10-16 15:41:57 +0000 | [diff] [blame] | 231 | if (ISSET(USE_REGEXP) && regexp_init(answer) == 0) |
| 232 | return -1; |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 233 | #endif |
David Lawrence Ramsey | 6be5339 | 2004-10-16 15:41:57 +0000 | [diff] [blame] | 234 | break; |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 235 | #ifndef NANO_SMALL |
David Lawrence Ramsey | 6be5339 | 2004-10-16 15:41:57 +0000 | [diff] [blame] | 236 | case TOGGLE_CASE_KEY: |
| 237 | TOGGLE(CASE_SENSITIVE); |
| 238 | backupstring = mallocstrcpy(backupstring, answer); |
| 239 | return 1; |
| 240 | case TOGGLE_BACKWARDS_KEY: |
| 241 | TOGGLE(REVERSE_SEARCH); |
| 242 | backupstring = mallocstrcpy(backupstring, answer); |
| 243 | return 1; |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 244 | #ifdef HAVE_REGEX_H |
David Lawrence Ramsey | 6be5339 | 2004-10-16 15:41:57 +0000 | [diff] [blame] | 245 | case TOGGLE_REGEXP_KEY: |
| 246 | TOGGLE(USE_REGEXP); |
| 247 | backupstring = mallocstrcpy(backupstring, answer); |
| 248 | return 1; |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 249 | #endif |
| 250 | #endif /* !NANO_SMALL */ |
David Lawrence Ramsey | 6be5339 | 2004-10-16 15:41:57 +0000 | [diff] [blame] | 251 | case NANO_TOOTHERSEARCH_KEY: |
| 252 | backupstring = mallocstrcpy(backupstring, answer); |
| 253 | return -2; /* Call the opposite search function. */ |
| 254 | case NANO_TOGOTOLINE_KEY: |
Chris Allegretta | 5beed50 | 2003-01-05 20:41:21 +0000 | [diff] [blame] | 255 | #ifndef NANO_SMALL |
David Lawrence Ramsey | 6be5339 | 2004-10-16 15:41:57 +0000 | [diff] [blame] | 256 | search_history.current = search_history.next; |
Chris Allegretta | 5beed50 | 2003-01-05 20:41:21 +0000 | [diff] [blame] | 257 | #endif |
David Lawrence Ramsey | 6be5339 | 2004-10-16 15:41:57 +0000 | [diff] [blame] | 258 | /* Put answer up on the statusbar. */ |
| 259 | do_gotoline(-1, FALSE); |
| 260 | /* Fall through. */ |
| 261 | default: |
| 262 | return -1; |
Chris Allegretta | 74bb31b | 2001-03-14 09:08:14 +0000 | [diff] [blame] | 263 | } |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 264 | } |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 265 | return 0; |
| 266 | } |
| 267 | |
David Lawrence Ramsey | c510042 | 2004-08-27 20:28:34 +0000 | [diff] [blame] | 268 | bool is_whole_word(int curr_pos, const char *datastr, const char |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 269 | *searchword) |
Chris Allegretta | 1bc0c7e | 2002-01-08 15:00:24 +0000 | [diff] [blame] | 270 | { |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 271 | size_t sln = curr_pos + strlen(searchword); |
Chris Allegretta | 1bc0c7e | 2002-01-08 15:00:24 +0000 | [diff] [blame] | 272 | |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 273 | /* Start of line or previous character is not a letter and end of |
| 274 | * line or next character is not a letter. */ |
David Lawrence Ramsey | d9fb3e6 | 2004-10-21 22:49:51 +0000 | [diff] [blame] | 275 | return (curr_pos < 1 || !isalpha(datastr[curr_pos - 1])) && |
| 276 | (sln == strlen(datastr) || !isalpha(datastr[sln])); |
Chris Allegretta | 1bc0c7e | 2002-01-08 15:00:24 +0000 | [diff] [blame] | 277 | } |
| 278 | |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 279 | /* Look for needle, starting at current, column current_x. If |
David Lawrence Ramsey | 4b7e3c3 | 2004-10-15 16:25:56 +0000 | [diff] [blame] | 280 | * no_sameline is TRUE, skip over begin when looking for needle. begin |
| 281 | * is the line where we first started searching, at column beginx. If |
David Lawrence Ramsey | 9819ed0 | 2004-10-21 15:32:11 +0000 | [diff] [blame] | 282 | * can_display_wrap is TRUE, we put messages on the statusbar, wrap |
David Lawrence Ramsey | 77b284a | 2004-10-27 02:21:01 +0000 | [diff] [blame] | 283 | * around the file boundaries. The return value specifies whether we |
| 284 | * found anything. If we did, set needle_len to the length of the |
| 285 | * string we found if it isn't NULL. */ |
David Lawrence Ramsey | c510042 | 2004-08-27 20:28:34 +0000 | [diff] [blame] | 286 | bool findnextstr(bool can_display_wrap, bool wholeword, bool |
| 287 | no_sameline, const filestruct *begin, size_t beginx, const char |
David Lawrence Ramsey | 77b284a | 2004-10-27 02:21:01 +0000 | [diff] [blame] | 288 | *needle, size_t *needle_len) |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 289 | { |
Chris Allegretta | 4dc03d5 | 2002-05-11 03:04:44 +0000 | [diff] [blame] | 290 | filestruct *fileptr = current; |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 291 | const char *rev_start = NULL, *found = NULL; |
David Lawrence Ramsey | 53752e8 | 2004-10-18 22:19:22 +0000 | [diff] [blame] | 292 | size_t found_len; |
| 293 | /* The length of the match we found. */ |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 294 | size_t current_x_find = 0; |
David Lawrence Ramsey | 53752e8 | 2004-10-18 22:19:22 +0000 | [diff] [blame] | 295 | /* The location of the match we found. */ |
David Lawrence Ramsey | c510042 | 2004-08-27 20:28:34 +0000 | [diff] [blame] | 296 | int current_y_find = current_y; |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 297 | |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 298 | /* rev_start might end up 1 character before the start or after the |
| 299 | * end of the line. This won't be a problem because strstrwrapper() |
| 300 | * will return immediately and say that no match was found, and |
| 301 | * rev_start will be properly set when the search continues on the |
| 302 | * previous or next line. */ |
David Lawrence Ramsey | 4b7e3c3 | 2004-10-15 16:25:56 +0000 | [diff] [blame] | 303 | rev_start = |
Chris Allegretta | e10f389 | 2001-10-02 03:54:40 +0000 | [diff] [blame] | 304 | #ifndef NANO_SMALL |
David Lawrence Ramsey | 4b7e3c3 | 2004-10-15 16:25:56 +0000 | [diff] [blame] | 305 | ISSET(REVERSE_SEARCH) ? fileptr->data + (current_x - 1) : |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 306 | #endif |
David Lawrence Ramsey | 4b7e3c3 | 2004-10-15 16:25:56 +0000 | [diff] [blame] | 307 | fileptr->data + (current_x + 1); |
Chris Allegretta | e4933a3 | 2001-06-13 02:35:44 +0000 | [diff] [blame] | 308 | |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 309 | /* Look for needle in searchstr. */ |
David Lawrence Ramsey | 6aec4b8 | 2004-03-15 20:26:30 +0000 | [diff] [blame] | 310 | while (TRUE) { |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 311 | found = strstrwrapper(fileptr->data, needle, rev_start); |
David Lawrence Ramsey | 45cfbec | 2003-11-28 16:04:24 +0000 | [diff] [blame] | 312 | |
David Lawrence Ramsey | 53752e8 | 2004-10-18 22:19:22 +0000 | [diff] [blame] | 313 | /* We've found a potential match. */ |
| 314 | if (found != NULL) { |
| 315 | bool found_whole = FALSE; |
| 316 | /* Is this potential match a whole word? */ |
| 317 | |
| 318 | /* Set found_len to the length of the potential match. */ |
| 319 | found_len = |
| 320 | #ifdef HAVE_REGEX_H |
| 321 | ISSET(USE_REGEXP) ? |
| 322 | regmatches[0].rm_eo - regmatches[0].rm_so : |
| 323 | #endif |
| 324 | strlen(needle); |
| 325 | |
| 326 | /* If we're searching for whole words, see if this potential |
| 327 | * match is a whole word. */ |
| 328 | if (wholeword) { |
David Lawrence Ramsey | 99869f5 | 2004-11-02 20:48:37 +0000 | [diff] [blame] | 329 | char *word = mallocstrncpy(NULL, found, found_len + 1); |
David Lawrence Ramsey | 53752e8 | 2004-10-18 22:19:22 +0000 | [diff] [blame] | 330 | word[found_len] = '\0'; |
| 331 | |
| 332 | found_whole = is_whole_word(found - fileptr->data, |
| 333 | fileptr->data, word); |
| 334 | free(word); |
| 335 | } |
| 336 | |
| 337 | /* If we're searching for whole words and this potential |
| 338 | * match isn't a whole word, or if we're not allowed to find |
| 339 | * a match on the same line we started on and this potential |
| 340 | * match is on that line, continue searching. */ |
| 341 | if ((!wholeword || found_whole) && (!no_sameline || |
| 342 | fileptr != current)) |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 343 | break; |
Chris Allegretta | e4933a3 | 2001-06-13 02:35:44 +0000 | [diff] [blame] | 344 | } |
| 345 | |
David Lawrence Ramsey | 2cc2a57 | 2004-10-18 02:06:53 +0000 | [diff] [blame] | 346 | /* We've finished processing the file, so get out. */ |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 347 | if (search_last_line) { |
| 348 | if (can_display_wrap) |
Chris Allegretta | e4933a3 | 2001-06-13 02:35:44 +0000 | [diff] [blame] | 349 | not_found_msg(needle); |
David Lawrence Ramsey | 4b7e3c3 | 2004-10-15 16:25:56 +0000 | [diff] [blame] | 350 | return FALSE; |
Chris Allegretta | e4933a3 | 2001-06-13 02:35:44 +0000 | [diff] [blame] | 351 | } |
David Lawrence Ramsey | c510042 | 2004-08-27 20:28:34 +0000 | [diff] [blame] | 352 | |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 353 | #ifndef NANO_SMALL |
David Lawrence Ramsey | c510042 | 2004-08-27 20:28:34 +0000 | [diff] [blame] | 354 | if (ISSET(REVERSE_SEARCH)) { |
| 355 | fileptr = fileptr->prev; |
| 356 | current_y_find--; |
| 357 | } else { |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 358 | #endif |
David Lawrence Ramsey | c510042 | 2004-08-27 20:28:34 +0000 | [diff] [blame] | 359 | fileptr = fileptr->next; |
| 360 | current_y_find++; |
| 361 | #ifndef NANO_SMALL |
| 362 | } |
| 363 | #endif |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 364 | |
David Lawrence Ramsey | 2cc2a57 | 2004-10-18 02:06:53 +0000 | [diff] [blame] | 365 | /* Start or end of buffer reached, so wrap around. */ |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 366 | if (fileptr == NULL) { |
| 367 | if (!can_display_wrap) |
David Lawrence Ramsey | 4b7e3c3 | 2004-10-15 16:25:56 +0000 | [diff] [blame] | 368 | return FALSE; |
David Lawrence Ramsey | c510042 | 2004-08-27 20:28:34 +0000 | [diff] [blame] | 369 | |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 370 | #ifndef NANO_SMALL |
David Lawrence Ramsey | c510042 | 2004-08-27 20:28:34 +0000 | [diff] [blame] | 371 | if (ISSET(REVERSE_SEARCH)) { |
| 372 | fileptr = filebot; |
| 373 | current_y_find = editwinrows - 1; |
| 374 | } else { |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 375 | #endif |
David Lawrence Ramsey | c510042 | 2004-08-27 20:28:34 +0000 | [diff] [blame] | 376 | fileptr = fileage; |
| 377 | current_y_find = 0; |
| 378 | #ifndef NANO_SMALL |
| 379 | } |
| 380 | #endif |
| 381 | |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 382 | if (can_display_wrap) |
| 383 | statusbar(_("Search Wrapped")); |
| 384 | } |
| 385 | |
| 386 | /* Original start line reached. */ |
David Lawrence Ramsey | 77b284a | 2004-10-27 02:21:01 +0000 | [diff] [blame] | 387 | if (fileptr == begin) |
David Lawrence Ramsey | c372488 | 2004-05-27 18:39:16 +0000 | [diff] [blame] | 388 | search_last_line = TRUE; |
David Lawrence Ramsey | 77b284a | 2004-10-27 02:21:01 +0000 | [diff] [blame] | 389 | |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 390 | rev_start = fileptr->data; |
| 391 | #ifndef NANO_SMALL |
| 392 | if (ISSET(REVERSE_SEARCH)) |
| 393 | rev_start += strlen(fileptr->data); |
| 394 | #endif |
| 395 | } |
| 396 | |
| 397 | /* We found an instance. */ |
| 398 | current_x_find = found - fileptr->data; |
| 399 | |
| 400 | /* Ensure we haven't wrapped around again! */ |
| 401 | if (search_last_line && |
| 402 | #ifndef NANO_SMALL |
| 403 | ((!ISSET(REVERSE_SEARCH) && current_x_find > beginx) || |
| 404 | (ISSET(REVERSE_SEARCH) && current_x_find < beginx)) |
| 405 | #else |
| 406 | current_x_find > beginx |
| 407 | #endif |
| 408 | ) { |
| 409 | |
| 410 | if (can_display_wrap) |
| 411 | not_found_msg(needle); |
David Lawrence Ramsey | 4b7e3c3 | 2004-10-15 16:25:56 +0000 | [diff] [blame] | 412 | return FALSE; |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 413 | } |
| 414 | |
| 415 | /* Set globals now that we are sure we found something. */ |
Chris Allegretta | d00e6df | 2000-11-29 04:33:26 +0000 | [diff] [blame] | 416 | current = fileptr; |
| 417 | current_x = current_x_find; |
David Lawrence Ramsey | c510042 | 2004-08-27 20:28:34 +0000 | [diff] [blame] | 418 | current_y = current_y_find; |
David Lawrence Ramsey | 2eb7459 | 2004-10-21 16:25:44 +0000 | [diff] [blame] | 419 | placewewant = xplustabs(); |
David Lawrence Ramsey | 9819ed0 | 2004-10-21 15:32:11 +0000 | [diff] [blame] | 420 | |
| 421 | /* needle_len holds the length of needle. */ |
David Lawrence Ramsey | 53752e8 | 2004-10-18 22:19:22 +0000 | [diff] [blame] | 422 | if (needle_len != NULL) |
| 423 | *needle_len = found_len; |
Chris Allegretta | d00e6df | 2000-11-29 04:33:26 +0000 | [diff] [blame] | 424 | |
David Lawrence Ramsey | 4b7e3c3 | 2004-10-15 16:25:56 +0000 | [diff] [blame] | 425 | return TRUE; |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 426 | } |
| 427 | |
David Lawrence Ramsey | e5e88fd | 2004-10-31 13:20:30 +0000 | [diff] [blame] | 428 | void findnextstr_wrap_reset(void) |
| 429 | { |
| 430 | search_last_line = FALSE; |
| 431 | } |
| 432 | |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 433 | /* Search for a string. */ |
David Lawrence Ramsey | 72e51ab | 2004-07-02 14:31:03 +0000 | [diff] [blame] | 434 | void do_search(void) |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 435 | { |
David Lawrence Ramsey | 86e851b | 2004-07-28 20:46:25 +0000 | [diff] [blame] | 436 | size_t old_pww = placewewant, fileptr_x = current_x; |
David Lawrence Ramsey | c510042 | 2004-08-27 20:28:34 +0000 | [diff] [blame] | 437 | int i; |
| 438 | bool didfind; |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 439 | filestruct *fileptr = current; |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 440 | |
David Lawrence Ramsey | c97acfb | 2003-09-10 20:08:00 +0000 | [diff] [blame] | 441 | #ifndef DISABLE_WRAPPING |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 442 | wrap_reset(); |
David Lawrence Ramsey | c97acfb | 2003-09-10 20:08:00 +0000 | [diff] [blame] | 443 | #endif |
David Lawrence Ramsey | e5d8f32 | 2004-09-30 22:07:21 +0000 | [diff] [blame] | 444 | |
David Lawrence Ramsey | d532f19 | 2004-10-04 22:37:56 +0000 | [diff] [blame] | 445 | i = search_init(FALSE, FALSE); |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 446 | if (i == -1) /* Cancel, Go to Line, blank search string, or |
| 447 | * regcomp() failed. */ |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 448 | search_abort(); |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 449 | else if (i == -2) /* Replace. */ |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 450 | do_replace(); |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 451 | #ifndef NANO_SMALL |
| 452 | else if (i == 1) /* Case Sensitive, Backwards, or Regexp search |
| 453 | * toggle. */ |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 454 | do_search(); |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 455 | #endif |
Chris Allegretta | 86f8b3a | 2000-10-31 05:28:33 +0000 | [diff] [blame] | 456 | |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 457 | if (i != 0) |
David Lawrence Ramsey | 72e51ab | 2004-07-02 14:31:03 +0000 | [diff] [blame] | 458 | return; |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 459 | |
| 460 | /* If answer is now "", copy last_search into answer. */ |
Chris Allegretta | 4dc03d5 | 2002-05-11 03:04:44 +0000 | [diff] [blame] | 461 | if (answer[0] == '\0') |
Chris Allegretta | 5bf51d3 | 2000-11-16 06:01:10 +0000 | [diff] [blame] | 462 | answer = mallocstrcpy(answer, last_search); |
| 463 | else |
| 464 | last_search = mallocstrcpy(last_search, answer); |
| 465 | |
Chris Allegretta | 5beed50 | 2003-01-05 20:41:21 +0000 | [diff] [blame] | 466 | #ifndef NANO_SMALL |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 467 | /* If answer is not "", add this search string to the search history |
| 468 | * list. */ |
Chris Allegretta | 688c8eb | 2003-01-14 23:36:11 +0000 | [diff] [blame] | 469 | if (answer[0] != '\0') |
Chris Allegretta | 6328792 | 2003-01-05 20:43:49 +0000 | [diff] [blame] | 470 | update_history(&search_history, answer); |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 471 | #endif |
Chris Allegretta | 5beed50 | 2003-01-05 20:41:21 +0000 | [diff] [blame] | 472 | |
David Lawrence Ramsey | e5e88fd | 2004-10-31 13:20:30 +0000 | [diff] [blame] | 473 | findnextstr_wrap_reset(); |
David Lawrence Ramsey | 53752e8 | 2004-10-18 22:19:22 +0000 | [diff] [blame] | 474 | didfind = findnextstr(TRUE, FALSE, FALSE, current, current_x, |
David Lawrence Ramsey | 77b284a | 2004-10-27 02:21:01 +0000 | [diff] [blame] | 475 | answer, NULL); |
Chris Allegretta | 1c2fddc | 2002-01-21 20:40:14 +0000 | [diff] [blame] | 476 | |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 477 | /* Check to see if there's only one occurrence of the string and |
| 478 | * we're on it now. */ |
| 479 | if (fileptr == current && fileptr_x == current_x && didfind) { |
| 480 | #ifdef HAVE_REGEX_H |
| 481 | /* Do the search again, skipping over the current line, if we're |
| 482 | * doing a bol and/or eol regex search ("^", "$", or "^$"), so |
| 483 | * that we find one only once per line. We should only end up |
| 484 | * back at the same position if the string isn't found again, in |
| 485 | * which case it's the only occurrence. */ |
David Lawrence Ramsey | fd3039a | 2004-07-17 19:49:12 +0000 | [diff] [blame] | 486 | if (ISSET(USE_REGEXP) && regexp_bol_or_eol(&search_regexp, |
| 487 | last_search)) { |
David Lawrence Ramsey | c510042 | 2004-08-27 20:28:34 +0000 | [diff] [blame] | 488 | didfind = findnextstr(TRUE, FALSE, TRUE, current, current_x, |
David Lawrence Ramsey | 77b284a | 2004-10-27 02:21:01 +0000 | [diff] [blame] | 489 | answer, NULL); |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 490 | if (fileptr == current && fileptr_x == current_x && !didfind) |
| 491 | statusbar(_("This is the only occurrence")); |
| 492 | } else { |
| 493 | #endif |
| 494 | statusbar(_("This is the only occurrence")); |
| 495 | #ifdef HAVE_REGEX_H |
| 496 | } |
| 497 | #endif |
| 498 | } |
Chris Allegretta | 1c2fddc | 2002-01-21 20:40:14 +0000 | [diff] [blame] | 499 | |
David Lawrence Ramsey | 2ed225f | 2004-05-28 20:44:09 +0000 | [diff] [blame] | 500 | placewewant = xplustabs(); |
David Lawrence Ramsey | c21790d | 2004-05-30 03:19:52 +0000 | [diff] [blame] | 501 | edit_redraw(fileptr, old_pww); |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 502 | search_abort(); |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 503 | } |
| 504 | |
David Lawrence Ramsey | 5aa3983 | 2004-05-05 21:36:50 +0000 | [diff] [blame] | 505 | #ifndef NANO_SMALL |
David Lawrence Ramsey | e049706 | 2003-08-23 21:11:06 +0000 | [diff] [blame] | 506 | /* Search for the next string without prompting. */ |
David Lawrence Ramsey | 72e51ab | 2004-07-02 14:31:03 +0000 | [diff] [blame] | 507 | void do_research(void) |
David Lawrence Ramsey | e049706 | 2003-08-23 21:11:06 +0000 | [diff] [blame] | 508 | { |
David Lawrence Ramsey | 576bf33 | 2004-07-12 03:10:30 +0000 | [diff] [blame] | 509 | size_t old_pww = placewewant, fileptr_x = current_x; |
David Lawrence Ramsey | c510042 | 2004-08-27 20:28:34 +0000 | [diff] [blame] | 510 | bool didfind; |
David Lawrence Ramsey | 2ed225f | 2004-05-28 20:44:09 +0000 | [diff] [blame] | 511 | filestruct *fileptr = current; |
David Lawrence Ramsey | e049706 | 2003-08-23 21:11:06 +0000 | [diff] [blame] | 512 | |
David Lawrence Ramsey | c97acfb | 2003-09-10 20:08:00 +0000 | [diff] [blame] | 513 | #ifndef DISABLE_WRAPPING |
David Lawrence Ramsey | e049706 | 2003-08-23 21:11:06 +0000 | [diff] [blame] | 514 | wrap_reset(); |
David Lawrence Ramsey | c97acfb | 2003-09-10 20:08:00 +0000 | [diff] [blame] | 515 | #endif |
David Lawrence Ramsey | ca74415 | 2004-10-01 18:47:17 +0000 | [diff] [blame] | 516 | |
David Lawrence Ramsey | e049706 | 2003-08-23 21:11:06 +0000 | [diff] [blame] | 517 | search_init_globals(); |
| 518 | |
| 519 | if (last_search[0] != '\0') { |
| 520 | |
| 521 | #ifdef HAVE_REGEX_H |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 522 | /* Since answer is "", use last_search! */ |
David Lawrence Ramsey | 4b741b9 | 2004-04-30 19:40:03 +0000 | [diff] [blame] | 523 | if (ISSET(USE_REGEXP) && regexp_init(last_search) == 0) |
David Lawrence Ramsey | 72e51ab | 2004-07-02 14:31:03 +0000 | [diff] [blame] | 524 | return; |
David Lawrence Ramsey | e049706 | 2003-08-23 21:11:06 +0000 | [diff] [blame] | 525 | #endif |
| 526 | |
David Lawrence Ramsey | e5e88fd | 2004-10-31 13:20:30 +0000 | [diff] [blame] | 527 | findnextstr_wrap_reset(); |
David Lawrence Ramsey | c510042 | 2004-08-27 20:28:34 +0000 | [diff] [blame] | 528 | didfind = findnextstr(TRUE, FALSE, FALSE, current, current_x, |
David Lawrence Ramsey | 77b284a | 2004-10-27 02:21:01 +0000 | [diff] [blame] | 529 | last_search, NULL); |
David Lawrence Ramsey | e049706 | 2003-08-23 21:11:06 +0000 | [diff] [blame] | 530 | |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 531 | /* Check to see if there's only one occurrence of the string and |
| 532 | * we're on it now. */ |
| 533 | if (fileptr == current && fileptr_x == current_x && didfind) { |
| 534 | #ifdef HAVE_REGEX_H |
| 535 | /* Do the search again, skipping over the current line, if |
| 536 | * we're doing a bol and/or eol regex search ("^", "$", or |
| 537 | * "^$"), so that we find one only once per line. We should |
| 538 | * only end up back at the same position if the string isn't |
| 539 | * found again, in which case it's the only occurrence. */ |
David Lawrence Ramsey | fd3039a | 2004-07-17 19:49:12 +0000 | [diff] [blame] | 540 | if (ISSET(USE_REGEXP) && regexp_bol_or_eol(&search_regexp, |
| 541 | last_search)) { |
David Lawrence Ramsey | c510042 | 2004-08-27 20:28:34 +0000 | [diff] [blame] | 542 | didfind = findnextstr(TRUE, FALSE, TRUE, current, |
David Lawrence Ramsey | 77b284a | 2004-10-27 02:21:01 +0000 | [diff] [blame] | 543 | current_x, answer, NULL); |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 544 | if (fileptr == current && fileptr_x == current_x && !didfind) |
| 545 | statusbar(_("This is the only occurrence")); |
| 546 | } else { |
| 547 | #endif |
| 548 | statusbar(_("This is the only occurrence")); |
| 549 | #ifdef HAVE_REGEX_H |
| 550 | } |
| 551 | #endif |
| 552 | } |
David Lawrence Ramsey | e049706 | 2003-08-23 21:11:06 +0000 | [diff] [blame] | 553 | } else |
| 554 | statusbar(_("No current search pattern")); |
| 555 | |
David Lawrence Ramsey | 2ed225f | 2004-05-28 20:44:09 +0000 | [diff] [blame] | 556 | placewewant = xplustabs(); |
David Lawrence Ramsey | c21790d | 2004-05-30 03:19:52 +0000 | [diff] [blame] | 557 | edit_redraw(fileptr, old_pww); |
David Lawrence Ramsey | e049706 | 2003-08-23 21:11:06 +0000 | [diff] [blame] | 558 | search_abort(); |
David Lawrence Ramsey | e049706 | 2003-08-23 21:11:06 +0000 | [diff] [blame] | 559 | } |
David Lawrence Ramsey | 5aa3983 | 2004-05-05 21:36:50 +0000 | [diff] [blame] | 560 | #endif |
David Lawrence Ramsey | e049706 | 2003-08-23 21:11:06 +0000 | [diff] [blame] | 561 | |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 562 | void replace_abort(void) |
| 563 | { |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 564 | /* Identical to search_abort(), so we'll call it here. If it does |
| 565 | * something different later, we can change it back. For now, it's |
| 566 | * just a waste to duplicate code. */ |
Chris Allegretta | 18bd029 | 2000-07-28 01:18:10 +0000 | [diff] [blame] | 567 | search_abort(); |
Chris Allegretta | a0e957b | 2000-10-24 22:25:36 +0000 | [diff] [blame] | 568 | placewewant = xplustabs(); |
Chris Allegretta | 9fc8d43 | 2000-07-07 01:49:52 +0000 | [diff] [blame] | 569 | } |
| 570 | |
Chris Allegretta | 805c26d | 2000-09-06 13:39:17 +0000 | [diff] [blame] | 571 | #ifdef HAVE_REGEX_H |
David Lawrence Ramsey | c510042 | 2004-08-27 20:28:34 +0000 | [diff] [blame] | 572 | int replace_regexp(char *string, bool create_flag) |
Chris Allegretta | 9fc8d43 | 2000-07-07 01:49:52 +0000 | [diff] [blame] | 573 | { |
David Lawrence Ramsey | c510042 | 2004-08-27 20:28:34 +0000 | [diff] [blame] | 574 | /* Split personality here - if create_flag is FALSE, just calculate |
Chris Allegretta | 9fc8d43 | 2000-07-07 01:49:52 +0000 | [diff] [blame] | 575 | * the size of the replacement line (necessary because of |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 576 | * subexpressions \1 to \9 in the replaced text). */ |
Chris Allegretta | 9fc8d43 | 2000-07-07 01:49:52 +0000 | [diff] [blame] | 577 | |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 578 | const char *c = last_replace; |
Chris Allegretta | bd9e7c3 | 2000-10-26 01:44:42 +0000 | [diff] [blame] | 579 | int search_match_count = regmatches[0].rm_eo - regmatches[0].rm_so; |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 580 | int new_size = strlen(current->data) + 1 - search_match_count; |
Chris Allegretta | 9fc8d43 | 2000-07-07 01:49:52 +0000 | [diff] [blame] | 581 | |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 582 | /* Iterate through the replacement text to handle subexpression |
| 583 | * replacement using \1, \2, \3, etc. */ |
David Lawrence Ramsey | 9b13ff3 | 2002-12-22 16:30:00 +0000 | [diff] [blame] | 584 | while (*c != '\0') { |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 585 | int num = (int)(*(c + 1) - '0'); |
| 586 | |
David Lawrence Ramsey | 40a6c8c | 2004-11-27 21:10:11 +0000 | [diff] [blame] | 587 | if (*c != '\\' || num < 1 || num > 9 || |
| 588 | num > search_regexp.re_nsub) { |
Chris Allegretta | bd9e7c3 | 2000-10-26 01:44:42 +0000 | [diff] [blame] | 589 | if (create_flag) |
| 590 | *string++ = *c; |
| 591 | c++; |
| 592 | new_size++; |
| 593 | } else { |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 594 | int i = regmatches[num].rm_eo - regmatches[num].rm_so; |
Chris Allegretta | 9fc8d43 | 2000-07-07 01:49:52 +0000 | [diff] [blame] | 595 | |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 596 | /* Skip over the replacement expression. */ |
| 597 | c += 2; |
Chris Allegretta | 9fc8d43 | 2000-07-07 01:49:52 +0000 | [diff] [blame] | 598 | |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 599 | /* But add the length of the subexpression to new_size. */ |
| 600 | new_size += i; |
Chris Allegretta | 9fc8d43 | 2000-07-07 01:49:52 +0000 | [diff] [blame] | 601 | |
David Lawrence Ramsey | c510042 | 2004-08-27 20:28:34 +0000 | [diff] [blame] | 602 | /* And if create_flag is TRUE, append the result of the |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 603 | * subexpression match to the new line. */ |
| 604 | if (create_flag) { |
| 605 | strncpy(string, current->data + current_x + |
| 606 | regmatches[num].rm_so, i); |
| 607 | string += i; |
Chris Allegretta | bd9e7c3 | 2000-10-26 01:44:42 +0000 | [diff] [blame] | 608 | } |
| 609 | } |
Chris Allegretta | 9fc8d43 | 2000-07-07 01:49:52 +0000 | [diff] [blame] | 610 | } |
| 611 | |
| 612 | if (create_flag) |
Chris Allegretta | 7662c86 | 2003-01-13 01:35:15 +0000 | [diff] [blame] | 613 | *string = '\0'; |
Chris Allegretta | 9fc8d43 | 2000-07-07 01:49:52 +0000 | [diff] [blame] | 614 | |
| 615 | return new_size; |
| 616 | } |
Chris Allegretta | 4780561 | 2000-07-07 02:35:34 +0000 | [diff] [blame] | 617 | #endif |
Chris Allegretta | bd9e7c3 | 2000-10-26 01:44:42 +0000 | [diff] [blame] | 618 | |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 619 | char *replace_line(const char *needle) |
Chris Allegretta | 9fc8d43 | 2000-07-07 01:49:52 +0000 | [diff] [blame] | 620 | { |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 621 | char *copy; |
Chris Allegretta | 9fc8d43 | 2000-07-07 01:49:52 +0000 | [diff] [blame] | 622 | int new_line_size; |
| 623 | int search_match_count; |
| 624 | |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 625 | /* Calculate the size of the new line. */ |
Chris Allegretta | 805c26d | 2000-09-06 13:39:17 +0000 | [diff] [blame] | 626 | #ifdef HAVE_REGEX_H |
Chris Allegretta | 9fc8d43 | 2000-07-07 01:49:52 +0000 | [diff] [blame] | 627 | if (ISSET(USE_REGEXP)) { |
David Lawrence Ramsey | fa39404 | 2004-05-23 21:11:14 +0000 | [diff] [blame] | 628 | search_match_count = regmatches[0].rm_eo - regmatches[0].rm_so; |
Chris Allegretta | bd9e7c3 | 2000-10-26 01:44:42 +0000 | [diff] [blame] | 629 | new_line_size = replace_regexp(NULL, 0); |
Chris Allegretta | 9fc8d43 | 2000-07-07 01:49:52 +0000 | [diff] [blame] | 630 | } else { |
Chris Allegretta | 4780561 | 2000-07-07 02:35:34 +0000 | [diff] [blame] | 631 | #endif |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 632 | search_match_count = strlen(needle); |
| 633 | new_line_size = strlen(current->data) - search_match_count + |
| 634 | strlen(answer) + 1; |
| 635 | #ifdef HAVE_REGEX_H |
Chris Allegretta | 9fc8d43 | 2000-07-07 01:49:52 +0000 | [diff] [blame] | 636 | } |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 637 | #endif |
Chris Allegretta | bd9e7c3 | 2000-10-26 01:44:42 +0000 | [diff] [blame] | 638 | |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 639 | /* Create the buffer. */ |
Chris Allegretta | 88b0915 | 2001-05-17 11:35:43 +0000 | [diff] [blame] | 640 | copy = charalloc(new_line_size); |
Chris Allegretta | 9fc8d43 | 2000-07-07 01:49:52 +0000 | [diff] [blame] | 641 | |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 642 | /* The head of the original line. */ |
Chris Allegretta | 9fc8d43 | 2000-07-07 01:49:52 +0000 | [diff] [blame] | 643 | strncpy(copy, current->data, current_x); |
Chris Allegretta | 9fc8d43 | 2000-07-07 01:49:52 +0000 | [diff] [blame] | 644 | |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 645 | /* The replacement text. */ |
Chris Allegretta | 805c26d | 2000-09-06 13:39:17 +0000 | [diff] [blame] | 646 | #ifdef HAVE_REGEX_H |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 647 | if (ISSET(USE_REGEXP)) |
| 648 | replace_regexp(copy + current_x, TRUE); |
Chris Allegretta | 9fc8d43 | 2000-07-07 01:49:52 +0000 | [diff] [blame] | 649 | else |
Chris Allegretta | 4780561 | 2000-07-07 02:35:34 +0000 | [diff] [blame] | 650 | #endif |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 651 | strcpy(copy + current_x, answer); |
Chris Allegretta | 9fc8d43 | 2000-07-07 01:49:52 +0000 | [diff] [blame] | 652 | |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 653 | /* The tail of the original line. */ |
| 654 | assert(current_x + search_match_count <= strlen(current->data)); |
| 655 | strcat(copy, current->data + current_x + search_match_count); |
Chris Allegretta | 9fc8d43 | 2000-07-07 01:49:52 +0000 | [diff] [blame] | 656 | |
| 657 | return copy; |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 658 | } |
| 659 | |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 660 | /* Step through each replace word and prompt user before replacing. |
David Lawrence Ramsey | 491cad3 | 2004-10-08 23:06:01 +0000 | [diff] [blame] | 661 | * Parameters real_current and real_current_x are needed in order to |
| 662 | * allow the cursor position to be updated when a word before the cursor |
| 663 | * is replaced by a shorter word. |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 664 | * |
| 665 | * needle is the string to seek. We replace it with answer. Return -1 |
David Lawrence Ramsey | 9bf486f | 2004-10-26 20:58:30 +0000 | [diff] [blame] | 666 | * if needle isn't found, else the number of replacements performed. If |
| 667 | * canceled isn't NULL, set it to TRUE if we canceled. */ |
David Lawrence Ramsey | 182b2c9 | 2004-11-03 16:02:41 +0000 | [diff] [blame] | 668 | ssize_t do_replace_loop(const char *needle, const filestruct |
| 669 | *real_current, size_t *real_current_x, bool wholewords, bool |
| 670 | *canceled) |
Chris Allegretta | 27eb13f | 2000-11-05 16:52:21 +0000 | [diff] [blame] | 671 | { |
David Lawrence Ramsey | 53752e8 | 2004-10-18 22:19:22 +0000 | [diff] [blame] | 672 | ssize_t numreplaced = -1; |
| 673 | size_t match_len; |
David Lawrence Ramsey | 3de81bc | 2004-11-22 17:08:41 +0000 | [diff] [blame] | 674 | size_t pww_save = placewewant; |
David Lawrence Ramsey | c510042 | 2004-08-27 20:28:34 +0000 | [diff] [blame] | 675 | bool replaceall = FALSE; |
David Lawrence Ramsey | b7cb6a3 | 2003-10-31 17:53:38 +0000 | [diff] [blame] | 676 | #ifdef HAVE_REGEX_H |
David Lawrence Ramsey | e190ff3 | 2004-01-03 21:42:25 +0000 | [diff] [blame] | 677 | /* The starting-line match and bol/eol regex flags. */ |
David Lawrence Ramsey | c510042 | 2004-08-27 20:28:34 +0000 | [diff] [blame] | 678 | bool begin_line = FALSE, bol_or_eol = FALSE; |
David Lawrence Ramsey | b7cb6a3 | 2003-10-31 17:53:38 +0000 | [diff] [blame] | 679 | #endif |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 680 | #ifndef NANO_SMALL |
David Lawrence Ramsey | 77b284a | 2004-10-27 02:21:01 +0000 | [diff] [blame] | 681 | bool old_mark_set = ISSET(MARK_ISSET); |
David Lawrence Ramsey | 40bdb68 | 2004-11-03 22:03:41 +0000 | [diff] [blame] | 682 | filestruct *edittop_save = edittop, *top, *bot; |
| 683 | size_t top_x, bot_x; |
| 684 | bool right_side_up = FALSE; |
| 685 | /* TRUE if (mark_beginbuf, mark_beginx) is the top of the mark, |
| 686 | * FALSE if (current, current_x) is. */ |
Chris Allegretta | 27eb13f | 2000-11-05 16:52:21 +0000 | [diff] [blame] | 687 | |
David Lawrence Ramsey | 491cad3 | 2004-10-08 23:06:01 +0000 | [diff] [blame] | 688 | if (old_mark_set) { |
David Lawrence Ramsey | 40bdb68 | 2004-11-03 22:03:41 +0000 | [diff] [blame] | 689 | /* If the mark is on, partition the filestruct so that it |
David Lawrence Ramsey | 90e59c1 | 2004-11-05 23:03:03 +0000 | [diff] [blame] | 690 | * contains only the marked text, set edittop to the top of the |
| 691 | * partition, turn the mark off, and refresh the screen. */ |
David Lawrence Ramsey | 40bdb68 | 2004-11-03 22:03:41 +0000 | [diff] [blame] | 692 | mark_order((const filestruct **)&top, &top_x, |
David Lawrence Ramsey | 90e59c1 | 2004-11-05 23:03:03 +0000 | [diff] [blame] | 693 | (const filestruct **)&bot, &bot_x, &right_side_up); |
David Lawrence Ramsey | 40bdb68 | 2004-11-03 22:03:41 +0000 | [diff] [blame] | 694 | filepart = partition_filestruct(top, top_x, bot, bot_x); |
| 695 | edittop = fileage; |
David Lawrence Ramsey | 491cad3 | 2004-10-08 23:06:01 +0000 | [diff] [blame] | 696 | UNSET(MARK_ISSET); |
| 697 | edit_refresh(); |
| 698 | } |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 699 | #endif |
Chris Allegretta | 27eb13f | 2000-11-05 16:52:21 +0000 | [diff] [blame] | 700 | |
David Lawrence Ramsey | 9bf486f | 2004-10-26 20:58:30 +0000 | [diff] [blame] | 701 | if (canceled != NULL) |
| 702 | *canceled = FALSE; |
| 703 | |
David Lawrence Ramsey | e5e88fd | 2004-10-31 13:20:30 +0000 | [diff] [blame] | 704 | findnextstr_wrap_reset(); |
David Lawrence Ramsey | c510042 | 2004-08-27 20:28:34 +0000 | [diff] [blame] | 705 | while (findnextstr(TRUE, wholewords, |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 706 | #ifdef HAVE_REGEX_H |
| 707 | /* We should find a bol and/or eol regex only once per line. If |
| 708 | * the bol_or_eol flag is set, it means that the last search |
| 709 | * found one on the beginning line, so we should skip over the |
| 710 | * beginning line when doing this search. */ |
| 711 | bol_or_eol |
| 712 | #else |
| 713 | FALSE |
| 714 | #endif |
David Lawrence Ramsey | 3de81bc | 2004-11-22 17:08:41 +0000 | [diff] [blame] | 715 | , real_current, *real_current_x, needle, &match_len)) { |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 716 | |
| 717 | int i = 0; |
David Lawrence Ramsey | 3497666 | 2004-10-09 16:26:32 +0000 | [diff] [blame] | 718 | |
David Lawrence Ramsey | 3288925 | 2004-10-21 15:44:36 +0000 | [diff] [blame] | 719 | #ifdef HAVE_REGEX_H |
| 720 | /* If the bol_or_eol flag is set, we've found a match on the |
| 721 | * beginning line already, and we're still on the beginning line |
| 722 | * after the search, it means that we've wrapped around, so |
| 723 | * we're done. */ |
| 724 | if (bol_or_eol && begin_line && current == real_current) |
| 725 | break; |
| 726 | /* Otherwise, set the begin_line flag if we've found a match on |
| 727 | * the beginning line, reset the bol_or_eol flag, and |
| 728 | * continue. */ |
| 729 | else { |
| 730 | if (current == real_current) |
| 731 | begin_line = TRUE; |
| 732 | bol_or_eol = FALSE; |
| 733 | } |
| 734 | #endif |
| 735 | |
David Lawrence Ramsey | f56cc9e | 2004-07-29 14:32:17 +0000 | [diff] [blame] | 736 | if (!replaceall) { |
David Lawrence Ramsey | 3de81bc | 2004-11-22 17:08:41 +0000 | [diff] [blame] | 737 | edit_redraw(real_current, pww_save); |
David Lawrence Ramsey | 1758640 | 2004-10-26 16:29:21 +0000 | [diff] [blame] | 738 | pww_save = placewewant; |
David Lawrence Ramsey | f56cc9e | 2004-07-29 14:32:17 +0000 | [diff] [blame] | 739 | } |
Chris Allegretta | 7662c86 | 2003-01-13 01:35:15 +0000 | [diff] [blame] | 740 | |
David Lawrence Ramsey | 29f03dc | 2004-11-03 21:11:38 +0000 | [diff] [blame] | 741 | /* Record for the return value that we found the search |
| 742 | * string. */ |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 743 | if (numreplaced == -1) |
| 744 | numreplaced = 0; |
David Lawrence Ramsey | 5ffbec5 | 2003-09-16 01:16:49 +0000 | [diff] [blame] | 745 | |
Chris Allegretta | d00e6df | 2000-11-29 04:33:26 +0000 | [diff] [blame] | 746 | if (!replaceall) { |
David Lawrence Ramsey | 5ffbec5 | 2003-09-16 01:16:49 +0000 | [diff] [blame] | 747 | char *exp_word; |
| 748 | size_t xpt = xplustabs(); |
| 749 | |
| 750 | exp_word = display_string(current->data, xpt, |
| 751 | strnlenpt(current->data, match_len + current_x) - xpt); |
| 752 | |
Chris Allegretta | d00e6df | 2000-11-29 04:33:26 +0000 | [diff] [blame] | 753 | curs_set(0); |
David Lawrence Ramsey | 5ffbec5 | 2003-09-16 01:16:49 +0000 | [diff] [blame] | 754 | do_replace_highlight(TRUE, exp_word); |
Chris Allegretta | d00e6df | 2000-11-29 04:33:26 +0000 | [diff] [blame] | 755 | |
David Lawrence Ramsey | 6aec4b8 | 2004-03-15 20:26:30 +0000 | [diff] [blame] | 756 | i = do_yesno(TRUE, _("Replace this instance?")); |
Chris Allegretta | 27eb13f | 2000-11-05 16:52:21 +0000 | [diff] [blame] | 757 | |
David Lawrence Ramsey | 5ffbec5 | 2003-09-16 01:16:49 +0000 | [diff] [blame] | 758 | do_replace_highlight(FALSE, exp_word); |
| 759 | free(exp_word); |
Chris Allegretta | d00e6df | 2000-11-29 04:33:26 +0000 | [diff] [blame] | 760 | curs_set(1); |
David Lawrence Ramsey | afb75f2 | 2003-12-29 02:15:23 +0000 | [diff] [blame] | 761 | |
David Lawrence Ramsey | 9bf486f | 2004-10-26 20:58:30 +0000 | [diff] [blame] | 762 | if (i == -1) { /* We canceled the replace. */ |
| 763 | if (canceled != NULL) |
| 764 | *canceled = TRUE; |
David Lawrence Ramsey | afb75f2 | 2003-12-29 02:15:23 +0000 | [diff] [blame] | 765 | break; |
David Lawrence Ramsey | 9bf486f | 2004-10-26 20:58:30 +0000 | [diff] [blame] | 766 | } |
Chris Allegretta | d00e6df | 2000-11-29 04:33:26 +0000 | [diff] [blame] | 767 | } |
| 768 | |
David Lawrence Ramsey | 18394ac | 2003-12-24 03:13:44 +0000 | [diff] [blame] | 769 | #ifdef HAVE_REGEX_H |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 770 | /* Set the bol_or_eol flag if we're doing a bol and/or eol regex |
David Lawrence Ramsey | e190ff3 | 2004-01-03 21:42:25 +0000 | [diff] [blame] | 771 | * replace ("^", "$", or "^$"). */ |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 772 | if (ISSET(USE_REGEXP) && regexp_bol_or_eol(&search_regexp, |
| 773 | needle)) |
David Lawrence Ramsey | a3370c4 | 2004-04-05 01:08:14 +0000 | [diff] [blame] | 774 | bol_or_eol = TRUE; |
David Lawrence Ramsey | 18394ac | 2003-12-24 03:13:44 +0000 | [diff] [blame] | 775 | #endif |
| 776 | |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 777 | if (i > 0 || replaceall) { /* Yes, replace it!!!! */ |
David Lawrence Ramsey | afb75f2 | 2003-12-29 02:15:23 +0000 | [diff] [blame] | 778 | char *copy; |
David Lawrence Ramsey | 687776b | 2004-10-30 01:16:08 +0000 | [diff] [blame] | 779 | size_t length_change; |
Chris Allegretta | 1939c35 | 2003-01-26 04:26:25 +0000 | [diff] [blame] | 780 | |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 781 | if (i == 2) |
David Lawrence Ramsey | 576bf33 | 2004-07-12 03:10:30 +0000 | [diff] [blame] | 782 | replaceall = TRUE; |
Chris Allegretta | 27eb13f | 2000-11-05 16:52:21 +0000 | [diff] [blame] | 783 | |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 784 | copy = replace_line(needle); |
Chris Allegretta | 27eb13f | 2000-11-05 16:52:21 +0000 | [diff] [blame] | 785 | |
Chris Allegretta | 1939c35 | 2003-01-26 04:26:25 +0000 | [diff] [blame] | 786 | length_change = strlen(copy) - strlen(current->data); |
| 787 | |
Chris Allegretta | 1939c35 | 2003-01-26 04:26:25 +0000 | [diff] [blame] | 788 | #ifndef NANO_SMALL |
David Lawrence Ramsey | dcc201b | 2004-11-05 14:37:18 +0000 | [diff] [blame] | 789 | /* If the mark was on and (mark_beginbuf, mark_begin_x) was |
| 790 | * the top of it, don't change mark_beginx. */ |
| 791 | if (!old_mark_set || !right_side_up) { |
| 792 | /* Keep mark_beginx in sync with the text changes. */ |
David Lawrence Ramsey | 40a6c8c | 2004-11-27 21:10:11 +0000 | [diff] [blame] | 793 | if (current == mark_beginbuf && |
| 794 | mark_beginx > current_x) { |
David Lawrence Ramsey | 40bdb68 | 2004-11-03 22:03:41 +0000 | [diff] [blame] | 795 | if (mark_beginx < current_x + match_len) |
| 796 | mark_beginx = current_x; |
| 797 | else |
| 798 | mark_beginx += length_change; |
| 799 | } |
Chris Allegretta | 1939c35 | 2003-01-26 04:26:25 +0000 | [diff] [blame] | 800 | } |
Chris Allegretta | 1939c35 | 2003-01-26 04:26:25 +0000 | [diff] [blame] | 801 | |
David Lawrence Ramsey | dcc201b | 2004-11-05 14:37:18 +0000 | [diff] [blame] | 802 | /* If the mark was on and (current, current_x) was the top |
| 803 | * of it, don't change real_current_x. */ |
| 804 | if (!old_mark_set || right_side_up) { |
David Lawrence Ramsey | 40bdb68 | 2004-11-03 22:03:41 +0000 | [diff] [blame] | 805 | #endif |
David Lawrence Ramsey | dcc201b | 2004-11-05 14:37:18 +0000 | [diff] [blame] | 806 | /* Keep real_current_x in sync with the text changes. */ |
David Lawrence Ramsey | 40a6c8c | 2004-11-27 21:10:11 +0000 | [diff] [blame] | 807 | if (current == real_current && |
| 808 | current_x <= *real_current_x) { |
David Lawrence Ramsey | 40bdb68 | 2004-11-03 22:03:41 +0000 | [diff] [blame] | 809 | if (*real_current_x < current_x + match_len) |
| 810 | *real_current_x = current_x + match_len; |
| 811 | *real_current_x += length_change; |
David Lawrence Ramsey | 40bdb68 | 2004-11-03 22:03:41 +0000 | [diff] [blame] | 812 | } |
David Lawrence Ramsey | dcc201b | 2004-11-05 14:37:18 +0000 | [diff] [blame] | 813 | #ifndef NANO_SMALL |
Chris Allegretta | 1939c35 | 2003-01-26 04:26:25 +0000 | [diff] [blame] | 814 | } |
David Lawrence Ramsey | dcc201b | 2004-11-05 14:37:18 +0000 | [diff] [blame] | 815 | #endif |
Chris Allegretta | 1939c35 | 2003-01-26 04:26:25 +0000 | [diff] [blame] | 816 | |
| 817 | /* Set the cursor at the last character of the replacement |
David Lawrence Ramsey | 45cfbec | 2003-11-28 16:04:24 +0000 | [diff] [blame] | 818 | * text, so searching will resume after the replacement |
David Lawrence Ramsey | 7a97e18 | 2004-10-30 01:03:15 +0000 | [diff] [blame] | 819 | * text. Note that current_x might be set to (size_t)-1 |
| 820 | * here. */ |
Chris Allegretta | 1939c35 | 2003-01-26 04:26:25 +0000 | [diff] [blame] | 821 | #ifndef NANO_SMALL |
David Lawrence Ramsey | 18394ac | 2003-12-24 03:13:44 +0000 | [diff] [blame] | 822 | if (!ISSET(REVERSE_SEARCH)) |
Chris Allegretta | 1939c35 | 2003-01-26 04:26:25 +0000 | [diff] [blame] | 823 | #endif |
| 824 | current_x += match_len + length_change - 1; |
| 825 | |
David Lawrence Ramsey | b7cb6a3 | 2003-10-31 17:53:38 +0000 | [diff] [blame] | 826 | /* Cleanup. */ |
Chris Allegretta | 1939c35 | 2003-01-26 04:26:25 +0000 | [diff] [blame] | 827 | totsize += length_change; |
Chris Allegretta | 27eb13f | 2000-11-05 16:52:21 +0000 | [diff] [blame] | 828 | free(current->data); |
| 829 | current->data = copy; |
Chris Allegretta | 27eb13f | 2000-11-05 16:52:21 +0000 | [diff] [blame] | 830 | |
David Lawrence Ramsey | 2ed225f | 2004-05-28 20:44:09 +0000 | [diff] [blame] | 831 | if (!replaceall) { |
| 832 | #ifdef ENABLE_COLOR |
| 833 | if (ISSET(COLOR_SYNTAX)) |
| 834 | edit_refresh(); |
| 835 | else |
| 836 | #endif |
| 837 | update_line(current, current_x); |
| 838 | } |
| 839 | |
Chris Allegretta | 27eb13f | 2000-11-05 16:52:21 +0000 | [diff] [blame] | 840 | set_modified(); |
| 841 | numreplaced++; |
David Lawrence Ramsey | afb75f2 | 2003-12-29 02:15:23 +0000 | [diff] [blame] | 842 | } |
Chris Allegretta | 27eb13f | 2000-11-05 16:52:21 +0000 | [diff] [blame] | 843 | } |
| 844 | |
David Lawrence Ramsey | 40bdb68 | 2004-11-03 22:03:41 +0000 | [diff] [blame] | 845 | #ifndef NANO_SMALL |
David Lawrence Ramsey | 40bdb68 | 2004-11-03 22:03:41 +0000 | [diff] [blame] | 846 | if (old_mark_set) { |
David Lawrence Ramsey | f978f04 | 2004-11-04 16:45:48 +0000 | [diff] [blame] | 847 | /* If the mark was on, unpartition the filestruct so that it |
| 848 | * contains all the text again, set edittop back to what it was |
| 849 | * before, turn the mark back on, and refresh the screen. */ |
David Lawrence Ramsey | 74d8707 | 2004-11-22 00:16:23 +0000 | [diff] [blame] | 850 | unpartition_filestruct(&filepart); |
David Lawrence Ramsey | 40bdb68 | 2004-11-03 22:03:41 +0000 | [diff] [blame] | 851 | edittop = edittop_save; |
| 852 | SET(MARK_ISSET); |
| 853 | edit_refresh(); |
| 854 | } |
| 855 | #endif |
| 856 | |
Chris Allegretta | 7662c86 | 2003-01-13 01:35:15 +0000 | [diff] [blame] | 857 | /* If text has been added to the magicline, make a new magicline. */ |
| 858 | if (filebot->data[0] != '\0') |
| 859 | new_magicline(); |
| 860 | |
Chris Allegretta | 27eb13f | 2000-11-05 16:52:21 +0000 | [diff] [blame] | 861 | return numreplaced; |
| 862 | } |
| 863 | |
Chris Allegretta | 7662c86 | 2003-01-13 01:35:15 +0000 | [diff] [blame] | 864 | /* Replace a string. */ |
David Lawrence Ramsey | 72e51ab | 2004-07-02 14:31:03 +0000 | [diff] [blame] | 865 | void do_replace(void) |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 866 | { |
David Lawrence Ramsey | 53752e8 | 2004-10-18 22:19:22 +0000 | [diff] [blame] | 867 | int i; |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 868 | filestruct *edittop_save, *begin; |
David Lawrence Ramsey | 2eb7459 | 2004-10-21 16:25:44 +0000 | [diff] [blame] | 869 | size_t beginx, pww_save; |
David Lawrence Ramsey | 53752e8 | 2004-10-18 22:19:22 +0000 | [diff] [blame] | 870 | ssize_t numreplaced; |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 871 | |
Chris Allegretta | 5050aa6 | 2001-04-22 07:10:21 +0000 | [diff] [blame] | 872 | if (ISSET(VIEW_MODE)) { |
| 873 | print_view_warning(); |
| 874 | replace_abort(); |
David Lawrence Ramsey | 72e51ab | 2004-07-02 14:31:03 +0000 | [diff] [blame] | 875 | return; |
Chris Allegretta | 5050aa6 | 2001-04-22 07:10:21 +0000 | [diff] [blame] | 876 | } |
| 877 | |
David Lawrence Ramsey | d532f19 | 2004-10-04 22:37:56 +0000 | [diff] [blame] | 878 | i = search_init(TRUE, FALSE); |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 879 | if (i == -1) { /* Cancel, Go to Line, blank search |
| 880 | * string, or regcomp() failed. */ |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 881 | replace_abort(); |
David Lawrence Ramsey | 72e51ab | 2004-07-02 14:31:03 +0000 | [diff] [blame] | 882 | return; |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 883 | } else if (i == -2) { /* No Replace. */ |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 884 | do_search(); |
David Lawrence Ramsey | 72e51ab | 2004-07-02 14:31:03 +0000 | [diff] [blame] | 885 | return; |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 886 | } else if (i == 1) /* Case Sensitive, Backwards, or Regexp |
| 887 | * search toggle. */ |
| 888 | do_replace(); |
| 889 | |
| 890 | if (i != 0) |
David Lawrence Ramsey | 72e51ab | 2004-07-02 14:31:03 +0000 | [diff] [blame] | 891 | return; |
Chris Allegretta | bd9e7c3 | 2000-10-26 01:44:42 +0000 | [diff] [blame] | 892 | |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 893 | /* If answer is not "", add answer to the search history list and |
| 894 | * copy answer into last_search. */ |
| 895 | if (answer[0] != '\0') { |
Chris Allegretta | 5beed50 | 2003-01-05 20:41:21 +0000 | [diff] [blame] | 896 | #ifndef NANO_SMALL |
Chris Allegretta | 6328792 | 2003-01-05 20:43:49 +0000 | [diff] [blame] | 897 | update_history(&search_history, answer); |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 898 | #endif |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 899 | last_search = mallocstrcpy(last_search, answer); |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 900 | } |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 901 | |
Chris Allegretta | 15c28f8 | 2003-01-05 21:47:06 +0000 | [diff] [blame] | 902 | #ifndef NANO_SMALL |
| 903 | replace_history.current = (historytype *)&replace_history.next; |
| 904 | last_replace = mallocstrcpy(last_replace, ""); |
| 905 | #endif |
Chris Allegretta | 6df90f5 | 2002-07-19 01:08:59 +0000 | [diff] [blame] | 906 | |
David Lawrence Ramsey | 6aec4b8 | 2004-03-15 20:26:30 +0000 | [diff] [blame] | 907 | i = statusq(FALSE, replace_list_2, last_replace, |
Chris Allegretta | 5beed50 | 2003-01-05 20:41:21 +0000 | [diff] [blame] | 908 | #ifndef NANO_SMALL |
David Lawrence Ramsey | 6aec4b8 | 2004-03-15 20:26:30 +0000 | [diff] [blame] | 909 | &replace_history, |
Chris Allegretta | 5beed50 | 2003-01-05 20:41:21 +0000 | [diff] [blame] | 910 | #endif |
David Lawrence Ramsey | 6aec4b8 | 2004-03-15 20:26:30 +0000 | [diff] [blame] | 911 | _("Replace with")); |
Chris Allegretta | 15c28f8 | 2003-01-05 21:47:06 +0000 | [diff] [blame] | 912 | |
Chris Allegretta | 5beed50 | 2003-01-05 20:41:21 +0000 | [diff] [blame] | 913 | #ifndef NANO_SMALL |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 914 | /* Add this replace string to the replace history list. i == 0 |
| 915 | * means that the string is not "". */ |
| 916 | if (i == 0) |
Chris Allegretta | 5beed50 | 2003-01-05 20:41:21 +0000 | [diff] [blame] | 917 | update_history(&replace_history, answer); |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 918 | #endif |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 919 | |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 920 | if (i != 0 && i != -2) { |
| 921 | if (i == -1) { /* Cancel. */ |
| 922 | if (last_replace[0] != '\0') |
| 923 | answer = mallocstrcpy(answer, last_replace); |
David Lawrence Ramsey | d132210 | 2004-08-26 04:22:54 +0000 | [diff] [blame] | 924 | statusbar(_("Cancelled")); |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 925 | } |
| 926 | replace_abort(); |
David Lawrence Ramsey | 72e51ab | 2004-07-02 14:31:03 +0000 | [diff] [blame] | 927 | return; |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 928 | } |
| 929 | |
| 930 | last_replace = mallocstrcpy(last_replace, answer); |
| 931 | |
| 932 | /* Save where we are. */ |
David Lawrence Ramsey | 27fbc69 | 2004-10-19 21:09:37 +0000 | [diff] [blame] | 933 | edittop_save = edittop; |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 934 | begin = current; |
Chris Allegretta | bc72e36 | 2002-02-16 20:03:44 +0000 | [diff] [blame] | 935 | beginx = current_x; |
David Lawrence Ramsey | 2eb7459 | 2004-10-21 16:25:44 +0000 | [diff] [blame] | 936 | pww_save = placewewant; |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 937 | |
David Lawrence Ramsey | 9bf486f | 2004-10-26 20:58:30 +0000 | [diff] [blame] | 938 | numreplaced = do_replace_loop(last_search, begin, &beginx, FALSE, |
| 939 | NULL); |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 940 | |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 941 | /* Restore where we were. */ |
David Lawrence Ramsey | 9062579 | 2004-07-30 20:21:34 +0000 | [diff] [blame] | 942 | edittop = edittop_save; |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 943 | current = begin; |
Chris Allegretta | bc72e36 | 2002-02-16 20:03:44 +0000 | [diff] [blame] | 944 | current_x = beginx; |
David Lawrence Ramsey | 2eb7459 | 2004-10-21 16:25:44 +0000 | [diff] [blame] | 945 | placewewant = pww_save; |
David Lawrence Ramsey | 27fbc69 | 2004-10-19 21:09:37 +0000 | [diff] [blame] | 946 | |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 947 | renumber_all(); |
David Lawrence Ramsey | 9062579 | 2004-07-30 20:21:34 +0000 | [diff] [blame] | 948 | edit_refresh(); |
Chris Allegretta | 7662c86 | 2003-01-13 01:35:15 +0000 | [diff] [blame] | 949 | |
| 950 | if (numreplaced >= 0) |
David Lawrence Ramsey | 53752e8 | 2004-10-18 22:19:22 +0000 | [diff] [blame] | 951 | statusbar(P_("Replaced %ld occurrence", "Replaced %ld occurrences", |
| 952 | (long)numreplaced), (long)numreplaced); |
Chris Allegretta | 7662c86 | 2003-01-13 01:35:15 +0000 | [diff] [blame] | 953 | |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 954 | replace_abort(); |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 955 | } |
| 956 | |
David Lawrence Ramsey | c53ab2a | 2004-08-04 18:24:53 +0000 | [diff] [blame] | 957 | void do_gotoline(int line, bool save_pos) |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 958 | { |
David Lawrence Ramsey | 9062579 | 2004-07-30 20:21:34 +0000 | [diff] [blame] | 959 | if (line <= 0) { /* Ask for it. */ |
David Lawrence Ramsey | 6aec4b8 | 2004-03-15 20:26:30 +0000 | [diff] [blame] | 960 | char *ans = mallocstrcpy(NULL, answer); |
David Lawrence Ramsey | e5d8f32 | 2004-09-30 22:07:21 +0000 | [diff] [blame] | 961 | int i = statusq(FALSE, gotoline_list, line < 0 ? ans : "", |
Chris Allegretta | 7662c86 | 2003-01-13 01:35:15 +0000 | [diff] [blame] | 962 | #ifndef NANO_SMALL |
David Lawrence Ramsey | 6aec4b8 | 2004-03-15 20:26:30 +0000 | [diff] [blame] | 963 | NULL, |
Chris Allegretta | 7662c86 | 2003-01-13 01:35:15 +0000 | [diff] [blame] | 964 | #endif |
David Lawrence Ramsey | 6aec4b8 | 2004-03-15 20:26:30 +0000 | [diff] [blame] | 965 | _("Enter line number")); |
| 966 | |
| 967 | free(ans); |
Chris Allegretta | a90d0cf | 2003-02-10 02:55:03 +0000 | [diff] [blame] | 968 | |
| 969 | /* Cancel, or Enter with blank string. */ |
David Lawrence Ramsey | 4c9e8f4 | 2004-10-04 16:01:37 +0000 | [diff] [blame] | 970 | if (i < 0) { |
David Lawrence Ramsey | b77ec62 | 2004-09-28 15:06:15 +0000 | [diff] [blame] | 971 | statusbar(_("Cancelled")); |
David Lawrence Ramsey | 4c9e8f4 | 2004-10-04 16:01:37 +0000 | [diff] [blame] | 972 | display_main_list(); |
David Lawrence Ramsey | e5d8f32 | 2004-09-30 22:07:21 +0000 | [diff] [blame] | 973 | return; |
| 974 | } |
| 975 | |
David Lawrence Ramsey | 4c9e8f4 | 2004-10-04 16:01:37 +0000 | [diff] [blame] | 976 | if (i == NANO_TOOTHERWHEREIS_KEY) { |
David Lawrence Ramsey | d532f19 | 2004-10-04 22:37:56 +0000 | [diff] [blame] | 977 | /* Keep answer up on the statusbar. */ |
| 978 | search_init(TRUE, TRUE); |
| 979 | |
David Lawrence Ramsey | 4c9e8f4 | 2004-10-04 16:01:37 +0000 | [diff] [blame] | 980 | do_search(); |
David Lawrence Ramsey | 72e51ab | 2004-07-02 14:31:03 +0000 | [diff] [blame] | 981 | return; |
Rocco Corsi | 4dfaf93 | 2001-04-20 01:59:55 +0000 | [diff] [blame] | 982 | } |
| 983 | |
David Lawrence Ramsey | 1f204c0 | 2004-10-15 01:39:46 +0000 | [diff] [blame] | 984 | /* Do a bounds check. Display a warning on an out-of-bounds |
| 985 | * line number only if we hit Enter at the statusbar prompt. */ |
David Lawrence Ramsey | c53ab2a | 2004-08-04 18:24:53 +0000 | [diff] [blame] | 986 | if (!parse_num(answer, &line) || line < 0) { |
David Lawrence Ramsey | 1f204c0 | 2004-10-15 01:39:46 +0000 | [diff] [blame] | 987 | if (i == 0) |
| 988 | statusbar(_("Come on, be reasonable")); |
Chris Allegretta | e1e0fd6 | 2003-04-15 01:15:09 +0000 | [diff] [blame] | 989 | display_main_list(); |
David Lawrence Ramsey | 72e51ab | 2004-07-02 14:31:03 +0000 | [diff] [blame] | 990 | return; |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 991 | } |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 992 | } |
| 993 | |
David Lawrence Ramsey | 9062579 | 2004-07-30 20:21:34 +0000 | [diff] [blame] | 994 | if (current->lineno > line) { |
| 995 | for (; current->prev != NULL && current->lineno > line; |
| 996 | current = current->prev) |
| 997 | ; |
| 998 | } else { |
| 999 | for (; current->next != NULL && current->lineno < line; |
| 1000 | current = current->next) |
| 1001 | ; |
| 1002 | } |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 1003 | |
Rocco Corsi | 4dfaf93 | 2001-04-20 01:59:55 +0000 | [diff] [blame] | 1004 | current_x = 0; |
Chris Allegretta | 2d7893d | 2001-07-11 02:08:33 +0000 | [diff] [blame] | 1005 | |
David Lawrence Ramsey | 72e51ab | 2004-07-02 14:31:03 +0000 | [diff] [blame] | 1006 | /* If save_pos is TRUE, don't change the cursor position when |
David Lawrence Ramsey | c6908f2 | 2004-03-11 02:20:25 +0000 | [diff] [blame] | 1007 | * updating the edit window. */ |
David Lawrence Ramsey | 20b8350 | 2004-08-26 18:07:58 +0000 | [diff] [blame] | 1008 | edit_update(save_pos ? NONE : CENTER); |
David Lawrence Ramsey | c6908f2 | 2004-03-11 02:20:25 +0000 | [diff] [blame] | 1009 | |
David Lawrence Ramsey | c596755 | 2002-06-21 03:20:06 +0000 | [diff] [blame] | 1010 | placewewant = 0; |
Chris Allegretta | e1e0fd6 | 2003-04-15 01:15:09 +0000 | [diff] [blame] | 1011 | display_main_list(); |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 1012 | } |
| 1013 | |
David Lawrence Ramsey | 72e51ab | 2004-07-02 14:31:03 +0000 | [diff] [blame] | 1014 | void do_gotoline_void(void) |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 1015 | { |
David Lawrence Ramsey | 72e51ab | 2004-07-02 14:31:03 +0000 | [diff] [blame] | 1016 | do_gotoline(0, FALSE); |
Chris Allegretta | bceb1b2 | 2000-06-19 04:22:15 +0000 | [diff] [blame] | 1017 | } |
Chris Allegretta | e1f1452 | 2001-09-19 03:19:43 +0000 | [diff] [blame] | 1018 | |
David Lawrence Ramsey | 5db0cdc | 2002-06-28 22:45:14 +0000 | [diff] [blame] | 1019 | #if defined(ENABLE_MULTIBUFFER) || !defined(DISABLE_SPELLER) |
David Lawrence Ramsey | 7a97e18 | 2004-10-30 01:03:15 +0000 | [diff] [blame] | 1020 | void do_gotopos(int line, size_t pos_x, int pos_y, size_t pos_pww) |
Chris Allegretta | e1f1452 | 2001-09-19 03:19:43 +0000 | [diff] [blame] | 1021 | { |
David Lawrence Ramsey | 9062579 | 2004-07-30 20:21:34 +0000 | [diff] [blame] | 1022 | /* Since do_gotoline() resets the x-coordinate but not the |
| 1023 | * y-coordinate, set the coordinates up this way. */ |
Chris Allegretta | e1f1452 | 2001-09-19 03:19:43 +0000 | [diff] [blame] | 1024 | current_y = pos_y; |
David Lawrence Ramsey | 72e51ab | 2004-07-02 14:31:03 +0000 | [diff] [blame] | 1025 | do_gotoline(line, TRUE); |
Chris Allegretta | 2084acc | 2001-11-29 03:43:08 +0000 | [diff] [blame] | 1026 | |
David Lawrence Ramsey | 9062579 | 2004-07-30 20:21:34 +0000 | [diff] [blame] | 1027 | /* Make sure that the x-coordinate is sane here. */ |
| 1028 | current_x = strlen(current->data); |
| 1029 | if (pos_x < current_x) |
| 1030 | current_x = pos_x; |
Chris Allegretta | 2084acc | 2001-11-29 03:43:08 +0000 | [diff] [blame] | 1031 | |
David Lawrence Ramsey | 9062579 | 2004-07-30 20:21:34 +0000 | [diff] [blame] | 1032 | /* Set the rest of the coordinates up. */ |
David Lawrence Ramsey | 86e851b | 2004-07-28 20:46:25 +0000 | [diff] [blame] | 1033 | placewewant = pos_pww; |
Chris Allegretta | e1f1452 | 2001-09-19 03:19:43 +0000 | [diff] [blame] | 1034 | update_line(current, pos_x); |
| 1035 | } |
| 1036 | #endif |
Chris Allegretta | 8d990b5 | 2001-09-22 22:14:25 +0000 | [diff] [blame] | 1037 | |
| 1038 | #if !defined(NANO_SMALL) && defined(HAVE_REGEX_H) |
David Lawrence Ramsey | 72e51ab | 2004-07-02 14:31:03 +0000 | [diff] [blame] | 1039 | void do_find_bracket(void) |
Chris Allegretta | 8d990b5 | 2001-09-22 22:14:25 +0000 | [diff] [blame] | 1040 | { |
| 1041 | char ch_under_cursor, wanted_ch; |
David Lawrence Ramsey | e21adfa | 2002-09-13 18:14:04 +0000 | [diff] [blame] | 1042 | const char *pos, *brackets = "([{<>}])"; |
Chris Allegretta | 8d990b5 | 2001-09-22 22:14:25 +0000 | [diff] [blame] | 1043 | char regexp_pat[] = "[ ]"; |
David Lawrence Ramsey | 1758640 | 2004-10-26 16:29:21 +0000 | [diff] [blame] | 1044 | size_t current_x_save, pww_save; |
David Lawrence Ramsey | 86e851b | 2004-07-28 20:46:25 +0000 | [diff] [blame] | 1045 | int count = 1; |
David Lawrence Ramsey | edab0cc | 2004-07-03 03:09:12 +0000 | [diff] [blame] | 1046 | long flags_save; |
Chris Allegretta | 8d990b5 | 2001-09-22 22:14:25 +0000 | [diff] [blame] | 1047 | filestruct *current_save; |
| 1048 | |
| 1049 | ch_under_cursor = current->data[current_x]; |
Chris Allegretta | 5beed50 | 2003-01-05 20:41:21 +0000 | [diff] [blame] | 1050 | |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 1051 | pos = strchr(brackets, ch_under_cursor); |
| 1052 | if (ch_under_cursor == '\0' || pos == NULL) { |
Chris Allegretta | 8d990b5 | 2001-09-22 22:14:25 +0000 | [diff] [blame] | 1053 | statusbar(_("Not a bracket")); |
David Lawrence Ramsey | 72e51ab | 2004-07-02 14:31:03 +0000 | [diff] [blame] | 1054 | return; |
Chris Allegretta | 8d990b5 | 2001-09-22 22:14:25 +0000 | [diff] [blame] | 1055 | } |
| 1056 | |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 1057 | assert(strlen(brackets) % 2 == 0); |
| 1058 | wanted_ch = brackets[(strlen(brackets) - 1) - (pos - brackets)]; |
Chris Allegretta | 8d990b5 | 2001-09-22 22:14:25 +0000 | [diff] [blame] | 1059 | |
Chris Allegretta | 8d990b5 | 2001-09-22 22:14:25 +0000 | [diff] [blame] | 1060 | current_save = current; |
David Lawrence Ramsey | b6377c9 | 2004-10-09 20:10:55 +0000 | [diff] [blame] | 1061 | current_x_save = current_x; |
David Lawrence Ramsey | 1758640 | 2004-10-26 16:29:21 +0000 | [diff] [blame] | 1062 | pww_save = placewewant; |
David Lawrence Ramsey | edab0cc | 2004-07-03 03:09:12 +0000 | [diff] [blame] | 1063 | flags_save = flags; |
Chris Allegretta | 8d990b5 | 2001-09-22 22:14:25 +0000 | [diff] [blame] | 1064 | SET(USE_REGEXP); |
| 1065 | |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 1066 | /* Apparent near redundancy with regexp_pat[] here is needed. |
| 1067 | * "[][]" works, "[[]]" doesn't. */ |
Chris Allegretta | 8d990b5 | 2001-09-22 22:14:25 +0000 | [diff] [blame] | 1068 | |
David Lawrence Ramsey | fd3039a | 2004-07-17 19:49:12 +0000 | [diff] [blame] | 1069 | if (pos < brackets + (strlen(brackets) / 2)) { |
| 1070 | /* On a left bracket. */ |
Chris Allegretta | 8d990b5 | 2001-09-22 22:14:25 +0000 | [diff] [blame] | 1071 | regexp_pat[1] = wanted_ch; |
| 1072 | regexp_pat[2] = ch_under_cursor; |
| 1073 | UNSET(REVERSE_SEARCH); |
David Lawrence Ramsey | fd3039a | 2004-07-17 19:49:12 +0000 | [diff] [blame] | 1074 | } else { |
| 1075 | /* On a right bracket. */ |
Chris Allegretta | 8d990b5 | 2001-09-22 22:14:25 +0000 | [diff] [blame] | 1076 | regexp_pat[1] = ch_under_cursor; |
| 1077 | regexp_pat[2] = wanted_ch; |
| 1078 | SET(REVERSE_SEARCH); |
| 1079 | } |
| 1080 | |
| 1081 | regexp_init(regexp_pat); |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 1082 | /* We constructed regexp_pat to be a valid expression. */ |
David Lawrence Ramsey | 4b741b9 | 2004-04-30 19:40:03 +0000 | [diff] [blame] | 1083 | assert(regexp_compiled); |
Chris Allegretta | 8d990b5 | 2001-09-22 22:14:25 +0000 | [diff] [blame] | 1084 | |
David Lawrence Ramsey | e5e88fd | 2004-10-31 13:20:30 +0000 | [diff] [blame] | 1085 | findnextstr_wrap_reset(); |
David Lawrence Ramsey | 6aec4b8 | 2004-03-15 20:26:30 +0000 | [diff] [blame] | 1086 | while (TRUE) { |
David Lawrence Ramsey | c510042 | 2004-08-27 20:28:34 +0000 | [diff] [blame] | 1087 | if (findnextstr(FALSE, FALSE, FALSE, current, current_x, |
David Lawrence Ramsey | 77b284a | 2004-10-27 02:21:01 +0000 | [diff] [blame] | 1088 | regexp_pat, NULL)) { |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 1089 | /* Found identical bracket. */ |
Chris Allegretta | 7662c86 | 2003-01-13 01:35:15 +0000 | [diff] [blame] | 1090 | if (current->data[current_x] == ch_under_cursor) |
Chris Allegretta | 8d990b5 | 2001-09-22 22:14:25 +0000 | [diff] [blame] | 1091 | count++; |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 1092 | /* Found complementary bracket. */ |
| 1093 | else if (--count == 0) { |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 1094 | placewewant = xplustabs(); |
David Lawrence Ramsey | 1758640 | 2004-10-26 16:29:21 +0000 | [diff] [blame] | 1095 | edit_redraw(current_save, pww_save); |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 1096 | break; |
Chris Allegretta | 8d990b5 | 2001-09-22 22:14:25 +0000 | [diff] [blame] | 1097 | } |
Chris Allegretta | 7662c86 | 2003-01-13 01:35:15 +0000 | [diff] [blame] | 1098 | } else { |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 1099 | /* Didn't find either a left or right bracket. */ |
Chris Allegretta | 8d990b5 | 2001-09-22 22:14:25 +0000 | [diff] [blame] | 1100 | statusbar(_("No matching bracket")); |
Chris Allegretta | 8d990b5 | 2001-09-22 22:14:25 +0000 | [diff] [blame] | 1101 | current = current_save; |
David Lawrence Ramsey | b6377c9 | 2004-10-09 20:10:55 +0000 | [diff] [blame] | 1102 | current_x = current_x_save; |
Chris Allegretta | e1e0fd6 | 2003-04-15 01:15:09 +0000 | [diff] [blame] | 1103 | update_line(current, current_x); |
Chris Allegretta | 8d990b5 | 2001-09-22 22:14:25 +0000 | [diff] [blame] | 1104 | break; |
| 1105 | } |
| 1106 | } |
| 1107 | |
David Lawrence Ramsey | 1044d74 | 2004-02-24 20:41:39 +0000 | [diff] [blame] | 1108 | regexp_cleanup(); |
David Lawrence Ramsey | edab0cc | 2004-07-03 03:09:12 +0000 | [diff] [blame] | 1109 | flags = flags_save; |
Chris Allegretta | 8d990b5 | 2001-09-22 22:14:25 +0000 | [diff] [blame] | 1110 | } |
| 1111 | #endif |
Chris Allegretta | 5beed50 | 2003-01-05 20:41:21 +0000 | [diff] [blame] | 1112 | |
| 1113 | #ifndef NANO_SMALL |
| 1114 | /* |
| 1115 | * search and replace history list support functions |
| 1116 | */ |
| 1117 | |
| 1118 | /* initialize search and replace history lists */ |
| 1119 | void history_init(void) |
| 1120 | { |
| 1121 | search_history.next = (historytype *)&search_history.prev; |
| 1122 | search_history.prev = NULL; |
| 1123 | search_history.tail = (historytype *)&search_history.next; |
| 1124 | search_history.current = search_history.next; |
| 1125 | search_history.count = 0; |
| 1126 | search_history.len = 0; |
| 1127 | |
| 1128 | replace_history.next = (historytype *)&replace_history.prev; |
| 1129 | replace_history.prev = NULL; |
| 1130 | replace_history.tail = (historytype *)&replace_history.next; |
| 1131 | replace_history.current = replace_history.next; |
| 1132 | replace_history.count = 0; |
| 1133 | replace_history.len = 0; |
| 1134 | } |
| 1135 | |
| 1136 | /* find first node containing string *s in history list *h */ |
David Lawrence Ramsey | 6420d44 | 2004-08-11 05:13:08 +0000 | [diff] [blame] | 1137 | historytype *find_node(historytype *h, const char *s) |
Chris Allegretta | 5beed50 | 2003-01-05 20:41:21 +0000 | [diff] [blame] | 1138 | { |
Chris Allegretta | 09fc430 | 2003-01-16 22:16:38 +0000 | [diff] [blame] | 1139 | for (; h->next != NULL; h = h->next) |
Chris Allegretta | 5beed50 | 2003-01-05 20:41:21 +0000 | [diff] [blame] | 1140 | if (strcmp(s, h->data) == 0) |
| 1141 | return h; |
| 1142 | return NULL; |
| 1143 | } |
| 1144 | |
| 1145 | /* remove node *r */ |
| 1146 | void remove_node(historytype *r) |
| 1147 | { |
| 1148 | r->prev->next = r->next; |
| 1149 | r->next->prev = r->prev; |
| 1150 | free(r->data); |
| 1151 | free(r); |
| 1152 | } |
| 1153 | |
| 1154 | /* add a node after node *h */ |
| 1155 | void insert_node(historytype *h, const char *s) |
| 1156 | { |
| 1157 | historytype *a; |
| 1158 | |
David Lawrence Ramsey | 70047ee | 2003-06-14 20:41:34 +0000 | [diff] [blame] | 1159 | a = (historytype *)nmalloc(sizeof(historytype)); |
Chris Allegretta | 5beed50 | 2003-01-05 20:41:21 +0000 | [diff] [blame] | 1160 | a->next = h->next; |
David Lawrence Ramsey | 6420d44 | 2004-08-11 05:13:08 +0000 | [diff] [blame] | 1161 | a->prev = h; |
Chris Allegretta | 5beed50 | 2003-01-05 20:41:21 +0000 | [diff] [blame] | 1162 | h->next->prev = a; |
| 1163 | h->next = a; |
| 1164 | a->data = mallocstrcpy(NULL, s); |
| 1165 | } |
| 1166 | |
| 1167 | /* update history list */ |
David Lawrence Ramsey | 6420d44 | 2004-08-11 05:13:08 +0000 | [diff] [blame] | 1168 | void update_history(historyheadtype *h, const char *s) |
Chris Allegretta | 5beed50 | 2003-01-05 20:41:21 +0000 | [diff] [blame] | 1169 | { |
| 1170 | historytype *p; |
| 1171 | |
Chris Allegretta | 09fc430 | 2003-01-16 22:16:38 +0000 | [diff] [blame] | 1172 | if ((p = find_node(h->next, s)) != NULL) { |
| 1173 | if (p == h->next) /* catch delete and re-insert of |
| 1174 | same string in 1st node */ |
Chris Allegretta | 5beed50 | 2003-01-05 20:41:21 +0000 | [diff] [blame] | 1175 | goto up_hs; |
Chris Allegretta | 09fc430 | 2003-01-16 22:16:38 +0000 | [diff] [blame] | 1176 | remove_node(p); /* delete identical older string */ |
Chris Allegretta | 5beed50 | 2003-01-05 20:41:21 +0000 | [diff] [blame] | 1177 | h->count--; |
| 1178 | } |
| 1179 | if (h->count == MAX_SEARCH_HISTORY) { /* list 'full', delete oldest */ |
| 1180 | remove_node(h->tail); |
| 1181 | h->count--; |
| 1182 | } |
| 1183 | insert_node((historytype *)h, s); |
| 1184 | h->count++; |
Chris Allegretta | f3de8b5 | 2003-01-16 23:44:46 +0000 | [diff] [blame] | 1185 | SET(HISTORY_CHANGED); |
Chris Allegretta | 09fc430 | 2003-01-16 22:16:38 +0000 | [diff] [blame] | 1186 | up_hs: |
Chris Allegretta | 5beed50 | 2003-01-05 20:41:21 +0000 | [diff] [blame] | 1187 | h->current = h->next; |
| 1188 | } |
| 1189 | |
| 1190 | /* return a pointer to either the next older history or NULL if no more */ |
| 1191 | char *get_history_older(historyheadtype *h) |
| 1192 | { |
Chris Allegretta | 09fc430 | 2003-01-16 22:16:38 +0000 | [diff] [blame] | 1193 | if (h->current->next != NULL) { /* any older entries? */ |
Chris Allegretta | 5beed50 | 2003-01-05 20:41:21 +0000 | [diff] [blame] | 1194 | h->current = h->current->next; /* yes */ |
| 1195 | return h->current->data; /* return it */ |
| 1196 | } |
| 1197 | return NULL; /* end of list */ |
| 1198 | } |
| 1199 | |
| 1200 | char *get_history_newer(historyheadtype *h) |
| 1201 | { |
Chris Allegretta | 09fc430 | 2003-01-16 22:16:38 +0000 | [diff] [blame] | 1202 | if (h->current->prev != NULL) { |
Chris Allegretta | 5beed50 | 2003-01-05 20:41:21 +0000 | [diff] [blame] | 1203 | h->current = h->current->prev; |
Chris Allegretta | 09fc430 | 2003-01-16 22:16:38 +0000 | [diff] [blame] | 1204 | if (h->current->prev != NULL) |
Chris Allegretta | 5beed50 | 2003-01-05 20:41:21 +0000 | [diff] [blame] | 1205 | return h->current->data; |
| 1206 | } |
| 1207 | return NULL; |
| 1208 | } |
| 1209 | |
| 1210 | /* get a completion */ |
| 1211 | char *get_history_completion(historyheadtype *h, char *s) |
| 1212 | { |
| 1213 | historytype *p; |
| 1214 | |
Chris Allegretta | 09fc430 | 2003-01-16 22:16:38 +0000 | [diff] [blame] | 1215 | for (p = h->current->next; p->next != NULL; p = p->next) { |
| 1216 | if (strncmp(s, p->data, h->len) == 0 && strlen(p->data) != h->len) { |
Chris Allegretta | 5beed50 | 2003-01-05 20:41:21 +0000 | [diff] [blame] | 1217 | h->current = p; |
| 1218 | return p->data; |
| 1219 | } |
| 1220 | } |
| 1221 | h->current = (historytype*)h; |
| 1222 | null_at(&s, h->len); |
| 1223 | return s; |
| 1224 | } |
| 1225 | |
David Lawrence Ramsey | 6420d44 | 2004-08-11 05:13:08 +0000 | [diff] [blame] | 1226 | #ifdef DEBUG |
Chris Allegretta | 5beed50 | 2003-01-05 20:41:21 +0000 | [diff] [blame] | 1227 | /* free a history list */ |
| 1228 | void free_history(historyheadtype *h) |
| 1229 | { |
David Lawrence Ramsey | 6420d44 | 2004-08-11 05:13:08 +0000 | [diff] [blame] | 1230 | historytype *p; |
Chris Allegretta | 5beed50 | 2003-01-05 20:41:21 +0000 | [diff] [blame] | 1231 | |
David Lawrence Ramsey | 6420d44 | 2004-08-11 05:13:08 +0000 | [diff] [blame] | 1232 | for (p = h->next; p->next != NULL; p = p->next) |
Chris Allegretta | 5beed50 | 2003-01-05 20:41:21 +0000 | [diff] [blame] | 1233 | remove_node(p); |
| 1234 | } |
David Lawrence Ramsey | 6420d44 | 2004-08-11 05:13:08 +0000 | [diff] [blame] | 1235 | #endif |
Chris Allegretta | 5beed50 | 2003-01-05 20:41:21 +0000 | [diff] [blame] | 1236 | |
| 1237 | /* end of history support functions */ |
| 1238 | #endif /* !NANO_SMALL */ |