search.c (84201) | search.c (84260) |
---|---|
1/*- 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Christos Zoulas of Cornell University. 7 * 8 * Redistribution and use in source and binary forms, with or without --- 18 unchanged lines hidden (view full) --- 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. | 1/*- 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Christos Zoulas of Cornell University. 7 * 8 * Redistribution and use in source and binary forms, with or without --- 18 unchanged lines hidden (view full) --- 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. |
35 * 36 * $NetBSD: search.c,v 1.10 2001/01/04 15:56:32 christos Exp $ |
|
35 */ 36 37#include <sys/cdefs.h> | 37 */ 38 39#include <sys/cdefs.h> |
38__FBSDID("$FreeBSD: head/lib/libedit/search.c 84201 2001-09-30 21:21:36Z dillon $"); | 40__FBSDID("$FreeBSD: head/lib/libedit/search.c 84260 2001-10-01 08:41:27Z obrien $"); |
39#if !defined(lint) && !defined(SCCSID) 40static char sccsid[] = "@(#)search.c 8.1 (Berkeley) 6/4/93"; 41#endif /* not lint && not SCCSID */ | 41#if !defined(lint) && !defined(SCCSID) 42static char sccsid[] = "@(#)search.c 8.1 (Berkeley) 6/4/93"; 43#endif /* not lint && not SCCSID */ |
44#include <sys/cdefs.h> 45__FBSDID("$FreeBSD: head/lib/libedit/search.c 84260 2001-10-01 08:41:27Z obrien $"); |
|
42 43/* 44 * search.c: History and character search functions 45 */ 46#include "sys.h" 47#include <stdlib.h> 48#if defined(REGEX) 49#include <regex.h> 50#elif defined(REGEXP) 51#include <regexp.h> 52#endif 53#include "el.h" 54 55/* 56 * Adjust cursor in vi mode to include the character under it 57 */ | 46 47/* 48 * search.c: History and character search functions 49 */ 50#include "sys.h" 51#include <stdlib.h> 52#if defined(REGEX) 53#include <regex.h> 54#elif defined(REGEXP) 55#include <regexp.h> 56#endif 57#include "el.h" 58 59/* 60 * Adjust cursor in vi mode to include the character under it 61 */ |
58#define EL_CURSOR(el) \ | 62#define EL_CURSOR(el) \ |
59 ((el)->el_line.cursor + (((el)->el_map.type == MAP_VI) && \ 60 ((el)->el_map.current == (el)->el_map.alt))) 61 62/* search_init(): 63 * Initialize the search stuff 64 */ 65protected int | 63 ((el)->el_line.cursor + (((el)->el_map.type == MAP_VI) && \ 64 ((el)->el_map.current == (el)->el_map.alt))) 65 66/* search_init(): 67 * Initialize the search stuff 68 */ 69protected int |
66search_init(el) 67 EditLine *el; | 70search_init(EditLine *el) |
68{ | 71{ |
69 el->el_search.patbuf = (char *) el_malloc(EL_BUFSIZ); 70 el->el_search.patlen = 0; 71 el->el_search.patdir = -1; 72 el->el_search.chacha = '\0'; 73 el->el_search.chadir = -1; 74 return 0; | 72 73 el->el_search.patbuf = (char *) el_malloc(EL_BUFSIZ); 74 if (el->el_search.patbuf == NULL) 75 return (-1); 76 el->el_search.patlen = 0; 77 el->el_search.patdir = -1; 78 el->el_search.chacha = '\0'; 79 el->el_search.chadir = -1; 80 return (0); |
75} 76 77 78/* search_end(): 79 * Initialize the search stuff 80 */ 81protected void | 81} 82 83 84/* search_end(): 85 * Initialize the search stuff 86 */ 87protected void |
82search_end(el) 83 EditLine *el; | 88search_end(EditLine *el) |
84{ | 89{ |
85 el_free((ptr_t) el->el_search.patbuf); 86 el->el_search.patbuf = NULL; | 90 91 el_free((ptr_t) el->el_search.patbuf); 92 el->el_search.patbuf = NULL; |
87} 88 | 93} 94 |
95 |
|
89#ifdef REGEXP 90/* regerror(): 91 * Handle regular expression errors 92 */ 93public void 94/*ARGSUSED*/ | 96#ifdef REGEXP 97/* regerror(): 98 * Handle regular expression errors 99 */ 100public void 101/*ARGSUSED*/ |
95regerror(msg) 96 const char *msg; | 102regerror(const char *msg) |
97{ 98} 99#endif 100 | 103{ 104} 105#endif 106 |
107 |
|
101/* el_match(): 102 * Return if string matches pattern 103 */ 104protected int | 108/* el_match(): 109 * Return if string matches pattern 110 */ 111protected int |
105el_match(str, pat) 106 const char *str; 107 const char *pat; | 112el_match(const char *str, const char *pat) |
108{ 109#if defined (REGEX) | 113{ 114#if defined (REGEX) |
110 regex_t re; 111 int rv; | 115 regex_t re; 116 int rv; |
112#elif defined (REGEXP) | 117#elif defined (REGEXP) |
113 regexp *rp; 114 int rv; 115#else 116 extern char *re_comp __P((const char *)); 117 extern int re_exec __P((const char *)); | 118 regexp *rp; 119 int rv; 120#else 121 extern char *re_comp(const char *); 122 extern int re_exec(const char *); |
118#endif 119 | 123#endif 124 |
120 if (strstr(str, pat) != NULL) 121 return 1; | 125 if (strstr(str, pat) != NULL) 126 return (1); |
122 123#if defined(REGEX) | 127 128#if defined(REGEX) |
124 if (regcomp(&re, pat, 0) == 0) { 125 rv = regexec(&re, str, 0, NULL, 0) == 0; 126 regfree(&re); 127 } else { 128 rv = 0; 129 } 130 return rv; | 129 if (regcomp(&re, pat, 0) == 0) { 130 rv = regexec(&re, str, 0, NULL, 0) == 0; 131 regfree(&re); 132 } else { 133 rv = 0; 134 } 135 return (rv); |
131#elif defined(REGEXP) | 136#elif defined(REGEXP) |
132 if ((re = regcomp(pat)) != NULL) { 133 rv = regexec(re, str); 134 free((ptr_t) re); 135 } else { 136 rv = 0; 137 } 138 return rv; | 137 if ((re = regcomp(pat)) != NULL) { 138 rv = regexec(re, str); 139 free((ptr_t) re); 140 } else { 141 rv = 0; 142 } 143 return (rv); |
139#else | 144#else |
140 if (re_comp(pat) != NULL) 141 return 0; 142 else 143 return re_exec(str) == 1; | 145 if (re_comp(pat) != NULL) 146 return (0); 147 else 148 return (re_exec(str) == 1); |
144#endif 145} 146 147 148/* c_hmatch(): 149 * return True if the pattern matches the prefix 150 */ 151protected int | 149#endif 150} 151 152 153/* c_hmatch(): 154 * return True if the pattern matches the prefix 155 */ 156protected int |
152c_hmatch(el, str) 153 EditLine *el; 154 const char *str; | 157c_hmatch(EditLine *el, const char *str) |
155{ 156#ifdef SDEBUG | 158{ 159#ifdef SDEBUG |
157 (void) fprintf(el->el_errfile, "match `%s' with `%s'\n", 158 el->el_search.patbuf, str); | 160 (void) fprintf(el->el_errfile, "match `%s' with `%s'\n", 161 el->el_search.patbuf, str); |
159#endif /* SDEBUG */ 160 | 162#endif /* SDEBUG */ 163 |
161 return el_match(str, el->el_search.patbuf); | 164 return (el_match(str, el->el_search.patbuf)); |
162} 163 164 165/* c_setpat(): 166 * Set the history seatch pattern 167 */ 168protected void | 165} 166 167 168/* c_setpat(): 169 * Set the history seatch pattern 170 */ 171protected void |
169c_setpat(el) 170 EditLine *el; | 172c_setpat(EditLine *el) |
171{ | 173{ |
172 if (el->el_state.lastcmd != ED_SEARCH_PREV_HISTORY && 173 el->el_state.lastcmd != ED_SEARCH_NEXT_HISTORY) { 174 el->el_search.patlen = EL_CURSOR(el) - el->el_line.buffer; 175 if (el->el_search.patlen >= EL_BUFSIZ) 176 el->el_search.patlen = EL_BUFSIZ -1; 177 if (el->el_search.patlen >= 0) { 178 (void) strncpy(el->el_search.patbuf, el->el_line.buffer, 179 el->el_search.patlen); 180 el->el_search.patbuf[el->el_search.patlen] = '\0'; | 174 if (el->el_state.lastcmd != ED_SEARCH_PREV_HISTORY && 175 el->el_state.lastcmd != ED_SEARCH_NEXT_HISTORY) { 176 el->el_search.patlen = EL_CURSOR(el) - el->el_line.buffer; 177 if (el->el_search.patlen >= EL_BUFSIZ) 178 el->el_search.patlen = EL_BUFSIZ - 1; 179 if (el->el_search.patlen != 0) { 180 (void) strncpy(el->el_search.patbuf, el->el_line.buffer, 181 el->el_search.patlen); 182 el->el_search.patbuf[el->el_search.patlen] = '\0'; 183 } else 184 el->el_search.patlen = strlen(el->el_search.patbuf); |
181 } | 185 } |
182 else 183 el->el_search.patlen = strlen(el->el_search.patbuf); 184 } | |
185#ifdef SDEBUG | 186#ifdef SDEBUG |
186 (void) fprintf(el->el_errfile, "\neventno = %d\n", el->el_history.eventno); 187 (void) fprintf(el->el_errfile, "patlen = %d\n", el->el_search.patlen); 188 (void) fprintf(el->el_errfile, "patbuf = \"%s\"\n", el->el_search.patbuf); 189 (void) fprintf(el->el_errfile, "cursor %d lastchar %d\n", 190 EL_CURSOR(el) - el->el_line.buffer, 191 el->el_line.lastchar - el->el_line.buffer); | 187 (void) fprintf(el->el_errfile, "\neventno = %d\n", 188 el->el_history.eventno); 189 (void) fprintf(el->el_errfile, "patlen = %d\n", el->el_search.patlen); 190 (void) fprintf(el->el_errfile, "patbuf = \"%s\"\n", 191 el->el_search.patbuf); 192 (void) fprintf(el->el_errfile, "cursor %d lastchar %d\n", 193 EL_CURSOR(el) - el->el_line.buffer, 194 el->el_line.lastchar - el->el_line.buffer); |
192#endif 193} 194 195 196/* ce_inc_search(): 197 * Emacs incremental search 198 */ 199protected el_action_t | 195#endif 196} 197 198 199/* ce_inc_search(): 200 * Emacs incremental search 201 */ 202protected el_action_t |
200ce_inc_search(el, dir) 201 EditLine *el; 202 int dir; | 203ce_inc_search(EditLine *el, int dir) |
203{ | 204{ |
204 static char STRfwd[] = { 'f', 'w', 'd', '\0' }, 205 STRbck[] = { 'b', 'c', 'k', '\0' }; 206 static char pchar = ':'; /* ':' = normal, '?' = failed */ 207 static char endcmd[2] = { '\0', '\0' }; 208 char ch, *cp, *ocursor = el->el_line.cursor, oldpchar = pchar; | 205 static const char STRfwd[] = {'f', 'w', 'd', '\0'}, 206 STRbck[] = {'b', 'c', 'k', '\0'}; 207 static char pchar = ':';/* ':' = normal, '?' = failed */ 208 static char endcmd[2] = {'\0', '\0'}; 209 char ch, *ocursor = el->el_line.cursor, oldpchar = pchar; 210 const char *cp; |
209 | 211 |
210 el_action_t ret = CC_NORM; | 212 el_action_t ret = CC_NORM; |
211 | 213 |
212 int ohisteventno = el->el_history.eventno, 213 oldpatlen = el->el_search.patlen, 214 newdir = dir, 215 done, redo; | 214 int ohisteventno = el->el_history.eventno; 215 int oldpatlen = el->el_search.patlen; 216 int newdir = dir; 217 int done, redo; |
216 | 218 |
217 if (el->el_line.lastchar + sizeof(STRfwd) / sizeof(char) + 2 + 218 el->el_search.patlen >= el->el_line.limit) 219 return CC_ERROR; | 219 if (el->el_line.lastchar + sizeof(STRfwd) / sizeof(char) + 2 + 220 el->el_search.patlen >= el->el_line.limit) 221 return (CC_ERROR); |
220 | 222 |
221 for (;;) { | 223 for (;;) { |
222 | 224 |
223 if (el->el_search.patlen == 0) { /* first round */ 224 pchar = ':'; | 225 if (el->el_search.patlen == 0) { /* first round */ 226 pchar = ':'; |
225#ifdef ANCHOR | 227#ifdef ANCHOR |
226 el->el_search.patbuf[el->el_search.patlen++] = '.'; 227 el->el_search.patbuf[el->el_search.patlen++] = '*'; | 228 el->el_search.patbuf[el->el_search.patlen++] = '.'; 229 el->el_search.patbuf[el->el_search.patlen++] = '*'; |
228#endif | 230#endif |
229 } 230 done = redo = 0; 231 *el->el_line.lastchar++ = '\n'; 232 for (cp = newdir == ED_SEARCH_PREV_HISTORY ? STRbck : STRfwd; 233 *cp; *el->el_line.lastchar++ = *cp++) 234 continue; 235 *el->el_line.lastchar++ = pchar; 236 for (cp = &el->el_search.patbuf[1]; 237 cp < &el->el_search.patbuf[el->el_search.patlen]; 238 *el->el_line.lastchar++ = *cp++) 239 continue; 240 *el->el_line.lastchar = '\0'; 241 re_refresh(el); 242 243 if (el_getc(el, &ch) != 1) 244 return ed_end_of_file(el, 0); 245 246 switch (el->el_map.current[(unsigned char) ch]) { 247 case ED_INSERT: 248 case ED_DIGIT: 249 if (el->el_search.patlen > EL_BUFSIZ - 3) 250 term_beep(el); 251 else { 252 el->el_search.patbuf[el->el_search.patlen++] = ch; 253 *el->el_line.lastchar++ = ch; | 231 } 232 done = redo = 0; 233 *el->el_line.lastchar++ = '\n'; 234 for (cp = (newdir == ED_SEARCH_PREV_HISTORY) ? STRbck : STRfwd; 235 *cp; *el->el_line.lastchar++ = *cp++) 236 continue; 237 *el->el_line.lastchar++ = pchar; 238 for (cp = &el->el_search.patbuf[1]; 239 cp < &el->el_search.patbuf[el->el_search.patlen]; 240 *el->el_line.lastchar++ = *cp++) 241 continue; |
254 *el->el_line.lastchar = '\0'; 255 re_refresh(el); | 242 *el->el_line.lastchar = '\0'; 243 re_refresh(el); |
256 } 257 break; | |
258 | 244 |
259 case EM_INC_SEARCH_NEXT: 260 newdir = ED_SEARCH_NEXT_HISTORY; 261 redo++; 262 break; | 245 if (el_getc(el, &ch) != 1) 246 return (ed_end_of_file(el, 0)); |
263 | 247 |
264 case EM_INC_SEARCH_PREV: 265 newdir = ED_SEARCH_PREV_HISTORY; 266 redo++; 267 break; 268 269 case ED_DELETE_PREV_CHAR: 270 if (el->el_search.patlen > 1) 271 done++; 272 else 273 term_beep(el); 274 break; 275 276 default: 277 switch (ch) { 278 case 0007: /* ^G: Abort */ 279 ret = CC_ERROR; 280 done++; 281 break; 282 283 case 0027: /* ^W: Append word */ 284 /* No can do if globbing characters in pattern */ 285 for (cp = &el->el_search.patbuf[1]; ; cp++) 286 if (cp >= &el->el_search.patbuf[el->el_search.patlen]) { 287 el->el_line.cursor += el->el_search.patlen - 1; 288 cp = c__next_word(el->el_line.cursor, 289 el->el_line.lastchar, 1, ce__isword); 290 while (el->el_line.cursor < cp && 291 *el->el_line.cursor != '\n') { 292 if (el->el_search.patlen > EL_BUFSIZ - 3) { | 248 switch (el->el_map.current[(unsigned char) ch]) { 249 case ED_INSERT: 250 case ED_DIGIT: 251 if (el->el_search.patlen > EL_BUFSIZ - 3) |
293 term_beep(el); | 252 term_beep(el); |
294 break; 295 } 296 el->el_search.patbuf[el->el_search.patlen++] = 297 *el->el_line.cursor; 298 *el->el_line.lastchar++ = *el->el_line.cursor++; | 253 else { 254 el->el_search.patbuf[el->el_search.patlen++] = 255 ch; 256 *el->el_line.lastchar++ = ch; 257 *el->el_line.lastchar = '\0'; 258 re_refresh(el); |
299 } | 259 } |
300 el->el_line.cursor = ocursor; 301 *el->el_line.lastchar = '\0'; 302 re_refresh(el); | |
303 break; | 260 break; |
304 } else if (isglob(*cp)) { 305 term_beep(el); | 261 262 case EM_INC_SEARCH_NEXT: 263 newdir = ED_SEARCH_NEXT_HISTORY; 264 redo++; |
306 break; | 265 break; |
307 } 308 break; | |
309 | 266 |
310 default: /* Terminate and execute cmd */ 311 endcmd[0] = ch; 312 el_push(el, endcmd); 313 /*FALLTHROUGH*/ | 267 case EM_INC_SEARCH_PREV: 268 newdir = ED_SEARCH_PREV_HISTORY; 269 redo++; 270 break; |
314 | 271 |
315 case 0033: /* ESC: Terminate */ 316 ret = CC_REFRESH; 317 done++; 318 break; 319 } 320 break; 321 } | 272 case ED_DELETE_PREV_CHAR: 273 if (el->el_search.patlen > 1) 274 done++; 275 else 276 term_beep(el); 277 break; |
322 | 278 |
323 while (el->el_line.lastchar > el->el_line.buffer && 324 *el->el_line.lastchar != '\n') 325 *el->el_line.lastchar-- = '\0'; 326 *el->el_line.lastchar = '\0'; | 279 default: 280 switch (ch) { 281 case 0007: /* ^G: Abort */ 282 ret = CC_ERROR; 283 done++; 284 break; |
327 | 285 |
328 if (!done) { | 286 case 0027: /* ^W: Append word */ 287 /* No can do if globbing characters in pattern */ 288 for (cp = &el->el_search.patbuf[1];; cp++) 289 if (cp >= &el->el_search.patbuf[el->el_search.patlen]) { 290 el->el_line.cursor += 291 el->el_search.patlen - 1; 292 cp = c__next_word(el->el_line.cursor, 293 el->el_line.lastchar, 1, 294 ce__isword); 295 while (el->el_line.cursor < cp && 296 *el->el_line.cursor != '\n') { 297 if (el->el_search.patlen > 298 EL_BUFSIZ - 3) { 299 term_beep(el); 300 break; 301 } 302 el->el_search.patbuf[el->el_search.patlen++] = 303 *el->el_line.cursor; 304 *el->el_line.lastchar++ = 305 *el->el_line.cursor++; 306 } 307 el->el_line.cursor = ocursor; 308 *el->el_line.lastchar = '\0'; 309 re_refresh(el); 310 break; 311 } else if (isglob(*cp)) { 312 term_beep(el); 313 break; 314 } 315 break; |
329 | 316 |
330 /* Can't search if unmatched '[' */ 331 for (cp = &el->el_search.patbuf[el->el_search.patlen-1], ch = ']'; 332 cp > el->el_search.patbuf; cp--) 333 if (*cp == '[' || *cp == ']') { 334 ch = *cp; 335 break; 336 } | 317 default: /* Terminate and execute cmd */ 318 endcmd[0] = ch; 319 el_push(el, endcmd); 320 /* FALLTHROUGH */ |
337 | 321 |
338 if (el->el_search.patlen > 1 && ch != '[') { 339 if (redo && newdir == dir) { 340 if (pchar == '?') { /* wrap around */ 341 el->el_history.eventno = 342 newdir == ED_SEARCH_PREV_HISTORY ? 0 : 0x7fffffff; 343 if (hist_get(el) == CC_ERROR) 344 /* el->el_history.eventno was fixed by first call */ 345 (void) hist_get(el); 346 el->el_line.cursor = newdir == ED_SEARCH_PREV_HISTORY ? 347 el->el_line.lastchar : el->el_line.buffer; 348 } else 349 el->el_line.cursor += 350 newdir == ED_SEARCH_PREV_HISTORY ? -1 : 1; | 322 case 0033: /* ESC: Terminate */ 323 ret = CC_REFRESH; 324 done++; 325 break; 326 } 327 break; |
351 } | 328 } |
329 330 while (el->el_line.lastchar > el->el_line.buffer && 331 *el->el_line.lastchar != '\n') 332 *el->el_line.lastchar-- = '\0'; 333 *el->el_line.lastchar = '\0'; 334 335 if (!done) { 336 337 /* Can't search if unmatched '[' */ 338 for (cp = &el->el_search.patbuf[el->el_search.patlen-1], 339 ch = ']'; 340 cp > el->el_search.patbuf; 341 cp--) 342 if (*cp == '[' || *cp == ']') { 343 ch = *cp; 344 break; 345 } 346 if (el->el_search.patlen > 1 && ch != '[') { 347 if (redo && newdir == dir) { 348 if (pchar == '?') { /* wrap around */ 349 el->el_history.eventno = 350 newdir == ED_SEARCH_PREV_HISTORY ? 0 : 0x7fffffff; 351 if (hist_get(el) == CC_ERROR) 352 /* el->el_history.event 353 * no was fixed by 354 * first call */ 355 (void) hist_get(el); 356 el->el_line.cursor = newdir == 357 ED_SEARCH_PREV_HISTORY ? 358 el->el_line.lastchar : 359 el->el_line.buffer; 360 } else 361 el->el_line.cursor += 362 newdir == 363 ED_SEARCH_PREV_HISTORY ? 364 -1 : 1; 365 } |
|
352#ifdef ANCHOR | 366#ifdef ANCHOR |
353 el->el_search.patbuf[el->el_search.patlen++] = '.'; 354 el->el_search.patbuf[el->el_search.patlen++] = '*'; | 367 el->el_search.patbuf[el->el_search.patlen++] = 368 '.'; 369 el->el_search.patbuf[el->el_search.patlen++] = 370 '*'; |
355#endif | 371#endif |
356 el->el_search.patbuf[el->el_search.patlen] = '\0'; 357 if (el->el_line.cursor < el->el_line.buffer || 358 el->el_line.cursor > el->el_line.lastchar || 359 (ret = ce_search_line(el, &el->el_search.patbuf[1], 360 newdir)) == CC_ERROR) { 361 /* avoid c_setpat */ 362 el->el_state.lastcmd = (el_action_t) newdir; 363 ret = newdir == ED_SEARCH_PREV_HISTORY ? 364 ed_search_prev_history(el, 0) : 365 ed_search_next_history(el, 0); 366 if (ret != CC_ERROR) { 367 el->el_line.cursor = newdir == ED_SEARCH_PREV_HISTORY ? 368 el->el_line.lastchar : el->el_line.buffer; 369 (void) ce_search_line(el, &el->el_search.patbuf[1], 370 newdir); 371 } 372 } 373 el->el_search.patbuf[--el->el_search.patlen] = '\0'; 374 if (ret == CC_ERROR) { 375 term_beep(el); 376 if (el->el_history.eventno != ohisteventno) { 377 el->el_history.eventno = ohisteventno; 378 if (hist_get(el) == CC_ERROR) 379 return CC_ERROR; 380 } 381 el->el_line.cursor = ocursor; 382 pchar = '?'; 383 } else { 384 pchar = ':'; 385 } 386 } | 372 el->el_search.patbuf[el->el_search.patlen] = 373 '\0'; 374 if (el->el_line.cursor < el->el_line.buffer || 375 el->el_line.cursor > el->el_line.lastchar || 376 (ret = ce_search_line(el, 377 &el->el_search.patbuf[1], 378 newdir)) == CC_ERROR) { 379 /* avoid c_setpat */ 380 el->el_state.lastcmd = 381 (el_action_t) newdir; 382 ret = newdir == ED_SEARCH_PREV_HISTORY ? 383 ed_search_prev_history(el, 0) : 384 ed_search_next_history(el, 0); 385 if (ret != CC_ERROR) { 386 el->el_line.cursor = newdir == 387 ED_SEARCH_PREV_HISTORY ? 388 el->el_line.lastchar : 389 el->el_line.buffer; 390 (void) ce_search_line(el, 391 &el->el_search.patbuf[1], 392 newdir); 393 } 394 } 395 el->el_search.patbuf[--el->el_search.patlen] = 396 '\0'; 397 if (ret == CC_ERROR) { 398 term_beep(el); 399 if (el->el_history.eventno != 400 ohisteventno) { 401 el->el_history.eventno = 402 ohisteventno; 403 if (hist_get(el) == CC_ERROR) 404 return (CC_ERROR); 405 } 406 el->el_line.cursor = ocursor; 407 pchar = '?'; 408 } else { 409 pchar = ':'; 410 } 411 } 412 ret = ce_inc_search(el, newdir); |
387 | 413 |
388 ret = ce_inc_search(el, newdir); | 414 if (ret == CC_ERROR && pchar == '?' && oldpchar == ':') 415 /* 416 * break abort of failed search at last 417 * non-failed 418 */ 419 ret = CC_NORM; |
389 | 420 |
390 if (ret == CC_ERROR && pchar == '?' && oldpchar == ':') 391 /* break abort of failed search at last non-failed */ 392 ret = CC_NORM; 393 | 421 } 422 if (ret == CC_NORM || (ret == CC_ERROR && oldpatlen == 0)) { 423 /* restore on normal return or error exit */ 424 pchar = oldpchar; 425 el->el_search.patlen = oldpatlen; 426 if (el->el_history.eventno != ohisteventno) { 427 el->el_history.eventno = ohisteventno; 428 if (hist_get(el) == CC_ERROR) 429 return (CC_ERROR); 430 } 431 el->el_line.cursor = ocursor; 432 if (ret == CC_ERROR) 433 re_refresh(el); 434 } 435 if (done || ret != CC_NORM) 436 return (ret); |
394 } | 437 } |
395 396 if (ret == CC_NORM || (ret == CC_ERROR && oldpatlen == 0)) { 397 /* restore on normal return or error exit */ 398 pchar = oldpchar; 399 el->el_search.patlen = oldpatlen; 400 if (el->el_history.eventno != ohisteventno) { 401 el->el_history.eventno = ohisteventno; 402 if (hist_get(el) == CC_ERROR) 403 return CC_ERROR; 404 } 405 el->el_line.cursor = ocursor; 406 if (ret == CC_ERROR) 407 re_refresh(el); 408 } 409 if (done || ret != CC_NORM) 410 return ret; 411 } | |
412} 413 414 415/* cv_search(): 416 * Vi search. 417 */ 418protected el_action_t | 438} 439 440 441/* cv_search(): 442 * Vi search. 443 */ 444protected el_action_t |
419cv_search(el, dir) 420 EditLine *el; 421 int dir; | 445cv_search(EditLine *el, int dir) |
422{ | 446{ |
423 char ch; 424 char tmpbuf[EL_BUFSIZ]; 425 int tmplen; | 447 char ch; 448 char tmpbuf[EL_BUFSIZ]; 449 int tmplen; |
426 | 450 |
427 tmplen = 0; | 451 tmplen = 0; |
428#ifdef ANCHOR | 452#ifdef ANCHOR |
429 tmpbuf[tmplen++] = '.'; 430 tmpbuf[tmplen++] = '*'; | 453 tmpbuf[tmplen++] = '.'; 454 tmpbuf[tmplen++] = '*'; |
431#endif 432 | 455#endif 456 |
433 el->el_line.buffer[0] = '\0'; 434 el->el_line.lastchar = el->el_line.buffer; 435 el->el_line.cursor = el->el_line.buffer; 436 el->el_search.patdir = dir; | 457 el->el_line.buffer[0] = '\0'; 458 el->el_line.lastchar = el->el_line.buffer; 459 el->el_line.cursor = el->el_line.buffer; 460 el->el_search.patdir = dir; |
437 | 461 |
438 c_insert(el, 2); /* prompt + '\n' */ 439 *el->el_line.cursor++ = '\n'; 440 *el->el_line.cursor++ = dir == ED_SEARCH_PREV_HISTORY ? '/' : '?'; 441 re_refresh(el); | 462 c_insert(el, 2); /* prompt + '\n' */ 463 *el->el_line.cursor++ = '\n'; 464 *el->el_line.cursor++ = dir == ED_SEARCH_PREV_HISTORY ? '/' : '?'; 465 re_refresh(el); |
442 443#ifdef ANCHOR | 466 467#ifdef ANCHOR |
444# define LEN 2 | 468#define LEN 2 |
445#else | 469#else |
446# define LEN 0 | 470#define LEN 0 |
447#endif 448 | 471#endif 472 |
449 tmplen = c_gets(el, &tmpbuf[LEN]) + LEN; 450 ch = tmpbuf[tmplen]; 451 tmpbuf[tmplen] = '\0'; | 473 tmplen = c_gets(el, &tmpbuf[LEN]) + LEN; 474 ch = tmpbuf[tmplen]; 475 tmpbuf[tmplen] = '\0'; |
452 | 476 |
453 if (tmplen == LEN) { 454 /* 455 * Use the old pattern, but wild-card it. 456 */ 457 if (el->el_search.patlen == 0) { 458 el->el_line.buffer[0] = '\0'; 459 el->el_line.lastchar = el->el_line.buffer; 460 el->el_line.cursor = el->el_line.buffer; 461 re_refresh(el); 462 return CC_ERROR; 463 } | 477 if (tmplen == LEN) { 478 /* 479 * Use the old pattern, but wild-card it. 480 */ 481 if (el->el_search.patlen == 0) { 482 el->el_line.buffer[0] = '\0'; 483 el->el_line.lastchar = el->el_line.buffer; 484 el->el_line.cursor = el->el_line.buffer; 485 re_refresh(el); 486 return (CC_ERROR); 487 } |
464#ifdef ANCHOR | 488#ifdef ANCHOR |
465 if (el->el_search.patbuf[0] != '.' && el->el_search.patbuf[0] != '*') { 466 (void)strncpy(tmpbuf, el->el_search.patbuf, sizeof(tmpbuf) - 1); 467 el->el_search.patbuf[0] = '.'; 468 el->el_search.patbuf[1] = '*'; 469 (void)strncpy(&el->el_search.patbuf[2], tmpbuf, EL_BUFSIZ - 3); 470 el->el_search.patlen++; 471 el->el_search.patbuf[el->el_search.patlen++] = '.'; 472 el->el_search.patbuf[el->el_search.patlen++] = '*'; 473 el->el_search.patbuf[el->el_search.patlen] = '\0'; 474 } | 489 if (el->el_search.patbuf[0] != '.' && 490 el->el_search.patbuf[0] != '*') { 491 (void) strncpy(tmpbuf, el->el_search.patbuf, 492 sizeof(tmpbuf) - 1); 493 el->el_search.patbuf[0] = '.'; 494 el->el_search.patbuf[1] = '*'; 495 (void) strncpy(&el->el_search.patbuf[2], tmpbuf, 496 EL_BUFSIZ - 3); 497 el->el_search.patlen++; 498 el->el_search.patbuf[el->el_search.patlen++] = '.'; 499 el->el_search.patbuf[el->el_search.patlen++] = '*'; 500 el->el_search.patbuf[el->el_search.patlen] = '\0'; 501 } |
475#endif | 502#endif |
476 } 477 else { | 503 } else { |
478#ifdef ANCHOR | 504#ifdef ANCHOR |
479 tmpbuf[tmplen++] = '.'; 480 tmpbuf[tmplen++] = '*'; | 505 tmpbuf[tmplen++] = '.'; 506 tmpbuf[tmplen++] = '*'; |
481#endif | 507#endif |
482 tmpbuf[tmplen] = '\0'; 483 (void)strncpy(el->el_search.patbuf, tmpbuf, EL_BUFSIZ - 1); 484 el->el_search.patlen = tmplen; 485 } 486 el->el_state.lastcmd = (el_action_t) dir; /* avoid c_setpat */ 487 el->el_line.cursor = el->el_line.lastchar = el->el_line.buffer; 488 if ((dir == ED_SEARCH_PREV_HISTORY ? ed_search_prev_history(el, 0) : 489 ed_search_next_history(el, 0)) == CC_ERROR) { 490 re_refresh(el); 491 return CC_ERROR; 492 } 493 else { 494 if (ch == 0033) { 495 re_refresh(el); 496 *el->el_line.lastchar++ = '\n'; 497 *el->el_line.lastchar = '\0'; 498 re_goto_bottom(el); 499 return CC_NEWLINE; | 508 tmpbuf[tmplen] = '\0'; 509 (void) strncpy(el->el_search.patbuf, tmpbuf, EL_BUFSIZ - 1); 510 el->el_search.patlen = tmplen; |
500 } | 511 } |
501 else 502 return CC_REFRESH; 503 } | 512 el->el_state.lastcmd = (el_action_t) dir; /* avoid c_setpat */ 513 el->el_line.cursor = el->el_line.lastchar = el->el_line.buffer; 514 if ((dir == ED_SEARCH_PREV_HISTORY ? ed_search_prev_history(el, 0) : 515 ed_search_next_history(el, 0)) == CC_ERROR) { 516 re_refresh(el); 517 return (CC_ERROR); 518 } else { 519 if (ch == 0033) { 520 re_refresh(el); 521 *el->el_line.lastchar++ = '\n'; 522 *el->el_line.lastchar = '\0'; 523 re_goto_bottom(el); 524 return (CC_NEWLINE); 525 } else 526 return (CC_REFRESH); 527 } |
504} 505 506 507/* ce_search_line(): 508 * Look for a pattern inside a line 509 */ 510protected el_action_t | 528} 529 530 531/* ce_search_line(): 532 * Look for a pattern inside a line 533 */ 534protected el_action_t |
511ce_search_line(el, pattern, dir) 512 EditLine *el; 513 char *pattern; 514 int dir; | 535ce_search_line(EditLine *el, char *pattern, int dir) |
515{ | 536{ |
516 char *cp; | 537 char *cp; |
517 | 538 |
518 if (dir == ED_SEARCH_PREV_HISTORY) { 519 for (cp = el->el_line.cursor; cp >= el->el_line.buffer; cp--) 520 if (el_match(cp, pattern)) { 521 el->el_line.cursor = cp; 522 return CC_NORM; 523 } 524 return CC_ERROR; 525 } else { 526 for (cp = el->el_line.cursor; *cp != '\0' && 527 cp < el->el_line.limit; cp++) 528 if (el_match(cp, pattern)) { 529 el->el_line.cursor = cp; 530 return CC_NORM; 531 } 532 return CC_ERROR; 533 } | 539 if (dir == ED_SEARCH_PREV_HISTORY) { 540 for (cp = el->el_line.cursor; cp >= el->el_line.buffer; cp--) 541 if (el_match(cp, pattern)) { 542 el->el_line.cursor = cp; 543 return (CC_NORM); 544 } 545 return (CC_ERROR); 546 } else { 547 for (cp = el->el_line.cursor; *cp != '\0' && 548 cp < el->el_line.limit; cp++) 549 if (el_match(cp, pattern)) { 550 el->el_line.cursor = cp; 551 return (CC_NORM); 552 } 553 return (CC_ERROR); 554 } |
534} 535 536 537/* cv_repeat_srch(): 538 * Vi repeat search 539 */ 540protected el_action_t | 555} 556 557 558/* cv_repeat_srch(): 559 * Vi repeat search 560 */ 561protected el_action_t |
541cv_repeat_srch(el, c) 542 EditLine *el; 543 int c; | 562cv_repeat_srch(EditLine *el, int c) |
544{ | 563{ |
564 |
|
545#ifdef SDEBUG | 565#ifdef SDEBUG |
546 (void) fprintf(el->el_errfile, "dir %d patlen %d patbuf %s\n", 547 c, el->el_search.patlen, el->el_search.patbuf); | 566 (void) fprintf(el->el_errfile, "dir %d patlen %d patbuf %s\n", 567 c, el->el_search.patlen, el->el_search.patbuf); |
548#endif 549 | 568#endif 569 |
550 el->el_state.lastcmd = (el_action_t) c; /* Hack to stop c_setpat */ 551 el->el_line.lastchar = el->el_line.buffer; | 570 el->el_state.lastcmd = (el_action_t) c; /* Hack to stop c_setpat */ 571 el->el_line.lastchar = el->el_line.buffer; |
552 | 572 |
553 switch (c) { 554 case ED_SEARCH_NEXT_HISTORY: 555 return ed_search_next_history(el, 0); 556 case ED_SEARCH_PREV_HISTORY: 557 return ed_search_prev_history(el, 0); 558 default: 559 return CC_ERROR; 560 } | 573 switch (c) { 574 case ED_SEARCH_NEXT_HISTORY: 575 return (ed_search_next_history(el, 0)); 576 case ED_SEARCH_PREV_HISTORY: 577 return (ed_search_prev_history(el, 0)); 578 default: 579 return (CC_ERROR); 580 } |
561} 562 563 564/* cv_csearch_back(): 565 * Vi character search reverse 566 */ 567protected el_action_t | 581} 582 583 584/* cv_csearch_back(): 585 * Vi character search reverse 586 */ 587protected el_action_t |
568cv_csearch_back(el, ch, count, tflag) 569 EditLine *el; 570 int ch, count, tflag; | 588cv_csearch_back(EditLine *el, int ch, int count, int tflag) |
571{ | 589{ |
572 char *cp; | 590 char *cp; |
573 | 591 |
574 cp = el->el_line.cursor; 575 while (count--) { 576 if (*cp == ch) 577 cp--; 578 while (cp > el->el_line.buffer && *cp != ch) 579 cp--; 580 } | 592 cp = el->el_line.cursor; 593 while (count--) { 594 if (*cp == ch) 595 cp--; 596 while (cp > el->el_line.buffer && *cp != ch) 597 cp--; 598 } |
581 | 599 |
582 if (cp < el->el_line.buffer || (cp == el->el_line.buffer && *cp != ch)) 583 return CC_ERROR; | 600 if (cp < el->el_line.buffer || (cp == el->el_line.buffer && *cp != ch)) 601 return (CC_ERROR); |
584 | 602 |
585 if (*cp == ch && tflag) 586 cp++; | 603 if (*cp == ch && tflag) 604 cp++; |
587 | 605 |
588 el->el_line.cursor = cp; | 606 el->el_line.cursor = cp; |
589 | 607 |
590 if (el->el_chared.c_vcmd.action & DELETE) { 591 el->el_line.cursor++; 592 cv_delfini(el); 593 return CC_REFRESH; 594 } 595 596 re_refresh_cursor(el); 597 return CC_NORM; | 608 if (el->el_chared.c_vcmd.action & DELETE) { 609 el->el_line.cursor++; 610 cv_delfini(el); 611 return (CC_REFRESH); 612 } 613 re_refresh_cursor(el); 614 return (CC_NORM); |
598} 599 600 601/* cv_csearch_fwd(): 602 * Vi character search forward 603 */ 604protected el_action_t | 615} 616 617 618/* cv_csearch_fwd(): 619 * Vi character search forward 620 */ 621protected el_action_t |
605cv_csearch_fwd(el, ch, count, tflag) 606 EditLine *el; 607 int ch, count, tflag; | 622cv_csearch_fwd(EditLine *el, int ch, int count, int tflag) |
608{ | 623{ |
609 char *cp; | 624 char *cp; |
610 | 625 |
611 cp = el->el_line.cursor; 612 while (count--) { 613 if(*cp == ch) 614 cp++; 615 while (cp < el->el_line.lastchar && *cp != ch) 616 cp++; 617 } | 626 cp = el->el_line.cursor; 627 while (count--) { 628 if (*cp == ch) 629 cp++; 630 while (cp < el->el_line.lastchar && *cp != ch) 631 cp++; 632 } |
618 | 633 |
619 if (cp >= el->el_line.lastchar) 620 return CC_ERROR; | 634 if (cp >= el->el_line.lastchar) 635 return (CC_ERROR); |
621 | 636 |
622 if (*cp == ch && tflag) 623 cp--; | 637 if (*cp == ch && tflag) 638 cp--; |
624 | 639 |
625 el->el_line.cursor = cp; | 640 el->el_line.cursor = cp; |
626 | 641 |
627 if (el->el_chared.c_vcmd.action & DELETE) { 628 el->el_line.cursor++; 629 cv_delfini(el); 630 return CC_REFRESH; 631 } 632 re_refresh_cursor(el); 633 return CC_NORM; | 642 if (el->el_chared.c_vcmd.action & DELETE) { 643 el->el_line.cursor++; 644 cv_delfini(el); 645 return (CC_REFRESH); 646 } 647 re_refresh_cursor(el); 648 return (CC_NORM); |
634} | 649} |