xref: /freebsd-src/contrib/libedit/chared.c (revision d0ef721ed3dc99bddc1e48605a6921ec60322efc)
1*d0ef721eSBaptiste Daroussin /*	$NetBSD: chared.c,v 1.59 2019/07/23 10:18:52 christos Exp $	*/
2*d0ef721eSBaptiste Daroussin 
3*d0ef721eSBaptiste Daroussin /*-
4*d0ef721eSBaptiste Daroussin  * Copyright (c) 1992, 1993
5*d0ef721eSBaptiste Daroussin  *	The Regents of the University of California.  All rights reserved.
6*d0ef721eSBaptiste Daroussin  *
7*d0ef721eSBaptiste Daroussin  * This code is derived from software contributed to Berkeley by
8*d0ef721eSBaptiste Daroussin  * Christos Zoulas of Cornell University.
9*d0ef721eSBaptiste Daroussin  *
10*d0ef721eSBaptiste Daroussin  * Redistribution and use in source and binary forms, with or without
11*d0ef721eSBaptiste Daroussin  * modification, are permitted provided that the following conditions
12*d0ef721eSBaptiste Daroussin  * are met:
13*d0ef721eSBaptiste Daroussin  * 1. Redistributions of source code must retain the above copyright
14*d0ef721eSBaptiste Daroussin  *    notice, this list of conditions and the following disclaimer.
15*d0ef721eSBaptiste Daroussin  * 2. Redistributions in binary form must reproduce the above copyright
16*d0ef721eSBaptiste Daroussin  *    notice, this list of conditions and the following disclaimer in the
17*d0ef721eSBaptiste Daroussin  *    documentation and/or other materials provided with the distribution.
18*d0ef721eSBaptiste Daroussin  * 3. Neither the name of the University nor the names of its contributors
19*d0ef721eSBaptiste Daroussin  *    may be used to endorse or promote products derived from this software
20*d0ef721eSBaptiste Daroussin  *    without specific prior written permission.
21*d0ef721eSBaptiste Daroussin  *
22*d0ef721eSBaptiste Daroussin  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23*d0ef721eSBaptiste Daroussin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24*d0ef721eSBaptiste Daroussin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25*d0ef721eSBaptiste Daroussin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26*d0ef721eSBaptiste Daroussin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27*d0ef721eSBaptiste Daroussin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28*d0ef721eSBaptiste Daroussin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29*d0ef721eSBaptiste Daroussin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30*d0ef721eSBaptiste Daroussin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31*d0ef721eSBaptiste Daroussin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32*d0ef721eSBaptiste Daroussin  * SUCH DAMAGE.
33*d0ef721eSBaptiste Daroussin  */
34*d0ef721eSBaptiste Daroussin 
35*d0ef721eSBaptiste Daroussin #include "config.h"
36*d0ef721eSBaptiste Daroussin #if !defined(lint) && !defined(SCCSID)
37*d0ef721eSBaptiste Daroussin #if 0
38*d0ef721eSBaptiste Daroussin static char sccsid[] = "@(#)chared.c	8.1 (Berkeley) 6/4/93";
39*d0ef721eSBaptiste Daroussin #else
40*d0ef721eSBaptiste Daroussin __RCSID("$NetBSD: chared.c,v 1.59 2019/07/23 10:18:52 christos Exp $");
41*d0ef721eSBaptiste Daroussin #endif
42*d0ef721eSBaptiste Daroussin #endif /* not lint && not SCCSID */
43*d0ef721eSBaptiste Daroussin 
44*d0ef721eSBaptiste Daroussin /*
45*d0ef721eSBaptiste Daroussin  * chared.c: Character editor utilities
46*d0ef721eSBaptiste Daroussin  */
47*d0ef721eSBaptiste Daroussin #include <ctype.h>
48*d0ef721eSBaptiste Daroussin #include <stdlib.h>
49*d0ef721eSBaptiste Daroussin #include <string.h>
50*d0ef721eSBaptiste Daroussin 
51*d0ef721eSBaptiste Daroussin #include "el.h"
52*d0ef721eSBaptiste Daroussin #include "common.h"
53*d0ef721eSBaptiste Daroussin #include "fcns.h"
54*d0ef721eSBaptiste Daroussin 
55*d0ef721eSBaptiste Daroussin /* value to leave unused in line buffer */
56*d0ef721eSBaptiste Daroussin #define	EL_LEAVE	2
57*d0ef721eSBaptiste Daroussin 
58*d0ef721eSBaptiste Daroussin /* cv_undo():
59*d0ef721eSBaptiste Daroussin  *	Handle state for the vi undo command
60*d0ef721eSBaptiste Daroussin  */
61*d0ef721eSBaptiste Daroussin libedit_private void
62*d0ef721eSBaptiste Daroussin cv_undo(EditLine *el)
63*d0ef721eSBaptiste Daroussin {
64*d0ef721eSBaptiste Daroussin 	c_undo_t *vu = &el->el_chared.c_undo;
65*d0ef721eSBaptiste Daroussin 	c_redo_t *r = &el->el_chared.c_redo;
66*d0ef721eSBaptiste Daroussin 	size_t size;
67*d0ef721eSBaptiste Daroussin 
68*d0ef721eSBaptiste Daroussin 	/* Save entire line for undo */
69*d0ef721eSBaptiste Daroussin 	size = (size_t)(el->el_line.lastchar - el->el_line.buffer);
70*d0ef721eSBaptiste Daroussin 	vu->len = (ssize_t)size;
71*d0ef721eSBaptiste Daroussin 	vu->cursor = (int)(el->el_line.cursor - el->el_line.buffer);
72*d0ef721eSBaptiste Daroussin 	(void)memcpy(vu->buf, el->el_line.buffer, size * sizeof(*vu->buf));
73*d0ef721eSBaptiste Daroussin 
74*d0ef721eSBaptiste Daroussin 	/* save command info for redo */
75*d0ef721eSBaptiste Daroussin 	r->count = el->el_state.doingarg ? el->el_state.argument : 0;
76*d0ef721eSBaptiste Daroussin 	r->action = el->el_chared.c_vcmd.action;
77*d0ef721eSBaptiste Daroussin 	r->pos = r->buf;
78*d0ef721eSBaptiste Daroussin 	r->cmd = el->el_state.thiscmd;
79*d0ef721eSBaptiste Daroussin 	r->ch = el->el_state.thisch;
80*d0ef721eSBaptiste Daroussin }
81*d0ef721eSBaptiste Daroussin 
82*d0ef721eSBaptiste Daroussin /* cv_yank():
83*d0ef721eSBaptiste Daroussin  *	Save yank/delete data for paste
84*d0ef721eSBaptiste Daroussin  */
85*d0ef721eSBaptiste Daroussin libedit_private void
86*d0ef721eSBaptiste Daroussin cv_yank(EditLine *el, const wchar_t *ptr, int size)
87*d0ef721eSBaptiste Daroussin {
88*d0ef721eSBaptiste Daroussin 	c_kill_t *k = &el->el_chared.c_kill;
89*d0ef721eSBaptiste Daroussin 
90*d0ef721eSBaptiste Daroussin 	(void)memcpy(k->buf, ptr, (size_t)size * sizeof(*k->buf));
91*d0ef721eSBaptiste Daroussin 	k->last = k->buf + size;
92*d0ef721eSBaptiste Daroussin }
93*d0ef721eSBaptiste Daroussin 
94*d0ef721eSBaptiste Daroussin 
95*d0ef721eSBaptiste Daroussin /* c_insert():
96*d0ef721eSBaptiste Daroussin  *	Insert num characters
97*d0ef721eSBaptiste Daroussin  */
98*d0ef721eSBaptiste Daroussin libedit_private void
99*d0ef721eSBaptiste Daroussin c_insert(EditLine *el, int num)
100*d0ef721eSBaptiste Daroussin {
101*d0ef721eSBaptiste Daroussin 	wchar_t *cp;
102*d0ef721eSBaptiste Daroussin 
103*d0ef721eSBaptiste Daroussin 	if (el->el_line.lastchar + num >= el->el_line.limit) {
104*d0ef721eSBaptiste Daroussin 		if (!ch_enlargebufs(el, (size_t)num))
105*d0ef721eSBaptiste Daroussin 			return;		/* can't go past end of buffer */
106*d0ef721eSBaptiste Daroussin 	}
107*d0ef721eSBaptiste Daroussin 
108*d0ef721eSBaptiste Daroussin 	if (el->el_line.cursor < el->el_line.lastchar) {
109*d0ef721eSBaptiste Daroussin 		/* if I must move chars */
110*d0ef721eSBaptiste Daroussin 		for (cp = el->el_line.lastchar; cp >= el->el_line.cursor; cp--)
111*d0ef721eSBaptiste Daroussin 			cp[num] = *cp;
112*d0ef721eSBaptiste Daroussin 	}
113*d0ef721eSBaptiste Daroussin 	el->el_line.lastchar += num;
114*d0ef721eSBaptiste Daroussin }
115*d0ef721eSBaptiste Daroussin 
116*d0ef721eSBaptiste Daroussin 
117*d0ef721eSBaptiste Daroussin /* c_delafter():
118*d0ef721eSBaptiste Daroussin  *	Delete num characters after the cursor
119*d0ef721eSBaptiste Daroussin  */
120*d0ef721eSBaptiste Daroussin libedit_private void
121*d0ef721eSBaptiste Daroussin c_delafter(EditLine *el, int num)
122*d0ef721eSBaptiste Daroussin {
123*d0ef721eSBaptiste Daroussin 
124*d0ef721eSBaptiste Daroussin 	if (el->el_line.cursor + num > el->el_line.lastchar)
125*d0ef721eSBaptiste Daroussin 		num = (int)(el->el_line.lastchar - el->el_line.cursor);
126*d0ef721eSBaptiste Daroussin 
127*d0ef721eSBaptiste Daroussin 	if (el->el_map.current != el->el_map.emacs) {
128*d0ef721eSBaptiste Daroussin 		cv_undo(el);
129*d0ef721eSBaptiste Daroussin 		cv_yank(el, el->el_line.cursor, num);
130*d0ef721eSBaptiste Daroussin 	}
131*d0ef721eSBaptiste Daroussin 
132*d0ef721eSBaptiste Daroussin 	if (num > 0) {
133*d0ef721eSBaptiste Daroussin 		wchar_t *cp;
134*d0ef721eSBaptiste Daroussin 
135*d0ef721eSBaptiste Daroussin 		for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++)
136*d0ef721eSBaptiste Daroussin 			*cp = cp[num];
137*d0ef721eSBaptiste Daroussin 
138*d0ef721eSBaptiste Daroussin 		el->el_line.lastchar -= num;
139*d0ef721eSBaptiste Daroussin 	}
140*d0ef721eSBaptiste Daroussin }
141*d0ef721eSBaptiste Daroussin 
142*d0ef721eSBaptiste Daroussin 
143*d0ef721eSBaptiste Daroussin /* c_delafter1():
144*d0ef721eSBaptiste Daroussin  *	Delete the character after the cursor, do not yank
145*d0ef721eSBaptiste Daroussin  */
146*d0ef721eSBaptiste Daroussin libedit_private void
147*d0ef721eSBaptiste Daroussin c_delafter1(EditLine *el)
148*d0ef721eSBaptiste Daroussin {
149*d0ef721eSBaptiste Daroussin 	wchar_t *cp;
150*d0ef721eSBaptiste Daroussin 
151*d0ef721eSBaptiste Daroussin 	for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++)
152*d0ef721eSBaptiste Daroussin 		*cp = cp[1];
153*d0ef721eSBaptiste Daroussin 
154*d0ef721eSBaptiste Daroussin 	el->el_line.lastchar--;
155*d0ef721eSBaptiste Daroussin }
156*d0ef721eSBaptiste Daroussin 
157*d0ef721eSBaptiste Daroussin 
158*d0ef721eSBaptiste Daroussin /* c_delbefore():
159*d0ef721eSBaptiste Daroussin  *	Delete num characters before the cursor
160*d0ef721eSBaptiste Daroussin  */
161*d0ef721eSBaptiste Daroussin libedit_private void
162*d0ef721eSBaptiste Daroussin c_delbefore(EditLine *el, int num)
163*d0ef721eSBaptiste Daroussin {
164*d0ef721eSBaptiste Daroussin 
165*d0ef721eSBaptiste Daroussin 	if (el->el_line.cursor - num < el->el_line.buffer)
166*d0ef721eSBaptiste Daroussin 		num = (int)(el->el_line.cursor - el->el_line.buffer);
167*d0ef721eSBaptiste Daroussin 
168*d0ef721eSBaptiste Daroussin 	if (el->el_map.current != el->el_map.emacs) {
169*d0ef721eSBaptiste Daroussin 		cv_undo(el);
170*d0ef721eSBaptiste Daroussin 		cv_yank(el, el->el_line.cursor - num, num);
171*d0ef721eSBaptiste Daroussin 	}
172*d0ef721eSBaptiste Daroussin 
173*d0ef721eSBaptiste Daroussin 	if (num > 0) {
174*d0ef721eSBaptiste Daroussin 		wchar_t *cp;
175*d0ef721eSBaptiste Daroussin 
176*d0ef721eSBaptiste Daroussin 		for (cp = el->el_line.cursor - num;
177*d0ef721eSBaptiste Daroussin 		    &cp[num] <= el->el_line.lastchar;
178*d0ef721eSBaptiste Daroussin 		    cp++)
179*d0ef721eSBaptiste Daroussin 			*cp = cp[num];
180*d0ef721eSBaptiste Daroussin 
181*d0ef721eSBaptiste Daroussin 		el->el_line.lastchar -= num;
182*d0ef721eSBaptiste Daroussin 	}
183*d0ef721eSBaptiste Daroussin }
184*d0ef721eSBaptiste Daroussin 
185*d0ef721eSBaptiste Daroussin 
186*d0ef721eSBaptiste Daroussin /* c_delbefore1():
187*d0ef721eSBaptiste Daroussin  *	Delete the character before the cursor, do not yank
188*d0ef721eSBaptiste Daroussin  */
189*d0ef721eSBaptiste Daroussin libedit_private void
190*d0ef721eSBaptiste Daroussin c_delbefore1(EditLine *el)
191*d0ef721eSBaptiste Daroussin {
192*d0ef721eSBaptiste Daroussin 	wchar_t *cp;
193*d0ef721eSBaptiste Daroussin 
194*d0ef721eSBaptiste Daroussin 	for (cp = el->el_line.cursor - 1; cp <= el->el_line.lastchar; cp++)
195*d0ef721eSBaptiste Daroussin 		*cp = cp[1];
196*d0ef721eSBaptiste Daroussin 
197*d0ef721eSBaptiste Daroussin 	el->el_line.lastchar--;
198*d0ef721eSBaptiste Daroussin }
199*d0ef721eSBaptiste Daroussin 
200*d0ef721eSBaptiste Daroussin 
201*d0ef721eSBaptiste Daroussin /* ce__isword():
202*d0ef721eSBaptiste Daroussin  *	Return if p is part of a word according to emacs
203*d0ef721eSBaptiste Daroussin  */
204*d0ef721eSBaptiste Daroussin libedit_private int
205*d0ef721eSBaptiste Daroussin ce__isword(wint_t p)
206*d0ef721eSBaptiste Daroussin {
207*d0ef721eSBaptiste Daroussin 	return iswalnum(p) || wcschr(L"*?_-.[]~=", p) != NULL;
208*d0ef721eSBaptiste Daroussin }
209*d0ef721eSBaptiste Daroussin 
210*d0ef721eSBaptiste Daroussin 
211*d0ef721eSBaptiste Daroussin /* cv__isword():
212*d0ef721eSBaptiste Daroussin  *	Return if p is part of a word according to vi
213*d0ef721eSBaptiste Daroussin  */
214*d0ef721eSBaptiste Daroussin libedit_private int
215*d0ef721eSBaptiste Daroussin cv__isword(wint_t p)
216*d0ef721eSBaptiste Daroussin {
217*d0ef721eSBaptiste Daroussin 	if (iswalnum(p) || p == L'_')
218*d0ef721eSBaptiste Daroussin 		return 1;
219*d0ef721eSBaptiste Daroussin 	if (iswgraph(p))
220*d0ef721eSBaptiste Daroussin 		return 2;
221*d0ef721eSBaptiste Daroussin 	return 0;
222*d0ef721eSBaptiste Daroussin }
223*d0ef721eSBaptiste Daroussin 
224*d0ef721eSBaptiste Daroussin 
225*d0ef721eSBaptiste Daroussin /* cv__isWord():
226*d0ef721eSBaptiste Daroussin  *	Return if p is part of a big word according to vi
227*d0ef721eSBaptiste Daroussin  */
228*d0ef721eSBaptiste Daroussin libedit_private int
229*d0ef721eSBaptiste Daroussin cv__isWord(wint_t p)
230*d0ef721eSBaptiste Daroussin {
231*d0ef721eSBaptiste Daroussin 	return !iswspace(p);
232*d0ef721eSBaptiste Daroussin }
233*d0ef721eSBaptiste Daroussin 
234*d0ef721eSBaptiste Daroussin 
235*d0ef721eSBaptiste Daroussin /* c__prev_word():
236*d0ef721eSBaptiste Daroussin  *	Find the previous word
237*d0ef721eSBaptiste Daroussin  */
238*d0ef721eSBaptiste Daroussin libedit_private wchar_t *
239*d0ef721eSBaptiste Daroussin c__prev_word(wchar_t *p, wchar_t *low, int n, int (*wtest)(wint_t))
240*d0ef721eSBaptiste Daroussin {
241*d0ef721eSBaptiste Daroussin 	p--;
242*d0ef721eSBaptiste Daroussin 
243*d0ef721eSBaptiste Daroussin 	while (n--) {
244*d0ef721eSBaptiste Daroussin 		while ((p >= low) && !(*wtest)(*p))
245*d0ef721eSBaptiste Daroussin 			p--;
246*d0ef721eSBaptiste Daroussin 		while ((p >= low) && (*wtest)(*p))
247*d0ef721eSBaptiste Daroussin 			p--;
248*d0ef721eSBaptiste Daroussin 	}
249*d0ef721eSBaptiste Daroussin 
250*d0ef721eSBaptiste Daroussin 	/* cp now points to one character before the word */
251*d0ef721eSBaptiste Daroussin 	p++;
252*d0ef721eSBaptiste Daroussin 	if (p < low)
253*d0ef721eSBaptiste Daroussin 		p = low;
254*d0ef721eSBaptiste Daroussin 	/* cp now points where we want it */
255*d0ef721eSBaptiste Daroussin 	return p;
256*d0ef721eSBaptiste Daroussin }
257*d0ef721eSBaptiste Daroussin 
258*d0ef721eSBaptiste Daroussin 
259*d0ef721eSBaptiste Daroussin /* c__next_word():
260*d0ef721eSBaptiste Daroussin  *	Find the next word
261*d0ef721eSBaptiste Daroussin  */
262*d0ef721eSBaptiste Daroussin libedit_private wchar_t *
263*d0ef721eSBaptiste Daroussin c__next_word(wchar_t *p, wchar_t *high, int n, int (*wtest)(wint_t))
264*d0ef721eSBaptiste Daroussin {
265*d0ef721eSBaptiste Daroussin 	while (n--) {
266*d0ef721eSBaptiste Daroussin 		while ((p < high) && !(*wtest)(*p))
267*d0ef721eSBaptiste Daroussin 			p++;
268*d0ef721eSBaptiste Daroussin 		while ((p < high) && (*wtest)(*p))
269*d0ef721eSBaptiste Daroussin 			p++;
270*d0ef721eSBaptiste Daroussin 	}
271*d0ef721eSBaptiste Daroussin 	if (p > high)
272*d0ef721eSBaptiste Daroussin 		p = high;
273*d0ef721eSBaptiste Daroussin 	/* p now points where we want it */
274*d0ef721eSBaptiste Daroussin 	return p;
275*d0ef721eSBaptiste Daroussin }
276*d0ef721eSBaptiste Daroussin 
277*d0ef721eSBaptiste Daroussin /* cv_next_word():
278*d0ef721eSBaptiste Daroussin  *	Find the next word vi style
279*d0ef721eSBaptiste Daroussin  */
280*d0ef721eSBaptiste Daroussin libedit_private wchar_t *
281*d0ef721eSBaptiste Daroussin cv_next_word(EditLine *el, wchar_t *p, wchar_t *high, int n,
282*d0ef721eSBaptiste Daroussin     int (*wtest)(wint_t))
283*d0ef721eSBaptiste Daroussin {
284*d0ef721eSBaptiste Daroussin 	int test;
285*d0ef721eSBaptiste Daroussin 
286*d0ef721eSBaptiste Daroussin 	while (n--) {
287*d0ef721eSBaptiste Daroussin 		test = (*wtest)(*p);
288*d0ef721eSBaptiste Daroussin 		while ((p < high) && (*wtest)(*p) == test)
289*d0ef721eSBaptiste Daroussin 			p++;
290*d0ef721eSBaptiste Daroussin 		/*
291*d0ef721eSBaptiste Daroussin 		 * vi historically deletes with cw only the word preserving the
292*d0ef721eSBaptiste Daroussin 		 * trailing whitespace! This is not what 'w' does..
293*d0ef721eSBaptiste Daroussin 		 */
294*d0ef721eSBaptiste Daroussin 		if (n || el->el_chared.c_vcmd.action != (DELETE|INSERT))
295*d0ef721eSBaptiste Daroussin 			while ((p < high) && iswspace(*p))
296*d0ef721eSBaptiste Daroussin 				p++;
297*d0ef721eSBaptiste Daroussin 	}
298*d0ef721eSBaptiste Daroussin 
299*d0ef721eSBaptiste Daroussin 	/* p now points where we want it */
300*d0ef721eSBaptiste Daroussin 	if (p > high)
301*d0ef721eSBaptiste Daroussin 		return high;
302*d0ef721eSBaptiste Daroussin 	else
303*d0ef721eSBaptiste Daroussin 		return p;
304*d0ef721eSBaptiste Daroussin }
305*d0ef721eSBaptiste Daroussin 
306*d0ef721eSBaptiste Daroussin 
307*d0ef721eSBaptiste Daroussin /* cv_prev_word():
308*d0ef721eSBaptiste Daroussin  *	Find the previous word vi style
309*d0ef721eSBaptiste Daroussin  */
310*d0ef721eSBaptiste Daroussin libedit_private wchar_t *
311*d0ef721eSBaptiste Daroussin cv_prev_word(wchar_t *p, wchar_t *low, int n, int (*wtest)(wint_t))
312*d0ef721eSBaptiste Daroussin {
313*d0ef721eSBaptiste Daroussin 	int test;
314*d0ef721eSBaptiste Daroussin 
315*d0ef721eSBaptiste Daroussin 	p--;
316*d0ef721eSBaptiste Daroussin 	while (n--) {
317*d0ef721eSBaptiste Daroussin 		while ((p > low) && iswspace(*p))
318*d0ef721eSBaptiste Daroussin 			p--;
319*d0ef721eSBaptiste Daroussin 		test = (*wtest)(*p);
320*d0ef721eSBaptiste Daroussin 		while ((p >= low) && (*wtest)(*p) == test)
321*d0ef721eSBaptiste Daroussin 			p--;
322*d0ef721eSBaptiste Daroussin 	}
323*d0ef721eSBaptiste Daroussin 	p++;
324*d0ef721eSBaptiste Daroussin 
325*d0ef721eSBaptiste Daroussin 	/* p now points where we want it */
326*d0ef721eSBaptiste Daroussin 	if (p < low)
327*d0ef721eSBaptiste Daroussin 		return low;
328*d0ef721eSBaptiste Daroussin 	else
329*d0ef721eSBaptiste Daroussin 		return p;
330*d0ef721eSBaptiste Daroussin }
331*d0ef721eSBaptiste Daroussin 
332*d0ef721eSBaptiste Daroussin 
333*d0ef721eSBaptiste Daroussin /* cv_delfini():
334*d0ef721eSBaptiste Daroussin  *	Finish vi delete action
335*d0ef721eSBaptiste Daroussin  */
336*d0ef721eSBaptiste Daroussin libedit_private void
337*d0ef721eSBaptiste Daroussin cv_delfini(EditLine *el)
338*d0ef721eSBaptiste Daroussin {
339*d0ef721eSBaptiste Daroussin 	int size;
340*d0ef721eSBaptiste Daroussin 	int action = el->el_chared.c_vcmd.action;
341*d0ef721eSBaptiste Daroussin 
342*d0ef721eSBaptiste Daroussin 	if (action & INSERT)
343*d0ef721eSBaptiste Daroussin 		el->el_map.current = el->el_map.key;
344*d0ef721eSBaptiste Daroussin 
345*d0ef721eSBaptiste Daroussin 	if (el->el_chared.c_vcmd.pos == 0)
346*d0ef721eSBaptiste Daroussin 		/* sanity */
347*d0ef721eSBaptiste Daroussin 		return;
348*d0ef721eSBaptiste Daroussin 
349*d0ef721eSBaptiste Daroussin 	size = (int)(el->el_line.cursor - el->el_chared.c_vcmd.pos);
350*d0ef721eSBaptiste Daroussin 	if (size == 0)
351*d0ef721eSBaptiste Daroussin 		size = 1;
352*d0ef721eSBaptiste Daroussin 	el->el_line.cursor = el->el_chared.c_vcmd.pos;
353*d0ef721eSBaptiste Daroussin 	if (action & YANK) {
354*d0ef721eSBaptiste Daroussin 		if (size > 0)
355*d0ef721eSBaptiste Daroussin 			cv_yank(el, el->el_line.cursor, size);
356*d0ef721eSBaptiste Daroussin 		else
357*d0ef721eSBaptiste Daroussin 			cv_yank(el, el->el_line.cursor + size, -size);
358*d0ef721eSBaptiste Daroussin 	} else {
359*d0ef721eSBaptiste Daroussin 		if (size > 0) {
360*d0ef721eSBaptiste Daroussin 			c_delafter(el, size);
361*d0ef721eSBaptiste Daroussin 			re_refresh_cursor(el);
362*d0ef721eSBaptiste Daroussin 		} else  {
363*d0ef721eSBaptiste Daroussin 			c_delbefore(el, -size);
364*d0ef721eSBaptiste Daroussin 			el->el_line.cursor += size;
365*d0ef721eSBaptiste Daroussin 		}
366*d0ef721eSBaptiste Daroussin 	}
367*d0ef721eSBaptiste Daroussin 	el->el_chared.c_vcmd.action = NOP;
368*d0ef721eSBaptiste Daroussin }
369*d0ef721eSBaptiste Daroussin 
370*d0ef721eSBaptiste Daroussin 
371*d0ef721eSBaptiste Daroussin /* cv__endword():
372*d0ef721eSBaptiste Daroussin  *	Go to the end of this word according to vi
373*d0ef721eSBaptiste Daroussin  */
374*d0ef721eSBaptiste Daroussin libedit_private wchar_t *
375*d0ef721eSBaptiste Daroussin cv__endword(wchar_t *p, wchar_t *high, int n, int (*wtest)(wint_t))
376*d0ef721eSBaptiste Daroussin {
377*d0ef721eSBaptiste Daroussin 	int test;
378*d0ef721eSBaptiste Daroussin 
379*d0ef721eSBaptiste Daroussin 	p++;
380*d0ef721eSBaptiste Daroussin 
381*d0ef721eSBaptiste Daroussin 	while (n--) {
382*d0ef721eSBaptiste Daroussin 		while ((p < high) && iswspace(*p))
383*d0ef721eSBaptiste Daroussin 			p++;
384*d0ef721eSBaptiste Daroussin 
385*d0ef721eSBaptiste Daroussin 		test = (*wtest)(*p);
386*d0ef721eSBaptiste Daroussin 		while ((p < high) && (*wtest)(*p) == test)
387*d0ef721eSBaptiste Daroussin 			p++;
388*d0ef721eSBaptiste Daroussin 	}
389*d0ef721eSBaptiste Daroussin 	p--;
390*d0ef721eSBaptiste Daroussin 	return p;
391*d0ef721eSBaptiste Daroussin }
392*d0ef721eSBaptiste Daroussin 
393*d0ef721eSBaptiste Daroussin /* ch_init():
394*d0ef721eSBaptiste Daroussin  *	Initialize the character editor
395*d0ef721eSBaptiste Daroussin  */
396*d0ef721eSBaptiste Daroussin libedit_private int
397*d0ef721eSBaptiste Daroussin ch_init(EditLine *el)
398*d0ef721eSBaptiste Daroussin {
399*d0ef721eSBaptiste Daroussin 	el->el_line.buffer		= el_calloc(EL_BUFSIZ,
400*d0ef721eSBaptiste Daroussin 	    sizeof(*el->el_line.buffer));
401*d0ef721eSBaptiste Daroussin 	if (el->el_line.buffer == NULL)
402*d0ef721eSBaptiste Daroussin 		return -1;
403*d0ef721eSBaptiste Daroussin 
404*d0ef721eSBaptiste Daroussin 	el->el_line.cursor		= el->el_line.buffer;
405*d0ef721eSBaptiste Daroussin 	el->el_line.lastchar		= el->el_line.buffer;
406*d0ef721eSBaptiste Daroussin 	el->el_line.limit		= &el->el_line.buffer[EL_BUFSIZ - EL_LEAVE];
407*d0ef721eSBaptiste Daroussin 
408*d0ef721eSBaptiste Daroussin 	el->el_chared.c_undo.buf	= el_calloc(EL_BUFSIZ,
409*d0ef721eSBaptiste Daroussin 	    sizeof(*el->el_chared.c_undo.buf));
410*d0ef721eSBaptiste Daroussin 	if (el->el_chared.c_undo.buf == NULL)
411*d0ef721eSBaptiste Daroussin 		return -1;
412*d0ef721eSBaptiste Daroussin 	el->el_chared.c_undo.len	= -1;
413*d0ef721eSBaptiste Daroussin 	el->el_chared.c_undo.cursor	= 0;
414*d0ef721eSBaptiste Daroussin 	el->el_chared.c_redo.buf	= el_calloc(EL_BUFSIZ,
415*d0ef721eSBaptiste Daroussin 	    sizeof(*el->el_chared.c_redo.buf));
416*d0ef721eSBaptiste Daroussin 	if (el->el_chared.c_redo.buf == NULL)
417*d0ef721eSBaptiste Daroussin 		return -1;
418*d0ef721eSBaptiste Daroussin 	el->el_chared.c_redo.pos	= el->el_chared.c_redo.buf;
419*d0ef721eSBaptiste Daroussin 	el->el_chared.c_redo.lim	= el->el_chared.c_redo.buf + EL_BUFSIZ;
420*d0ef721eSBaptiste Daroussin 	el->el_chared.c_redo.cmd	= ED_UNASSIGNED;
421*d0ef721eSBaptiste Daroussin 
422*d0ef721eSBaptiste Daroussin 	el->el_chared.c_vcmd.action	= NOP;
423*d0ef721eSBaptiste Daroussin 	el->el_chared.c_vcmd.pos	= el->el_line.buffer;
424*d0ef721eSBaptiste Daroussin 
425*d0ef721eSBaptiste Daroussin 	el->el_chared.c_kill.buf	= el_calloc(EL_BUFSIZ,
426*d0ef721eSBaptiste Daroussin 	    sizeof(*el->el_chared.c_kill.buf));
427*d0ef721eSBaptiste Daroussin 	if (el->el_chared.c_kill.buf == NULL)
428*d0ef721eSBaptiste Daroussin 		return -1;
429*d0ef721eSBaptiste Daroussin 	el->el_chared.c_kill.mark	= el->el_line.buffer;
430*d0ef721eSBaptiste Daroussin 	el->el_chared.c_kill.last	= el->el_chared.c_kill.buf;
431*d0ef721eSBaptiste Daroussin 	el->el_chared.c_resizefun	= NULL;
432*d0ef721eSBaptiste Daroussin 	el->el_chared.c_resizearg	= NULL;
433*d0ef721eSBaptiste Daroussin 	el->el_chared.c_aliasfun	= NULL;
434*d0ef721eSBaptiste Daroussin 	el->el_chared.c_aliasarg	= NULL;
435*d0ef721eSBaptiste Daroussin 
436*d0ef721eSBaptiste Daroussin 	el->el_map.current		= el->el_map.key;
437*d0ef721eSBaptiste Daroussin 
438*d0ef721eSBaptiste Daroussin 	el->el_state.inputmode		= MODE_INSERT; /* XXX: save a default */
439*d0ef721eSBaptiste Daroussin 	el->el_state.doingarg		= 0;
440*d0ef721eSBaptiste Daroussin 	el->el_state.metanext		= 0;
441*d0ef721eSBaptiste Daroussin 	el->el_state.argument		= 1;
442*d0ef721eSBaptiste Daroussin 	el->el_state.lastcmd		= ED_UNASSIGNED;
443*d0ef721eSBaptiste Daroussin 
444*d0ef721eSBaptiste Daroussin 	return 0;
445*d0ef721eSBaptiste Daroussin }
446*d0ef721eSBaptiste Daroussin 
447*d0ef721eSBaptiste Daroussin /* ch_reset():
448*d0ef721eSBaptiste Daroussin  *	Reset the character editor
449*d0ef721eSBaptiste Daroussin  */
450*d0ef721eSBaptiste Daroussin libedit_private void
451*d0ef721eSBaptiste Daroussin ch_reset(EditLine *el)
452*d0ef721eSBaptiste Daroussin {
453*d0ef721eSBaptiste Daroussin 	el->el_line.cursor		= el->el_line.buffer;
454*d0ef721eSBaptiste Daroussin 	el->el_line.lastchar		= el->el_line.buffer;
455*d0ef721eSBaptiste Daroussin 
456*d0ef721eSBaptiste Daroussin 	el->el_chared.c_undo.len	= -1;
457*d0ef721eSBaptiste Daroussin 	el->el_chared.c_undo.cursor	= 0;
458*d0ef721eSBaptiste Daroussin 
459*d0ef721eSBaptiste Daroussin 	el->el_chared.c_vcmd.action	= NOP;
460*d0ef721eSBaptiste Daroussin 	el->el_chared.c_vcmd.pos	= el->el_line.buffer;
461*d0ef721eSBaptiste Daroussin 
462*d0ef721eSBaptiste Daroussin 	el->el_chared.c_kill.mark	= el->el_line.buffer;
463*d0ef721eSBaptiste Daroussin 
464*d0ef721eSBaptiste Daroussin 	el->el_map.current		= el->el_map.key;
465*d0ef721eSBaptiste Daroussin 
466*d0ef721eSBaptiste Daroussin 	el->el_state.inputmode		= MODE_INSERT; /* XXX: save a default */
467*d0ef721eSBaptiste Daroussin 	el->el_state.doingarg		= 0;
468*d0ef721eSBaptiste Daroussin 	el->el_state.metanext		= 0;
469*d0ef721eSBaptiste Daroussin 	el->el_state.argument		= 1;
470*d0ef721eSBaptiste Daroussin 	el->el_state.lastcmd		= ED_UNASSIGNED;
471*d0ef721eSBaptiste Daroussin 
472*d0ef721eSBaptiste Daroussin 	el->el_history.eventno		= 0;
473*d0ef721eSBaptiste Daroussin }
474*d0ef721eSBaptiste Daroussin 
475*d0ef721eSBaptiste Daroussin /* ch_enlargebufs():
476*d0ef721eSBaptiste Daroussin  *	Enlarge line buffer to be able to hold twice as much characters.
477*d0ef721eSBaptiste Daroussin  *	Returns 1 if successful, 0 if not.
478*d0ef721eSBaptiste Daroussin  */
479*d0ef721eSBaptiste Daroussin libedit_private int
480*d0ef721eSBaptiste Daroussin ch_enlargebufs(EditLine *el, size_t addlen)
481*d0ef721eSBaptiste Daroussin {
482*d0ef721eSBaptiste Daroussin 	size_t sz, newsz;
483*d0ef721eSBaptiste Daroussin 	wchar_t *newbuffer, *oldbuf, *oldkbuf;
484*d0ef721eSBaptiste Daroussin 
485*d0ef721eSBaptiste Daroussin 	sz = (size_t)(el->el_line.limit - el->el_line.buffer + EL_LEAVE);
486*d0ef721eSBaptiste Daroussin 	newsz = sz * 2;
487*d0ef721eSBaptiste Daroussin 	/*
488*d0ef721eSBaptiste Daroussin 	 * If newly required length is longer than current buffer, we need
489*d0ef721eSBaptiste Daroussin 	 * to make the buffer big enough to hold both old and new stuff.
490*d0ef721eSBaptiste Daroussin 	 */
491*d0ef721eSBaptiste Daroussin 	if (addlen > sz) {
492*d0ef721eSBaptiste Daroussin 		while(newsz - sz < addlen)
493*d0ef721eSBaptiste Daroussin 			newsz *= 2;
494*d0ef721eSBaptiste Daroussin 	}
495*d0ef721eSBaptiste Daroussin 
496*d0ef721eSBaptiste Daroussin 	/*
497*d0ef721eSBaptiste Daroussin 	 * Reallocate line buffer.
498*d0ef721eSBaptiste Daroussin 	 */
499*d0ef721eSBaptiste Daroussin 	newbuffer = el_realloc(el->el_line.buffer, newsz * sizeof(*newbuffer));
500*d0ef721eSBaptiste Daroussin 	if (!newbuffer)
501*d0ef721eSBaptiste Daroussin 		return 0;
502*d0ef721eSBaptiste Daroussin 
503*d0ef721eSBaptiste Daroussin 	/* zero the newly added memory, leave old data in */
504*d0ef721eSBaptiste Daroussin 	(void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer));
505*d0ef721eSBaptiste Daroussin 
506*d0ef721eSBaptiste Daroussin 	oldbuf = el->el_line.buffer;
507*d0ef721eSBaptiste Daroussin 
508*d0ef721eSBaptiste Daroussin 	el->el_line.buffer = newbuffer;
509*d0ef721eSBaptiste Daroussin 	el->el_line.cursor = newbuffer + (el->el_line.cursor - oldbuf);
510*d0ef721eSBaptiste Daroussin 	el->el_line.lastchar = newbuffer + (el->el_line.lastchar - oldbuf);
511*d0ef721eSBaptiste Daroussin 	/* don't set new size until all buffers are enlarged */
512*d0ef721eSBaptiste Daroussin 	el->el_line.limit  = &newbuffer[sz - EL_LEAVE];
513*d0ef721eSBaptiste Daroussin 
514*d0ef721eSBaptiste Daroussin 	/*
515*d0ef721eSBaptiste Daroussin 	 * Reallocate kill buffer.
516*d0ef721eSBaptiste Daroussin 	 */
517*d0ef721eSBaptiste Daroussin 	newbuffer = el_realloc(el->el_chared.c_kill.buf, newsz *
518*d0ef721eSBaptiste Daroussin 	    sizeof(*newbuffer));
519*d0ef721eSBaptiste Daroussin 	if (!newbuffer)
520*d0ef721eSBaptiste Daroussin 		return 0;
521*d0ef721eSBaptiste Daroussin 
522*d0ef721eSBaptiste Daroussin 	/* zero the newly added memory, leave old data in */
523*d0ef721eSBaptiste Daroussin 	(void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer));
524*d0ef721eSBaptiste Daroussin 
525*d0ef721eSBaptiste Daroussin 	oldkbuf = el->el_chared.c_kill.buf;
526*d0ef721eSBaptiste Daroussin 
527*d0ef721eSBaptiste Daroussin 	el->el_chared.c_kill.buf = newbuffer;
528*d0ef721eSBaptiste Daroussin 	el->el_chared.c_kill.last = newbuffer +
529*d0ef721eSBaptiste Daroussin 					(el->el_chared.c_kill.last - oldkbuf);
530*d0ef721eSBaptiste Daroussin 	el->el_chared.c_kill.mark = el->el_line.buffer +
531*d0ef721eSBaptiste Daroussin 					(el->el_chared.c_kill.mark - oldbuf);
532*d0ef721eSBaptiste Daroussin 
533*d0ef721eSBaptiste Daroussin 	/*
534*d0ef721eSBaptiste Daroussin 	 * Reallocate undo buffer.
535*d0ef721eSBaptiste Daroussin 	 */
536*d0ef721eSBaptiste Daroussin 	newbuffer = el_realloc(el->el_chared.c_undo.buf,
537*d0ef721eSBaptiste Daroussin 	    newsz * sizeof(*newbuffer));
538*d0ef721eSBaptiste Daroussin 	if (!newbuffer)
539*d0ef721eSBaptiste Daroussin 		return 0;
540*d0ef721eSBaptiste Daroussin 
541*d0ef721eSBaptiste Daroussin 	/* zero the newly added memory, leave old data in */
542*d0ef721eSBaptiste Daroussin 	(void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer));
543*d0ef721eSBaptiste Daroussin 	el->el_chared.c_undo.buf = newbuffer;
544*d0ef721eSBaptiste Daroussin 
545*d0ef721eSBaptiste Daroussin 	newbuffer = el_realloc(el->el_chared.c_redo.buf,
546*d0ef721eSBaptiste Daroussin 	    newsz * sizeof(*newbuffer));
547*d0ef721eSBaptiste Daroussin 	if (!newbuffer)
548*d0ef721eSBaptiste Daroussin 		return 0;
549*d0ef721eSBaptiste Daroussin 	el->el_chared.c_redo.pos = newbuffer +
550*d0ef721eSBaptiste Daroussin 			(el->el_chared.c_redo.pos - el->el_chared.c_redo.buf);
551*d0ef721eSBaptiste Daroussin 	el->el_chared.c_redo.lim = newbuffer +
552*d0ef721eSBaptiste Daroussin 			(el->el_chared.c_redo.lim - el->el_chared.c_redo.buf);
553*d0ef721eSBaptiste Daroussin 	el->el_chared.c_redo.buf = newbuffer;
554*d0ef721eSBaptiste Daroussin 
555*d0ef721eSBaptiste Daroussin 	if (!hist_enlargebuf(el, sz, newsz))
556*d0ef721eSBaptiste Daroussin 		return 0;
557*d0ef721eSBaptiste Daroussin 
558*d0ef721eSBaptiste Daroussin 	/* Safe to set enlarged buffer size */
559*d0ef721eSBaptiste Daroussin 	el->el_line.limit  = &el->el_line.buffer[newsz - EL_LEAVE];
560*d0ef721eSBaptiste Daroussin 	if (el->el_chared.c_resizefun)
561*d0ef721eSBaptiste Daroussin 		(*el->el_chared.c_resizefun)(el, el->el_chared.c_resizearg);
562*d0ef721eSBaptiste Daroussin 	return 1;
563*d0ef721eSBaptiste Daroussin }
564*d0ef721eSBaptiste Daroussin 
565*d0ef721eSBaptiste Daroussin /* ch_end():
566*d0ef721eSBaptiste Daroussin  *	Free the data structures used by the editor
567*d0ef721eSBaptiste Daroussin  */
568*d0ef721eSBaptiste Daroussin libedit_private void
569*d0ef721eSBaptiste Daroussin ch_end(EditLine *el)
570*d0ef721eSBaptiste Daroussin {
571*d0ef721eSBaptiste Daroussin 	el_free(el->el_line.buffer);
572*d0ef721eSBaptiste Daroussin 	el->el_line.buffer = NULL;
573*d0ef721eSBaptiste Daroussin 	el->el_line.limit = NULL;
574*d0ef721eSBaptiste Daroussin 	el_free(el->el_chared.c_undo.buf);
575*d0ef721eSBaptiste Daroussin 	el->el_chared.c_undo.buf = NULL;
576*d0ef721eSBaptiste Daroussin 	el_free(el->el_chared.c_redo.buf);
577*d0ef721eSBaptiste Daroussin 	el->el_chared.c_redo.buf = NULL;
578*d0ef721eSBaptiste Daroussin 	el->el_chared.c_redo.pos = NULL;
579*d0ef721eSBaptiste Daroussin 	el->el_chared.c_redo.lim = NULL;
580*d0ef721eSBaptiste Daroussin 	el->el_chared.c_redo.cmd = ED_UNASSIGNED;
581*d0ef721eSBaptiste Daroussin 	el_free(el->el_chared.c_kill.buf);
582*d0ef721eSBaptiste Daroussin 	el->el_chared.c_kill.buf = NULL;
583*d0ef721eSBaptiste Daroussin 	ch_reset(el);
584*d0ef721eSBaptiste Daroussin }
585*d0ef721eSBaptiste Daroussin 
586*d0ef721eSBaptiste Daroussin 
587*d0ef721eSBaptiste Daroussin /* el_insertstr():
588*d0ef721eSBaptiste Daroussin  *	Insert string at cursor
589*d0ef721eSBaptiste Daroussin  */
590*d0ef721eSBaptiste Daroussin int
591*d0ef721eSBaptiste Daroussin el_winsertstr(EditLine *el, const wchar_t *s)
592*d0ef721eSBaptiste Daroussin {
593*d0ef721eSBaptiste Daroussin 	size_t len;
594*d0ef721eSBaptiste Daroussin 
595*d0ef721eSBaptiste Daroussin 	if (s == NULL || (len = wcslen(s)) == 0)
596*d0ef721eSBaptiste Daroussin 		return -1;
597*d0ef721eSBaptiste Daroussin 	if (el->el_line.lastchar + len >= el->el_line.limit) {
598*d0ef721eSBaptiste Daroussin 		if (!ch_enlargebufs(el, len))
599*d0ef721eSBaptiste Daroussin 			return -1;
600*d0ef721eSBaptiste Daroussin 	}
601*d0ef721eSBaptiste Daroussin 
602*d0ef721eSBaptiste Daroussin 	c_insert(el, (int)len);
603*d0ef721eSBaptiste Daroussin 	while (*s)
604*d0ef721eSBaptiste Daroussin 		*el->el_line.cursor++ = *s++;
605*d0ef721eSBaptiste Daroussin 	return 0;
606*d0ef721eSBaptiste Daroussin }
607*d0ef721eSBaptiste Daroussin 
608*d0ef721eSBaptiste Daroussin 
609*d0ef721eSBaptiste Daroussin /* el_deletestr():
610*d0ef721eSBaptiste Daroussin  *	Delete num characters before the cursor
611*d0ef721eSBaptiste Daroussin  */
612*d0ef721eSBaptiste Daroussin void
613*d0ef721eSBaptiste Daroussin el_deletestr(EditLine *el, int n)
614*d0ef721eSBaptiste Daroussin {
615*d0ef721eSBaptiste Daroussin 	if (n <= 0)
616*d0ef721eSBaptiste Daroussin 		return;
617*d0ef721eSBaptiste Daroussin 
618*d0ef721eSBaptiste Daroussin 	if (el->el_line.cursor < &el->el_line.buffer[n])
619*d0ef721eSBaptiste Daroussin 		return;
620*d0ef721eSBaptiste Daroussin 
621*d0ef721eSBaptiste Daroussin 	c_delbefore(el, n);		/* delete before dot */
622*d0ef721eSBaptiste Daroussin 	el->el_line.cursor -= n;
623*d0ef721eSBaptiste Daroussin 	if (el->el_line.cursor < el->el_line.buffer)
624*d0ef721eSBaptiste Daroussin 		el->el_line.cursor = el->el_line.buffer;
625*d0ef721eSBaptiste Daroussin }
626*d0ef721eSBaptiste Daroussin 
627*d0ef721eSBaptiste Daroussin /* el_cursor():
628*d0ef721eSBaptiste Daroussin  *	Move the cursor to the left or the right of the current position
629*d0ef721eSBaptiste Daroussin  */
630*d0ef721eSBaptiste Daroussin int
631*d0ef721eSBaptiste Daroussin el_cursor(EditLine *el, int n)
632*d0ef721eSBaptiste Daroussin {
633*d0ef721eSBaptiste Daroussin 	if (n == 0)
634*d0ef721eSBaptiste Daroussin 		goto out;
635*d0ef721eSBaptiste Daroussin 
636*d0ef721eSBaptiste Daroussin 	el->el_line.cursor += n;
637*d0ef721eSBaptiste Daroussin 
638*d0ef721eSBaptiste Daroussin 	if (el->el_line.cursor < el->el_line.buffer)
639*d0ef721eSBaptiste Daroussin 		el->el_line.cursor = el->el_line.buffer;
640*d0ef721eSBaptiste Daroussin 	if (el->el_line.cursor > el->el_line.lastchar)
641*d0ef721eSBaptiste Daroussin 		el->el_line.cursor = el->el_line.lastchar;
642*d0ef721eSBaptiste Daroussin out:
643*d0ef721eSBaptiste Daroussin 	return (int)(el->el_line.cursor - el->el_line.buffer);
644*d0ef721eSBaptiste Daroussin }
645*d0ef721eSBaptiste Daroussin 
646*d0ef721eSBaptiste Daroussin /* c_gets():
647*d0ef721eSBaptiste Daroussin  *	Get a string
648*d0ef721eSBaptiste Daroussin  */
649*d0ef721eSBaptiste Daroussin libedit_private int
650*d0ef721eSBaptiste Daroussin c_gets(EditLine *el, wchar_t *buf, const wchar_t *prompt)
651*d0ef721eSBaptiste Daroussin {
652*d0ef721eSBaptiste Daroussin 	ssize_t len;
653*d0ef721eSBaptiste Daroussin 	wchar_t *cp = el->el_line.buffer, ch;
654*d0ef721eSBaptiste Daroussin 
655*d0ef721eSBaptiste Daroussin 	if (prompt) {
656*d0ef721eSBaptiste Daroussin 		len = (ssize_t)wcslen(prompt);
657*d0ef721eSBaptiste Daroussin 		(void)memcpy(cp, prompt, (size_t)len * sizeof(*cp));
658*d0ef721eSBaptiste Daroussin 		cp += len;
659*d0ef721eSBaptiste Daroussin 	}
660*d0ef721eSBaptiste Daroussin 	len = 0;
661*d0ef721eSBaptiste Daroussin 
662*d0ef721eSBaptiste Daroussin 	for (;;) {
663*d0ef721eSBaptiste Daroussin 		el->el_line.cursor = cp;
664*d0ef721eSBaptiste Daroussin 		*cp = ' ';
665*d0ef721eSBaptiste Daroussin 		el->el_line.lastchar = cp + 1;
666*d0ef721eSBaptiste Daroussin 		re_refresh(el);
667*d0ef721eSBaptiste Daroussin 
668*d0ef721eSBaptiste Daroussin 		if (el_wgetc(el, &ch) != 1) {
669*d0ef721eSBaptiste Daroussin 			ed_end_of_file(el, 0);
670*d0ef721eSBaptiste Daroussin 			len = -1;
671*d0ef721eSBaptiste Daroussin 			break;
672*d0ef721eSBaptiste Daroussin 		}
673*d0ef721eSBaptiste Daroussin 
674*d0ef721eSBaptiste Daroussin 		switch (ch) {
675*d0ef721eSBaptiste Daroussin 
676*d0ef721eSBaptiste Daroussin 		case L'\b':	/* Delete and backspace */
677*d0ef721eSBaptiste Daroussin 		case 0177:
678*d0ef721eSBaptiste Daroussin 			if (len == 0) {
679*d0ef721eSBaptiste Daroussin 				len = -1;
680*d0ef721eSBaptiste Daroussin 				break;
681*d0ef721eSBaptiste Daroussin 			}
682*d0ef721eSBaptiste Daroussin 			len--;
683*d0ef721eSBaptiste Daroussin 			cp--;
684*d0ef721eSBaptiste Daroussin 			continue;
685*d0ef721eSBaptiste Daroussin 
686*d0ef721eSBaptiste Daroussin 		case 0033:	/* ESC */
687*d0ef721eSBaptiste Daroussin 		case L'\r':	/* Newline */
688*d0ef721eSBaptiste Daroussin 		case L'\n':
689*d0ef721eSBaptiste Daroussin 			buf[len] = ch;
690*d0ef721eSBaptiste Daroussin 			break;
691*d0ef721eSBaptiste Daroussin 
692*d0ef721eSBaptiste Daroussin 		default:
693*d0ef721eSBaptiste Daroussin 			if (len >= (ssize_t)(EL_BUFSIZ - 16))
694*d0ef721eSBaptiste Daroussin 				terminal_beep(el);
695*d0ef721eSBaptiste Daroussin 			else {
696*d0ef721eSBaptiste Daroussin 				buf[len++] = ch;
697*d0ef721eSBaptiste Daroussin 				*cp++ = ch;
698*d0ef721eSBaptiste Daroussin 			}
699*d0ef721eSBaptiste Daroussin 			continue;
700*d0ef721eSBaptiste Daroussin 		}
701*d0ef721eSBaptiste Daroussin 		break;
702*d0ef721eSBaptiste Daroussin 	}
703*d0ef721eSBaptiste Daroussin 
704*d0ef721eSBaptiste Daroussin 	el->el_line.buffer[0] = '\0';
705*d0ef721eSBaptiste Daroussin 	el->el_line.lastchar = el->el_line.buffer;
706*d0ef721eSBaptiste Daroussin 	el->el_line.cursor = el->el_line.buffer;
707*d0ef721eSBaptiste Daroussin 	return (int)len;
708*d0ef721eSBaptiste Daroussin }
709*d0ef721eSBaptiste Daroussin 
710*d0ef721eSBaptiste Daroussin 
711*d0ef721eSBaptiste Daroussin /* c_hpos():
712*d0ef721eSBaptiste Daroussin  *	Return the current horizontal position of the cursor
713*d0ef721eSBaptiste Daroussin  */
714*d0ef721eSBaptiste Daroussin libedit_private int
715*d0ef721eSBaptiste Daroussin c_hpos(EditLine *el)
716*d0ef721eSBaptiste Daroussin {
717*d0ef721eSBaptiste Daroussin 	wchar_t *ptr;
718*d0ef721eSBaptiste Daroussin 
719*d0ef721eSBaptiste Daroussin 	/*
720*d0ef721eSBaptiste Daroussin 	 * Find how many characters till the beginning of this line.
721*d0ef721eSBaptiste Daroussin 	 */
722*d0ef721eSBaptiste Daroussin 	if (el->el_line.cursor == el->el_line.buffer)
723*d0ef721eSBaptiste Daroussin 		return 0;
724*d0ef721eSBaptiste Daroussin 	else {
725*d0ef721eSBaptiste Daroussin 		for (ptr = el->el_line.cursor - 1;
726*d0ef721eSBaptiste Daroussin 		     ptr >= el->el_line.buffer && *ptr != '\n';
727*d0ef721eSBaptiste Daroussin 		     ptr--)
728*d0ef721eSBaptiste Daroussin 			continue;
729*d0ef721eSBaptiste Daroussin 		return (int)(el->el_line.cursor - ptr - 1);
730*d0ef721eSBaptiste Daroussin 	}
731*d0ef721eSBaptiste Daroussin }
732*d0ef721eSBaptiste Daroussin 
733*d0ef721eSBaptiste Daroussin libedit_private int
734*d0ef721eSBaptiste Daroussin ch_resizefun(EditLine *el, el_zfunc_t f, void *a)
735*d0ef721eSBaptiste Daroussin {
736*d0ef721eSBaptiste Daroussin 	el->el_chared.c_resizefun = f;
737*d0ef721eSBaptiste Daroussin 	el->el_chared.c_resizearg = a;
738*d0ef721eSBaptiste Daroussin 	return 0;
739*d0ef721eSBaptiste Daroussin }
740*d0ef721eSBaptiste Daroussin 
741*d0ef721eSBaptiste Daroussin libedit_private int
742*d0ef721eSBaptiste Daroussin ch_aliasfun(EditLine *el, el_afunc_t f, void *a)
743*d0ef721eSBaptiste Daroussin {
744*d0ef721eSBaptiste Daroussin 	el->el_chared.c_aliasfun = f;
745*d0ef721eSBaptiste Daroussin 	el->el_chared.c_aliasarg = a;
746*d0ef721eSBaptiste Daroussin 	return 0;
747*d0ef721eSBaptiste Daroussin }
748