xref: /dflybsd-src/contrib/libedit/src/chared.c (revision 698e9e6cd5f042847de67460caaa3fde98cdfe99)
1*cdf8408cSAntonio Huete Jimenez /*	$NetBSD: chared.c,v 1.62 2022/02/08 21:13:22 rillig Exp $	*/
232fe07f8SJohn Marino 
332fe07f8SJohn Marino /*-
432fe07f8SJohn Marino  * Copyright (c) 1992, 1993
532fe07f8SJohn Marino  *	The Regents of the University of California.  All rights reserved.
632fe07f8SJohn Marino  *
732fe07f8SJohn Marino  * This code is derived from software contributed to Berkeley by
832fe07f8SJohn Marino  * Christos Zoulas of Cornell University.
932fe07f8SJohn Marino  *
1032fe07f8SJohn Marino  * Redistribution and use in source and binary forms, with or without
1132fe07f8SJohn Marino  * modification, are permitted provided that the following conditions
1232fe07f8SJohn Marino  * are met:
1332fe07f8SJohn Marino  * 1. Redistributions of source code must retain the above copyright
1432fe07f8SJohn Marino  *    notice, this list of conditions and the following disclaimer.
1532fe07f8SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
1632fe07f8SJohn Marino  *    notice, this list of conditions and the following disclaimer in the
1732fe07f8SJohn Marino  *    documentation and/or other materials provided with the distribution.
1832fe07f8SJohn Marino  * 3. Neither the name of the University nor the names of its contributors
1932fe07f8SJohn Marino  *    may be used to endorse or promote products derived from this software
2032fe07f8SJohn Marino  *    without specific prior written permission.
2132fe07f8SJohn Marino  *
2232fe07f8SJohn Marino  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2332fe07f8SJohn Marino  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2432fe07f8SJohn Marino  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2532fe07f8SJohn Marino  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2632fe07f8SJohn Marino  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2732fe07f8SJohn Marino  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2832fe07f8SJohn Marino  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2932fe07f8SJohn Marino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3032fe07f8SJohn Marino  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3132fe07f8SJohn Marino  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3232fe07f8SJohn Marino  * SUCH DAMAGE.
3332fe07f8SJohn Marino  */
3432fe07f8SJohn Marino 
3532fe07f8SJohn Marino #include "config.h"
3632fe07f8SJohn Marino #if !defined(lint) && !defined(SCCSID)
3732fe07f8SJohn Marino #if 0
3832fe07f8SJohn Marino static char sccsid[] = "@(#)chared.c	8.1 (Berkeley) 6/4/93";
3932fe07f8SJohn Marino #else
40*cdf8408cSAntonio Huete Jimenez __RCSID("$NetBSD: chared.c,v 1.62 2022/02/08 21:13:22 rillig Exp $");
4132fe07f8SJohn Marino #endif
4232fe07f8SJohn Marino #endif /* not lint && not SCCSID */
4332fe07f8SJohn Marino 
4432fe07f8SJohn Marino /*
4532fe07f8SJohn Marino  * chared.c: Character editor utilities
4632fe07f8SJohn Marino  */
4712db70c8Szrj #include <ctype.h>
4832fe07f8SJohn Marino #include <stdlib.h>
4912db70c8Szrj #include <string.h>
5032fe07f8SJohn Marino 
5112db70c8Szrj #include "el.h"
5212db70c8Szrj #include "common.h"
5312db70c8Szrj #include "fcns.h"
5432fe07f8SJohn Marino 
5532fe07f8SJohn Marino /* value to leave unused in line buffer */
5632fe07f8SJohn Marino #define	EL_LEAVE	2
5732fe07f8SJohn Marino 
5832fe07f8SJohn Marino /* cv_undo():
5932fe07f8SJohn Marino  *	Handle state for the vi undo command
6032fe07f8SJohn Marino  */
6112db70c8Szrj libedit_private void
cv_undo(EditLine * el)6232fe07f8SJohn Marino cv_undo(EditLine *el)
6332fe07f8SJohn Marino {
6432fe07f8SJohn Marino 	c_undo_t *vu = &el->el_chared.c_undo;
6532fe07f8SJohn Marino 	c_redo_t *r = &el->el_chared.c_redo;
6632fe07f8SJohn Marino 	size_t size;
6732fe07f8SJohn Marino 
6832fe07f8SJohn Marino 	/* Save entire line for undo */
6932fe07f8SJohn Marino 	size = (size_t)(el->el_line.lastchar - el->el_line.buffer);
7032fe07f8SJohn Marino 	vu->len = (ssize_t)size;
7132fe07f8SJohn Marino 	vu->cursor = (int)(el->el_line.cursor - el->el_line.buffer);
7232fe07f8SJohn Marino 	(void)memcpy(vu->buf, el->el_line.buffer, size * sizeof(*vu->buf));
7332fe07f8SJohn Marino 
7432fe07f8SJohn Marino 	/* save command info for redo */
7532fe07f8SJohn Marino 	r->count = el->el_state.doingarg ? el->el_state.argument : 0;
7632fe07f8SJohn Marino 	r->action = el->el_chared.c_vcmd.action;
7732fe07f8SJohn Marino 	r->pos = r->buf;
7832fe07f8SJohn Marino 	r->cmd = el->el_state.thiscmd;
7932fe07f8SJohn Marino 	r->ch = el->el_state.thisch;
8032fe07f8SJohn Marino }
8132fe07f8SJohn Marino 
8232fe07f8SJohn Marino /* cv_yank():
8332fe07f8SJohn Marino  *	Save yank/delete data for paste
8432fe07f8SJohn Marino  */
8512db70c8Szrj libedit_private void
cv_yank(EditLine * el,const wchar_t * ptr,int size)8612db70c8Szrj cv_yank(EditLine *el, const wchar_t *ptr, int size)
8732fe07f8SJohn Marino {
8832fe07f8SJohn Marino 	c_kill_t *k = &el->el_chared.c_kill;
8932fe07f8SJohn Marino 
9032fe07f8SJohn Marino 	(void)memcpy(k->buf, ptr, (size_t)size * sizeof(*k->buf));
9132fe07f8SJohn Marino 	k->last = k->buf + size;
9232fe07f8SJohn Marino }
9332fe07f8SJohn Marino 
9432fe07f8SJohn Marino 
9532fe07f8SJohn Marino /* c_insert():
9632fe07f8SJohn Marino  *	Insert num characters
9732fe07f8SJohn Marino  */
9812db70c8Szrj libedit_private void
c_insert(EditLine * el,int num)9932fe07f8SJohn Marino c_insert(EditLine *el, int num)
10032fe07f8SJohn Marino {
10112db70c8Szrj 	wchar_t *cp;
10232fe07f8SJohn Marino 
10332fe07f8SJohn Marino 	if (el->el_line.lastchar + num >= el->el_line.limit) {
10432fe07f8SJohn Marino 		if (!ch_enlargebufs(el, (size_t)num))
10532fe07f8SJohn Marino 			return;		/* can't go past end of buffer */
10632fe07f8SJohn Marino 	}
10732fe07f8SJohn Marino 
10832fe07f8SJohn Marino 	if (el->el_line.cursor < el->el_line.lastchar) {
10932fe07f8SJohn Marino 		/* if I must move chars */
11032fe07f8SJohn Marino 		for (cp = el->el_line.lastchar; cp >= el->el_line.cursor; cp--)
11132fe07f8SJohn Marino 			cp[num] = *cp;
11232fe07f8SJohn Marino 	}
11332fe07f8SJohn Marino 	el->el_line.lastchar += num;
11432fe07f8SJohn Marino }
11532fe07f8SJohn Marino 
11632fe07f8SJohn Marino 
11732fe07f8SJohn Marino /* c_delafter():
11832fe07f8SJohn Marino  *	Delete num characters after the cursor
11932fe07f8SJohn Marino  */
12012db70c8Szrj libedit_private void
c_delafter(EditLine * el,int num)12132fe07f8SJohn Marino c_delafter(EditLine *el, int num)
12232fe07f8SJohn Marino {
12332fe07f8SJohn Marino 
12432fe07f8SJohn Marino 	if (el->el_line.cursor + num > el->el_line.lastchar)
12532fe07f8SJohn Marino 		num = (int)(el->el_line.lastchar - el->el_line.cursor);
12632fe07f8SJohn Marino 
12732fe07f8SJohn Marino 	if (el->el_map.current != el->el_map.emacs) {
12832fe07f8SJohn Marino 		cv_undo(el);
12932fe07f8SJohn Marino 		cv_yank(el, el->el_line.cursor, num);
13032fe07f8SJohn Marino 	}
13132fe07f8SJohn Marino 
13232fe07f8SJohn Marino 	if (num > 0) {
13312db70c8Szrj 		wchar_t *cp;
13432fe07f8SJohn Marino 
13532fe07f8SJohn Marino 		for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++)
13632fe07f8SJohn Marino 			*cp = cp[num];
13732fe07f8SJohn Marino 
13832fe07f8SJohn Marino 		el->el_line.lastchar -= num;
13932fe07f8SJohn Marino 	}
14032fe07f8SJohn Marino }
14132fe07f8SJohn Marino 
14232fe07f8SJohn Marino 
14332fe07f8SJohn Marino /* c_delafter1():
14432fe07f8SJohn Marino  *	Delete the character after the cursor, do not yank
14532fe07f8SJohn Marino  */
14612db70c8Szrj libedit_private void
c_delafter1(EditLine * el)14732fe07f8SJohn Marino c_delafter1(EditLine *el)
14832fe07f8SJohn Marino {
14912db70c8Szrj 	wchar_t *cp;
15032fe07f8SJohn Marino 
15132fe07f8SJohn Marino 	for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++)
15232fe07f8SJohn Marino 		*cp = cp[1];
15332fe07f8SJohn Marino 
15432fe07f8SJohn Marino 	el->el_line.lastchar--;
15532fe07f8SJohn Marino }
15632fe07f8SJohn Marino 
15732fe07f8SJohn Marino 
15832fe07f8SJohn Marino /* c_delbefore():
15932fe07f8SJohn Marino  *	Delete num characters before the cursor
16032fe07f8SJohn Marino  */
16112db70c8Szrj libedit_private void
c_delbefore(EditLine * el,int num)16232fe07f8SJohn Marino c_delbefore(EditLine *el, int num)
16332fe07f8SJohn Marino {
16432fe07f8SJohn Marino 
16532fe07f8SJohn Marino 	if (el->el_line.cursor - num < el->el_line.buffer)
16632fe07f8SJohn Marino 		num = (int)(el->el_line.cursor - el->el_line.buffer);
16732fe07f8SJohn Marino 
16832fe07f8SJohn Marino 	if (el->el_map.current != el->el_map.emacs) {
16932fe07f8SJohn Marino 		cv_undo(el);
17032fe07f8SJohn Marino 		cv_yank(el, el->el_line.cursor - num, num);
17132fe07f8SJohn Marino 	}
17232fe07f8SJohn Marino 
17332fe07f8SJohn Marino 	if (num > 0) {
17412db70c8Szrj 		wchar_t *cp;
17532fe07f8SJohn Marino 
17632fe07f8SJohn Marino 		for (cp = el->el_line.cursor - num;
17760ecde0cSDaniel Fojt 		    &cp[num] <= el->el_line.lastchar;
17832fe07f8SJohn Marino 		    cp++)
17932fe07f8SJohn Marino 			*cp = cp[num];
18032fe07f8SJohn Marino 
18132fe07f8SJohn Marino 		el->el_line.lastchar -= num;
18232fe07f8SJohn Marino 	}
18332fe07f8SJohn Marino }
18432fe07f8SJohn Marino 
18532fe07f8SJohn Marino 
18632fe07f8SJohn Marino /* c_delbefore1():
18732fe07f8SJohn Marino  *	Delete the character before the cursor, do not yank
18832fe07f8SJohn Marino  */
18912db70c8Szrj libedit_private void
c_delbefore1(EditLine * el)19032fe07f8SJohn Marino c_delbefore1(EditLine *el)
19132fe07f8SJohn Marino {
19212db70c8Szrj 	wchar_t *cp;
19332fe07f8SJohn Marino 
19432fe07f8SJohn Marino 	for (cp = el->el_line.cursor - 1; cp <= el->el_line.lastchar; cp++)
19532fe07f8SJohn Marino 		*cp = cp[1];
19632fe07f8SJohn Marino 
19732fe07f8SJohn Marino 	el->el_line.lastchar--;
19832fe07f8SJohn Marino }
19932fe07f8SJohn Marino 
20032fe07f8SJohn Marino 
20132fe07f8SJohn Marino /* ce__isword():
20232fe07f8SJohn Marino  *	Return if p is part of a word according to emacs
20332fe07f8SJohn Marino  */
20412db70c8Szrj libedit_private int
ce__isword(wint_t p)20512db70c8Szrj ce__isword(wint_t p)
20632fe07f8SJohn Marino {
20712db70c8Szrj 	return iswalnum(p) || wcschr(L"*?_-.[]~=", p) != NULL;
20832fe07f8SJohn Marino }
20932fe07f8SJohn Marino 
21032fe07f8SJohn Marino 
21132fe07f8SJohn Marino /* cv__isword():
21232fe07f8SJohn Marino  *	Return if p is part of a word according to vi
21332fe07f8SJohn Marino  */
21412db70c8Szrj libedit_private int
cv__isword(wint_t p)21512db70c8Szrj cv__isword(wint_t p)
21632fe07f8SJohn Marino {
21712db70c8Szrj 	if (iswalnum(p) || p == L'_')
21832fe07f8SJohn Marino 		return 1;
21912db70c8Szrj 	if (iswgraph(p))
22032fe07f8SJohn Marino 		return 2;
22132fe07f8SJohn Marino 	return 0;
22232fe07f8SJohn Marino }
22332fe07f8SJohn Marino 
22432fe07f8SJohn Marino 
22532fe07f8SJohn Marino /* cv__isWord():
22632fe07f8SJohn Marino  *	Return if p is part of a big word according to vi
22732fe07f8SJohn Marino  */
22812db70c8Szrj libedit_private int
cv__isWord(wint_t p)22912db70c8Szrj cv__isWord(wint_t p)
23032fe07f8SJohn Marino {
23112db70c8Szrj 	return !iswspace(p);
23232fe07f8SJohn Marino }
23332fe07f8SJohn Marino 
23432fe07f8SJohn Marino 
23532fe07f8SJohn Marino /* c__prev_word():
23632fe07f8SJohn Marino  *	Find the previous word
23732fe07f8SJohn Marino  */
23812db70c8Szrj libedit_private wchar_t *
c__prev_word(wchar_t * p,wchar_t * low,int n,int (* wtest)(wint_t))23912db70c8Szrj c__prev_word(wchar_t *p, wchar_t *low, int n, int (*wtest)(wint_t))
24032fe07f8SJohn Marino {
24132fe07f8SJohn Marino 	p--;
24232fe07f8SJohn Marino 
24332fe07f8SJohn Marino 	while (n--) {
24432fe07f8SJohn Marino 		while ((p >= low) && !(*wtest)(*p))
24532fe07f8SJohn Marino 			p--;
24632fe07f8SJohn Marino 		while ((p >= low) && (*wtest)(*p))
24732fe07f8SJohn Marino 			p--;
24832fe07f8SJohn Marino 	}
24932fe07f8SJohn Marino 
25032fe07f8SJohn Marino 	/* cp now points to one character before the word */
25132fe07f8SJohn Marino 	p++;
25232fe07f8SJohn Marino 	if (p < low)
25332fe07f8SJohn Marino 		p = low;
25432fe07f8SJohn Marino 	/* cp now points where we want it */
25532fe07f8SJohn Marino 	return p;
25632fe07f8SJohn Marino }
25732fe07f8SJohn Marino 
25832fe07f8SJohn Marino 
25932fe07f8SJohn Marino /* c__next_word():
26032fe07f8SJohn Marino  *	Find the next word
26132fe07f8SJohn Marino  */
26212db70c8Szrj libedit_private wchar_t *
c__next_word(wchar_t * p,wchar_t * high,int n,int (* wtest)(wint_t))26312db70c8Szrj c__next_word(wchar_t *p, wchar_t *high, int n, int (*wtest)(wint_t))
26432fe07f8SJohn Marino {
26532fe07f8SJohn Marino 	while (n--) {
26632fe07f8SJohn Marino 		while ((p < high) && !(*wtest)(*p))
26732fe07f8SJohn Marino 			p++;
26832fe07f8SJohn Marino 		while ((p < high) && (*wtest)(*p))
26932fe07f8SJohn Marino 			p++;
27032fe07f8SJohn Marino 	}
27132fe07f8SJohn Marino 	if (p > high)
27232fe07f8SJohn Marino 		p = high;
27332fe07f8SJohn Marino 	/* p now points where we want it */
27432fe07f8SJohn Marino 	return p;
27532fe07f8SJohn Marino }
27632fe07f8SJohn Marino 
27732fe07f8SJohn Marino /* cv_next_word():
27832fe07f8SJohn Marino  *	Find the next word vi style
27932fe07f8SJohn Marino  */
28012db70c8Szrj libedit_private wchar_t *
cv_next_word(EditLine * el,wchar_t * p,wchar_t * high,int n,int (* wtest)(wint_t))28112db70c8Szrj cv_next_word(EditLine *el, wchar_t *p, wchar_t *high, int n,
28212db70c8Szrj     int (*wtest)(wint_t))
28332fe07f8SJohn Marino {
28432fe07f8SJohn Marino 	int test;
28532fe07f8SJohn Marino 
28632fe07f8SJohn Marino 	while (n--) {
28732fe07f8SJohn Marino 		test = (*wtest)(*p);
28832fe07f8SJohn Marino 		while ((p < high) && (*wtest)(*p) == test)
28932fe07f8SJohn Marino 			p++;
29032fe07f8SJohn Marino 		/*
29132fe07f8SJohn Marino 		 * vi historically deletes with cw only the word preserving the
29232fe07f8SJohn Marino 		 * trailing whitespace! This is not what 'w' does..
29332fe07f8SJohn Marino 		 */
29432fe07f8SJohn Marino 		if (n || el->el_chared.c_vcmd.action != (DELETE|INSERT))
29512db70c8Szrj 			while ((p < high) && iswspace(*p))
29632fe07f8SJohn Marino 				p++;
29732fe07f8SJohn Marino 	}
29832fe07f8SJohn Marino 
29932fe07f8SJohn Marino 	/* p now points where we want it */
30032fe07f8SJohn Marino 	if (p > high)
30132fe07f8SJohn Marino 		return high;
30232fe07f8SJohn Marino 	else
30332fe07f8SJohn Marino 		return p;
30432fe07f8SJohn Marino }
30532fe07f8SJohn Marino 
30632fe07f8SJohn Marino 
30732fe07f8SJohn Marino /* cv_prev_word():
30832fe07f8SJohn Marino  *	Find the previous word vi style
30932fe07f8SJohn Marino  */
31012db70c8Szrj libedit_private wchar_t *
cv_prev_word(wchar_t * p,wchar_t * low,int n,int (* wtest)(wint_t))31112db70c8Szrj cv_prev_word(wchar_t *p, wchar_t *low, int n, int (*wtest)(wint_t))
31232fe07f8SJohn Marino {
31332fe07f8SJohn Marino 	int test;
31432fe07f8SJohn Marino 
31532fe07f8SJohn Marino 	p--;
31632fe07f8SJohn Marino 	while (n--) {
31712db70c8Szrj 		while ((p > low) && iswspace(*p))
31832fe07f8SJohn Marino 			p--;
31932fe07f8SJohn Marino 		test = (*wtest)(*p);
32032fe07f8SJohn Marino 		while ((p >= low) && (*wtest)(*p) == test)
32132fe07f8SJohn Marino 			p--;
32232fe07f8SJohn Marino 	}
32332fe07f8SJohn Marino 	p++;
32432fe07f8SJohn Marino 
32532fe07f8SJohn Marino 	/* p now points where we want it */
32632fe07f8SJohn Marino 	if (p < low)
32732fe07f8SJohn Marino 		return low;
32832fe07f8SJohn Marino 	else
32932fe07f8SJohn Marino 		return p;
33032fe07f8SJohn Marino }
33132fe07f8SJohn Marino 
33232fe07f8SJohn Marino 
33332fe07f8SJohn Marino /* cv_delfini():
33432fe07f8SJohn Marino  *	Finish vi delete action
33532fe07f8SJohn Marino  */
33612db70c8Szrj libedit_private void
cv_delfini(EditLine * el)33732fe07f8SJohn Marino cv_delfini(EditLine *el)
33832fe07f8SJohn Marino {
33932fe07f8SJohn Marino 	int size;
34032fe07f8SJohn Marino 	int action = el->el_chared.c_vcmd.action;
34132fe07f8SJohn Marino 
34232fe07f8SJohn Marino 	if (action & INSERT)
34332fe07f8SJohn Marino 		el->el_map.current = el->el_map.key;
34432fe07f8SJohn Marino 
34532fe07f8SJohn Marino 	if (el->el_chared.c_vcmd.pos == 0)
34632fe07f8SJohn Marino 		/* sanity */
34732fe07f8SJohn Marino 		return;
34832fe07f8SJohn Marino 
34932fe07f8SJohn Marino 	size = (int)(el->el_line.cursor - el->el_chared.c_vcmd.pos);
35032fe07f8SJohn Marino 	if (size == 0)
35132fe07f8SJohn Marino 		size = 1;
35232fe07f8SJohn Marino 	el->el_line.cursor = el->el_chared.c_vcmd.pos;
35332fe07f8SJohn Marino 	if (action & YANK) {
35432fe07f8SJohn Marino 		if (size > 0)
35532fe07f8SJohn Marino 			cv_yank(el, el->el_line.cursor, size);
35632fe07f8SJohn Marino 		else
35732fe07f8SJohn Marino 			cv_yank(el, el->el_line.cursor + size, -size);
35832fe07f8SJohn Marino 	} else {
35932fe07f8SJohn Marino 		if (size > 0) {
36032fe07f8SJohn Marino 			c_delafter(el, size);
36132fe07f8SJohn Marino 			re_refresh_cursor(el);
36232fe07f8SJohn Marino 		} else  {
36332fe07f8SJohn Marino 			c_delbefore(el, -size);
36432fe07f8SJohn Marino 			el->el_line.cursor += size;
36532fe07f8SJohn Marino 		}
36632fe07f8SJohn Marino 	}
36732fe07f8SJohn Marino 	el->el_chared.c_vcmd.action = NOP;
36832fe07f8SJohn Marino }
36932fe07f8SJohn Marino 
37032fe07f8SJohn Marino 
37132fe07f8SJohn Marino /* cv__endword():
37232fe07f8SJohn Marino  *	Go to the end of this word according to vi
37332fe07f8SJohn Marino  */
37412db70c8Szrj libedit_private wchar_t *
cv__endword(wchar_t * p,wchar_t * high,int n,int (* wtest)(wint_t))37512db70c8Szrj cv__endword(wchar_t *p, wchar_t *high, int n, int (*wtest)(wint_t))
37632fe07f8SJohn Marino {
37732fe07f8SJohn Marino 	int test;
37832fe07f8SJohn Marino 
37932fe07f8SJohn Marino 	p++;
38032fe07f8SJohn Marino 
38132fe07f8SJohn Marino 	while (n--) {
38212db70c8Szrj 		while ((p < high) && iswspace(*p))
38332fe07f8SJohn Marino 			p++;
38432fe07f8SJohn Marino 
38532fe07f8SJohn Marino 		test = (*wtest)(*p);
38632fe07f8SJohn Marino 		while ((p < high) && (*wtest)(*p) == test)
38732fe07f8SJohn Marino 			p++;
38832fe07f8SJohn Marino 	}
38932fe07f8SJohn Marino 	p--;
39032fe07f8SJohn Marino 	return p;
39132fe07f8SJohn Marino }
39232fe07f8SJohn Marino 
39332fe07f8SJohn Marino /* ch_init():
39432fe07f8SJohn Marino  *	Initialize the character editor
39532fe07f8SJohn Marino  */
39612db70c8Szrj libedit_private int
ch_init(EditLine * el)39732fe07f8SJohn Marino ch_init(EditLine *el)
39832fe07f8SJohn Marino {
39960ecde0cSDaniel Fojt 	el->el_line.buffer		= el_calloc(EL_BUFSIZ,
40032fe07f8SJohn Marino 	    sizeof(*el->el_line.buffer));
40132fe07f8SJohn Marino 	if (el->el_line.buffer == NULL)
40232fe07f8SJohn Marino 		return -1;
40332fe07f8SJohn Marino 
40432fe07f8SJohn Marino 	el->el_line.cursor		= el->el_line.buffer;
40532fe07f8SJohn Marino 	el->el_line.lastchar		= el->el_line.buffer;
40632fe07f8SJohn Marino 	el->el_line.limit		= &el->el_line.buffer[EL_BUFSIZ - EL_LEAVE];
40732fe07f8SJohn Marino 
40860ecde0cSDaniel Fojt 	el->el_chared.c_undo.buf	= el_calloc(EL_BUFSIZ,
40932fe07f8SJohn Marino 	    sizeof(*el->el_chared.c_undo.buf));
41032fe07f8SJohn Marino 	if (el->el_chared.c_undo.buf == NULL)
41132fe07f8SJohn Marino 		return -1;
41232fe07f8SJohn Marino 	el->el_chared.c_undo.len	= -1;
41332fe07f8SJohn Marino 	el->el_chared.c_undo.cursor	= 0;
41460ecde0cSDaniel Fojt 	el->el_chared.c_redo.buf	= el_calloc(EL_BUFSIZ,
41532fe07f8SJohn Marino 	    sizeof(*el->el_chared.c_redo.buf));
41632fe07f8SJohn Marino 	if (el->el_chared.c_redo.buf == NULL)
41732fe07f8SJohn Marino 		return -1;
41832fe07f8SJohn Marino 	el->el_chared.c_redo.pos	= el->el_chared.c_redo.buf;
41932fe07f8SJohn Marino 	el->el_chared.c_redo.lim	= el->el_chared.c_redo.buf + EL_BUFSIZ;
42032fe07f8SJohn Marino 	el->el_chared.c_redo.cmd	= ED_UNASSIGNED;
42132fe07f8SJohn Marino 
42232fe07f8SJohn Marino 	el->el_chared.c_vcmd.action	= NOP;
42332fe07f8SJohn Marino 	el->el_chared.c_vcmd.pos	= el->el_line.buffer;
42432fe07f8SJohn Marino 
42560ecde0cSDaniel Fojt 	el->el_chared.c_kill.buf	= el_calloc(EL_BUFSIZ,
42632fe07f8SJohn Marino 	    sizeof(*el->el_chared.c_kill.buf));
42732fe07f8SJohn Marino 	if (el->el_chared.c_kill.buf == NULL)
42832fe07f8SJohn Marino 		return -1;
42932fe07f8SJohn Marino 	el->el_chared.c_kill.mark	= el->el_line.buffer;
43032fe07f8SJohn Marino 	el->el_chared.c_kill.last	= el->el_chared.c_kill.buf;
43132fe07f8SJohn Marino 	el->el_chared.c_resizefun	= NULL;
43232fe07f8SJohn Marino 	el->el_chared.c_resizearg	= NULL;
43384b940c1SJohn Marino 	el->el_chared.c_aliasfun	= NULL;
43484b940c1SJohn Marino 	el->el_chared.c_aliasarg	= NULL;
43532fe07f8SJohn Marino 
43632fe07f8SJohn Marino 	el->el_map.current		= el->el_map.key;
43732fe07f8SJohn Marino 
43832fe07f8SJohn Marino 	el->el_state.inputmode		= MODE_INSERT; /* XXX: save a default */
43932fe07f8SJohn Marino 	el->el_state.doingarg		= 0;
44032fe07f8SJohn Marino 	el->el_state.metanext		= 0;
44132fe07f8SJohn Marino 	el->el_state.argument		= 1;
44232fe07f8SJohn Marino 	el->el_state.lastcmd		= ED_UNASSIGNED;
44332fe07f8SJohn Marino 
44432fe07f8SJohn Marino 	return 0;
44532fe07f8SJohn Marino }
44632fe07f8SJohn Marino 
44732fe07f8SJohn Marino /* ch_reset():
44832fe07f8SJohn Marino  *	Reset the character editor
44932fe07f8SJohn Marino  */
45012db70c8Szrj libedit_private void
ch_reset(EditLine * el)45112db70c8Szrj ch_reset(EditLine *el)
45232fe07f8SJohn Marino {
45332fe07f8SJohn Marino 	el->el_line.cursor		= el->el_line.buffer;
45432fe07f8SJohn Marino 	el->el_line.lastchar		= el->el_line.buffer;
45532fe07f8SJohn Marino 
45632fe07f8SJohn Marino 	el->el_chared.c_undo.len	= -1;
45732fe07f8SJohn Marino 	el->el_chared.c_undo.cursor	= 0;
45832fe07f8SJohn Marino 
45932fe07f8SJohn Marino 	el->el_chared.c_vcmd.action	= NOP;
46032fe07f8SJohn Marino 	el->el_chared.c_vcmd.pos	= el->el_line.buffer;
46132fe07f8SJohn Marino 
46232fe07f8SJohn Marino 	el->el_chared.c_kill.mark	= el->el_line.buffer;
46332fe07f8SJohn Marino 
46432fe07f8SJohn Marino 	el->el_map.current		= el->el_map.key;
46532fe07f8SJohn Marino 
46632fe07f8SJohn Marino 	el->el_state.inputmode		= MODE_INSERT; /* XXX: save a default */
46732fe07f8SJohn Marino 	el->el_state.doingarg		= 0;
46832fe07f8SJohn Marino 	el->el_state.metanext		= 0;
46932fe07f8SJohn Marino 	el->el_state.argument		= 1;
47032fe07f8SJohn Marino 	el->el_state.lastcmd		= ED_UNASSIGNED;
47132fe07f8SJohn Marino 
47232fe07f8SJohn Marino 	el->el_history.eventno		= 0;
47332fe07f8SJohn Marino }
47432fe07f8SJohn Marino 
47532fe07f8SJohn Marino /* ch_enlargebufs():
47632fe07f8SJohn Marino  *	Enlarge line buffer to be able to hold twice as much characters.
47732fe07f8SJohn Marino  *	Returns 1 if successful, 0 if not.
47832fe07f8SJohn Marino  */
47912db70c8Szrj libedit_private int
ch_enlargebufs(EditLine * el,size_t addlen)48032fe07f8SJohn Marino ch_enlargebufs(EditLine *el, size_t addlen)
48132fe07f8SJohn Marino {
48232fe07f8SJohn Marino 	size_t sz, newsz;
48312db70c8Szrj 	wchar_t *newbuffer, *oldbuf, *oldkbuf;
48432fe07f8SJohn Marino 
48532fe07f8SJohn Marino 	sz = (size_t)(el->el_line.limit - el->el_line.buffer + EL_LEAVE);
48632fe07f8SJohn Marino 	newsz = sz * 2;
48732fe07f8SJohn Marino 	/*
48832fe07f8SJohn Marino 	 * If newly required length is longer than current buffer, we need
48932fe07f8SJohn Marino 	 * to make the buffer big enough to hold both old and new stuff.
49032fe07f8SJohn Marino 	 */
49132fe07f8SJohn Marino 	if (addlen > sz) {
49232fe07f8SJohn Marino 		while(newsz - sz < addlen)
49332fe07f8SJohn Marino 			newsz *= 2;
49432fe07f8SJohn Marino 	}
49532fe07f8SJohn Marino 
49632fe07f8SJohn Marino 	/*
49732fe07f8SJohn Marino 	 * Reallocate line buffer.
49832fe07f8SJohn Marino 	 */
49932fe07f8SJohn Marino 	newbuffer = el_realloc(el->el_line.buffer, newsz * sizeof(*newbuffer));
50032fe07f8SJohn Marino 	if (!newbuffer)
50132fe07f8SJohn Marino 		return 0;
50232fe07f8SJohn Marino 
50332fe07f8SJohn Marino 	/* zero the newly added memory, leave old data in */
50432fe07f8SJohn Marino 	(void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer));
50532fe07f8SJohn Marino 
50632fe07f8SJohn Marino 	oldbuf = el->el_line.buffer;
50732fe07f8SJohn Marino 
50832fe07f8SJohn Marino 	el->el_line.buffer = newbuffer;
50932fe07f8SJohn Marino 	el->el_line.cursor = newbuffer + (el->el_line.cursor - oldbuf);
51032fe07f8SJohn Marino 	el->el_line.lastchar = newbuffer + (el->el_line.lastchar - oldbuf);
51132fe07f8SJohn Marino 	/* don't set new size until all buffers are enlarged */
51232fe07f8SJohn Marino 	el->el_line.limit  = &newbuffer[sz - EL_LEAVE];
51332fe07f8SJohn Marino 
51432fe07f8SJohn Marino 	/*
51532fe07f8SJohn Marino 	 * Reallocate kill buffer.
51632fe07f8SJohn Marino 	 */
51732fe07f8SJohn Marino 	newbuffer = el_realloc(el->el_chared.c_kill.buf, newsz *
51832fe07f8SJohn Marino 	    sizeof(*newbuffer));
51932fe07f8SJohn Marino 	if (!newbuffer)
52032fe07f8SJohn Marino 		return 0;
52132fe07f8SJohn Marino 
52232fe07f8SJohn Marino 	/* zero the newly added memory, leave old data in */
52332fe07f8SJohn Marino 	(void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer));
52432fe07f8SJohn Marino 
52532fe07f8SJohn Marino 	oldkbuf = el->el_chared.c_kill.buf;
52632fe07f8SJohn Marino 
52732fe07f8SJohn Marino 	el->el_chared.c_kill.buf = newbuffer;
52832fe07f8SJohn Marino 	el->el_chared.c_kill.last = newbuffer +
52932fe07f8SJohn Marino 					(el->el_chared.c_kill.last - oldkbuf);
53032fe07f8SJohn Marino 	el->el_chared.c_kill.mark = el->el_line.buffer +
53132fe07f8SJohn Marino 					(el->el_chared.c_kill.mark - oldbuf);
53232fe07f8SJohn Marino 
53332fe07f8SJohn Marino 	/*
53432fe07f8SJohn Marino 	 * Reallocate undo buffer.
53532fe07f8SJohn Marino 	 */
53632fe07f8SJohn Marino 	newbuffer = el_realloc(el->el_chared.c_undo.buf,
53732fe07f8SJohn Marino 	    newsz * sizeof(*newbuffer));
53832fe07f8SJohn Marino 	if (!newbuffer)
53932fe07f8SJohn Marino 		return 0;
54032fe07f8SJohn Marino 
54132fe07f8SJohn Marino 	/* zero the newly added memory, leave old data in */
54232fe07f8SJohn Marino 	(void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer));
54332fe07f8SJohn Marino 	el->el_chared.c_undo.buf = newbuffer;
54432fe07f8SJohn Marino 
54532fe07f8SJohn Marino 	newbuffer = el_realloc(el->el_chared.c_redo.buf,
54632fe07f8SJohn Marino 	    newsz * sizeof(*newbuffer));
54732fe07f8SJohn Marino 	if (!newbuffer)
54832fe07f8SJohn Marino 		return 0;
54932fe07f8SJohn Marino 	el->el_chared.c_redo.pos = newbuffer +
55032fe07f8SJohn Marino 			(el->el_chared.c_redo.pos - el->el_chared.c_redo.buf);
55132fe07f8SJohn Marino 	el->el_chared.c_redo.lim = newbuffer +
55232fe07f8SJohn Marino 			(el->el_chared.c_redo.lim - el->el_chared.c_redo.buf);
55332fe07f8SJohn Marino 	el->el_chared.c_redo.buf = newbuffer;
55432fe07f8SJohn Marino 
55532fe07f8SJohn Marino 	if (!hist_enlargebuf(el, sz, newsz))
55632fe07f8SJohn Marino 		return 0;
55732fe07f8SJohn Marino 
55832fe07f8SJohn Marino 	/* Safe to set enlarged buffer size */
55932fe07f8SJohn Marino 	el->el_line.limit  = &el->el_line.buffer[newsz - EL_LEAVE];
56032fe07f8SJohn Marino 	if (el->el_chared.c_resizefun)
56132fe07f8SJohn Marino 		(*el->el_chared.c_resizefun)(el, el->el_chared.c_resizearg);
56232fe07f8SJohn Marino 	return 1;
56332fe07f8SJohn Marino }
56432fe07f8SJohn Marino 
56532fe07f8SJohn Marino /* ch_end():
56632fe07f8SJohn Marino  *	Free the data structures used by the editor
56732fe07f8SJohn Marino  */
56812db70c8Szrj libedit_private void
ch_end(EditLine * el)56932fe07f8SJohn Marino ch_end(EditLine *el)
57032fe07f8SJohn Marino {
57132fe07f8SJohn Marino 	el_free(el->el_line.buffer);
57232fe07f8SJohn Marino 	el->el_line.buffer = NULL;
57332fe07f8SJohn Marino 	el->el_line.limit = NULL;
57432fe07f8SJohn Marino 	el_free(el->el_chared.c_undo.buf);
57532fe07f8SJohn Marino 	el->el_chared.c_undo.buf = NULL;
57632fe07f8SJohn Marino 	el_free(el->el_chared.c_redo.buf);
57732fe07f8SJohn Marino 	el->el_chared.c_redo.buf = NULL;
57832fe07f8SJohn Marino 	el->el_chared.c_redo.pos = NULL;
57932fe07f8SJohn Marino 	el->el_chared.c_redo.lim = NULL;
58032fe07f8SJohn Marino 	el->el_chared.c_redo.cmd = ED_UNASSIGNED;
58132fe07f8SJohn Marino 	el_free(el->el_chared.c_kill.buf);
58232fe07f8SJohn Marino 	el->el_chared.c_kill.buf = NULL;
58312db70c8Szrj 	ch_reset(el);
58432fe07f8SJohn Marino }
58532fe07f8SJohn Marino 
58632fe07f8SJohn Marino 
58732fe07f8SJohn Marino /* el_insertstr():
588ae19eda8Szrj  *	Insert string at cursor
58932fe07f8SJohn Marino  */
59012db70c8Szrj int
el_winsertstr(EditLine * el,const wchar_t * s)59112db70c8Szrj el_winsertstr(EditLine *el, const wchar_t *s)
59232fe07f8SJohn Marino {
59332fe07f8SJohn Marino 	size_t len;
59432fe07f8SJohn Marino 
59512db70c8Szrj 	if (s == NULL || (len = wcslen(s)) == 0)
59632fe07f8SJohn Marino 		return -1;
59732fe07f8SJohn Marino 	if (el->el_line.lastchar + len >= el->el_line.limit) {
59832fe07f8SJohn Marino 		if (!ch_enlargebufs(el, len))
59932fe07f8SJohn Marino 			return -1;
60032fe07f8SJohn Marino 	}
60132fe07f8SJohn Marino 
60232fe07f8SJohn Marino 	c_insert(el, (int)len);
60332fe07f8SJohn Marino 	while (*s)
60432fe07f8SJohn Marino 		*el->el_line.cursor++ = *s++;
60532fe07f8SJohn Marino 	return 0;
60632fe07f8SJohn Marino }
60732fe07f8SJohn Marino 
60832fe07f8SJohn Marino 
60932fe07f8SJohn Marino /* el_deletestr():
61032fe07f8SJohn Marino  *	Delete num characters before the cursor
61132fe07f8SJohn Marino  */
61212db70c8Szrj void
el_deletestr(EditLine * el,int n)61332fe07f8SJohn Marino el_deletestr(EditLine *el, int n)
61432fe07f8SJohn Marino {
61532fe07f8SJohn Marino 	if (n <= 0)
61632fe07f8SJohn Marino 		return;
61732fe07f8SJohn Marino 
61832fe07f8SJohn Marino 	if (el->el_line.cursor < &el->el_line.buffer[n])
61932fe07f8SJohn Marino 		return;
62032fe07f8SJohn Marino 
62132fe07f8SJohn Marino 	c_delbefore(el, n);		/* delete before dot */
62232fe07f8SJohn Marino 	el->el_line.cursor -= n;
62332fe07f8SJohn Marino 	if (el->el_line.cursor < el->el_line.buffer)
62432fe07f8SJohn Marino 		el->el_line.cursor = el->el_line.buffer;
62532fe07f8SJohn Marino }
62632fe07f8SJohn Marino 
627*cdf8408cSAntonio Huete Jimenez /* el_deletestr1():
628*cdf8408cSAntonio Huete Jimenez  *	Delete characters between start and end
629*cdf8408cSAntonio Huete Jimenez  */
630*cdf8408cSAntonio Huete Jimenez int
el_deletestr1(EditLine * el,int start,int end)631*cdf8408cSAntonio Huete Jimenez el_deletestr1(EditLine *el, int start, int end)
632*cdf8408cSAntonio Huete Jimenez {
633*cdf8408cSAntonio Huete Jimenez 	size_t line_length, len;
634*cdf8408cSAntonio Huete Jimenez 	wchar_t *p1, *p2;
635*cdf8408cSAntonio Huete Jimenez 
636*cdf8408cSAntonio Huete Jimenez 	if (end <= start)
637*cdf8408cSAntonio Huete Jimenez 		return 0;
638*cdf8408cSAntonio Huete Jimenez 
639*cdf8408cSAntonio Huete Jimenez 	line_length = (size_t)(el->el_line.lastchar - el->el_line.buffer);
640*cdf8408cSAntonio Huete Jimenez 
641*cdf8408cSAntonio Huete Jimenez 	if (start >= (int)line_length || end >= (int)line_length)
642*cdf8408cSAntonio Huete Jimenez 		return 0;
643*cdf8408cSAntonio Huete Jimenez 
644*cdf8408cSAntonio Huete Jimenez 	len = (size_t)(end - start);
645*cdf8408cSAntonio Huete Jimenez 	if (len > line_length - (size_t)end)
646*cdf8408cSAntonio Huete Jimenez 		len = line_length - (size_t)end;
647*cdf8408cSAntonio Huete Jimenez 
648*cdf8408cSAntonio Huete Jimenez 	p1 = el->el_line.buffer + start;
649*cdf8408cSAntonio Huete Jimenez 	p2 = el->el_line.buffer + end;
650*cdf8408cSAntonio Huete Jimenez 	for (size_t i = 0; i < len; i++) {
651*cdf8408cSAntonio Huete Jimenez 		*p1++ = *p2++;
652*cdf8408cSAntonio Huete Jimenez 		el->el_line.lastchar--;
653*cdf8408cSAntonio Huete Jimenez 	}
654*cdf8408cSAntonio Huete Jimenez 
655*cdf8408cSAntonio Huete Jimenez 	if (el->el_line.cursor < el->el_line.buffer)
656*cdf8408cSAntonio Huete Jimenez 		el->el_line.cursor = el->el_line.buffer;
657*cdf8408cSAntonio Huete Jimenez 
658*cdf8408cSAntonio Huete Jimenez 	return end - start;
659*cdf8408cSAntonio Huete Jimenez }
660*cdf8408cSAntonio Huete Jimenez 
661*cdf8408cSAntonio Huete Jimenez /* el_wreplacestr():
662*cdf8408cSAntonio Huete Jimenez  *	Replace the contents of the line with the provided string
663*cdf8408cSAntonio Huete Jimenez  */
664*cdf8408cSAntonio Huete Jimenez int
el_wreplacestr(EditLine * el,const wchar_t * s)665*cdf8408cSAntonio Huete Jimenez el_wreplacestr(EditLine *el, const wchar_t *s)
666*cdf8408cSAntonio Huete Jimenez {
667*cdf8408cSAntonio Huete Jimenez 	size_t len;
668*cdf8408cSAntonio Huete Jimenez 	wchar_t * p;
669*cdf8408cSAntonio Huete Jimenez 
670*cdf8408cSAntonio Huete Jimenez 	if (s == NULL || (len = wcslen(s)) == 0)
671*cdf8408cSAntonio Huete Jimenez 		return -1;
672*cdf8408cSAntonio Huete Jimenez 
673*cdf8408cSAntonio Huete Jimenez 	if (el->el_line.buffer + len >= el->el_line.limit) {
674*cdf8408cSAntonio Huete Jimenez 		if (!ch_enlargebufs(el, len))
675*cdf8408cSAntonio Huete Jimenez 			return -1;
676*cdf8408cSAntonio Huete Jimenez 	}
677*cdf8408cSAntonio Huete Jimenez 
678*cdf8408cSAntonio Huete Jimenez 	p = el->el_line.buffer;
679*cdf8408cSAntonio Huete Jimenez 	for (size_t i = 0; i < len; i++)
680*cdf8408cSAntonio Huete Jimenez 		*p++ = *s++;
681*cdf8408cSAntonio Huete Jimenez 
682*cdf8408cSAntonio Huete Jimenez 	el->el_line.buffer[len] = '\0';
683*cdf8408cSAntonio Huete Jimenez 	el->el_line.lastchar = el->el_line.buffer + len;
684*cdf8408cSAntonio Huete Jimenez 	if (el->el_line.cursor > el->el_line.lastchar)
685*cdf8408cSAntonio Huete Jimenez 		el->el_line.cursor = el->el_line.lastchar;
686*cdf8408cSAntonio Huete Jimenez 
687*cdf8408cSAntonio Huete Jimenez 	return 0;
688*cdf8408cSAntonio Huete Jimenez }
689*cdf8408cSAntonio Huete Jimenez 
69084b940c1SJohn Marino /* el_cursor():
69184b940c1SJohn Marino  *	Move the cursor to the left or the right of the current position
69284b940c1SJohn Marino  */
69312db70c8Szrj int
el_cursor(EditLine * el,int n)69484b940c1SJohn Marino el_cursor(EditLine *el, int n)
69584b940c1SJohn Marino {
69684b940c1SJohn Marino 	if (n == 0)
69784b940c1SJohn Marino 		goto out;
69884b940c1SJohn Marino 
69984b940c1SJohn Marino 	el->el_line.cursor += n;
70084b940c1SJohn Marino 
70184b940c1SJohn Marino 	if (el->el_line.cursor < el->el_line.buffer)
70284b940c1SJohn Marino 		el->el_line.cursor = el->el_line.buffer;
70384b940c1SJohn Marino 	if (el->el_line.cursor > el->el_line.lastchar)
70484b940c1SJohn Marino 		el->el_line.cursor = el->el_line.lastchar;
70584b940c1SJohn Marino out:
70684b940c1SJohn Marino 	return (int)(el->el_line.cursor - el->el_line.buffer);
70784b940c1SJohn Marino }
70884b940c1SJohn Marino 
70932fe07f8SJohn Marino /* c_gets():
71032fe07f8SJohn Marino  *	Get a string
71132fe07f8SJohn Marino  */
71212db70c8Szrj libedit_private int
c_gets(EditLine * el,wchar_t * buf,const wchar_t * prompt)71312db70c8Szrj c_gets(EditLine *el, wchar_t *buf, const wchar_t *prompt)
71432fe07f8SJohn Marino {
71532fe07f8SJohn Marino 	ssize_t len;
71612db70c8Szrj 	wchar_t *cp = el->el_line.buffer, ch;
71732fe07f8SJohn Marino 
71832fe07f8SJohn Marino 	if (prompt) {
71912db70c8Szrj 		len = (ssize_t)wcslen(prompt);
72032fe07f8SJohn Marino 		(void)memcpy(cp, prompt, (size_t)len * sizeof(*cp));
72132fe07f8SJohn Marino 		cp += len;
72232fe07f8SJohn Marino 	}
72332fe07f8SJohn Marino 	len = 0;
72432fe07f8SJohn Marino 
72532fe07f8SJohn Marino 	for (;;) {
72632fe07f8SJohn Marino 		el->el_line.cursor = cp;
72732fe07f8SJohn Marino 		*cp = ' ';
72832fe07f8SJohn Marino 		el->el_line.lastchar = cp + 1;
72932fe07f8SJohn Marino 		re_refresh(el);
73032fe07f8SJohn Marino 
73112db70c8Szrj 		if (el_wgetc(el, &ch) != 1) {
73232fe07f8SJohn Marino 			ed_end_of_file(el, 0);
73332fe07f8SJohn Marino 			len = -1;
73432fe07f8SJohn Marino 			break;
73532fe07f8SJohn Marino 		}
73632fe07f8SJohn Marino 
73732fe07f8SJohn Marino 		switch (ch) {
73832fe07f8SJohn Marino 
73912db70c8Szrj 		case L'\b':	/* Delete and backspace */
74032fe07f8SJohn Marino 		case 0177:
74132fe07f8SJohn Marino 			if (len == 0) {
74232fe07f8SJohn Marino 				len = -1;
74332fe07f8SJohn Marino 				break;
74432fe07f8SJohn Marino 			}
74512db70c8Szrj 			len--;
74632fe07f8SJohn Marino 			cp--;
74732fe07f8SJohn Marino 			continue;
74832fe07f8SJohn Marino 
74932fe07f8SJohn Marino 		case 0033:	/* ESC */
75012db70c8Szrj 		case L'\r':	/* Newline */
75112db70c8Szrj 		case L'\n':
75232fe07f8SJohn Marino 			buf[len] = ch;
75332fe07f8SJohn Marino 			break;
75432fe07f8SJohn Marino 
75532fe07f8SJohn Marino 		default:
75632fe07f8SJohn Marino 			if (len >= (ssize_t)(EL_BUFSIZ - 16))
75732fe07f8SJohn Marino 				terminal_beep(el);
75832fe07f8SJohn Marino 			else {
75932fe07f8SJohn Marino 				buf[len++] = ch;
76032fe07f8SJohn Marino 				*cp++ = ch;
76132fe07f8SJohn Marino 			}
76232fe07f8SJohn Marino 			continue;
76332fe07f8SJohn Marino 		}
76432fe07f8SJohn Marino 		break;
76532fe07f8SJohn Marino 	}
76632fe07f8SJohn Marino 
76732fe07f8SJohn Marino 	el->el_line.buffer[0] = '\0';
76832fe07f8SJohn Marino 	el->el_line.lastchar = el->el_line.buffer;
76932fe07f8SJohn Marino 	el->el_line.cursor = el->el_line.buffer;
77032fe07f8SJohn Marino 	return (int)len;
77132fe07f8SJohn Marino }
77232fe07f8SJohn Marino 
77332fe07f8SJohn Marino 
77432fe07f8SJohn Marino /* c_hpos():
77532fe07f8SJohn Marino  *	Return the current horizontal position of the cursor
77632fe07f8SJohn Marino  */
77712db70c8Szrj libedit_private int
c_hpos(EditLine * el)77832fe07f8SJohn Marino c_hpos(EditLine *el)
77932fe07f8SJohn Marino {
78012db70c8Szrj 	wchar_t *ptr;
78132fe07f8SJohn Marino 
78232fe07f8SJohn Marino 	/*
78332fe07f8SJohn Marino 	 * Find how many characters till the beginning of this line.
78432fe07f8SJohn Marino 	 */
78532fe07f8SJohn Marino 	if (el->el_line.cursor == el->el_line.buffer)
78632fe07f8SJohn Marino 		return 0;
78732fe07f8SJohn Marino 	else {
78832fe07f8SJohn Marino 		for (ptr = el->el_line.cursor - 1;
78932fe07f8SJohn Marino 		     ptr >= el->el_line.buffer && *ptr != '\n';
79032fe07f8SJohn Marino 		     ptr--)
79132fe07f8SJohn Marino 			continue;
79232fe07f8SJohn Marino 		return (int)(el->el_line.cursor - ptr - 1);
79332fe07f8SJohn Marino 	}
79432fe07f8SJohn Marino }
79532fe07f8SJohn Marino 
79612db70c8Szrj libedit_private int
ch_resizefun(EditLine * el,el_zfunc_t f,void * a)79732fe07f8SJohn Marino ch_resizefun(EditLine *el, el_zfunc_t f, void *a)
79832fe07f8SJohn Marino {
79932fe07f8SJohn Marino 	el->el_chared.c_resizefun = f;
80032fe07f8SJohn Marino 	el->el_chared.c_resizearg = a;
80132fe07f8SJohn Marino 	return 0;
80232fe07f8SJohn Marino }
80384b940c1SJohn Marino 
80412db70c8Szrj libedit_private int
ch_aliasfun(EditLine * el,el_afunc_t f,void * a)80584b940c1SJohn Marino ch_aliasfun(EditLine *el, el_afunc_t f, void *a)
80684b940c1SJohn Marino {
80784b940c1SJohn Marino 	el->el_chared.c_aliasfun = f;
80884b940c1SJohn Marino 	el->el_chared.c_aliasarg = a;
80984b940c1SJohn Marino 	return 0;
81084b940c1SJohn Marino }
811