xref: /freebsd/contrib/libedit/chared.c (revision baff8195)
1*baff8195SBaptiste Daroussin /*	$NetBSD: chared.c,v 1.63 2022/10/30 19:11:31 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*baff8195SBaptiste Daroussin __RCSID("$NetBSD: chared.c,v 1.63 2022/10/30 19:11:31 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--;
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
cv_delfini(EditLine * el)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 *
cv__endword(wchar_t * p,wchar_t * high,int n,int (* wtest)(wint_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
ch_init(EditLine * el)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)
417*baff8195SBaptiste Daroussin 		goto out;
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)
428*baff8195SBaptiste Daroussin 		goto out;
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;
445*baff8195SBaptiste Daroussin out:
446*baff8195SBaptiste Daroussin 	ch_end(el);
447*baff8195SBaptiste Daroussin 	return -1;
448d0ef721eSBaptiste Daroussin }
449d0ef721eSBaptiste Daroussin 
450d0ef721eSBaptiste Daroussin /* ch_reset():
451d0ef721eSBaptiste Daroussin  *	Reset the character editor
452d0ef721eSBaptiste Daroussin  */
453d0ef721eSBaptiste Daroussin libedit_private void
ch_reset(EditLine * el)454d0ef721eSBaptiste Daroussin ch_reset(EditLine *el)
455d0ef721eSBaptiste Daroussin {
456d0ef721eSBaptiste Daroussin 	el->el_line.cursor		= el->el_line.buffer;
457d0ef721eSBaptiste Daroussin 	el->el_line.lastchar		= el->el_line.buffer;
458d0ef721eSBaptiste Daroussin 
459d0ef721eSBaptiste Daroussin 	el->el_chared.c_undo.len	= -1;
460d0ef721eSBaptiste Daroussin 	el->el_chared.c_undo.cursor	= 0;
461d0ef721eSBaptiste Daroussin 
462d0ef721eSBaptiste Daroussin 	el->el_chared.c_vcmd.action	= NOP;
463d0ef721eSBaptiste Daroussin 	el->el_chared.c_vcmd.pos	= el->el_line.buffer;
464d0ef721eSBaptiste Daroussin 
465d0ef721eSBaptiste Daroussin 	el->el_chared.c_kill.mark	= el->el_line.buffer;
466d0ef721eSBaptiste Daroussin 
467d0ef721eSBaptiste Daroussin 	el->el_map.current		= el->el_map.key;
468d0ef721eSBaptiste Daroussin 
469d0ef721eSBaptiste Daroussin 	el->el_state.inputmode		= MODE_INSERT; /* XXX: save a default */
470d0ef721eSBaptiste Daroussin 	el->el_state.doingarg		= 0;
471d0ef721eSBaptiste Daroussin 	el->el_state.metanext		= 0;
472d0ef721eSBaptiste Daroussin 	el->el_state.argument		= 1;
473d0ef721eSBaptiste Daroussin 	el->el_state.lastcmd		= ED_UNASSIGNED;
474d0ef721eSBaptiste Daroussin 
475d0ef721eSBaptiste Daroussin 	el->el_history.eventno		= 0;
476d0ef721eSBaptiste Daroussin }
477d0ef721eSBaptiste Daroussin 
478d0ef721eSBaptiste Daroussin /* ch_enlargebufs():
479d0ef721eSBaptiste Daroussin  *	Enlarge line buffer to be able to hold twice as much characters.
480d0ef721eSBaptiste Daroussin  *	Returns 1 if successful, 0 if not.
481d0ef721eSBaptiste Daroussin  */
482d0ef721eSBaptiste Daroussin libedit_private int
ch_enlargebufs(EditLine * el,size_t addlen)483d0ef721eSBaptiste Daroussin ch_enlargebufs(EditLine *el, size_t addlen)
484d0ef721eSBaptiste Daroussin {
485d0ef721eSBaptiste Daroussin 	size_t sz, newsz;
486d0ef721eSBaptiste Daroussin 	wchar_t *newbuffer, *oldbuf, *oldkbuf;
487d0ef721eSBaptiste Daroussin 
488d0ef721eSBaptiste Daroussin 	sz = (size_t)(el->el_line.limit - el->el_line.buffer + EL_LEAVE);
489d0ef721eSBaptiste Daroussin 	newsz = sz * 2;
490d0ef721eSBaptiste Daroussin 	/*
491d0ef721eSBaptiste Daroussin 	 * If newly required length is longer than current buffer, we need
492d0ef721eSBaptiste Daroussin 	 * to make the buffer big enough to hold both old and new stuff.
493d0ef721eSBaptiste Daroussin 	 */
494d0ef721eSBaptiste Daroussin 	if (addlen > sz) {
495d0ef721eSBaptiste Daroussin 		while(newsz - sz < addlen)
496d0ef721eSBaptiste Daroussin 			newsz *= 2;
497d0ef721eSBaptiste Daroussin 	}
498d0ef721eSBaptiste Daroussin 
499d0ef721eSBaptiste Daroussin 	/*
500d0ef721eSBaptiste Daroussin 	 * Reallocate line buffer.
501d0ef721eSBaptiste Daroussin 	 */
502d0ef721eSBaptiste Daroussin 	newbuffer = el_realloc(el->el_line.buffer, newsz * sizeof(*newbuffer));
503d0ef721eSBaptiste Daroussin 	if (!newbuffer)
504d0ef721eSBaptiste Daroussin 		return 0;
505d0ef721eSBaptiste Daroussin 
506d0ef721eSBaptiste Daroussin 	/* zero the newly added memory, leave old data in */
507d0ef721eSBaptiste Daroussin 	(void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer));
508d0ef721eSBaptiste Daroussin 
509d0ef721eSBaptiste Daroussin 	oldbuf = el->el_line.buffer;
510d0ef721eSBaptiste Daroussin 
511d0ef721eSBaptiste Daroussin 	el->el_line.buffer = newbuffer;
512d0ef721eSBaptiste Daroussin 	el->el_line.cursor = newbuffer + (el->el_line.cursor - oldbuf);
513d0ef721eSBaptiste Daroussin 	el->el_line.lastchar = newbuffer + (el->el_line.lastchar - oldbuf);
514d0ef721eSBaptiste Daroussin 	/* don't set new size until all buffers are enlarged */
515d0ef721eSBaptiste Daroussin 	el->el_line.limit  = &newbuffer[sz - EL_LEAVE];
516d0ef721eSBaptiste Daroussin 
517d0ef721eSBaptiste Daroussin 	/*
518d0ef721eSBaptiste Daroussin 	 * Reallocate kill buffer.
519d0ef721eSBaptiste Daroussin 	 */
520d0ef721eSBaptiste Daroussin 	newbuffer = el_realloc(el->el_chared.c_kill.buf, newsz *
521d0ef721eSBaptiste Daroussin 	    sizeof(*newbuffer));
522d0ef721eSBaptiste Daroussin 	if (!newbuffer)
523d0ef721eSBaptiste Daroussin 		return 0;
524d0ef721eSBaptiste Daroussin 
525d0ef721eSBaptiste Daroussin 	/* zero the newly added memory, leave old data in */
526d0ef721eSBaptiste Daroussin 	(void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer));
527d0ef721eSBaptiste Daroussin 
528d0ef721eSBaptiste Daroussin 	oldkbuf = el->el_chared.c_kill.buf;
529d0ef721eSBaptiste Daroussin 
530d0ef721eSBaptiste Daroussin 	el->el_chared.c_kill.buf = newbuffer;
531d0ef721eSBaptiste Daroussin 	el->el_chared.c_kill.last = newbuffer +
532d0ef721eSBaptiste Daroussin 					(el->el_chared.c_kill.last - oldkbuf);
533d0ef721eSBaptiste Daroussin 	el->el_chared.c_kill.mark = el->el_line.buffer +
534d0ef721eSBaptiste Daroussin 					(el->el_chared.c_kill.mark - oldbuf);
535d0ef721eSBaptiste Daroussin 
536d0ef721eSBaptiste Daroussin 	/*
537d0ef721eSBaptiste Daroussin 	 * Reallocate undo buffer.
538d0ef721eSBaptiste Daroussin 	 */
539d0ef721eSBaptiste Daroussin 	newbuffer = el_realloc(el->el_chared.c_undo.buf,
540d0ef721eSBaptiste Daroussin 	    newsz * sizeof(*newbuffer));
541d0ef721eSBaptiste Daroussin 	if (!newbuffer)
542d0ef721eSBaptiste Daroussin 		return 0;
543d0ef721eSBaptiste Daroussin 
544d0ef721eSBaptiste Daroussin 	/* zero the newly added memory, leave old data in */
545d0ef721eSBaptiste Daroussin 	(void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer));
546d0ef721eSBaptiste Daroussin 	el->el_chared.c_undo.buf = newbuffer;
547d0ef721eSBaptiste Daroussin 
548d0ef721eSBaptiste Daroussin 	newbuffer = el_realloc(el->el_chared.c_redo.buf,
549d0ef721eSBaptiste Daroussin 	    newsz * sizeof(*newbuffer));
550d0ef721eSBaptiste Daroussin 	if (!newbuffer)
551d0ef721eSBaptiste Daroussin 		return 0;
552d0ef721eSBaptiste Daroussin 	el->el_chared.c_redo.pos = newbuffer +
553d0ef721eSBaptiste Daroussin 			(el->el_chared.c_redo.pos - el->el_chared.c_redo.buf);
554d0ef721eSBaptiste Daroussin 	el->el_chared.c_redo.lim = newbuffer +
555d0ef721eSBaptiste Daroussin 			(el->el_chared.c_redo.lim - el->el_chared.c_redo.buf);
556d0ef721eSBaptiste Daroussin 	el->el_chared.c_redo.buf = newbuffer;
557d0ef721eSBaptiste Daroussin 
558d0ef721eSBaptiste Daroussin 	if (!hist_enlargebuf(el, sz, newsz))
559d0ef721eSBaptiste Daroussin 		return 0;
560d0ef721eSBaptiste Daroussin 
561d0ef721eSBaptiste Daroussin 	/* Safe to set enlarged buffer size */
562d0ef721eSBaptiste Daroussin 	el->el_line.limit  = &el->el_line.buffer[newsz - EL_LEAVE];
563d0ef721eSBaptiste Daroussin 	if (el->el_chared.c_resizefun)
564d0ef721eSBaptiste Daroussin 		(*el->el_chared.c_resizefun)(el, el->el_chared.c_resizearg);
565d0ef721eSBaptiste Daroussin 	return 1;
566d0ef721eSBaptiste Daroussin }
567d0ef721eSBaptiste Daroussin 
568d0ef721eSBaptiste Daroussin /* ch_end():
569d0ef721eSBaptiste Daroussin  *	Free the data structures used by the editor
570d0ef721eSBaptiste Daroussin  */
571d0ef721eSBaptiste Daroussin libedit_private void
ch_end(EditLine * el)572d0ef721eSBaptiste Daroussin ch_end(EditLine *el)
573d0ef721eSBaptiste Daroussin {
574d0ef721eSBaptiste Daroussin 	el_free(el->el_line.buffer);
575d0ef721eSBaptiste Daroussin 	el->el_line.buffer = NULL;
576d0ef721eSBaptiste Daroussin 	el->el_line.limit = NULL;
577d0ef721eSBaptiste Daroussin 	el_free(el->el_chared.c_undo.buf);
578d0ef721eSBaptiste Daroussin 	el->el_chared.c_undo.buf = NULL;
579d0ef721eSBaptiste Daroussin 	el_free(el->el_chared.c_redo.buf);
580d0ef721eSBaptiste Daroussin 	el->el_chared.c_redo.buf = NULL;
581d0ef721eSBaptiste Daroussin 	el->el_chared.c_redo.pos = NULL;
582d0ef721eSBaptiste Daroussin 	el->el_chared.c_redo.lim = NULL;
583d0ef721eSBaptiste Daroussin 	el->el_chared.c_redo.cmd = ED_UNASSIGNED;
584d0ef721eSBaptiste Daroussin 	el_free(el->el_chared.c_kill.buf);
585d0ef721eSBaptiste Daroussin 	el->el_chared.c_kill.buf = NULL;
586d0ef721eSBaptiste Daroussin 	ch_reset(el);
587d0ef721eSBaptiste Daroussin }
588d0ef721eSBaptiste Daroussin 
589d0ef721eSBaptiste Daroussin 
590d0ef721eSBaptiste Daroussin /* el_insertstr():
591d0ef721eSBaptiste Daroussin  *	Insert string at cursor
592d0ef721eSBaptiste Daroussin  */
593d0ef721eSBaptiste Daroussin int
el_winsertstr(EditLine * el,const wchar_t * s)594d0ef721eSBaptiste Daroussin el_winsertstr(EditLine *el, const wchar_t *s)
595d0ef721eSBaptiste Daroussin {
596d0ef721eSBaptiste Daroussin 	size_t len;
597d0ef721eSBaptiste Daroussin 
598d0ef721eSBaptiste Daroussin 	if (s == NULL || (len = wcslen(s)) == 0)
599d0ef721eSBaptiste Daroussin 		return -1;
600d0ef721eSBaptiste Daroussin 	if (el->el_line.lastchar + len >= el->el_line.limit) {
601d0ef721eSBaptiste Daroussin 		if (!ch_enlargebufs(el, len))
602d0ef721eSBaptiste Daroussin 			return -1;
603d0ef721eSBaptiste Daroussin 	}
604d0ef721eSBaptiste Daroussin 
605d0ef721eSBaptiste Daroussin 	c_insert(el, (int)len);
606d0ef721eSBaptiste Daroussin 	while (*s)
607d0ef721eSBaptiste Daroussin 		*el->el_line.cursor++ = *s++;
608d0ef721eSBaptiste Daroussin 	return 0;
609d0ef721eSBaptiste Daroussin }
610d0ef721eSBaptiste Daroussin 
611d0ef721eSBaptiste Daroussin 
612d0ef721eSBaptiste Daroussin /* el_deletestr():
613d0ef721eSBaptiste Daroussin  *	Delete num characters before the cursor
614d0ef721eSBaptiste Daroussin  */
615d0ef721eSBaptiste Daroussin void
el_deletestr(EditLine * el,int n)616d0ef721eSBaptiste Daroussin el_deletestr(EditLine *el, int n)
617d0ef721eSBaptiste Daroussin {
618d0ef721eSBaptiste Daroussin 	if (n <= 0)
619d0ef721eSBaptiste Daroussin 		return;
620d0ef721eSBaptiste Daroussin 
621d0ef721eSBaptiste Daroussin 	if (el->el_line.cursor < &el->el_line.buffer[n])
622d0ef721eSBaptiste Daroussin 		return;
623d0ef721eSBaptiste Daroussin 
624d0ef721eSBaptiste Daroussin 	c_delbefore(el, n);		/* delete before dot */
625d0ef721eSBaptiste Daroussin 	el->el_line.cursor -= n;
626d0ef721eSBaptiste Daroussin 	if (el->el_line.cursor < el->el_line.buffer)
627d0ef721eSBaptiste Daroussin 		el->el_line.cursor = el->el_line.buffer;
628d0ef721eSBaptiste Daroussin }
629d0ef721eSBaptiste Daroussin 
6307f399375SBaptiste Daroussin /* el_deletestr1():
6317f399375SBaptiste Daroussin  *	Delete characters between start and end
6327f399375SBaptiste Daroussin  */
6337f399375SBaptiste Daroussin int
el_deletestr1(EditLine * el,int start,int end)6347f399375SBaptiste Daroussin el_deletestr1(EditLine *el, int start, int end)
6357f399375SBaptiste Daroussin {
6367f399375SBaptiste Daroussin 	size_t line_length, len;
6377f399375SBaptiste Daroussin 	wchar_t *p1, *p2;
6387f399375SBaptiste Daroussin 
6397f399375SBaptiste Daroussin 	if (end <= start)
6407f399375SBaptiste Daroussin 		return 0;
6417f399375SBaptiste Daroussin 
6427f399375SBaptiste Daroussin 	line_length = (size_t)(el->el_line.lastchar - el->el_line.buffer);
6437f399375SBaptiste Daroussin 
6447f399375SBaptiste Daroussin 	if (start >= (int)line_length || end >= (int)line_length)
6457f399375SBaptiste Daroussin 		return 0;
6467f399375SBaptiste Daroussin 
6477f399375SBaptiste Daroussin 	len = (size_t)(end - start);
6487f399375SBaptiste Daroussin 	if (len > line_length - (size_t)end)
6497f399375SBaptiste Daroussin 		len = line_length - (size_t)end;
6507f399375SBaptiste Daroussin 
6517f399375SBaptiste Daroussin 	p1 = el->el_line.buffer + start;
6527f399375SBaptiste Daroussin 	p2 = el->el_line.buffer + end;
6537f399375SBaptiste Daroussin 	for (size_t i = 0; i < len; i++) {
6547f399375SBaptiste Daroussin 		*p1++ = *p2++;
6557f399375SBaptiste Daroussin 		el->el_line.lastchar--;
6567f399375SBaptiste Daroussin 	}
6577f399375SBaptiste Daroussin 
6587f399375SBaptiste Daroussin 	if (el->el_line.cursor < el->el_line.buffer)
6597f399375SBaptiste Daroussin 		el->el_line.cursor = el->el_line.buffer;
6607f399375SBaptiste Daroussin 
6617f399375SBaptiste Daroussin 	return end - start;
6627f399375SBaptiste Daroussin }
6637f399375SBaptiste Daroussin 
6647f399375SBaptiste Daroussin /* el_wreplacestr():
6657f399375SBaptiste Daroussin  *	Replace the contents of the line with the provided string
6667f399375SBaptiste Daroussin  */
6677f399375SBaptiste Daroussin int
el_wreplacestr(EditLine * el,const wchar_t * s)6687f399375SBaptiste Daroussin el_wreplacestr(EditLine *el, const wchar_t *s)
6697f399375SBaptiste Daroussin {
6707f399375SBaptiste Daroussin 	size_t len;
6717f399375SBaptiste Daroussin 	wchar_t * p;
6727f399375SBaptiste Daroussin 
6737f399375SBaptiste Daroussin 	if (s == NULL || (len = wcslen(s)) == 0)
6747f399375SBaptiste Daroussin 		return -1;
6757f399375SBaptiste Daroussin 
6767f399375SBaptiste Daroussin 	if (el->el_line.buffer + len >= el->el_line.limit) {
6777f399375SBaptiste Daroussin 		if (!ch_enlargebufs(el, len))
6787f399375SBaptiste Daroussin 			return -1;
6797f399375SBaptiste Daroussin 	}
6807f399375SBaptiste Daroussin 
6817f399375SBaptiste Daroussin 	p = el->el_line.buffer;
6827f399375SBaptiste Daroussin 	for (size_t i = 0; i < len; i++)
6837f399375SBaptiste Daroussin 		*p++ = *s++;
6847f399375SBaptiste Daroussin 
6857f399375SBaptiste Daroussin 	el->el_line.buffer[len] = '\0';
6867f399375SBaptiste Daroussin 	el->el_line.lastchar = el->el_line.buffer + len;
6877f399375SBaptiste Daroussin 	if (el->el_line.cursor > el->el_line.lastchar)
6887f399375SBaptiste Daroussin 		el->el_line.cursor = el->el_line.lastchar;
6897f399375SBaptiste Daroussin 
6907f399375SBaptiste Daroussin 	return 0;
6917f399375SBaptiste Daroussin }
6927f399375SBaptiste Daroussin 
693d0ef721eSBaptiste Daroussin /* el_cursor():
694d0ef721eSBaptiste Daroussin  *	Move the cursor to the left or the right of the current position
695d0ef721eSBaptiste Daroussin  */
696d0ef721eSBaptiste Daroussin int
el_cursor(EditLine * el,int n)697d0ef721eSBaptiste Daroussin el_cursor(EditLine *el, int n)
698d0ef721eSBaptiste Daroussin {
699d0ef721eSBaptiste Daroussin 	if (n == 0)
700d0ef721eSBaptiste Daroussin 		goto out;
701d0ef721eSBaptiste Daroussin 
702d0ef721eSBaptiste Daroussin 	el->el_line.cursor += n;
703d0ef721eSBaptiste Daroussin 
704d0ef721eSBaptiste Daroussin 	if (el->el_line.cursor < el->el_line.buffer)
705d0ef721eSBaptiste Daroussin 		el->el_line.cursor = el->el_line.buffer;
706d0ef721eSBaptiste Daroussin 	if (el->el_line.cursor > el->el_line.lastchar)
707d0ef721eSBaptiste Daroussin 		el->el_line.cursor = el->el_line.lastchar;
708d0ef721eSBaptiste Daroussin out:
709d0ef721eSBaptiste Daroussin 	return (int)(el->el_line.cursor - el->el_line.buffer);
710d0ef721eSBaptiste Daroussin }
711d0ef721eSBaptiste Daroussin 
712d0ef721eSBaptiste Daroussin /* c_gets():
713d0ef721eSBaptiste Daroussin  *	Get a string
714d0ef721eSBaptiste Daroussin  */
715d0ef721eSBaptiste Daroussin libedit_private int
c_gets(EditLine * el,wchar_t * buf,const wchar_t * prompt)716d0ef721eSBaptiste Daroussin c_gets(EditLine *el, wchar_t *buf, const wchar_t *prompt)
717d0ef721eSBaptiste Daroussin {
718d0ef721eSBaptiste Daroussin 	ssize_t len;
719d0ef721eSBaptiste Daroussin 	wchar_t *cp = el->el_line.buffer, ch;
720d0ef721eSBaptiste Daroussin 
721d0ef721eSBaptiste Daroussin 	if (prompt) {
722d0ef721eSBaptiste Daroussin 		len = (ssize_t)wcslen(prompt);
723d0ef721eSBaptiste Daroussin 		(void)memcpy(cp, prompt, (size_t)len * sizeof(*cp));
724d0ef721eSBaptiste Daroussin 		cp += len;
725d0ef721eSBaptiste Daroussin 	}
726d0ef721eSBaptiste Daroussin 	len = 0;
727d0ef721eSBaptiste Daroussin 
728d0ef721eSBaptiste Daroussin 	for (;;) {
729d0ef721eSBaptiste Daroussin 		el->el_line.cursor = cp;
730d0ef721eSBaptiste Daroussin 		*cp = ' ';
731d0ef721eSBaptiste Daroussin 		el->el_line.lastchar = cp + 1;
732d0ef721eSBaptiste Daroussin 		re_refresh(el);
733d0ef721eSBaptiste Daroussin 
734d0ef721eSBaptiste Daroussin 		if (el_wgetc(el, &ch) != 1) {
735d0ef721eSBaptiste Daroussin 			ed_end_of_file(el, 0);
736d0ef721eSBaptiste Daroussin 			len = -1;
737d0ef721eSBaptiste Daroussin 			break;
738d0ef721eSBaptiste Daroussin 		}
739d0ef721eSBaptiste Daroussin 
740d0ef721eSBaptiste Daroussin 		switch (ch) {
741d0ef721eSBaptiste Daroussin 
742d0ef721eSBaptiste Daroussin 		case L'\b':	/* Delete and backspace */
743d0ef721eSBaptiste Daroussin 		case 0177:
744d0ef721eSBaptiste Daroussin 			if (len == 0) {
745d0ef721eSBaptiste Daroussin 				len = -1;
746d0ef721eSBaptiste Daroussin 				break;
747d0ef721eSBaptiste Daroussin 			}
748d0ef721eSBaptiste Daroussin 			len--;
749d0ef721eSBaptiste Daroussin 			cp--;
750d0ef721eSBaptiste Daroussin 			continue;
751d0ef721eSBaptiste Daroussin 
752d0ef721eSBaptiste Daroussin 		case 0033:	/* ESC */
753d0ef721eSBaptiste Daroussin 		case L'\r':	/* Newline */
754d0ef721eSBaptiste Daroussin 		case L'\n':
755d0ef721eSBaptiste Daroussin 			buf[len] = ch;
756d0ef721eSBaptiste Daroussin 			break;
757d0ef721eSBaptiste Daroussin 
758d0ef721eSBaptiste Daroussin 		default:
759d0ef721eSBaptiste Daroussin 			if (len >= (ssize_t)(EL_BUFSIZ - 16))
760d0ef721eSBaptiste Daroussin 				terminal_beep(el);
761d0ef721eSBaptiste Daroussin 			else {
762d0ef721eSBaptiste Daroussin 				buf[len++] = ch;
763d0ef721eSBaptiste Daroussin 				*cp++ = ch;
764d0ef721eSBaptiste Daroussin 			}
765d0ef721eSBaptiste Daroussin 			continue;
766d0ef721eSBaptiste Daroussin 		}
767d0ef721eSBaptiste Daroussin 		break;
768d0ef721eSBaptiste Daroussin 	}
769d0ef721eSBaptiste Daroussin 
770d0ef721eSBaptiste Daroussin 	el->el_line.buffer[0] = '\0';
771d0ef721eSBaptiste Daroussin 	el->el_line.lastchar = el->el_line.buffer;
772d0ef721eSBaptiste Daroussin 	el->el_line.cursor = el->el_line.buffer;
773d0ef721eSBaptiste Daroussin 	return (int)len;
774d0ef721eSBaptiste Daroussin }
775d0ef721eSBaptiste Daroussin 
776d0ef721eSBaptiste Daroussin 
777d0ef721eSBaptiste Daroussin /* c_hpos():
778d0ef721eSBaptiste Daroussin  *	Return the current horizontal position of the cursor
779d0ef721eSBaptiste Daroussin  */
780d0ef721eSBaptiste Daroussin libedit_private int
c_hpos(EditLine * el)781d0ef721eSBaptiste Daroussin c_hpos(EditLine *el)
782d0ef721eSBaptiste Daroussin {
783d0ef721eSBaptiste Daroussin 	wchar_t *ptr;
784d0ef721eSBaptiste Daroussin 
785d0ef721eSBaptiste Daroussin 	/*
786d0ef721eSBaptiste Daroussin 	 * Find how many characters till the beginning of this line.
787d0ef721eSBaptiste Daroussin 	 */
788d0ef721eSBaptiste Daroussin 	if (el->el_line.cursor == el->el_line.buffer)
789d0ef721eSBaptiste Daroussin 		return 0;
790d0ef721eSBaptiste Daroussin 	else {
791d0ef721eSBaptiste Daroussin 		for (ptr = el->el_line.cursor - 1;
792d0ef721eSBaptiste Daroussin 		     ptr >= el->el_line.buffer && *ptr != '\n';
793d0ef721eSBaptiste Daroussin 		     ptr--)
794d0ef721eSBaptiste Daroussin 			continue;
795d0ef721eSBaptiste Daroussin 		return (int)(el->el_line.cursor - ptr - 1);
796d0ef721eSBaptiste Daroussin 	}
797d0ef721eSBaptiste Daroussin }
798d0ef721eSBaptiste Daroussin 
799d0ef721eSBaptiste Daroussin libedit_private int
ch_resizefun(EditLine * el,el_zfunc_t f,void * a)800d0ef721eSBaptiste Daroussin ch_resizefun(EditLine *el, el_zfunc_t f, void *a)
801d0ef721eSBaptiste Daroussin {
802d0ef721eSBaptiste Daroussin 	el->el_chared.c_resizefun = f;
803d0ef721eSBaptiste Daroussin 	el->el_chared.c_resizearg = a;
804d0ef721eSBaptiste Daroussin 	return 0;
805d0ef721eSBaptiste Daroussin }
806d0ef721eSBaptiste Daroussin 
807d0ef721eSBaptiste Daroussin libedit_private int
ch_aliasfun(EditLine * el,el_afunc_t f,void * a)808d0ef721eSBaptiste Daroussin ch_aliasfun(EditLine *el, el_afunc_t f, void *a)
809d0ef721eSBaptiste Daroussin {
810d0ef721eSBaptiste Daroussin 	el->el_chared.c_aliasfun = f;
811d0ef721eSBaptiste Daroussin 	el->el_chared.c_aliasarg = a;
812d0ef721eSBaptiste Daroussin 	return 0;
813d0ef721eSBaptiste Daroussin }
814