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