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