xref: /freebsd/contrib/libedit/chared.c (revision 136d69caf03bc38de95c4df34c5a683e9ce81bfa)
1*136d69caSBaptiste Daroussin /*	$NetBSD: chared.c,v 1.64 2024/06/29 14:13:14 christos 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*136d69caSBaptiste Daroussin __RCSID("$NetBSD: chared.c,v 1.64 2024/06/29 14:13:14 christos 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
cv_undo(EditLine * el)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
cv_yank(EditLine * el,const wchar_t * ptr,int size)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
c_insert(EditLine * el,int num)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
c_delafter(EditLine * el,int num)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
c_delafter1(EditLine * el)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
c_delbefore(EditLine * el,int num)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
c_delbefore1(EditLine * el)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
ce__isword(wint_t p)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
cv__isword(wint_t p)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
cv__isWord(wint_t p)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 *
c__prev_word(wchar_t * p,wchar_t * low,int n,int (* wtest)(wint_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 *
c__next_word(wchar_t * p,wchar_t * high,int n,int (* wtest)(wint_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 *
cv_next_word(EditLine * el,wchar_t * p,wchar_t * high,int n,int (* wtest)(wint_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 *
cv_prev_word(wchar_t * p,wchar_t * low,int n,int (* wtest)(wint_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--;
322*136d69caSBaptiste Daroussin 		if (p < low)
323*136d69caSBaptiste Daroussin 			return low;
324d0ef721eSBaptiste Daroussin 	}
325d0ef721eSBaptiste Daroussin 	p++;
326d0ef721eSBaptiste Daroussin 
327d0ef721eSBaptiste Daroussin 	/* p now points where we want it */
328d0ef721eSBaptiste Daroussin 	if (p < low)
329d0ef721eSBaptiste Daroussin 		return low;
330d0ef721eSBaptiste Daroussin 	else
331d0ef721eSBaptiste Daroussin 		return p;
332d0ef721eSBaptiste Daroussin }
333d0ef721eSBaptiste Daroussin 
334d0ef721eSBaptiste Daroussin 
335d0ef721eSBaptiste Daroussin /* cv_delfini():
336d0ef721eSBaptiste Daroussin  *	Finish vi delete action
337d0ef721eSBaptiste Daroussin  */
338d0ef721eSBaptiste Daroussin libedit_private void
cv_delfini(EditLine * el)339d0ef721eSBaptiste Daroussin cv_delfini(EditLine *el)
340d0ef721eSBaptiste Daroussin {
341d0ef721eSBaptiste Daroussin 	int size;
342d0ef721eSBaptiste Daroussin 	int action = el->el_chared.c_vcmd.action;
343d0ef721eSBaptiste Daroussin 
344d0ef721eSBaptiste Daroussin 	if (action & INSERT)
345d0ef721eSBaptiste Daroussin 		el->el_map.current = el->el_map.key;
346d0ef721eSBaptiste Daroussin 
347d0ef721eSBaptiste Daroussin 	if (el->el_chared.c_vcmd.pos == 0)
348d0ef721eSBaptiste Daroussin 		/* sanity */
349d0ef721eSBaptiste Daroussin 		return;
350d0ef721eSBaptiste Daroussin 
351d0ef721eSBaptiste Daroussin 	size = (int)(el->el_line.cursor - el->el_chared.c_vcmd.pos);
352d0ef721eSBaptiste Daroussin 	if (size == 0)
353d0ef721eSBaptiste Daroussin 		size = 1;
354d0ef721eSBaptiste Daroussin 	el->el_line.cursor = el->el_chared.c_vcmd.pos;
355d0ef721eSBaptiste Daroussin 	if (action & YANK) {
356d0ef721eSBaptiste Daroussin 		if (size > 0)
357d0ef721eSBaptiste Daroussin 			cv_yank(el, el->el_line.cursor, size);
358d0ef721eSBaptiste Daroussin 		else
359d0ef721eSBaptiste Daroussin 			cv_yank(el, el->el_line.cursor + size, -size);
360d0ef721eSBaptiste Daroussin 	} else {
361d0ef721eSBaptiste Daroussin 		if (size > 0) {
362d0ef721eSBaptiste Daroussin 			c_delafter(el, size);
363d0ef721eSBaptiste Daroussin 			re_refresh_cursor(el);
364d0ef721eSBaptiste Daroussin 		} else  {
365d0ef721eSBaptiste Daroussin 			c_delbefore(el, -size);
366d0ef721eSBaptiste Daroussin 			el->el_line.cursor += size;
367d0ef721eSBaptiste Daroussin 		}
368d0ef721eSBaptiste Daroussin 	}
369d0ef721eSBaptiste Daroussin 	el->el_chared.c_vcmd.action = NOP;
370d0ef721eSBaptiste Daroussin }
371d0ef721eSBaptiste Daroussin 
372d0ef721eSBaptiste Daroussin 
373d0ef721eSBaptiste Daroussin /* cv__endword():
374d0ef721eSBaptiste Daroussin  *	Go to the end of this word according to vi
375d0ef721eSBaptiste Daroussin  */
376d0ef721eSBaptiste Daroussin libedit_private wchar_t *
cv__endword(wchar_t * p,wchar_t * high,int n,int (* wtest)(wint_t))377d0ef721eSBaptiste Daroussin cv__endword(wchar_t *p, wchar_t *high, int n, int (*wtest)(wint_t))
378d0ef721eSBaptiste Daroussin {
379d0ef721eSBaptiste Daroussin 	int test;
380d0ef721eSBaptiste Daroussin 
381d0ef721eSBaptiste Daroussin 	p++;
382d0ef721eSBaptiste Daroussin 
383d0ef721eSBaptiste Daroussin 	while (n--) {
384d0ef721eSBaptiste Daroussin 		while ((p < high) && iswspace(*p))
385d0ef721eSBaptiste Daroussin 			p++;
386d0ef721eSBaptiste Daroussin 
387d0ef721eSBaptiste Daroussin 		test = (*wtest)(*p);
388d0ef721eSBaptiste Daroussin 		while ((p < high) && (*wtest)(*p) == test)
389d0ef721eSBaptiste Daroussin 			p++;
390d0ef721eSBaptiste Daroussin 	}
391d0ef721eSBaptiste Daroussin 	p--;
392d0ef721eSBaptiste Daroussin 	return p;
393d0ef721eSBaptiste Daroussin }
394d0ef721eSBaptiste Daroussin 
395d0ef721eSBaptiste Daroussin /* ch_init():
396d0ef721eSBaptiste Daroussin  *	Initialize the character editor
397d0ef721eSBaptiste Daroussin  */
398d0ef721eSBaptiste Daroussin libedit_private int
ch_init(EditLine * el)399d0ef721eSBaptiste Daroussin ch_init(EditLine *el)
400d0ef721eSBaptiste Daroussin {
401d0ef721eSBaptiste Daroussin 	el->el_line.buffer		= el_calloc(EL_BUFSIZ,
402d0ef721eSBaptiste Daroussin 	    sizeof(*el->el_line.buffer));
403d0ef721eSBaptiste Daroussin 	if (el->el_line.buffer == NULL)
404d0ef721eSBaptiste Daroussin 		return -1;
405d0ef721eSBaptiste Daroussin 
406d0ef721eSBaptiste Daroussin 	el->el_line.cursor		= el->el_line.buffer;
407d0ef721eSBaptiste Daroussin 	el->el_line.lastchar		= el->el_line.buffer;
408d0ef721eSBaptiste Daroussin 	el->el_line.limit		= &el->el_line.buffer[EL_BUFSIZ - EL_LEAVE];
409d0ef721eSBaptiste Daroussin 
410d0ef721eSBaptiste Daroussin 	el->el_chared.c_undo.buf	= el_calloc(EL_BUFSIZ,
411d0ef721eSBaptiste Daroussin 	    sizeof(*el->el_chared.c_undo.buf));
412d0ef721eSBaptiste Daroussin 	if (el->el_chared.c_undo.buf == NULL)
413d0ef721eSBaptiste Daroussin 		return -1;
414d0ef721eSBaptiste Daroussin 	el->el_chared.c_undo.len	= -1;
415d0ef721eSBaptiste Daroussin 	el->el_chared.c_undo.cursor	= 0;
416d0ef721eSBaptiste Daroussin 	el->el_chared.c_redo.buf	= el_calloc(EL_BUFSIZ,
417d0ef721eSBaptiste Daroussin 	    sizeof(*el->el_chared.c_redo.buf));
418d0ef721eSBaptiste Daroussin 	if (el->el_chared.c_redo.buf == NULL)
419baff8195SBaptiste Daroussin 		goto out;
420d0ef721eSBaptiste Daroussin 	el->el_chared.c_redo.pos	= el->el_chared.c_redo.buf;
421d0ef721eSBaptiste Daroussin 	el->el_chared.c_redo.lim	= el->el_chared.c_redo.buf + EL_BUFSIZ;
422d0ef721eSBaptiste Daroussin 	el->el_chared.c_redo.cmd	= ED_UNASSIGNED;
423d0ef721eSBaptiste Daroussin 
424d0ef721eSBaptiste Daroussin 	el->el_chared.c_vcmd.action	= NOP;
425d0ef721eSBaptiste Daroussin 	el->el_chared.c_vcmd.pos	= el->el_line.buffer;
426d0ef721eSBaptiste Daroussin 
427d0ef721eSBaptiste Daroussin 	el->el_chared.c_kill.buf	= el_calloc(EL_BUFSIZ,
428d0ef721eSBaptiste Daroussin 	    sizeof(*el->el_chared.c_kill.buf));
429d0ef721eSBaptiste Daroussin 	if (el->el_chared.c_kill.buf == NULL)
430baff8195SBaptiste Daroussin 		goto out;
431d0ef721eSBaptiste Daroussin 	el->el_chared.c_kill.mark	= el->el_line.buffer;
432d0ef721eSBaptiste Daroussin 	el->el_chared.c_kill.last	= el->el_chared.c_kill.buf;
433d0ef721eSBaptiste Daroussin 	el->el_chared.c_resizefun	= NULL;
434d0ef721eSBaptiste Daroussin 	el->el_chared.c_resizearg	= NULL;
435d0ef721eSBaptiste Daroussin 	el->el_chared.c_aliasfun	= NULL;
436d0ef721eSBaptiste Daroussin 	el->el_chared.c_aliasarg	= NULL;
437d0ef721eSBaptiste Daroussin 
438d0ef721eSBaptiste Daroussin 	el->el_map.current		= el->el_map.key;
439d0ef721eSBaptiste Daroussin 
440d0ef721eSBaptiste Daroussin 	el->el_state.inputmode		= MODE_INSERT; /* XXX: save a default */
441d0ef721eSBaptiste Daroussin 	el->el_state.doingarg		= 0;
442d0ef721eSBaptiste Daroussin 	el->el_state.metanext		= 0;
443d0ef721eSBaptiste Daroussin 	el->el_state.argument		= 1;
444d0ef721eSBaptiste Daroussin 	el->el_state.lastcmd		= ED_UNASSIGNED;
445d0ef721eSBaptiste Daroussin 
446d0ef721eSBaptiste Daroussin 	return 0;
447baff8195SBaptiste Daroussin out:
448baff8195SBaptiste Daroussin 	ch_end(el);
449baff8195SBaptiste Daroussin 	return -1;
450d0ef721eSBaptiste Daroussin }
451d0ef721eSBaptiste Daroussin 
452d0ef721eSBaptiste Daroussin /* ch_reset():
453d0ef721eSBaptiste Daroussin  *	Reset the character editor
454d0ef721eSBaptiste Daroussin  */
455d0ef721eSBaptiste Daroussin libedit_private void
ch_reset(EditLine * el)456d0ef721eSBaptiste Daroussin ch_reset(EditLine *el)
457d0ef721eSBaptiste Daroussin {
458d0ef721eSBaptiste Daroussin 	el->el_line.cursor		= el->el_line.buffer;
459d0ef721eSBaptiste Daroussin 	el->el_line.lastchar		= el->el_line.buffer;
460d0ef721eSBaptiste Daroussin 
461d0ef721eSBaptiste Daroussin 	el->el_chared.c_undo.len	= -1;
462d0ef721eSBaptiste Daroussin 	el->el_chared.c_undo.cursor	= 0;
463d0ef721eSBaptiste Daroussin 
464d0ef721eSBaptiste Daroussin 	el->el_chared.c_vcmd.action	= NOP;
465d0ef721eSBaptiste Daroussin 	el->el_chared.c_vcmd.pos	= el->el_line.buffer;
466d0ef721eSBaptiste Daroussin 
467d0ef721eSBaptiste Daroussin 	el->el_chared.c_kill.mark	= el->el_line.buffer;
468d0ef721eSBaptiste Daroussin 
469d0ef721eSBaptiste Daroussin 	el->el_map.current		= el->el_map.key;
470d0ef721eSBaptiste Daroussin 
471d0ef721eSBaptiste Daroussin 	el->el_state.inputmode		= MODE_INSERT; /* XXX: save a default */
472d0ef721eSBaptiste Daroussin 	el->el_state.doingarg		= 0;
473d0ef721eSBaptiste Daroussin 	el->el_state.metanext		= 0;
474d0ef721eSBaptiste Daroussin 	el->el_state.argument		= 1;
475d0ef721eSBaptiste Daroussin 	el->el_state.lastcmd		= ED_UNASSIGNED;
476d0ef721eSBaptiste Daroussin 
477d0ef721eSBaptiste Daroussin 	el->el_history.eventno		= 0;
478d0ef721eSBaptiste Daroussin }
479d0ef721eSBaptiste Daroussin 
480d0ef721eSBaptiste Daroussin /* ch_enlargebufs():
481d0ef721eSBaptiste Daroussin  *	Enlarge line buffer to be able to hold twice as much characters.
482d0ef721eSBaptiste Daroussin  *	Returns 1 if successful, 0 if not.
483d0ef721eSBaptiste Daroussin  */
484d0ef721eSBaptiste Daroussin libedit_private int
ch_enlargebufs(EditLine * el,size_t addlen)485d0ef721eSBaptiste Daroussin ch_enlargebufs(EditLine *el, size_t addlen)
486d0ef721eSBaptiste Daroussin {
487d0ef721eSBaptiste Daroussin 	size_t sz, newsz;
488d0ef721eSBaptiste Daroussin 	wchar_t *newbuffer, *oldbuf, *oldkbuf;
489d0ef721eSBaptiste Daroussin 
490d0ef721eSBaptiste Daroussin 	sz = (size_t)(el->el_line.limit - el->el_line.buffer + EL_LEAVE);
491d0ef721eSBaptiste Daroussin 	newsz = sz * 2;
492d0ef721eSBaptiste Daroussin 	/*
493d0ef721eSBaptiste Daroussin 	 * If newly required length is longer than current buffer, we need
494d0ef721eSBaptiste Daroussin 	 * to make the buffer big enough to hold both old and new stuff.
495d0ef721eSBaptiste Daroussin 	 */
496d0ef721eSBaptiste Daroussin 	if (addlen > sz) {
497d0ef721eSBaptiste Daroussin 		while(newsz - sz < addlen)
498d0ef721eSBaptiste Daroussin 			newsz *= 2;
499d0ef721eSBaptiste Daroussin 	}
500d0ef721eSBaptiste Daroussin 
501d0ef721eSBaptiste Daroussin 	/*
502d0ef721eSBaptiste Daroussin 	 * Reallocate line buffer.
503d0ef721eSBaptiste Daroussin 	 */
504d0ef721eSBaptiste Daroussin 	newbuffer = el_realloc(el->el_line.buffer, newsz * sizeof(*newbuffer));
505d0ef721eSBaptiste Daroussin 	if (!newbuffer)
506d0ef721eSBaptiste Daroussin 		return 0;
507d0ef721eSBaptiste Daroussin 
508d0ef721eSBaptiste Daroussin 	/* zero the newly added memory, leave old data in */
509d0ef721eSBaptiste Daroussin 	(void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer));
510d0ef721eSBaptiste Daroussin 
511d0ef721eSBaptiste Daroussin 	oldbuf = el->el_line.buffer;
512d0ef721eSBaptiste Daroussin 
513d0ef721eSBaptiste Daroussin 	el->el_line.buffer = newbuffer;
514d0ef721eSBaptiste Daroussin 	el->el_line.cursor = newbuffer + (el->el_line.cursor - oldbuf);
515d0ef721eSBaptiste Daroussin 	el->el_line.lastchar = newbuffer + (el->el_line.lastchar - oldbuf);
516d0ef721eSBaptiste Daroussin 	/* don't set new size until all buffers are enlarged */
517d0ef721eSBaptiste Daroussin 	el->el_line.limit  = &newbuffer[sz - EL_LEAVE];
518d0ef721eSBaptiste Daroussin 
519d0ef721eSBaptiste Daroussin 	/*
520d0ef721eSBaptiste Daroussin 	 * Reallocate kill buffer.
521d0ef721eSBaptiste Daroussin 	 */
522d0ef721eSBaptiste Daroussin 	newbuffer = el_realloc(el->el_chared.c_kill.buf, newsz *
523d0ef721eSBaptiste Daroussin 	    sizeof(*newbuffer));
524d0ef721eSBaptiste Daroussin 	if (!newbuffer)
525d0ef721eSBaptiste Daroussin 		return 0;
526d0ef721eSBaptiste Daroussin 
527d0ef721eSBaptiste Daroussin 	/* zero the newly added memory, leave old data in */
528d0ef721eSBaptiste Daroussin 	(void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer));
529d0ef721eSBaptiste Daroussin 
530d0ef721eSBaptiste Daroussin 	oldkbuf = el->el_chared.c_kill.buf;
531d0ef721eSBaptiste Daroussin 
532d0ef721eSBaptiste Daroussin 	el->el_chared.c_kill.buf = newbuffer;
533d0ef721eSBaptiste Daroussin 	el->el_chared.c_kill.last = newbuffer +
534d0ef721eSBaptiste Daroussin 					(el->el_chared.c_kill.last - oldkbuf);
535d0ef721eSBaptiste Daroussin 	el->el_chared.c_kill.mark = el->el_line.buffer +
536d0ef721eSBaptiste Daroussin 					(el->el_chared.c_kill.mark - oldbuf);
537d0ef721eSBaptiste Daroussin 
538d0ef721eSBaptiste Daroussin 	/*
539d0ef721eSBaptiste Daroussin 	 * Reallocate undo buffer.
540d0ef721eSBaptiste Daroussin 	 */
541d0ef721eSBaptiste Daroussin 	newbuffer = el_realloc(el->el_chared.c_undo.buf,
542d0ef721eSBaptiste Daroussin 	    newsz * sizeof(*newbuffer));
543d0ef721eSBaptiste Daroussin 	if (!newbuffer)
544d0ef721eSBaptiste Daroussin 		return 0;
545d0ef721eSBaptiste Daroussin 
546d0ef721eSBaptiste Daroussin 	/* zero the newly added memory, leave old data in */
547d0ef721eSBaptiste Daroussin 	(void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer));
548d0ef721eSBaptiste Daroussin 	el->el_chared.c_undo.buf = newbuffer;
549d0ef721eSBaptiste Daroussin 
550d0ef721eSBaptiste Daroussin 	newbuffer = el_realloc(el->el_chared.c_redo.buf,
551d0ef721eSBaptiste Daroussin 	    newsz * sizeof(*newbuffer));
552d0ef721eSBaptiste Daroussin 	if (!newbuffer)
553d0ef721eSBaptiste Daroussin 		return 0;
554d0ef721eSBaptiste Daroussin 	el->el_chared.c_redo.pos = newbuffer +
555d0ef721eSBaptiste Daroussin 			(el->el_chared.c_redo.pos - el->el_chared.c_redo.buf);
556d0ef721eSBaptiste Daroussin 	el->el_chared.c_redo.lim = newbuffer +
557d0ef721eSBaptiste Daroussin 			(el->el_chared.c_redo.lim - el->el_chared.c_redo.buf);
558d0ef721eSBaptiste Daroussin 	el->el_chared.c_redo.buf = newbuffer;
559d0ef721eSBaptiste Daroussin 
560d0ef721eSBaptiste Daroussin 	if (!hist_enlargebuf(el, sz, newsz))
561d0ef721eSBaptiste Daroussin 		return 0;
562d0ef721eSBaptiste Daroussin 
563d0ef721eSBaptiste Daroussin 	/* Safe to set enlarged buffer size */
564d0ef721eSBaptiste Daroussin 	el->el_line.limit  = &el->el_line.buffer[newsz - EL_LEAVE];
565d0ef721eSBaptiste Daroussin 	if (el->el_chared.c_resizefun)
566d0ef721eSBaptiste Daroussin 		(*el->el_chared.c_resizefun)(el, el->el_chared.c_resizearg);
567d0ef721eSBaptiste Daroussin 	return 1;
568d0ef721eSBaptiste Daroussin }
569d0ef721eSBaptiste Daroussin 
570d0ef721eSBaptiste Daroussin /* ch_end():
571d0ef721eSBaptiste Daroussin  *	Free the data structures used by the editor
572d0ef721eSBaptiste Daroussin  */
573d0ef721eSBaptiste Daroussin libedit_private void
ch_end(EditLine * el)574d0ef721eSBaptiste Daroussin ch_end(EditLine *el)
575d0ef721eSBaptiste Daroussin {
576d0ef721eSBaptiste Daroussin 	el_free(el->el_line.buffer);
577d0ef721eSBaptiste Daroussin 	el->el_line.buffer = NULL;
578d0ef721eSBaptiste Daroussin 	el->el_line.limit = NULL;
579d0ef721eSBaptiste Daroussin 	el_free(el->el_chared.c_undo.buf);
580d0ef721eSBaptiste Daroussin 	el->el_chared.c_undo.buf = NULL;
581d0ef721eSBaptiste Daroussin 	el_free(el->el_chared.c_redo.buf);
582d0ef721eSBaptiste Daroussin 	el->el_chared.c_redo.buf = NULL;
583d0ef721eSBaptiste Daroussin 	el->el_chared.c_redo.pos = NULL;
584d0ef721eSBaptiste Daroussin 	el->el_chared.c_redo.lim = NULL;
585d0ef721eSBaptiste Daroussin 	el->el_chared.c_redo.cmd = ED_UNASSIGNED;
586d0ef721eSBaptiste Daroussin 	el_free(el->el_chared.c_kill.buf);
587d0ef721eSBaptiste Daroussin 	el->el_chared.c_kill.buf = NULL;
588d0ef721eSBaptiste Daroussin 	ch_reset(el);
589d0ef721eSBaptiste Daroussin }
590d0ef721eSBaptiste Daroussin 
591d0ef721eSBaptiste Daroussin 
592d0ef721eSBaptiste Daroussin /* el_insertstr():
593d0ef721eSBaptiste Daroussin  *	Insert string at cursor
594d0ef721eSBaptiste Daroussin  */
595d0ef721eSBaptiste Daroussin int
el_winsertstr(EditLine * el,const wchar_t * s)596d0ef721eSBaptiste Daroussin el_winsertstr(EditLine *el, const wchar_t *s)
597d0ef721eSBaptiste Daroussin {
598d0ef721eSBaptiste Daroussin 	size_t len;
599d0ef721eSBaptiste Daroussin 
600d0ef721eSBaptiste Daroussin 	if (s == NULL || (len = wcslen(s)) == 0)
601d0ef721eSBaptiste Daroussin 		return -1;
602d0ef721eSBaptiste Daroussin 	if (el->el_line.lastchar + len >= el->el_line.limit) {
603d0ef721eSBaptiste Daroussin 		if (!ch_enlargebufs(el, len))
604d0ef721eSBaptiste Daroussin 			return -1;
605d0ef721eSBaptiste Daroussin 	}
606d0ef721eSBaptiste Daroussin 
607d0ef721eSBaptiste Daroussin 	c_insert(el, (int)len);
608d0ef721eSBaptiste Daroussin 	while (*s)
609d0ef721eSBaptiste Daroussin 		*el->el_line.cursor++ = *s++;
610d0ef721eSBaptiste Daroussin 	return 0;
611d0ef721eSBaptiste Daroussin }
612d0ef721eSBaptiste Daroussin 
613d0ef721eSBaptiste Daroussin 
614d0ef721eSBaptiste Daroussin /* el_deletestr():
615d0ef721eSBaptiste Daroussin  *	Delete num characters before the cursor
616d0ef721eSBaptiste Daroussin  */
617d0ef721eSBaptiste Daroussin void
el_deletestr(EditLine * el,int n)618d0ef721eSBaptiste Daroussin el_deletestr(EditLine *el, int n)
619d0ef721eSBaptiste Daroussin {
620d0ef721eSBaptiste Daroussin 	if (n <= 0)
621d0ef721eSBaptiste Daroussin 		return;
622d0ef721eSBaptiste Daroussin 
623d0ef721eSBaptiste Daroussin 	if (el->el_line.cursor < &el->el_line.buffer[n])
624d0ef721eSBaptiste Daroussin 		return;
625d0ef721eSBaptiste Daroussin 
626d0ef721eSBaptiste Daroussin 	c_delbefore(el, n);		/* delete before dot */
627d0ef721eSBaptiste Daroussin 	el->el_line.cursor -= n;
628d0ef721eSBaptiste Daroussin 	if (el->el_line.cursor < el->el_line.buffer)
629d0ef721eSBaptiste Daroussin 		el->el_line.cursor = el->el_line.buffer;
630d0ef721eSBaptiste Daroussin }
631d0ef721eSBaptiste Daroussin 
6327f399375SBaptiste Daroussin /* el_deletestr1():
6337f399375SBaptiste Daroussin  *	Delete characters between start and end
6347f399375SBaptiste Daroussin  */
6357f399375SBaptiste Daroussin int
el_deletestr1(EditLine * el,int start,int end)6367f399375SBaptiste Daroussin el_deletestr1(EditLine *el, int start, int end)
6377f399375SBaptiste Daroussin {
6387f399375SBaptiste Daroussin 	size_t line_length, len;
6397f399375SBaptiste Daroussin 	wchar_t *p1, *p2;
6407f399375SBaptiste Daroussin 
6417f399375SBaptiste Daroussin 	if (end <= start)
6427f399375SBaptiste Daroussin 		return 0;
6437f399375SBaptiste Daroussin 
6447f399375SBaptiste Daroussin 	line_length = (size_t)(el->el_line.lastchar - el->el_line.buffer);
6457f399375SBaptiste Daroussin 
6467f399375SBaptiste Daroussin 	if (start >= (int)line_length || end >= (int)line_length)
6477f399375SBaptiste Daroussin 		return 0;
6487f399375SBaptiste Daroussin 
6497f399375SBaptiste Daroussin 	len = (size_t)(end - start);
6507f399375SBaptiste Daroussin 	if (len > line_length - (size_t)end)
6517f399375SBaptiste Daroussin 		len = line_length - (size_t)end;
6527f399375SBaptiste Daroussin 
6537f399375SBaptiste Daroussin 	p1 = el->el_line.buffer + start;
6547f399375SBaptiste Daroussin 	p2 = el->el_line.buffer + end;
6557f399375SBaptiste Daroussin 	for (size_t i = 0; i < len; i++) {
6567f399375SBaptiste Daroussin 		*p1++ = *p2++;
6577f399375SBaptiste Daroussin 		el->el_line.lastchar--;
6587f399375SBaptiste Daroussin 	}
6597f399375SBaptiste Daroussin 
6607f399375SBaptiste Daroussin 	if (el->el_line.cursor < el->el_line.buffer)
6617f399375SBaptiste Daroussin 		el->el_line.cursor = el->el_line.buffer;
6627f399375SBaptiste Daroussin 
6637f399375SBaptiste Daroussin 	return end - start;
6647f399375SBaptiste Daroussin }
6657f399375SBaptiste Daroussin 
6667f399375SBaptiste Daroussin /* el_wreplacestr():
6677f399375SBaptiste Daroussin  *	Replace the contents of the line with the provided string
6687f399375SBaptiste Daroussin  */
6697f399375SBaptiste Daroussin int
el_wreplacestr(EditLine * el,const wchar_t * s)6707f399375SBaptiste Daroussin el_wreplacestr(EditLine *el, const wchar_t *s)
6717f399375SBaptiste Daroussin {
6727f399375SBaptiste Daroussin 	size_t len;
6737f399375SBaptiste Daroussin 	wchar_t * p;
6747f399375SBaptiste Daroussin 
6757f399375SBaptiste Daroussin 	if (s == NULL || (len = wcslen(s)) == 0)
6767f399375SBaptiste Daroussin 		return -1;
6777f399375SBaptiste Daroussin 
6787f399375SBaptiste Daroussin 	if (el->el_line.buffer + len >= el->el_line.limit) {
6797f399375SBaptiste Daroussin 		if (!ch_enlargebufs(el, len))
6807f399375SBaptiste Daroussin 			return -1;
6817f399375SBaptiste Daroussin 	}
6827f399375SBaptiste Daroussin 
6837f399375SBaptiste Daroussin 	p = el->el_line.buffer;
6847f399375SBaptiste Daroussin 	for (size_t i = 0; i < len; i++)
6857f399375SBaptiste Daroussin 		*p++ = *s++;
6867f399375SBaptiste Daroussin 
6877f399375SBaptiste Daroussin 	el->el_line.buffer[len] = '\0';
6887f399375SBaptiste Daroussin 	el->el_line.lastchar = el->el_line.buffer + len;
6897f399375SBaptiste Daroussin 	if (el->el_line.cursor > el->el_line.lastchar)
6907f399375SBaptiste Daroussin 		el->el_line.cursor = el->el_line.lastchar;
6917f399375SBaptiste Daroussin 
6927f399375SBaptiste Daroussin 	return 0;
6937f399375SBaptiste Daroussin }
6947f399375SBaptiste Daroussin 
695d0ef721eSBaptiste Daroussin /* el_cursor():
696d0ef721eSBaptiste Daroussin  *	Move the cursor to the left or the right of the current position
697d0ef721eSBaptiste Daroussin  */
698d0ef721eSBaptiste Daroussin int
el_cursor(EditLine * el,int n)699d0ef721eSBaptiste Daroussin el_cursor(EditLine *el, int n)
700d0ef721eSBaptiste Daroussin {
701d0ef721eSBaptiste Daroussin 	if (n == 0)
702d0ef721eSBaptiste Daroussin 		goto out;
703d0ef721eSBaptiste Daroussin 
704d0ef721eSBaptiste Daroussin 	el->el_line.cursor += n;
705d0ef721eSBaptiste Daroussin 
706d0ef721eSBaptiste Daroussin 	if (el->el_line.cursor < el->el_line.buffer)
707d0ef721eSBaptiste Daroussin 		el->el_line.cursor = el->el_line.buffer;
708d0ef721eSBaptiste Daroussin 	if (el->el_line.cursor > el->el_line.lastchar)
709d0ef721eSBaptiste Daroussin 		el->el_line.cursor = el->el_line.lastchar;
710d0ef721eSBaptiste Daroussin out:
711d0ef721eSBaptiste Daroussin 	return (int)(el->el_line.cursor - el->el_line.buffer);
712d0ef721eSBaptiste Daroussin }
713d0ef721eSBaptiste Daroussin 
714d0ef721eSBaptiste Daroussin /* c_gets():
715d0ef721eSBaptiste Daroussin  *	Get a string
716d0ef721eSBaptiste Daroussin  */
717d0ef721eSBaptiste Daroussin libedit_private int
c_gets(EditLine * el,wchar_t * buf,const wchar_t * prompt)718d0ef721eSBaptiste Daroussin c_gets(EditLine *el, wchar_t *buf, const wchar_t *prompt)
719d0ef721eSBaptiste Daroussin {
720d0ef721eSBaptiste Daroussin 	ssize_t len;
721d0ef721eSBaptiste Daroussin 	wchar_t *cp = el->el_line.buffer, ch;
722d0ef721eSBaptiste Daroussin 
723d0ef721eSBaptiste Daroussin 	if (prompt) {
724d0ef721eSBaptiste Daroussin 		len = (ssize_t)wcslen(prompt);
725d0ef721eSBaptiste Daroussin 		(void)memcpy(cp, prompt, (size_t)len * sizeof(*cp));
726d0ef721eSBaptiste Daroussin 		cp += len;
727d0ef721eSBaptiste Daroussin 	}
728d0ef721eSBaptiste Daroussin 	len = 0;
729d0ef721eSBaptiste Daroussin 
730d0ef721eSBaptiste Daroussin 	for (;;) {
731d0ef721eSBaptiste Daroussin 		el->el_line.cursor = cp;
732d0ef721eSBaptiste Daroussin 		*cp = ' ';
733d0ef721eSBaptiste Daroussin 		el->el_line.lastchar = cp + 1;
734d0ef721eSBaptiste Daroussin 		re_refresh(el);
735d0ef721eSBaptiste Daroussin 
736d0ef721eSBaptiste Daroussin 		if (el_wgetc(el, &ch) != 1) {
737d0ef721eSBaptiste Daroussin 			ed_end_of_file(el, 0);
738d0ef721eSBaptiste Daroussin 			len = -1;
739d0ef721eSBaptiste Daroussin 			break;
740d0ef721eSBaptiste Daroussin 		}
741d0ef721eSBaptiste Daroussin 
742d0ef721eSBaptiste Daroussin 		switch (ch) {
743d0ef721eSBaptiste Daroussin 
744d0ef721eSBaptiste Daroussin 		case L'\b':	/* Delete and backspace */
745d0ef721eSBaptiste Daroussin 		case 0177:
746d0ef721eSBaptiste Daroussin 			if (len == 0) {
747d0ef721eSBaptiste Daroussin 				len = -1;
748d0ef721eSBaptiste Daroussin 				break;
749d0ef721eSBaptiste Daroussin 			}
750d0ef721eSBaptiste Daroussin 			len--;
751d0ef721eSBaptiste Daroussin 			cp--;
752d0ef721eSBaptiste Daroussin 			continue;
753d0ef721eSBaptiste Daroussin 
754d0ef721eSBaptiste Daroussin 		case 0033:	/* ESC */
755d0ef721eSBaptiste Daroussin 		case L'\r':	/* Newline */
756d0ef721eSBaptiste Daroussin 		case L'\n':
757d0ef721eSBaptiste Daroussin 			buf[len] = ch;
758d0ef721eSBaptiste Daroussin 			break;
759d0ef721eSBaptiste Daroussin 
760d0ef721eSBaptiste Daroussin 		default:
761d0ef721eSBaptiste Daroussin 			if (len >= (ssize_t)(EL_BUFSIZ - 16))
762d0ef721eSBaptiste Daroussin 				terminal_beep(el);
763d0ef721eSBaptiste Daroussin 			else {
764d0ef721eSBaptiste Daroussin 				buf[len++] = ch;
765d0ef721eSBaptiste Daroussin 				*cp++ = ch;
766d0ef721eSBaptiste Daroussin 			}
767d0ef721eSBaptiste Daroussin 			continue;
768d0ef721eSBaptiste Daroussin 		}
769d0ef721eSBaptiste Daroussin 		break;
770d0ef721eSBaptiste Daroussin 	}
771d0ef721eSBaptiste Daroussin 
772d0ef721eSBaptiste Daroussin 	el->el_line.buffer[0] = '\0';
773d0ef721eSBaptiste Daroussin 	el->el_line.lastchar = el->el_line.buffer;
774d0ef721eSBaptiste Daroussin 	el->el_line.cursor = el->el_line.buffer;
775d0ef721eSBaptiste Daroussin 	return (int)len;
776d0ef721eSBaptiste Daroussin }
777d0ef721eSBaptiste Daroussin 
778d0ef721eSBaptiste Daroussin 
779d0ef721eSBaptiste Daroussin /* c_hpos():
780d0ef721eSBaptiste Daroussin  *	Return the current horizontal position of the cursor
781d0ef721eSBaptiste Daroussin  */
782d0ef721eSBaptiste Daroussin libedit_private int
c_hpos(EditLine * el)783d0ef721eSBaptiste Daroussin c_hpos(EditLine *el)
784d0ef721eSBaptiste Daroussin {
785d0ef721eSBaptiste Daroussin 	wchar_t *ptr;
786d0ef721eSBaptiste Daroussin 
787d0ef721eSBaptiste Daroussin 	/*
788d0ef721eSBaptiste Daroussin 	 * Find how many characters till the beginning of this line.
789d0ef721eSBaptiste Daroussin 	 */
790d0ef721eSBaptiste Daroussin 	if (el->el_line.cursor == el->el_line.buffer)
791d0ef721eSBaptiste Daroussin 		return 0;
792d0ef721eSBaptiste Daroussin 	else {
793d0ef721eSBaptiste Daroussin 		for (ptr = el->el_line.cursor - 1;
794d0ef721eSBaptiste Daroussin 		     ptr >= el->el_line.buffer && *ptr != '\n';
795d0ef721eSBaptiste Daroussin 		     ptr--)
796d0ef721eSBaptiste Daroussin 			continue;
797d0ef721eSBaptiste Daroussin 		return (int)(el->el_line.cursor - ptr - 1);
798d0ef721eSBaptiste Daroussin 	}
799d0ef721eSBaptiste Daroussin }
800d0ef721eSBaptiste Daroussin 
801d0ef721eSBaptiste Daroussin libedit_private int
ch_resizefun(EditLine * el,el_zfunc_t f,void * a)802d0ef721eSBaptiste Daroussin ch_resizefun(EditLine *el, el_zfunc_t f, void *a)
803d0ef721eSBaptiste Daroussin {
804d0ef721eSBaptiste Daroussin 	el->el_chared.c_resizefun = f;
805d0ef721eSBaptiste Daroussin 	el->el_chared.c_resizearg = a;
806d0ef721eSBaptiste Daroussin 	return 0;
807d0ef721eSBaptiste Daroussin }
808d0ef721eSBaptiste Daroussin 
809d0ef721eSBaptiste Daroussin libedit_private int
ch_aliasfun(EditLine * el,el_afunc_t f,void * a)810d0ef721eSBaptiste Daroussin ch_aliasfun(EditLine *el, el_afunc_t f, void *a)
811d0ef721eSBaptiste Daroussin {
812d0ef721eSBaptiste Daroussin 	el->el_chared.c_aliasfun = f;
813d0ef721eSBaptiste Daroussin 	el->el_chared.c_aliasarg = a;
814d0ef721eSBaptiste Daroussin 	return 0;
815d0ef721eSBaptiste Daroussin }
816