~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to cmd-line-utils/libedit/search.c

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

Show diffs side-by-side

added added

removed removed

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