Deleted Added
full compact
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}