11573Srgrimes/*-
21573Srgrimes * Copyright (c) 1992, 1993
31573Srgrimes *	The Regents of the University of California.  All rights reserved.
41573Srgrimes *
51573Srgrimes * This code is derived from software contributed to Berkeley by
61573Srgrimes * Christos Zoulas of Cornell University.
71573Srgrimes *
81573Srgrimes * Redistribution and use in source and binary forms, with or without
91573Srgrimes * modification, are permitted provided that the following conditions
101573Srgrimes * are met:
111573Srgrimes * 1. Redistributions of source code must retain the above copyright
121573Srgrimes *    notice, this list of conditions and the following disclaimer.
131573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
141573Srgrimes *    notice, this list of conditions and the following disclaimer in the
151573Srgrimes *    documentation and/or other materials provided with the distribution.
16148834Sstefanf * 3. Neither the name of the University nor the names of its contributors
171573Srgrimes *    may be used to endorse or promote products derived from this software
181573Srgrimes *    without specific prior written permission.
191573Srgrimes *
201573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
211573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
221573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
231573Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
241573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
251573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
261573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
271573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
281573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
291573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
301573Srgrimes * SUCH DAMAGE.
3184260Sobrien *
32238178Spfg *	$NetBSD: chared.c,v 1.27 2009/02/15 21:55:23 christos Exp $
331573Srgrimes */
341573Srgrimes
351573Srgrimes#if !defined(lint) && !defined(SCCSID)
361573Srgrimesstatic char sccsid[] = "@(#)chared.c	8.1 (Berkeley) 6/4/93";
371573Srgrimes#endif /* not lint && not SCCSID */
3884260Sobrien#include <sys/cdefs.h>
3984260Sobrien__FBSDID("$FreeBSD$");
401573Srgrimes
418870Srgrimes/*
421573Srgrimes * chared.c: Character editor utilities
431573Srgrimes */
441573Srgrimes#include "sys.h"
451573Srgrimes
461573Srgrimes#include <stdlib.h>
471573Srgrimes#include "el.h"
481573Srgrimes
49148834Sstefanfprivate void ch__clearmacro(EditLine *);
50148834Sstefanf
5184260Sobrien/* value to leave unused in line buffer */
5284260Sobrien#define	EL_LEAVE	2
5384260Sobrien
541573Srgrimes/* cv_undo():
551573Srgrimes *	Handle state for the vi undo command
561573Srgrimes */
571573Srgrimesprotected void
58148834Sstefanfcv_undo(EditLine *el)
591573Srgrimes{
6084260Sobrien	c_undo_t *vu = &el->el_chared.c_undo;
61148834Sstefanf	c_redo_t *r = &el->el_chared.c_redo;
62238178Spfg	size_t size;
63148834Sstefanf
64148834Sstefanf	/* Save entire line for undo */
65148834Sstefanf	size = el->el_line.lastchar - el->el_line.buffer;
66148834Sstefanf	vu->len = size;
67238178Spfg	vu->cursor = (int)(el->el_line.cursor - el->el_line.buffer);
68148834Sstefanf	memcpy(vu->buf, el->el_line.buffer, size);
69148834Sstefanf
70148834Sstefanf	/* save command info for redo */
71148834Sstefanf	r->count = el->el_state.doingarg ? el->el_state.argument : 0;
72148834Sstefanf	r->action = el->el_chared.c_vcmd.action;
73148834Sstefanf	r->pos = r->buf;
74148834Sstefanf	r->cmd = el->el_state.thiscmd;
75148834Sstefanf	r->ch = el->el_state.thisch;
761573Srgrimes}
771573Srgrimes
78148834Sstefanf/* cv_yank():
79148834Sstefanf *	Save yank/delete data for paste
80148834Sstefanf */
81148834Sstefanfprotected void
82148834Sstefanfcv_yank(EditLine *el, const char *ptr, int size)
83148834Sstefanf{
84148834Sstefanf	c_kill_t *k = &el->el_chared.c_kill;
851573Srgrimes
86238178Spfg	memcpy(k->buf, ptr, (size_t)size);
87148834Sstefanf	k->last = k->buf + size;
88148834Sstefanf}
89148834Sstefanf
90148834Sstefanf
918870Srgrimes/* c_insert():
921573Srgrimes *	Insert num characters
931573Srgrimes */
941573Srgrimesprotected void
9584260Sobrienc_insert(EditLine *el, int num)
961573Srgrimes{
9784260Sobrien	char *cp;
981573Srgrimes
99148834Sstefanf	if (el->el_line.lastchar + num >= el->el_line.limit) {
100238178Spfg		if (!ch_enlargebufs(el, (size_t)num))
101148834Sstefanf			return;		/* can't go past end of buffer */
102148834Sstefanf	}
1031573Srgrimes
10484260Sobrien	if (el->el_line.cursor < el->el_line.lastchar) {
10584260Sobrien		/* if I must move chars */
10684260Sobrien		for (cp = el->el_line.lastchar; cp >= el->el_line.cursor; cp--)
10784260Sobrien			cp[num] = *cp;
10884260Sobrien	}
10984260Sobrien	el->el_line.lastchar += num;
11084260Sobrien}
1111573Srgrimes
1121573Srgrimes
1131573Srgrimes/* c_delafter():
1141573Srgrimes *	Delete num characters after the cursor
1151573Srgrimes */
1161573Srgrimesprotected void
11784260Sobrienc_delafter(EditLine *el, int num)
1181573Srgrimes{
1191573Srgrimes
12084260Sobrien	if (el->el_line.cursor + num > el->el_line.lastchar)
121238178Spfg		num = (int)(el->el_line.lastchar - el->el_line.cursor);
1221573Srgrimes
123148834Sstefanf	if (el->el_map.current != el->el_map.emacs) {
124148834Sstefanf		cv_undo(el);
125148834Sstefanf		cv_yank(el, el->el_line.cursor, num);
126148834Sstefanf	}
127148834Sstefanf
12884260Sobrien	if (num > 0) {
12984260Sobrien		char *cp;
1301573Srgrimes
13184260Sobrien		for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++)
13284260Sobrien			*cp = cp[num];
1331573Srgrimes
13484260Sobrien		el->el_line.lastchar -= num;
13584260Sobrien	}
1361573Srgrimes}
1371573Srgrimes
1381573Srgrimes
139148834Sstefanf/* c_delafter1():
140148834Sstefanf *	Delete the character after the cursor, do not yank
141148834Sstefanf */
142148834Sstefanfprotected void
143148834Sstefanfc_delafter1(EditLine *el)
144148834Sstefanf{
145148834Sstefanf	char *cp;
146148834Sstefanf
147148834Sstefanf	for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++)
148148834Sstefanf		*cp = cp[1];
149148834Sstefanf
150148834Sstefanf	el->el_line.lastchar--;
151148834Sstefanf}
152148834Sstefanf
153148834Sstefanf
1541573Srgrimes/* c_delbefore():
1551573Srgrimes *	Delete num characters before the cursor
1561573Srgrimes */
1571573Srgrimesprotected void
15884260Sobrienc_delbefore(EditLine *el, int num)
1591573Srgrimes{
1601573Srgrimes
16184260Sobrien	if (el->el_line.cursor - num < el->el_line.buffer)
162238178Spfg		num = (int)(el->el_line.cursor - el->el_line.buffer);
1631573Srgrimes
164148834Sstefanf	if (el->el_map.current != el->el_map.emacs) {
165148834Sstefanf		cv_undo(el);
166148834Sstefanf		cv_yank(el, el->el_line.cursor - num, num);
167148834Sstefanf	}
168148834Sstefanf
16984260Sobrien	if (num > 0) {
17084260Sobrien		char *cp;
1711573Srgrimes
17284260Sobrien		for (cp = el->el_line.cursor - num;
17384260Sobrien		    cp <= el->el_line.lastchar;
17484260Sobrien		    cp++)
17584260Sobrien			*cp = cp[num];
1761573Srgrimes
17784260Sobrien		el->el_line.lastchar -= num;
17884260Sobrien	}
1791573Srgrimes}
1801573Srgrimes
1811573Srgrimes
182148834Sstefanf/* c_delbefore1():
183148834Sstefanf *	Delete the character before the cursor, do not yank
184148834Sstefanf */
185148834Sstefanfprotected void
186148834Sstefanfc_delbefore1(EditLine *el)
187148834Sstefanf{
188148834Sstefanf	char *cp;
189148834Sstefanf
190148834Sstefanf	for (cp = el->el_line.cursor - 1; cp <= el->el_line.lastchar; cp++)
191148834Sstefanf		*cp = cp[1];
192148834Sstefanf
193148834Sstefanf	el->el_line.lastchar--;
194148834Sstefanf}
195148834Sstefanf
196148834Sstefanf
1971573Srgrimes/* ce__isword():
1981573Srgrimes *	Return if p is part of a word according to emacs
1991573Srgrimes */
2001573Srgrimesprotected int
20184260Sobrience__isword(int p)
2021573Srgrimes{
203148834Sstefanf	return (isalnum(p) || strchr("*?_-.[]~=", p) != NULL);
2041573Srgrimes}
2051573Srgrimes
2061573Srgrimes
2071573Srgrimes/* cv__isword():
208148834Sstefanf *	Return if p is part of a word according to vi
2091573Srgrimes */
2101573Srgrimesprotected int
21184260Sobriencv__isword(int p)
2121573Srgrimes{
213148834Sstefanf	if (isalnum(p) || p == '_')
214148834Sstefanf		return 1;
215148834Sstefanf	if (isgraph(p))
216148834Sstefanf		return 2;
217148834Sstefanf	return 0;
21837199Sbrian}
21937199Sbrian
22037199Sbrian
221148834Sstefanf/* cv__isWord():
222148834Sstefanf *	Return if p is part of a big word according to vi
22337199Sbrian */
22437199Sbrianprotected int
225148834Sstefanfcv__isWord(int p)
22637199Sbrian{
227148834Sstefanf	return (!isspace(p));
2281573Srgrimes}
2291573Srgrimes
2301573Srgrimes
2311573Srgrimes/* c__prev_word():
2321573Srgrimes *	Find the previous word
2331573Srgrimes */
2341573Srgrimesprotected char *
23584260Sobrienc__prev_word(char *p, char *low, int n, int (*wtest)(int))
2361573Srgrimes{
23784260Sobrien	p--;
2381573Srgrimes
23984260Sobrien	while (n--) {
24084260Sobrien		while ((p >= low) && !(*wtest)((unsigned char) *p))
24184260Sobrien			p--;
24284260Sobrien		while ((p >= low) && (*wtest)((unsigned char) *p))
24384260Sobrien			p--;
24484260Sobrien	}
2451573Srgrimes
24684260Sobrien	/* cp now points to one character before the word */
24784260Sobrien	p++;
24884260Sobrien	if (p < low)
24984260Sobrien		p = low;
25084260Sobrien	/* cp now points where we want it */
25184260Sobrien	return (p);
2521573Srgrimes}
2531573Srgrimes
2541573Srgrimes
2551573Srgrimes/* c__next_word():
2561573Srgrimes *	Find the next word
2571573Srgrimes */
2581573Srgrimesprotected char *
25984260Sobrienc__next_word(char *p, char *high, int n, int (*wtest)(int))
2601573Srgrimes{
26184260Sobrien	while (n--) {
26284260Sobrien		while ((p < high) && !(*wtest)((unsigned char) *p))
26384260Sobrien			p++;
26484260Sobrien		while ((p < high) && (*wtest)((unsigned char) *p))
26584260Sobrien			p++;
26684260Sobrien	}
26784260Sobrien	if (p > high)
26884260Sobrien		p = high;
26984260Sobrien	/* p now points where we want it */
27084260Sobrien	return (p);
2711573Srgrimes}
2721573Srgrimes
2731573Srgrimes/* cv_next_word():
2741573Srgrimes *	Find the next word vi style
2751573Srgrimes */
2761573Srgrimesprotected char *
27784260Sobriencv_next_word(EditLine *el, char *p, char *high, int n, int (*wtest)(int))
2781573Srgrimes{
27984260Sobrien	int test;
2801573Srgrimes
28184260Sobrien	while (n--) {
28284260Sobrien		test = (*wtest)((unsigned char) *p);
28384260Sobrien		while ((p < high) && (*wtest)((unsigned char) *p) == test)
28484260Sobrien			p++;
28584260Sobrien		/*
28684260Sobrien		 * vi historically deletes with cw only the word preserving the
28784260Sobrien		 * trailing whitespace! This is not what 'w' does..
28884260Sobrien		 */
289148834Sstefanf		if (n || el->el_chared.c_vcmd.action != (DELETE|INSERT))
29084260Sobrien			while ((p < high) && isspace((unsigned char) *p))
29184260Sobrien				p++;
29284260Sobrien	}
2931573Srgrimes
29484260Sobrien	/* p now points where we want it */
29584260Sobrien	if (p > high)
29684260Sobrien		return (high);
29784260Sobrien	else
29884260Sobrien		return (p);
2991573Srgrimes}
3001573Srgrimes
3011573Srgrimes
3021573Srgrimes/* cv_prev_word():
3031573Srgrimes *	Find the previous word vi style
3041573Srgrimes */
3051573Srgrimesprotected char *
306148834Sstefanfcv_prev_word(char *p, char *low, int n, int (*wtest)(int))
3071573Srgrimes{
30884260Sobrien	int test;
3091573Srgrimes
310148834Sstefanf	p--;
31184260Sobrien	while (n--) {
312148834Sstefanf		while ((p > low) && isspace((unsigned char) *p))
313148834Sstefanf			p--;
31484260Sobrien		test = (*wtest)((unsigned char) *p);
31584260Sobrien		while ((p >= low) && (*wtest)((unsigned char) *p) == test)
31684260Sobrien			p--;
31784260Sobrien	}
318148834Sstefanf	p++;
3191573Srgrimes
32084260Sobrien	/* p now points where we want it */
32184260Sobrien	if (p < low)
32284260Sobrien		return (low);
32384260Sobrien	else
32484260Sobrien		return (p);
3251573Srgrimes}
3261573Srgrimes
3271573Srgrimes
3281573Srgrimes#ifdef notdef
3291573Srgrimes/* c__number():
3301573Srgrimes *	Ignore character p points to, return number appearing after that.
3311573Srgrimes * 	A '$' by itself means a big number; "$-" is for negative; '^' means 1.
3321573Srgrimes * 	Return p pointing to last char used.
3331573Srgrimes */
3341573Srgrimesprotected char *
33584260Sobrienc__number(
33684260Sobrien    char *p,	/* character position */
33784260Sobrien    int *num,	/* Return value	*/
33884260Sobrien    int dval)	/* dval is the number to subtract from like $-3 */
3391573Srgrimes{
34084260Sobrien	int i;
34184260Sobrien	int sign = 1;
3421573Srgrimes
34384260Sobrien	if (*++p == '^') {
34484260Sobrien		*num = 1;
34584260Sobrien		return (p);
3461573Srgrimes	}
34784260Sobrien	if (*p == '$') {
34884260Sobrien		if (*++p != '-') {
34984260Sobrien			*num = 0x7fffffff;	/* Handle $ */
35084260Sobrien			return (--p);
35184260Sobrien		}
35284260Sobrien		sign = -1;			/* Handle $- */
35384260Sobrien		++p;
35484260Sobrien	}
35584260Sobrien	for (i = 0; isdigit((unsigned char) *p); i = 10 * i + *p++ - '0')
35684260Sobrien		continue;
35784260Sobrien	*num = (sign < 0 ? dval - i : i);
35884260Sobrien	return (--p);
3591573Srgrimes}
3601573Srgrimes#endif
3611573Srgrimes
3621573Srgrimes/* cv_delfini():
3631573Srgrimes *	Finish vi delete action
3641573Srgrimes */
3651573Srgrimesprotected void
36684260Sobriencv_delfini(EditLine *el)
3671573Srgrimes{
36884260Sobrien	int size;
369148834Sstefanf	int action = el->el_chared.c_vcmd.action;
3701573Srgrimes
371148834Sstefanf	if (action & INSERT)
37284260Sobrien		el->el_map.current = el->el_map.key;
3731573Srgrimes
37484260Sobrien	if (el->el_chared.c_vcmd.pos == 0)
375148834Sstefanf		/* sanity */
37684260Sobrien		return;
3771573Srgrimes
378238178Spfg	size = (int)(el->el_line.cursor - el->el_chared.c_vcmd.pos);
379148834Sstefanf	if (size == 0)
380148834Sstefanf		size = 1;
381148834Sstefanf	el->el_line.cursor = el->el_chared.c_vcmd.pos;
382148834Sstefanf	if (action & YANK) {
383148834Sstefanf		if (size > 0)
384148834Sstefanf			cv_yank(el, el->el_line.cursor, size);
385148834Sstefanf		else
386148834Sstefanf			cv_yank(el, el->el_line.cursor + size, -size);
38784260Sobrien	} else {
388148834Sstefanf		if (size > 0) {
389148834Sstefanf			c_delafter(el, size);
390148834Sstefanf			re_refresh_cursor(el);
391148834Sstefanf		} else  {
392148834Sstefanf			c_delbefore(el, -size);
393148834Sstefanf			el->el_line.cursor += size;
394148834Sstefanf		}
39584260Sobrien	}
396148834Sstefanf	el->el_chared.c_vcmd.action = NOP;
3971573Srgrimes}
3981573Srgrimes
3991573Srgrimes
4001573Srgrimes#ifdef notdef
4011573Srgrimes/* ce__endword():
4021573Srgrimes *	Go to the end of this word according to emacs
4031573Srgrimes */
4041573Srgrimesprotected char *
40584260Sobrience__endword(char *p, char *high, int n)
4061573Srgrimes{
40784260Sobrien	p++;
4081573Srgrimes
40984260Sobrien	while (n--) {
41084260Sobrien		while ((p < high) && isspace((unsigned char) *p))
41184260Sobrien			p++;
41284260Sobrien		while ((p < high) && !isspace((unsigned char) *p))
41384260Sobrien			p++;
41484260Sobrien	}
4151573Srgrimes
41684260Sobrien	p--;
41784260Sobrien	return (p);
4181573Srgrimes}
4191573Srgrimes#endif
4201573Srgrimes
4211573Srgrimes
4221573Srgrimes/* cv__endword():
4231573Srgrimes *	Go to the end of this word according to vi
4241573Srgrimes */
4251573Srgrimesprotected char *
426148834Sstefanfcv__endword(char *p, char *high, int n, int (*wtest)(int))
4271573Srgrimes{
428148834Sstefanf	int test;
429148834Sstefanf
43084260Sobrien	p++;
4311573Srgrimes
43284260Sobrien	while (n--) {
43384260Sobrien		while ((p < high) && isspace((unsigned char) *p))
43484260Sobrien			p++;
4351573Srgrimes
436148834Sstefanf		test = (*wtest)((unsigned char) *p);
437148834Sstefanf		while ((p < high) && (*wtest)((unsigned char) *p) == test)
438148834Sstefanf			p++;
43984260Sobrien	}
44084260Sobrien	p--;
44184260Sobrien	return (p);
4421573Srgrimes}
4431573Srgrimes
4441573Srgrimes/* ch_init():
4451573Srgrimes *	Initialize the character editor
4461573Srgrimes */
4471573Srgrimesprotected int
44884260Sobriench_init(EditLine *el)
4491573Srgrimes{
450148834Sstefanf	c_macro_t *ma = &el->el_chared.c_macro;
451148834Sstefanf
45284260Sobrien	el->el_line.buffer		= (char *) el_malloc(EL_BUFSIZ);
45384260Sobrien	if (el->el_line.buffer == NULL)
45484260Sobrien		return (-1);
4551573Srgrimes
45684260Sobrien	(void) memset(el->el_line.buffer, 0, EL_BUFSIZ);
45784260Sobrien	el->el_line.cursor		= el->el_line.buffer;
45884260Sobrien	el->el_line.lastchar		= el->el_line.buffer;
459148834Sstefanf	el->el_line.limit		= &el->el_line.buffer[EL_BUFSIZ - EL_LEAVE];
4601573Srgrimes
46184260Sobrien	el->el_chared.c_undo.buf	= (char *) el_malloc(EL_BUFSIZ);
46284260Sobrien	if (el->el_chared.c_undo.buf == NULL)
46384260Sobrien		return (-1);
46484260Sobrien	(void) memset(el->el_chared.c_undo.buf, 0, EL_BUFSIZ);
465148834Sstefanf	el->el_chared.c_undo.len	= -1;
466148834Sstefanf	el->el_chared.c_undo.cursor	= 0;
467148834Sstefanf	el->el_chared.c_redo.buf	= (char *) el_malloc(EL_BUFSIZ);
468148834Sstefanf	if (el->el_chared.c_redo.buf == NULL)
469148834Sstefanf		return (-1);
470148834Sstefanf	el->el_chared.c_redo.pos	= el->el_chared.c_redo.buf;
471148834Sstefanf	el->el_chared.c_redo.lim	= el->el_chared.c_redo.buf + EL_BUFSIZ;
472148834Sstefanf	el->el_chared.c_redo.cmd	= ED_UNASSIGNED;
4731573Srgrimes
47484260Sobrien	el->el_chared.c_vcmd.action	= NOP;
47584260Sobrien	el->el_chared.c_vcmd.pos	= el->el_line.buffer;
4761573Srgrimes
47784260Sobrien	el->el_chared.c_kill.buf	= (char *) el_malloc(EL_BUFSIZ);
47884260Sobrien	if (el->el_chared.c_kill.buf == NULL)
47984260Sobrien		return (-1);
48084260Sobrien	(void) memset(el->el_chared.c_kill.buf, 0, EL_BUFSIZ);
48184260Sobrien	el->el_chared.c_kill.mark	= el->el_line.buffer;
48284260Sobrien	el->el_chared.c_kill.last	= el->el_chared.c_kill.buf;
4831573Srgrimes
48484260Sobrien	el->el_map.current		= el->el_map.key;
4851573Srgrimes
48684260Sobrien	el->el_state.inputmode		= MODE_INSERT; /* XXX: save a default */
48784260Sobrien	el->el_state.doingarg		= 0;
48884260Sobrien	el->el_state.metanext		= 0;
48984260Sobrien	el->el_state.argument		= 1;
49084260Sobrien	el->el_state.lastcmd		= ED_UNASSIGNED;
49184260Sobrien
492148834Sstefanf	ma->level	= -1;
493148834Sstefanf	ma->offset	= 0;
494148834Sstefanf	ma->macro	= (char **) el_malloc(EL_MAXMACRO * sizeof(char *));
495148834Sstefanf	if (ma->macro == NULL)
49684260Sobrien		return (-1);
49784260Sobrien	return (0);
4981573Srgrimes}
4991573Srgrimes
5001573Srgrimes/* ch_reset():
5011573Srgrimes *	Reset the character editor
5021573Srgrimes */
5031573Srgrimesprotected void
504148834Sstefanfch_reset(EditLine *el, int mclear)
5051573Srgrimes{
50684260Sobrien	el->el_line.cursor		= el->el_line.buffer;
50784260Sobrien	el->el_line.lastchar		= el->el_line.buffer;
5081573Srgrimes
509148834Sstefanf	el->el_chared.c_undo.len	= -1;
510148834Sstefanf	el->el_chared.c_undo.cursor	= 0;
5111573Srgrimes
51284260Sobrien	el->el_chared.c_vcmd.action	= NOP;
51384260Sobrien	el->el_chared.c_vcmd.pos	= el->el_line.buffer;
5141573Srgrimes
51584260Sobrien	el->el_chared.c_kill.mark	= el->el_line.buffer;
5161573Srgrimes
51784260Sobrien	el->el_map.current		= el->el_map.key;
5181573Srgrimes
51984260Sobrien	el->el_state.inputmode		= MODE_INSERT; /* XXX: save a default */
52084260Sobrien	el->el_state.doingarg		= 0;
52184260Sobrien	el->el_state.metanext		= 0;
52284260Sobrien	el->el_state.argument		= 1;
52384260Sobrien	el->el_state.lastcmd		= ED_UNASSIGNED;
5241573Srgrimes
525148897Sstefanf	el->el_history.eventno		= 0;
526148897Sstefanf
527148834Sstefanf	if (mclear)
528148834Sstefanf		ch__clearmacro(el);
529148834Sstefanf}
5301573Srgrimes
531148834Sstefanfprivate void
532238178Spfgch__clearmacro(EditLine *el)
533148834Sstefanf{
534148834Sstefanf	c_macro_t *ma = &el->el_chared.c_macro;
535148834Sstefanf	while (ma->level >= 0)
536148834Sstefanf		el_free((ptr_t)ma->macro[ma->level--]);
5371573Srgrimes}
5381573Srgrimes
53984260Sobrien/* ch_enlargebufs():
54084260Sobrien *	Enlarge line buffer to be able to hold twice as much characters.
54184260Sobrien *	Returns 1 if successful, 0 if not.
54284260Sobrien */
54384260Sobrienprotected int
544238178Spfgch_enlargebufs(EditLine *el, size_t addlen)
54584260Sobrien{
54684260Sobrien	size_t sz, newsz;
54784260Sobrien	char *newbuffer, *oldbuf, *oldkbuf;
5481573Srgrimes
54984260Sobrien	sz = el->el_line.limit - el->el_line.buffer + EL_LEAVE;
55084260Sobrien	newsz = sz * 2;
55184260Sobrien	/*
55284260Sobrien	 * If newly required length is longer than current buffer, we need
55384260Sobrien	 * to make the buffer big enough to hold both old and new stuff.
55484260Sobrien	 */
55584260Sobrien	if (addlen > sz) {
55684260Sobrien		while(newsz - sz < addlen)
55784260Sobrien			newsz *= 2;
55884260Sobrien	}
55984260Sobrien
56084260Sobrien	/*
56184260Sobrien	 * Reallocate line buffer.
56284260Sobrien	 */
56384260Sobrien	newbuffer = el_realloc(el->el_line.buffer, newsz);
56484260Sobrien	if (!newbuffer)
56584260Sobrien		return 0;
56684260Sobrien
56784260Sobrien	/* zero the newly added memory, leave old data in */
56884260Sobrien	(void) memset(&newbuffer[sz], 0, newsz - sz);
56984260Sobrien
57084260Sobrien	oldbuf = el->el_line.buffer;
57184260Sobrien
57284260Sobrien	el->el_line.buffer = newbuffer;
57384260Sobrien	el->el_line.cursor = newbuffer + (el->el_line.cursor - oldbuf);
57484260Sobrien	el->el_line.lastchar = newbuffer + (el->el_line.lastchar - oldbuf);
575148834Sstefanf	/* don't set new size until all buffers are enlarged */
576148834Sstefanf	el->el_line.limit  = &newbuffer[sz - EL_LEAVE];
57784260Sobrien
57884260Sobrien	/*
57984260Sobrien	 * Reallocate kill buffer.
58084260Sobrien	 */
58184260Sobrien	newbuffer = el_realloc(el->el_chared.c_kill.buf, newsz);
58284260Sobrien	if (!newbuffer)
58384260Sobrien		return 0;
58484260Sobrien
58584260Sobrien	/* zero the newly added memory, leave old data in */
58684260Sobrien	(void) memset(&newbuffer[sz], 0, newsz - sz);
58784260Sobrien
58884260Sobrien	oldkbuf = el->el_chared.c_kill.buf;
58984260Sobrien
59084260Sobrien	el->el_chared.c_kill.buf = newbuffer;
59184260Sobrien	el->el_chared.c_kill.last = newbuffer +
59284260Sobrien					(el->el_chared.c_kill.last - oldkbuf);
59384260Sobrien	el->el_chared.c_kill.mark = el->el_line.buffer +
59484260Sobrien					(el->el_chared.c_kill.mark - oldbuf);
59584260Sobrien
59684260Sobrien	/*
59784260Sobrien	 * Reallocate undo buffer.
59884260Sobrien	 */
59984260Sobrien	newbuffer = el_realloc(el->el_chared.c_undo.buf, newsz);
60084260Sobrien	if (!newbuffer)
60184260Sobrien		return 0;
60284260Sobrien
60384260Sobrien	/* zero the newly added memory, leave old data in */
60484260Sobrien	(void) memset(&newbuffer[sz], 0, newsz - sz);
605148834Sstefanf	el->el_chared.c_undo.buf = newbuffer;
60684260Sobrien
607148834Sstefanf	newbuffer = el_realloc(el->el_chared.c_redo.buf, newsz);
608148834Sstefanf	if (!newbuffer)
609148834Sstefanf		return 0;
610148834Sstefanf	el->el_chared.c_redo.pos = newbuffer +
611148834Sstefanf			(el->el_chared.c_redo.pos - el->el_chared.c_redo.buf);
612148834Sstefanf	el->el_chared.c_redo.lim = newbuffer +
613148834Sstefanf			(el->el_chared.c_redo.lim - el->el_chared.c_redo.buf);
614148834Sstefanf	el->el_chared.c_redo.buf = newbuffer;
61584260Sobrien
61684260Sobrien	if (!hist_enlargebuf(el, sz, newsz))
61784260Sobrien		return 0;
61884260Sobrien
619148834Sstefanf	/* Safe to set enlarged buffer size */
620148834Sstefanf	el->el_line.limit  = &el->el_line.buffer[newsz - EL_LEAVE];
62184260Sobrien	return 1;
62284260Sobrien}
62384260Sobrien
6241573Srgrimes/* ch_end():
6251573Srgrimes *	Free the data structures used by the editor
6261573Srgrimes */
6271573Srgrimesprotected void
62884260Sobriench_end(EditLine *el)
6291573Srgrimes{
63084260Sobrien	el_free((ptr_t) el->el_line.buffer);
63184260Sobrien	el->el_line.buffer = NULL;
63284260Sobrien	el->el_line.limit = NULL;
63384260Sobrien	el_free((ptr_t) el->el_chared.c_undo.buf);
63484260Sobrien	el->el_chared.c_undo.buf = NULL;
635148834Sstefanf	el_free((ptr_t) el->el_chared.c_redo.buf);
636148834Sstefanf	el->el_chared.c_redo.buf = NULL;
637148834Sstefanf	el->el_chared.c_redo.pos = NULL;
638148834Sstefanf	el->el_chared.c_redo.lim = NULL;
639148834Sstefanf	el->el_chared.c_redo.cmd = ED_UNASSIGNED;
64084260Sobrien	el_free((ptr_t) el->el_chared.c_kill.buf);
64184260Sobrien	el->el_chared.c_kill.buf = NULL;
642148834Sstefanf	ch_reset(el, 1);
64384260Sobrien	el_free((ptr_t) el->el_chared.c_macro.macro);
64484260Sobrien	el->el_chared.c_macro.macro = NULL;
6451573Srgrimes}
6461573Srgrimes
6471573Srgrimes
6481573Srgrimes/* el_insertstr():
6491573Srgrimes *	Insert string at cursorI
6501573Srgrimes */
6511573Srgrimespublic int
65284260Sobrienel_insertstr(EditLine *el, const char *s)
6531573Srgrimes{
65484260Sobrien	size_t len;
6551573Srgrimes
65684260Sobrien	if ((len = strlen(s)) == 0)
65784260Sobrien		return (-1);
65884260Sobrien	if (el->el_line.lastchar + len >= el->el_line.limit) {
65984260Sobrien		if (!ch_enlargebufs(el, len))
66084260Sobrien			return (-1);
66184260Sobrien	}
6621573Srgrimes
66384260Sobrien	c_insert(el, (int)len);
66484260Sobrien	while (*s)
66584260Sobrien		*el->el_line.cursor++ = *s++;
66684260Sobrien	return (0);
6671573Srgrimes}
6681573Srgrimes
6691573Srgrimes
6701573Srgrimes/* el_deletestr():
6711573Srgrimes *	Delete num characters before the cursor
6721573Srgrimes */
6731573Srgrimespublic void
67484260Sobrienel_deletestr(EditLine *el, int n)
6751573Srgrimes{
67684260Sobrien	if (n <= 0)
67784260Sobrien		return;
6781573Srgrimes
67984260Sobrien	if (el->el_line.cursor < &el->el_line.buffer[n])
68084260Sobrien		return;
6811573Srgrimes
68284260Sobrien	c_delbefore(el, n);		/* delete before dot */
68384260Sobrien	el->el_line.cursor -= n;
68484260Sobrien	if (el->el_line.cursor < el->el_line.buffer)
68584260Sobrien		el->el_line.cursor = el->el_line.buffer;
6861573Srgrimes}
6871573Srgrimes
6881573Srgrimes/* c_gets():
6891573Srgrimes *	Get a string
6901573Srgrimes */
6911573Srgrimesprotected int
692148834Sstefanfc_gets(EditLine *el, char *buf, const char *prompt)
6931573Srgrimes{
69484260Sobrien	char ch;
695238178Spfg	ssize_t len;
696148834Sstefanf	char *cp = el->el_line.buffer;
6971573Srgrimes
698148834Sstefanf	if (prompt) {
699148834Sstefanf		len = strlen(prompt);
700238178Spfg		memcpy(cp, prompt, (size_t)len);
701148834Sstefanf		cp += len;
702148834Sstefanf	}
703148834Sstefanf	len = 0;
704148834Sstefanf
705148834Sstefanf	for (;;) {
706148834Sstefanf		el->el_line.cursor = cp;
707148834Sstefanf		*cp = ' ';
708148834Sstefanf		el->el_line.lastchar = cp + 1;
709148834Sstefanf		re_refresh(el);
710148834Sstefanf
711148834Sstefanf		if (el_getc(el, &ch) != 1) {
712148834Sstefanf			ed_end_of_file(el, 0);
713148834Sstefanf			len = -1;
714148834Sstefanf			break;
715148834Sstefanf		}
716148834Sstefanf
71784260Sobrien		switch (ch) {
718148834Sstefanf
71984260Sobrien		case '\010':	/* Delete and backspace */
72084260Sobrien		case '\177':
721238178Spfg			if (len == 0) {
722148834Sstefanf				len = -1;
723148834Sstefanf				break;
72484260Sobrien			}
725148834Sstefanf			cp--;
726148834Sstefanf			continue;
7271573Srgrimes
72884260Sobrien		case '\033':	/* ESC */
72984260Sobrien		case '\r':	/* Newline */
73084260Sobrien		case '\n':
731148834Sstefanf			buf[len] = ch;
73284260Sobrien			break;
7331573Srgrimes
73484260Sobrien		default:
735148834Sstefanf			if (len >= EL_BUFSIZ - 16)
73684260Sobrien				term_beep(el);
73784260Sobrien			else {
73884260Sobrien				buf[len++] = ch;
739148834Sstefanf				*cp++ = ch;
74084260Sobrien			}
741148834Sstefanf			continue;
74284260Sobrien		}
743148834Sstefanf		break;
7441573Srgrimes	}
745148834Sstefanf
746148834Sstefanf	el->el_line.buffer[0] = '\0';
747148834Sstefanf	el->el_line.lastchar = el->el_line.buffer;
748148834Sstefanf	el->el_line.cursor = el->el_line.buffer;
749238178Spfg	return (int)len;
7501573Srgrimes}
7511573Srgrimes
7521573Srgrimes
7531573Srgrimes/* c_hpos():
7541573Srgrimes *	Return the current horizontal position of the cursor
7551573Srgrimes */
7561573Srgrimesprotected int
75784260Sobrienc_hpos(EditLine *el)
7581573Srgrimes{
75984260Sobrien	char *ptr;
7601573Srgrimes
76184260Sobrien	/*
76284260Sobrien	 * Find how many characters till the beginning of this line.
76384260Sobrien	 */
76484260Sobrien	if (el->el_line.cursor == el->el_line.buffer)
76584260Sobrien		return (0);
76684260Sobrien	else {
76784260Sobrien		for (ptr = el->el_line.cursor - 1;
76884260Sobrien		     ptr >= el->el_line.buffer && *ptr != '\n';
76984260Sobrien		     ptr--)
77084260Sobrien			continue;
771238178Spfg		return (int)(el->el_line.cursor - ptr - 1);
77284260Sobrien	}
7731573Srgrimes}
774