154231Sbostic /*-
2*61275Sbostic * Copyright (c) 1992, 1993
3*61275Sbostic * The Regents of the University of California. All rights reserved.
454231Sbostic *
554231Sbostic * This code is derived from software contributed to Berkeley by
654231Sbostic * Christos Zoulas of Cornell University.
754231Sbostic *
854231Sbostic * %sccs.include.redist.c%
954231Sbostic */
1054231Sbostic
1154624Schristos #if !defined(lint) && !defined(SCCSID)
12*61275Sbostic static char sccsid[] = "@(#)search.c 8.1 (Berkeley) 06/04/93";
1354624Schristos #endif /* not lint && not SCCSID */
1454231Sbostic
1554231Sbostic /*
1654624Schristos * search.c: History and character search functions
1754231Sbostic */
1854231Sbostic #include "sys.h"
1954231Sbostic #include <stdlib.h>
2054679Schristos #ifdef REGEXP
2154231Sbostic #include <regexp.h>
2254231Sbostic #endif
2354231Sbostic #include "el.h"
2454231Sbostic
2554624Schristos /*
2654624Schristos * Adjust cursor in vi mode to include the character under it
2754624Schristos */
2854624Schristos #define EL_CURSOR(el) \
2954624Schristos ((el)->el_line.cursor + (((el)->el_map.type == MAP_VI) && \
3054624Schristos ((el)->el_map.current == (el)->el_map.alt)))
3154231Sbostic
3254231Sbostic /* search_init():
3354231Sbostic * Initialize the search stuff
3454231Sbostic */
3554231Sbostic protected int
search_init(el)3654231Sbostic search_init(el)
3754231Sbostic EditLine *el;
3854231Sbostic {
3954231Sbostic el->el_search.patbuf = (char *) el_malloc(EL_BUFSIZ);
4054231Sbostic el->el_search.patlen = 0;
4154231Sbostic el->el_search.patdir = -1;
4254231Sbostic el->el_search.chacha = '\0';
4354231Sbostic el->el_search.chadir = -1;
4454231Sbostic return 0;
4554231Sbostic }
4654231Sbostic
4754231Sbostic
4854231Sbostic /* search_end():
4954231Sbostic * Initialize the search stuff
5054231Sbostic */
5154231Sbostic protected void
search_end(el)5254231Sbostic search_end(el)
5354231Sbostic EditLine *el;
5454231Sbostic {
5554231Sbostic el_free((ptr_t) el->el_search.patbuf);
5654231Sbostic el->el_search.patbuf = NULL;
5754231Sbostic }
5854231Sbostic
5954679Schristos #ifdef REGEXP
6054231Sbostic /* regerror():
6154231Sbostic * Handle regular expression errors
6254231Sbostic */
6354231Sbostic public void
6454231Sbostic /*ARGSUSED*/
regerror(msg)6554231Sbostic regerror(msg)
6654231Sbostic const char *msg;
6754231Sbostic {
6854231Sbostic }
6954231Sbostic #endif
7054231Sbostic
7154231Sbostic /* el_match():
7254231Sbostic * Return if string matches pattern
7354231Sbostic */
7454624Schristos protected int
el_match(str,pat)7554231Sbostic el_match(str, pat)
7654231Sbostic const char *str;
7754231Sbostic const char *pat;
7854231Sbostic {
7954679Schristos #ifndef REGEXP
8054231Sbostic extern char *re_comp __P((const char *));
8154231Sbostic extern int re_exec __P((const char *));
8254231Sbostic #else
8354231Sbostic regexp *re;
8454231Sbostic int rv;
8554231Sbostic #endif
8654231Sbostic
8754231Sbostic if (strstr(str, pat) != NULL)
8854231Sbostic return 1;
8954679Schristos #ifndef REGEXP
9054231Sbostic if (re_comp(pat) != NULL)
9154231Sbostic return 0;
9254231Sbostic else
9354231Sbostic return re_exec(str) == 1;
9454231Sbostic #else
9555353Schristos if ((re = regcomp(pat)) != NULL) {
9654231Sbostic rv = regexec(re, str);
9754231Sbostic free((ptr_t) re);
9854231Sbostic }
9954231Sbostic else
10054231Sbostic rv = 0;
10154231Sbostic return rv;
10254231Sbostic #endif
10354231Sbostic
10454231Sbostic }
10554231Sbostic
10654231Sbostic
10754231Sbostic /* c_hmatch():
10854231Sbostic * return True if the pattern matches the prefix
10954231Sbostic */
11054231Sbostic protected int
c_hmatch(el,str)11154231Sbostic c_hmatch(el, str)
11254231Sbostic EditLine *el;
11354231Sbostic const char *str;
11454231Sbostic {
11554231Sbostic #ifdef SDEBUG
11654231Sbostic (void) fprintf(el->el_errfile, "match `%s' with `%s'\n",
11754231Sbostic el->el_search.patbuf, str);
11854231Sbostic #endif /* SDEBUG */
11954231Sbostic
12054231Sbostic return el_match(str, el->el_search.patbuf);
12154231Sbostic }
12254231Sbostic
12354231Sbostic
12454231Sbostic /* c_setpat():
12554231Sbostic * Set the history seatch pattern
12654231Sbostic */
12754231Sbostic protected void
c_setpat(el)12854231Sbostic c_setpat(el)
12954231Sbostic EditLine *el;
13054231Sbostic {
13154231Sbostic if (el->el_state.lastcmd != ED_SEARCH_PREV_HISTORY &&
13254231Sbostic el->el_state.lastcmd != ED_SEARCH_NEXT_HISTORY) {
13354624Schristos el->el_search.patlen = EL_CURSOR(el) - el->el_line.buffer;
13454231Sbostic if (el->el_search.patlen >= EL_BUFSIZ)
13554231Sbostic el->el_search.patlen = EL_BUFSIZ -1;
13654231Sbostic if (el->el_search.patlen >= 0) {
13754231Sbostic (void) strncpy(el->el_search.patbuf, el->el_line.buffer,
13854231Sbostic el->el_search.patlen);
13954231Sbostic el->el_search.patbuf[el->el_search.patlen] = '\0';
14054231Sbostic }
14154231Sbostic else
14254231Sbostic el->el_search.patlen = strlen(el->el_search.patbuf);
14354231Sbostic }
14454231Sbostic #ifdef SDEBUG
14554231Sbostic (void) fprintf(el->el_errfile, "\neventno = %d\n", el->el_history.eventno);
14654231Sbostic (void) fprintf(el->el_errfile, "patlen = %d\n", el->el_search.patlen);
14754231Sbostic (void) fprintf(el->el_errfile, "patbuf = \"%s\"\n", el->el_search.patbuf);
14854231Sbostic (void) fprintf(el->el_errfile, "cursor %d lastchar %d\n",
14954624Schristos EL_CURSOR(el) - el->el_line.buffer,
15054231Sbostic el->el_line.lastchar - el->el_line.buffer);
15154231Sbostic #endif
15254231Sbostic }
15354231Sbostic
15454231Sbostic
15554231Sbostic /* ce_inc_search():
15654231Sbostic * Emacs incremental search
15754231Sbostic */
15854231Sbostic protected el_action_t
ce_inc_search(el,dir)15954231Sbostic ce_inc_search(el, dir)
16054231Sbostic EditLine *el;
16154231Sbostic int dir;
16254231Sbostic {
16354231Sbostic static char STRfwd[] = { 'f', 'w', 'd', '\0' },
16454231Sbostic STRbck[] = { 'b', 'c', 'k', '\0' };
16554231Sbostic static char pchar = ':'; /* ':' = normal, '?' = failed */
16654231Sbostic static char endcmd[2] = { '\0', '\0' };
16754231Sbostic char ch, *cp, *ocursor = el->el_line.cursor, oldpchar = pchar;
16854231Sbostic
16954231Sbostic el_action_t ret = CC_NORM;
17054231Sbostic
17154231Sbostic int ohisteventno = el->el_history.eventno,
17254231Sbostic oldpatlen = el->el_search.patlen,
17354231Sbostic newdir = dir,
17454231Sbostic done, redo;
17554231Sbostic
17654231Sbostic if (el->el_line.lastchar + sizeof(STRfwd) / sizeof(char) + 2 +
17754231Sbostic el->el_search.patlen >= el->el_line.limit)
17854231Sbostic return CC_ERROR;
17954231Sbostic
18054231Sbostic for (;;) {
18154231Sbostic
18254231Sbostic if (el->el_search.patlen == 0) { /* first round */
18354231Sbostic pchar = ':';
18454231Sbostic #ifdef ANCHOR
18554231Sbostic el->el_search.patbuf[el->el_search.patlen++] = '.';
18654231Sbostic el->el_search.patbuf[el->el_search.patlen++] = '*';
18754231Sbostic #endif
18854231Sbostic }
18954231Sbostic done = redo = 0;
19054231Sbostic *el->el_line.lastchar++ = '\n';
19154231Sbostic for (cp = newdir == ED_SEARCH_PREV_HISTORY ? STRbck : STRfwd;
19254231Sbostic *cp; *el->el_line.lastchar++ = *cp++)
19354231Sbostic continue;
19454231Sbostic *el->el_line.lastchar++ = pchar;
19554231Sbostic for (cp = &el->el_search.patbuf[1];
19654231Sbostic cp < &el->el_search.patbuf[el->el_search.patlen];
19754231Sbostic *el->el_line.lastchar++ = *cp++)
19854231Sbostic continue;
19954231Sbostic *el->el_line.lastchar = '\0';
20054231Sbostic re_refresh(el);
20154231Sbostic
20254231Sbostic if (el_getc(el, &ch) != 1)
20354231Sbostic return ed_end_of_file(el, 0);
20454231Sbostic
20554231Sbostic switch (el->el_map.current[(unsigned char) ch]) {
20654231Sbostic case ED_INSERT:
20754231Sbostic case ED_DIGIT:
20854231Sbostic if (el->el_search.patlen > EL_BUFSIZ - 3)
20954231Sbostic term_beep(el);
21054231Sbostic else {
21154231Sbostic el->el_search.patbuf[el->el_search.patlen++] = ch;
21254231Sbostic *el->el_line.lastchar++ = ch;
21354231Sbostic *el->el_line.lastchar = '\0';
21454231Sbostic re_refresh(el);
21554231Sbostic }
21654231Sbostic break;
21754231Sbostic
21854231Sbostic case EM_INC_SEARCH_NEXT:
21954231Sbostic newdir = ED_SEARCH_NEXT_HISTORY;
22054231Sbostic redo++;
22154231Sbostic break;
22254231Sbostic
22354231Sbostic case EM_INC_SEARCH_PREV:
22454231Sbostic newdir = ED_SEARCH_PREV_HISTORY;
22554231Sbostic redo++;
22654231Sbostic break;
22754231Sbostic
22854231Sbostic case ED_DELETE_PREV_CHAR:
22954231Sbostic if (el->el_search.patlen > 1)
23054231Sbostic done++;
23154231Sbostic else
23254231Sbostic term_beep(el);
23354231Sbostic break;
23454231Sbostic
23554231Sbostic default:
23654231Sbostic switch (ch) {
23754231Sbostic case 0007: /* ^G: Abort */
23854231Sbostic ret = CC_ERROR;
23954231Sbostic done++;
24054231Sbostic break;
24154231Sbostic
24254231Sbostic case 0027: /* ^W: Append word */
24354231Sbostic /* No can do if globbing characters in pattern */
24454231Sbostic for (cp = &el->el_search.patbuf[1]; ; cp++)
24554231Sbostic if (cp >= &el->el_search.patbuf[el->el_search.patlen]) {
24654231Sbostic el->el_line.cursor += el->el_search.patlen - 1;
24754231Sbostic cp = c__next_word(el->el_line.cursor,
24854231Sbostic el->el_line.lastchar, 1, ce__isword);
24954231Sbostic while (el->el_line.cursor < cp &&
25054231Sbostic *el->el_line.cursor != '\n') {
25154231Sbostic if (el->el_search.patlen > EL_BUFSIZ - 3) {
25254231Sbostic term_beep(el);
25354231Sbostic break;
25454231Sbostic }
25554231Sbostic el->el_search.patbuf[el->el_search.patlen++] =
25654231Sbostic *el->el_line.cursor;
25754231Sbostic *el->el_line.lastchar++ = *el->el_line.cursor++;
25854231Sbostic }
25954231Sbostic el->el_line.cursor = ocursor;
26054231Sbostic *el->el_line.lastchar = '\0';
26154231Sbostic re_refresh(el);
26254231Sbostic break;
26354231Sbostic } else if (isglob(*cp)) {
26454231Sbostic term_beep(el);
26554231Sbostic break;
26654231Sbostic }
26754231Sbostic break;
26854231Sbostic
26954231Sbostic default: /* Terminate and execute cmd */
27054231Sbostic endcmd[0] = ch;
27154231Sbostic el_push(el, endcmd);
27254231Sbostic /*FALLTHROUGH*/
27354231Sbostic
27454231Sbostic case 0033: /* ESC: Terminate */
27554231Sbostic ret = CC_REFRESH;
27654231Sbostic done++;
27754231Sbostic break;
27854231Sbostic }
27954231Sbostic break;
28054231Sbostic }
28154231Sbostic
28254231Sbostic while (el->el_line.lastchar > el->el_line.buffer &&
28354231Sbostic *el->el_line.lastchar != '\n')
28454231Sbostic *el->el_line.lastchar-- = '\0';
28554231Sbostic *el->el_line.lastchar = '\0';
28654231Sbostic
28754231Sbostic if (!done) {
28854231Sbostic
28954231Sbostic /* Can't search if unmatched '[' */
29054231Sbostic for (cp = &el->el_search.patbuf[el->el_search.patlen-1], ch = ']';
29154231Sbostic cp > el->el_search.patbuf; cp--)
29254231Sbostic if (*cp == '[' || *cp == ']') {
29354231Sbostic ch = *cp;
29454231Sbostic break;
29554231Sbostic }
29654231Sbostic
29754231Sbostic if (el->el_search.patlen > 1 && ch != '[') {
29854231Sbostic if (redo && newdir == dir) {
29954231Sbostic if (pchar == '?') { /* wrap around */
30054231Sbostic el->el_history.eventno =
30154231Sbostic newdir == ED_SEARCH_PREV_HISTORY ? 0 : 0x7fffffff;
30254231Sbostic if (hist_get(el) == CC_ERROR)
30354231Sbostic /* el->el_history.eventno was fixed by first call */
30454231Sbostic (void) hist_get(el);
30554231Sbostic el->el_line.cursor = newdir == ED_SEARCH_PREV_HISTORY ?
30654231Sbostic el->el_line.lastchar : el->el_line.buffer;
30754231Sbostic } else
30854231Sbostic el->el_line.cursor +=
30954231Sbostic newdir == ED_SEARCH_PREV_HISTORY ? -1 : 1;
31054231Sbostic }
31154231Sbostic #ifdef ANCHOR
31254231Sbostic el->el_search.patbuf[el->el_search.patlen++] = '.';
31354231Sbostic el->el_search.patbuf[el->el_search.patlen++] = '*';
31454231Sbostic #endif
31554231Sbostic el->el_search.patbuf[el->el_search.patlen] = '\0';
31654231Sbostic if (el->el_line.cursor < el->el_line.buffer ||
31754231Sbostic el->el_line.cursor > el->el_line.lastchar ||
31854231Sbostic (ret = ce_search_line(el, &el->el_search.patbuf[1],
31954231Sbostic newdir)) == CC_ERROR) {
32054231Sbostic /* avoid c_setpat */
32154231Sbostic el->el_state.lastcmd = (el_action_t) newdir;
32254231Sbostic ret = newdir == ED_SEARCH_PREV_HISTORY ?
32354231Sbostic ed_search_prev_history(el, 0) :
32454231Sbostic ed_search_next_history(el, 0);
32554231Sbostic if (ret != CC_ERROR) {
32654231Sbostic el->el_line.cursor = newdir == ED_SEARCH_PREV_HISTORY ?
32754231Sbostic el->el_line.lastchar : el->el_line.buffer;
32854231Sbostic (void) ce_search_line(el, &el->el_search.patbuf[1],
32954231Sbostic newdir);
33054231Sbostic }
33154231Sbostic }
33254231Sbostic el->el_search.patbuf[--el->el_search.patlen] = '\0';
33354231Sbostic if (ret == CC_ERROR) {
33454231Sbostic term_beep(el);
33554231Sbostic if (el->el_history.eventno != ohisteventno) {
33654231Sbostic el->el_history.eventno = ohisteventno;
33754231Sbostic if (hist_get(el) == CC_ERROR)
33854231Sbostic return CC_ERROR;
33954231Sbostic }
34054231Sbostic el->el_line.cursor = ocursor;
34154231Sbostic pchar = '?';
34254231Sbostic } else {
34354231Sbostic pchar = ':';
34454231Sbostic }
34554231Sbostic }
34654231Sbostic
34754231Sbostic ret = ce_inc_search(el, newdir);
34854231Sbostic
34954231Sbostic if (ret == CC_ERROR && pchar == '?' && oldpchar == ':')
35054231Sbostic /* break abort of failed search at last non-failed */
35154231Sbostic ret = CC_NORM;
35254231Sbostic
35354231Sbostic }
35454231Sbostic
35554231Sbostic if (ret == CC_NORM || (ret == CC_ERROR && oldpatlen == 0)) {
35654231Sbostic /* restore on normal return or error exit */
35754231Sbostic pchar = oldpchar;
35854231Sbostic el->el_search.patlen = oldpatlen;
35954231Sbostic if (el->el_history.eventno != ohisteventno) {
36054231Sbostic el->el_history.eventno = ohisteventno;
36154231Sbostic if (hist_get(el) == CC_ERROR)
36254231Sbostic return CC_ERROR;
36354231Sbostic }
36454231Sbostic el->el_line.cursor = ocursor;
36554231Sbostic if (ret == CC_ERROR)
36654231Sbostic re_refresh(el);
36754231Sbostic }
36854231Sbostic if (done || ret != CC_NORM)
36954231Sbostic return ret;
37054231Sbostic }
37154231Sbostic }
37254231Sbostic
37354231Sbostic
37454231Sbostic /* cv_search():
37554231Sbostic * Vi search.
37654231Sbostic */
37754231Sbostic protected el_action_t
cv_search(el,dir)37854231Sbostic cv_search(el, dir)
37954231Sbostic EditLine *el;
38054231Sbostic int dir;
38154231Sbostic {
38254231Sbostic char ch;
38354231Sbostic char tmpbuf[EL_BUFSIZ];
38454231Sbostic int tmplen;
38554231Sbostic
38654231Sbostic tmplen = 0;
38754231Sbostic #ifdef ANCHOR
38854231Sbostic tmpbuf[tmplen++] = '.';
38954231Sbostic tmpbuf[tmplen++] = '*';
39054231Sbostic #endif
39154231Sbostic
39254231Sbostic el->el_line.buffer[0] = '\0';
39354231Sbostic el->el_line.lastchar = el->el_line.buffer;
39454231Sbostic el->el_line.cursor = el->el_line.buffer;
39554231Sbostic el->el_search.patdir = dir;
39654231Sbostic
39754231Sbostic c_insert(el, 2); /* prompt + '\n' */
39854231Sbostic *el->el_line.cursor++ = '\n';
39955300Smarc *el->el_line.cursor++ = dir == ED_SEARCH_PREV_HISTORY ? '/' : '?';
40054231Sbostic re_refresh(el);
40154231Sbostic
40254231Sbostic #ifdef ANCHOR
40354231Sbostic # define LEN 2
40454231Sbostic #else
40554231Sbostic # define LEN 0
40654231Sbostic #endif
40754231Sbostic
40854231Sbostic tmplen = c_gets(el, &tmpbuf[LEN]) + LEN;
40954231Sbostic ch = tmpbuf[tmplen];
41054231Sbostic tmpbuf[tmplen] = '\0';
41154231Sbostic
41254231Sbostic if (tmplen == LEN) {
41354231Sbostic /*
41454231Sbostic * Use the old pattern, but wild-card it.
41554231Sbostic */
41654231Sbostic if (el->el_search.patlen == 0) {
41754231Sbostic el->el_line.buffer[0] = '\0';
41854231Sbostic el->el_line.lastchar = el->el_line.buffer;
41954231Sbostic el->el_line.cursor = el->el_line.buffer;
42054231Sbostic re_refresh(el);
42154231Sbostic return CC_ERROR;
42254231Sbostic }
42354231Sbostic #ifdef ANCHOR
42454231Sbostic if (el->el_search.patbuf[0] != '.' && el->el_search.patbuf[0] != '*') {
42554231Sbostic (void) strcpy(tmpbuf, el->el_search.patbuf);
42654231Sbostic el->el_search.patbuf[0] = '.';
42754231Sbostic el->el_search.patbuf[1] = '*';
42854231Sbostic (void) strcpy(&el->el_search.patbuf[2], tmpbuf);
42954231Sbostic el->el_search.patlen++;
43054231Sbostic el->el_search.patbuf[el->el_search.patlen++] = '.';
43154231Sbostic el->el_search.patbuf[el->el_search.patlen++] = '*';
43254231Sbostic el->el_search.patbuf[el->el_search.patlen] = '\0';
43354231Sbostic }
43454231Sbostic #endif
43554231Sbostic }
43654231Sbostic else {
43754231Sbostic #ifdef ANCHOR
43854231Sbostic tmpbuf[tmplen++] = '.';
43954231Sbostic tmpbuf[tmplen++] = '*';
44054231Sbostic #endif
44154231Sbostic tmpbuf[tmplen] = '\0';
44254231Sbostic (void) strcpy(el->el_search.patbuf, tmpbuf);
44354231Sbostic el->el_search.patlen = tmplen;
44454231Sbostic }
44554231Sbostic el->el_state.lastcmd = (el_action_t) dir; /* avoid c_setpat */
44654231Sbostic el->el_line.cursor = el->el_line.lastchar = el->el_line.buffer;
44754231Sbostic if ((dir == ED_SEARCH_PREV_HISTORY ? ed_search_prev_history(el, 0) :
44854231Sbostic ed_search_next_history(el, 0)) == CC_ERROR) {
44954231Sbostic re_refresh(el);
45054231Sbostic return CC_ERROR;
45154231Sbostic }
45254231Sbostic else {
45354231Sbostic if (ch == 0033) {
45454231Sbostic re_refresh(el);
45554231Sbostic *el->el_line.lastchar++ = '\n';
45654231Sbostic *el->el_line.lastchar = '\0';
45754231Sbostic re_goto_bottom(el);
45854231Sbostic return CC_NEWLINE;
45954231Sbostic }
46054231Sbostic else
46154231Sbostic return CC_REFRESH;
46254231Sbostic }
46354231Sbostic }
46454231Sbostic
46554231Sbostic
46654231Sbostic /* ce_search_line():
46754231Sbostic * Look for a pattern inside a line
46854231Sbostic */
46954231Sbostic protected el_action_t
ce_search_line(el,pattern,dir)47054231Sbostic ce_search_line(el, pattern, dir)
47154231Sbostic EditLine *el;
47254231Sbostic char *pattern;
47354231Sbostic int dir;
47454231Sbostic {
47554231Sbostic char *cp;
47654231Sbostic
47754231Sbostic if (dir == ED_SEARCH_PREV_HISTORY) {
47854231Sbostic for (cp = el->el_line.cursor; cp >= el->el_line.buffer; cp--)
47954231Sbostic if (el_match(cp, pattern)) {
48054231Sbostic el->el_line.cursor = cp;
48154231Sbostic return CC_NORM;
48254231Sbostic }
48354231Sbostic return CC_ERROR;
48454231Sbostic } else {
48554231Sbostic for (cp = el->el_line.cursor; *cp != '\0' &&
48654231Sbostic cp < el->el_line.limit; cp++)
48754231Sbostic if (el_match(cp, pattern)) {
48854231Sbostic el->el_line.cursor = cp;
48954231Sbostic return CC_NORM;
49054231Sbostic }
49154231Sbostic return CC_ERROR;
49254231Sbostic }
49354231Sbostic }
49454231Sbostic
49554231Sbostic
49654231Sbostic /* cv_repeat_srch():
49754231Sbostic * Vi repeat search
49854231Sbostic */
49954231Sbostic protected el_action_t
cv_repeat_srch(el,c)50054231Sbostic cv_repeat_srch(el, c)
50154231Sbostic EditLine *el;
50254231Sbostic int c;
50354231Sbostic {
50454231Sbostic #ifdef SDEBUG
50554231Sbostic (void) fprintf(el->el_errfile, "dir %d patlen %d patbuf %s\n",
50654231Sbostic c, el->el_search.patlen, el->el_search.patbuf);
50754231Sbostic #endif
50854231Sbostic
50954231Sbostic el->el_state.lastcmd = (el_action_t) c; /* Hack to stop c_setpat */
51054231Sbostic el->el_line.lastchar = el->el_line.buffer;
51154231Sbostic
51254231Sbostic switch (c) {
51354231Sbostic case ED_SEARCH_NEXT_HISTORY:
51454231Sbostic return ed_search_next_history(el, 0);
51554231Sbostic case ED_SEARCH_PREV_HISTORY:
51654231Sbostic return ed_search_prev_history(el, 0);
51754231Sbostic default:
51854231Sbostic return CC_ERROR;
51954231Sbostic }
52054231Sbostic }
52154231Sbostic
52254231Sbostic
52354231Sbostic /* cv_csearch_back():
52454231Sbostic * Vi character search reverse
52554231Sbostic */
52654231Sbostic protected el_action_t
cv_csearch_back(el,ch,count,tflag)52754231Sbostic cv_csearch_back(el, ch, count, tflag)
52854231Sbostic EditLine *el;
52954231Sbostic int ch, count, tflag;
53054231Sbostic {
53154231Sbostic char *cp;
53254231Sbostic
53354231Sbostic cp = el->el_line.cursor;
53454231Sbostic while (count--) {
53554231Sbostic if (*cp == ch)
53654231Sbostic cp--;
53754231Sbostic while (cp > el->el_line.buffer && *cp != ch)
53854231Sbostic cp--;
53954231Sbostic }
54054231Sbostic
54154231Sbostic if (cp < el->el_line.buffer || (cp == el->el_line.buffer && *cp != ch))
54254231Sbostic return CC_ERROR;
54354231Sbostic
54454231Sbostic if (*cp == ch && tflag)
54554231Sbostic cp++;
54654231Sbostic
54754231Sbostic el->el_line.cursor = cp;
54854231Sbostic
54954231Sbostic if (el->el_chared.c_vcmd.action & DELETE) {
55054231Sbostic el->el_line.cursor++;
55154231Sbostic cv_delfini(el);
55254231Sbostic return CC_REFRESH;
55354231Sbostic }
55454231Sbostic
55554231Sbostic re_refresh_cursor(el);
55654231Sbostic return CC_NORM;
55754231Sbostic }
55854231Sbostic
55954231Sbostic
56054231Sbostic /* cv_csearch_fwd():
56154231Sbostic * Vi character search forward
56254231Sbostic */
56354231Sbostic protected el_action_t
cv_csearch_fwd(el,ch,count,tflag)56454231Sbostic cv_csearch_fwd(el, ch, count, tflag)
56554231Sbostic EditLine *el;
56654231Sbostic int ch, count, tflag;
56754231Sbostic {
56854231Sbostic char *cp;
56954231Sbostic
57054231Sbostic cp = el->el_line.cursor;
57154231Sbostic while (count--) {
57254231Sbostic if(*cp == ch)
57354231Sbostic cp++;
57454231Sbostic while (cp < el->el_line.lastchar && *cp != ch)
57554231Sbostic cp++;
57654231Sbostic }
57754231Sbostic
57854231Sbostic if (cp >= el->el_line.lastchar)
57954231Sbostic return CC_ERROR;
58054231Sbostic
58154231Sbostic if (*cp == ch && tflag)
58254231Sbostic cp--;
58354231Sbostic
58454231Sbostic el->el_line.cursor = cp;
58554231Sbostic
58654231Sbostic if (el->el_chared.c_vcmd.action & DELETE) {
58754231Sbostic el->el_line.cursor++;
58854231Sbostic cv_delfini(el);
58954231Sbostic return CC_REFRESH;
59054231Sbostic }
59154231Sbostic re_refresh_cursor(el);
59254231Sbostic return CC_NORM;
59354231Sbostic }
594