xref: /openbsd-src/lib/libedit/common.c (revision 5b133f3f277e80f096764111e64f3a1284acb179)
1*5b133f3fSguenther /*	$OpenBSD: common.c,v 1.23 2023/03/08 04:43:05 guenther Exp $	*/
2aed0ee81Snicm /*	$NetBSD: common.c,v 1.24 2009/12/30 22:37:40 christos Exp $	*/
3babb851aSmillert 
4df930be7Sderaadt /*-
5df930be7Sderaadt  * Copyright (c) 1992, 1993
6df930be7Sderaadt  *	The Regents of the University of California.  All rights reserved.
7df930be7Sderaadt  *
8df930be7Sderaadt  * This code is derived from software contributed to Berkeley by
9df930be7Sderaadt  * Christos Zoulas of Cornell University.
10df930be7Sderaadt  *
11df930be7Sderaadt  * Redistribution and use in source and binary forms, with or without
12df930be7Sderaadt  * modification, are permitted provided that the following conditions
13df930be7Sderaadt  * are met:
14df930be7Sderaadt  * 1. Redistributions of source code must retain the above copyright
15df930be7Sderaadt  *    notice, this list of conditions and the following disclaimer.
16df930be7Sderaadt  * 2. Redistributions in binary form must reproduce the above copyright
17df930be7Sderaadt  *    notice, this list of conditions and the following disclaimer in the
18df930be7Sderaadt  *    documentation and/or other materials provided with the distribution.
196580fee3Smillert  * 3. Neither the name of the University nor the names of its contributors
20df930be7Sderaadt  *    may be used to endorse or promote products derived from this software
21df930be7Sderaadt  *    without specific prior written permission.
22df930be7Sderaadt  *
23df930be7Sderaadt  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24df930be7Sderaadt  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25df930be7Sderaadt  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26df930be7Sderaadt  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27df930be7Sderaadt  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28df930be7Sderaadt  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29df930be7Sderaadt  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30df930be7Sderaadt  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31df930be7Sderaadt  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32df930be7Sderaadt  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33df930be7Sderaadt  * SUCH DAMAGE.
34df930be7Sderaadt  */
35df930be7Sderaadt 
36d484b7d0Sotto #include "config.h"
37df930be7Sderaadt 
38df930be7Sderaadt /*
39df930be7Sderaadt  * common.c: Common Editor functions
40df930be7Sderaadt  */
417ccfa089Sschwarze #include <ctype.h>
427ccfa089Sschwarze #include <string.h>
437ccfa089Sschwarze 
44df930be7Sderaadt #include "el.h"
455564fb94Sschwarze #include "common.h"
4613e01c7aSschwarze #include "fcns.h"
475564fb94Sschwarze #include "parse.h"
485564fb94Sschwarze #include "vi.h"
49df930be7Sderaadt 
50df930be7Sderaadt /* ed_end_of_file():
51df930be7Sderaadt  *	Indicate end of file
52df930be7Sderaadt  *	[^D]
53df930be7Sderaadt  */
54df930be7Sderaadt protected el_action_t
ed_end_of_file(EditLine * el,wint_t c)55b2589f0bSschwarze ed_end_of_file(EditLine *el, wint_t c __attribute__((__unused__)))
56df930be7Sderaadt {
57d484b7d0Sotto 
58df930be7Sderaadt 	re_goto_bottom(el);
59df930be7Sderaadt 	*el->el_line.lastchar = '\0';
6028d54ee8Sschwarze 	return CC_EOF;
61df930be7Sderaadt }
62df930be7Sderaadt 
63df930be7Sderaadt 
64df930be7Sderaadt /* ed_insert():
65df930be7Sderaadt  *	Add character to the line
66df930be7Sderaadt  *	Insert a character [bound to all insert keys]
67df930be7Sderaadt  */
68df930be7Sderaadt protected el_action_t
ed_insert(EditLine * el,wint_t c)69b2589f0bSschwarze ed_insert(EditLine *el, wint_t c)
70df930be7Sderaadt {
71d484b7d0Sotto 	int count = el->el_state.argument;
72df930be7Sderaadt 
73df930be7Sderaadt 	if (c == '\0')
7428d54ee8Sschwarze 		return CC_ERROR;
75df930be7Sderaadt 
76df930be7Sderaadt 	if (el->el_line.lastchar + el->el_state.argument >=
77d484b7d0Sotto 	    el->el_line.limit) {
78d484b7d0Sotto 		/* end of buffer space, try to allocate more */
79d484b7d0Sotto 		if (!ch_enlargebufs(el, (size_t) count))
80d484b7d0Sotto 			return CC_ERROR;	/* error allocating more */
81df930be7Sderaadt 	}
82df930be7Sderaadt 
83d484b7d0Sotto 	if (count == 1) {
84d484b7d0Sotto 		if (el->el_state.inputmode == MODE_INSERT
85d484b7d0Sotto 		    || el->el_line.cursor >= el->el_line.lastchar)
86df930be7Sderaadt 			c_insert(el, 1);
87df930be7Sderaadt 
88df930be7Sderaadt 		*el->el_line.cursor++ = c;
89df930be7Sderaadt 		re_fastaddc(el);		/* fast refresh for one char. */
90d484b7d0Sotto 	} else {
91d484b7d0Sotto 		if (el->el_state.inputmode != MODE_REPLACE_1)
92df930be7Sderaadt 			c_insert(el, el->el_state.argument);
93df930be7Sderaadt 
94d484b7d0Sotto 		while (count-- && el->el_line.cursor < el->el_line.lastchar)
95df930be7Sderaadt 			*el->el_line.cursor++ = c;
96df930be7Sderaadt 		re_refresh(el);
97df930be7Sderaadt 	}
98df930be7Sderaadt 
99df930be7Sderaadt 	if (el->el_state.inputmode == MODE_REPLACE_1)
100d484b7d0Sotto 		return vi_command_mode(el, 0);
101df930be7Sderaadt 
10228d54ee8Sschwarze 	return CC_NORM;
103df930be7Sderaadt }
104df930be7Sderaadt 
105df930be7Sderaadt 
106df930be7Sderaadt /* ed_delete_prev_word():
107df930be7Sderaadt  *	Delete from beginning of current word to cursor
108df930be7Sderaadt  *	[M-^?] [^W]
109df930be7Sderaadt  */
110df930be7Sderaadt protected el_action_t
ed_delete_prev_word(EditLine * el,wint_t c)111b2589f0bSschwarze ed_delete_prev_word(EditLine *el, wint_t c __attribute__((__unused__)))
112df930be7Sderaadt {
113e3191321Sschwarze 	wchar_t *cp, *p, *kp;
114df930be7Sderaadt 
115df930be7Sderaadt 	if (el->el_line.cursor == el->el_line.buffer)
11628d54ee8Sschwarze 		return CC_ERROR;
117df930be7Sderaadt 
118df930be7Sderaadt 	cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
119df930be7Sderaadt 	    el->el_state.argument, ce__isword);
120df930be7Sderaadt 
121df930be7Sderaadt 	for (p = cp, kp = el->el_chared.c_kill.buf; p < el->el_line.cursor; p++)
122df930be7Sderaadt 		*kp++ = *p;
123df930be7Sderaadt 	el->el_chared.c_kill.last = kp;
124df930be7Sderaadt 
125aed0ee81Snicm 	c_delbefore(el, (int)(el->el_line.cursor - cp));/* delete before dot */
126df930be7Sderaadt 	el->el_line.cursor = cp;
127df930be7Sderaadt 	if (el->el_line.cursor < el->el_line.buffer)
128df930be7Sderaadt 		el->el_line.cursor = el->el_line.buffer; /* bounds check */
12928d54ee8Sschwarze 	return CC_REFRESH;
130df930be7Sderaadt }
131df930be7Sderaadt 
132df930be7Sderaadt 
133df930be7Sderaadt /* ed_delete_next_char():
134df930be7Sderaadt  *	Delete character under cursor
135df930be7Sderaadt  *	[^D] [x]
136df930be7Sderaadt  */
137df930be7Sderaadt protected el_action_t
ed_delete_next_char(EditLine * el,wint_t c)138b2589f0bSschwarze ed_delete_next_char(EditLine *el, wint_t c)
139df930be7Sderaadt {
140df930be7Sderaadt #ifdef notdef			/* XXX */
141df930be7Sderaadt #define	EL	el->el_line
14230806f50Sschwarze 	(void) fprintf(el->el_errfile,
143565aa7e8Sschwarze 	    "\nD(b: %p(%ls)  c: %p(%ls) last: %p(%ls) limit: %p(%ls)\n",
144d484b7d0Sotto 	    EL.buffer, EL.buffer, EL.cursor, EL.cursor, EL.lastchar,
145d484b7d0Sotto 	    EL.lastchar, EL.limit, EL.limit);
146df930be7Sderaadt #endif
147d484b7d0Sotto 	if (el->el_line.cursor == el->el_line.lastchar) {
148d484b7d0Sotto 			/* if I'm at the end */
149df930be7Sderaadt 		if (el->el_map.type == MAP_VI) {
150df930be7Sderaadt 			if (el->el_line.cursor == el->el_line.buffer) {
151df930be7Sderaadt 				/* if I'm also at the beginning */
152df930be7Sderaadt #ifdef KSHVI
15328d54ee8Sschwarze 				return CC_ERROR;
154df930be7Sderaadt #else
155aed0ee81Snicm 				/* then do an EOF */
156fd40972aSschwarze 				terminal_writec(el, c);
15728d54ee8Sschwarze 				return CC_EOF;
158df930be7Sderaadt #endif
159d484b7d0Sotto 			} else {
160df930be7Sderaadt #ifdef KSHVI
161df930be7Sderaadt 				el->el_line.cursor--;
162df930be7Sderaadt #else
16328d54ee8Sschwarze 				return CC_ERROR;
164df930be7Sderaadt #endif
165df930be7Sderaadt 			}
166d484b7d0Sotto 		} else {
167df930be7Sderaadt 			if (el->el_line.cursor != el->el_line.buffer)
168df930be7Sderaadt 				el->el_line.cursor--;
169df930be7Sderaadt 			else
17028d54ee8Sschwarze 				return CC_ERROR;
171df930be7Sderaadt 		}
172df930be7Sderaadt 	}
173df930be7Sderaadt 	c_delafter(el, el->el_state.argument);	/* delete after dot */
174d484b7d0Sotto 	if (el->el_line.cursor >= el->el_line.lastchar &&
175d484b7d0Sotto 	    el->el_line.cursor > el->el_line.buffer)
176d484b7d0Sotto 			/* bounds check */
177d484b7d0Sotto 		el->el_line.cursor = el->el_line.lastchar - 1;
17828d54ee8Sschwarze 	return CC_REFRESH;
179df930be7Sderaadt }
180df930be7Sderaadt 
181df930be7Sderaadt 
182df930be7Sderaadt /* ed_kill_line():
183df930be7Sderaadt  *	Cut to the end of line
184df930be7Sderaadt  *	[^K] [^K]
185df930be7Sderaadt  */
186df930be7Sderaadt protected el_action_t
ed_kill_line(EditLine * el,wint_t c)187b2589f0bSschwarze ed_kill_line(EditLine *el, wint_t c __attribute__((__unused__)))
188df930be7Sderaadt {
189e3191321Sschwarze 	wchar_t *kp, *cp;
190df930be7Sderaadt 
191df930be7Sderaadt 	cp = el->el_line.cursor;
192df930be7Sderaadt 	kp = el->el_chared.c_kill.buf;
193df930be7Sderaadt 	while (cp < el->el_line.lastchar)
194df930be7Sderaadt 		*kp++ = *cp++;	/* copy it */
195df930be7Sderaadt 	el->el_chared.c_kill.last = kp;
196d484b7d0Sotto 			/* zap! -- delete to end */
197d484b7d0Sotto 	el->el_line.lastchar = el->el_line.cursor;
19828d54ee8Sschwarze 	return CC_REFRESH;
199df930be7Sderaadt }
200df930be7Sderaadt 
201df930be7Sderaadt 
202df930be7Sderaadt /* ed_move_to_end():
203df930be7Sderaadt  *	Move cursor to the end of line
204df930be7Sderaadt  *	[^E] [^E]
205df930be7Sderaadt  */
206df930be7Sderaadt protected el_action_t
ed_move_to_end(EditLine * el,wint_t c)207b2589f0bSschwarze ed_move_to_end(EditLine *el, wint_t c __attribute__((__unused__)))
208df930be7Sderaadt {
209d484b7d0Sotto 
210df930be7Sderaadt 	el->el_line.cursor = el->el_line.lastchar;
211df930be7Sderaadt 	if (el->el_map.type == MAP_VI) {
212d484b7d0Sotto 		if (el->el_chared.c_vcmd.action != NOP) {
213df930be7Sderaadt 			cv_delfini(el);
21428d54ee8Sschwarze 			return CC_REFRESH;
215df930be7Sderaadt 		}
216aed0ee81Snicm #ifdef VI_MOVE
217aed0ee81Snicm 		el->el_line.cursor--;
218aed0ee81Snicm #endif
219df930be7Sderaadt 	}
22028d54ee8Sschwarze 	return CC_CURSOR;
221df930be7Sderaadt }
222df930be7Sderaadt 
223df930be7Sderaadt 
224df930be7Sderaadt /* ed_move_to_beg():
225df930be7Sderaadt  *	Move cursor to the beginning of line
226df930be7Sderaadt  *	[^A] [^A]
227df930be7Sderaadt  */
228df930be7Sderaadt protected el_action_t
ed_move_to_beg(EditLine * el,wint_t c)229b2589f0bSschwarze ed_move_to_beg(EditLine *el, wint_t c __attribute__((__unused__)))
230df930be7Sderaadt {
231d484b7d0Sotto 
232df930be7Sderaadt 	el->el_line.cursor = el->el_line.buffer;
233df930be7Sderaadt 
234df930be7Sderaadt 	if (el->el_map.type == MAP_VI) {
235df930be7Sderaadt 			/* We want FIRST non space character */
236565aa7e8Sschwarze 		while (iswspace(*el->el_line.cursor))
237df930be7Sderaadt 			el->el_line.cursor++;
238d484b7d0Sotto 		if (el->el_chared.c_vcmd.action != NOP) {
239df930be7Sderaadt 			cv_delfini(el);
24028d54ee8Sschwarze 			return CC_REFRESH;
241df930be7Sderaadt 		}
242df930be7Sderaadt 	}
24328d54ee8Sschwarze 	return CC_CURSOR;
244df930be7Sderaadt }
245df930be7Sderaadt 
246df930be7Sderaadt 
247df930be7Sderaadt /* ed_transpose_chars():
248df930be7Sderaadt  *	Exchange the character to the left of the cursor with the one under it
249df930be7Sderaadt  *	[^T] [^T]
250df930be7Sderaadt  */
251df930be7Sderaadt protected el_action_t
ed_transpose_chars(EditLine * el,wint_t c)252b2589f0bSschwarze ed_transpose_chars(EditLine *el, wint_t c)
253df930be7Sderaadt {
254d484b7d0Sotto 
255df930be7Sderaadt 	if (el->el_line.cursor < el->el_line.lastchar) {
256df930be7Sderaadt 		if (el->el_line.lastchar <= &el->el_line.buffer[1])
25728d54ee8Sschwarze 			return CC_ERROR;
258df930be7Sderaadt 		else
259df930be7Sderaadt 			el->el_line.cursor++;
260df930be7Sderaadt 	}
261df930be7Sderaadt 	if (el->el_line.cursor > &el->el_line.buffer[1]) {
262df930be7Sderaadt 		/* must have at least two chars entered */
263df930be7Sderaadt 		c = el->el_line.cursor[-2];
264df930be7Sderaadt 		el->el_line.cursor[-2] = el->el_line.cursor[-1];
265df930be7Sderaadt 		el->el_line.cursor[-1] = c;
26628d54ee8Sschwarze 		return CC_REFRESH;
267d484b7d0Sotto 	} else
26828d54ee8Sschwarze 		return CC_ERROR;
269df930be7Sderaadt }
270df930be7Sderaadt 
271df930be7Sderaadt 
272df930be7Sderaadt /* ed_next_char():
273df930be7Sderaadt  *	Move to the right one character
274df930be7Sderaadt  *	[^F] [^F]
275df930be7Sderaadt  */
276df930be7Sderaadt protected el_action_t
ed_next_char(EditLine * el,wint_t c)277b2589f0bSschwarze ed_next_char(EditLine *el, wint_t c __attribute__((__unused__)))
278df930be7Sderaadt {
279e3191321Sschwarze 	wchar_t *lim = el->el_line.lastchar;
280d484b7d0Sotto 
281d484b7d0Sotto 	if (el->el_line.cursor >= lim ||
282d484b7d0Sotto 	    (el->el_line.cursor == lim - 1 &&
283d484b7d0Sotto 	    el->el_map.type == MAP_VI &&
284d484b7d0Sotto 	    el->el_chared.c_vcmd.action == NOP))
28528d54ee8Sschwarze 		return CC_ERROR;
286df930be7Sderaadt 
287df930be7Sderaadt 	el->el_line.cursor += el->el_state.argument;
288d484b7d0Sotto 	if (el->el_line.cursor > lim)
289d484b7d0Sotto 		el->el_line.cursor = lim;
290df930be7Sderaadt 
291df930be7Sderaadt 	if (el->el_map.type == MAP_VI)
292d484b7d0Sotto 		if (el->el_chared.c_vcmd.action != NOP) {
293df930be7Sderaadt 			cv_delfini(el);
29428d54ee8Sschwarze 			return CC_REFRESH;
295df930be7Sderaadt 		}
29628d54ee8Sschwarze 	return CC_CURSOR;
297df930be7Sderaadt }
298df930be7Sderaadt 
299df930be7Sderaadt 
300df930be7Sderaadt /* ed_prev_word():
301df930be7Sderaadt  *	Move to the beginning of the current word
302df930be7Sderaadt  *	[M-b] [b]
303df930be7Sderaadt  */
304df930be7Sderaadt protected el_action_t
ed_prev_word(EditLine * el,wint_t c)305b2589f0bSschwarze ed_prev_word(EditLine *el, wint_t c __attribute__((__unused__)))
306df930be7Sderaadt {
307df930be7Sderaadt 
308d484b7d0Sotto 	if (el->el_line.cursor == el->el_line.buffer)
30928d54ee8Sschwarze 		return CC_ERROR;
310d484b7d0Sotto 
311d484b7d0Sotto 	el->el_line.cursor = c__prev_word(el->el_line.cursor,
312d484b7d0Sotto 	    el->el_line.buffer,
313df930be7Sderaadt 	    el->el_state.argument,
314df930be7Sderaadt 	    ce__isword);
315df930be7Sderaadt 
316df930be7Sderaadt 	if (el->el_map.type == MAP_VI)
317d484b7d0Sotto 		if (el->el_chared.c_vcmd.action != NOP) {
318df930be7Sderaadt 			cv_delfini(el);
31928d54ee8Sschwarze 			return CC_REFRESH;
320df930be7Sderaadt 		}
32128d54ee8Sschwarze 	return CC_CURSOR;
322df930be7Sderaadt }
323df930be7Sderaadt 
324df930be7Sderaadt 
325df930be7Sderaadt /* ed_prev_char():
326df930be7Sderaadt  *	Move to the left one character
327df930be7Sderaadt  *	[^B] [^B]
328df930be7Sderaadt  */
329df930be7Sderaadt protected el_action_t
ed_prev_char(EditLine * el,wint_t c)330b2589f0bSschwarze ed_prev_char(EditLine *el, wint_t c __attribute__((__unused__)))
331df930be7Sderaadt {
332d484b7d0Sotto 
333df930be7Sderaadt 	if (el->el_line.cursor > el->el_line.buffer) {
334df930be7Sderaadt 		el->el_line.cursor -= el->el_state.argument;
335df930be7Sderaadt 		if (el->el_line.cursor < el->el_line.buffer)
336df930be7Sderaadt 			el->el_line.cursor = el->el_line.buffer;
337df930be7Sderaadt 
338df930be7Sderaadt 		if (el->el_map.type == MAP_VI)
339d484b7d0Sotto 			if (el->el_chared.c_vcmd.action != NOP) {
340df930be7Sderaadt 				cv_delfini(el);
34128d54ee8Sschwarze 				return CC_REFRESH;
342df930be7Sderaadt 			}
34328d54ee8Sschwarze 		return CC_CURSOR;
344d484b7d0Sotto 	} else
34528d54ee8Sschwarze 		return CC_ERROR;
346df930be7Sderaadt }
347df930be7Sderaadt 
348df930be7Sderaadt 
349df930be7Sderaadt /* ed_quoted_insert():
350df930be7Sderaadt  *	Add the next character typed verbatim
351df930be7Sderaadt  *	[^V] [^V]
352df930be7Sderaadt  */
353df930be7Sderaadt protected el_action_t
ed_quoted_insert(EditLine * el,wint_t c)354b2589f0bSschwarze ed_quoted_insert(EditLine *el, wint_t c)
355df930be7Sderaadt {
356df930be7Sderaadt 	int num;
357df930be7Sderaadt 
358df930be7Sderaadt 	tty_quotemode(el);
359df2a7d38Sschwarze 	num = el_wgetc(el, &c);
360df930be7Sderaadt 	tty_noquotemode(el);
361df930be7Sderaadt 	if (num == 1)
36228d54ee8Sschwarze 		return ed_insert(el, c);
363df930be7Sderaadt 	else
36428d54ee8Sschwarze 		return ed_end_of_file(el, 0);
365df930be7Sderaadt }
366df930be7Sderaadt 
367df930be7Sderaadt 
368df930be7Sderaadt /* ed_digit():
369df930be7Sderaadt  *	Adds to argument or enters a digit
370df930be7Sderaadt  */
371df930be7Sderaadt protected el_action_t
ed_digit(EditLine * el,wint_t c)372b2589f0bSschwarze ed_digit(EditLine *el, wint_t c)
373df930be7Sderaadt {
374d484b7d0Sotto 
375565aa7e8Sschwarze 	if (!iswdigit(c))
37628d54ee8Sschwarze 		return CC_ERROR;
377df930be7Sderaadt 
378df930be7Sderaadt 	if (el->el_state.doingarg) {
379df930be7Sderaadt 			/* if doing an arg, add this in... */
380df930be7Sderaadt 		if (el->el_state.lastcmd == EM_UNIVERSAL_ARGUMENT)
381df930be7Sderaadt 			el->el_state.argument = c - '0';
382df930be7Sderaadt 		else {
383df930be7Sderaadt 			if (el->el_state.argument > 1000000)
38428d54ee8Sschwarze 				return CC_ERROR;
385df930be7Sderaadt 			el->el_state.argument =
386df930be7Sderaadt 			    (el->el_state.argument * 10) + (c - '0');
387df930be7Sderaadt 		}
38828d54ee8Sschwarze 		return CC_ARGHACK;
389df930be7Sderaadt 	}
390df930be7Sderaadt 
391d484b7d0Sotto 	return ed_insert(el, c);
392df930be7Sderaadt }
393df930be7Sderaadt 
394df930be7Sderaadt 
395df930be7Sderaadt /* ed_argument_digit():
396df930be7Sderaadt  *	Digit that starts argument
397df930be7Sderaadt  *	For ESC-n
398df930be7Sderaadt  */
399df930be7Sderaadt protected el_action_t
ed_argument_digit(EditLine * el,wint_t c)400b2589f0bSschwarze ed_argument_digit(EditLine *el, wint_t c)
401df930be7Sderaadt {
402d484b7d0Sotto 
403565aa7e8Sschwarze 	if (!iswdigit(c))
40428d54ee8Sschwarze 		return CC_ERROR;
405df930be7Sderaadt 
406df930be7Sderaadt 	if (el->el_state.doingarg) {
407df930be7Sderaadt 		if (el->el_state.argument > 1000000)
40828d54ee8Sschwarze 			return CC_ERROR;
409d484b7d0Sotto 		el->el_state.argument = (el->el_state.argument * 10) +
410d484b7d0Sotto 		    (c - '0');
411d484b7d0Sotto 	} else {		/* else starting an argument */
412df930be7Sderaadt 		el->el_state.argument = c - '0';
413df930be7Sderaadt 		el->el_state.doingarg = 1;
414df930be7Sderaadt 	}
41528d54ee8Sschwarze 	return CC_ARGHACK;
416df930be7Sderaadt }
417df930be7Sderaadt 
418df930be7Sderaadt 
419df930be7Sderaadt /* ed_unassigned():
420df930be7Sderaadt  *	Indicates unbound character
421df930be7Sderaadt  *	Bound to keys that are not assigned
422df930be7Sderaadt  */
423df930be7Sderaadt protected el_action_t
ed_unassigned(EditLine * el,wint_t c)424b2589f0bSschwarze ed_unassigned(EditLine *el, wint_t c __attribute__((__unused__)))
425df930be7Sderaadt {
426d484b7d0Sotto 
42728d54ee8Sschwarze 	return CC_ERROR;
428df930be7Sderaadt }
429df930be7Sderaadt 
430df930be7Sderaadt 
43155643de9Sschwarze /* ed_ignore():
43255643de9Sschwarze  *	Input characters that have no effect
43355643de9Sschwarze  *	[^C ^O ^Q ^S ^Z ^\ ^]] [^C ^O ^Q ^S ^\]
434df930be7Sderaadt  */
435df930be7Sderaadt protected el_action_t
ed_ignore(EditLine * el,wint_t c)43655643de9Sschwarze ed_ignore(EditLine *el __attribute__((__unused__)),
437b2589f0bSschwarze 	      wint_t c __attribute__((__unused__)))
438df930be7Sderaadt {
439d484b7d0Sotto 
44028d54ee8Sschwarze 	return CC_NORM;
441df930be7Sderaadt }
442df930be7Sderaadt 
443df930be7Sderaadt 
444df930be7Sderaadt /* ed_newline():
445df930be7Sderaadt  *	Execute command
446df930be7Sderaadt  *	[^J]
447df930be7Sderaadt  */
448df930be7Sderaadt protected el_action_t
ed_newline(EditLine * el,wint_t c)449b2589f0bSschwarze ed_newline(EditLine *el, wint_t c __attribute__((__unused__)))
450df930be7Sderaadt {
451d484b7d0Sotto 
452df930be7Sderaadt 	re_goto_bottom(el);
453df930be7Sderaadt 	*el->el_line.lastchar++ = '\n';
454df930be7Sderaadt 	*el->el_line.lastchar = '\0';
45528d54ee8Sschwarze 	return CC_NEWLINE;
456df930be7Sderaadt }
457df930be7Sderaadt 
458df930be7Sderaadt 
459df930be7Sderaadt /* ed_delete_prev_char():
460df930be7Sderaadt  *	Delete the character to the left of the cursor
461df930be7Sderaadt  *	[^?]
462df930be7Sderaadt  */
463df930be7Sderaadt protected el_action_t
ed_delete_prev_char(EditLine * el,wint_t c)464b2589f0bSschwarze ed_delete_prev_char(EditLine *el, wint_t c __attribute__((__unused__)))
465df930be7Sderaadt {
466d484b7d0Sotto 
467df930be7Sderaadt 	if (el->el_line.cursor <= el->el_line.buffer)
46828d54ee8Sschwarze 		return CC_ERROR;
469df930be7Sderaadt 
470df930be7Sderaadt 	c_delbefore(el, el->el_state.argument);
471df930be7Sderaadt 	el->el_line.cursor -= el->el_state.argument;
472df930be7Sderaadt 	if (el->el_line.cursor < el->el_line.buffer)
473df930be7Sderaadt 		el->el_line.cursor = el->el_line.buffer;
47428d54ee8Sschwarze 	return CC_REFRESH;
475df930be7Sderaadt }
476df930be7Sderaadt 
477df930be7Sderaadt 
478df930be7Sderaadt /* ed_clear_screen():
479df930be7Sderaadt  *	Clear screen leaving current line at the top
480df930be7Sderaadt  *	[^L]
481df930be7Sderaadt  */
482df930be7Sderaadt protected el_action_t
ed_clear_screen(EditLine * el,wint_t c)483b2589f0bSschwarze ed_clear_screen(EditLine *el, wint_t c __attribute__((__unused__)))
484df930be7Sderaadt {
485d484b7d0Sotto 
486fd40972aSschwarze 	terminal_clear_screen(el);	/* clear the whole real screen */
487df930be7Sderaadt 	re_clear_display(el);	/* reset everything */
48828d54ee8Sschwarze 	return CC_REFRESH;
489df930be7Sderaadt }
490df930be7Sderaadt 
491df930be7Sderaadt 
492df930be7Sderaadt /* ed_redisplay():
493df930be7Sderaadt  *	Redisplay everything
494df930be7Sderaadt  *	^R
495df930be7Sderaadt  */
496df930be7Sderaadt protected el_action_t
ed_redisplay(EditLine * el,wint_t c)497d484b7d0Sotto ed_redisplay(EditLine *el __attribute__((__unused__)),
498b2589f0bSschwarze 	     wint_t c __attribute__((__unused__)))
499df930be7Sderaadt {
500d484b7d0Sotto 
50128d54ee8Sschwarze 	return CC_REDISPLAY;
502df930be7Sderaadt }
503df930be7Sderaadt 
504df930be7Sderaadt 
505df930be7Sderaadt /* ed_start_over():
506df930be7Sderaadt  *	Erase current line and start from scratch
507df930be7Sderaadt  *	[^G]
508df930be7Sderaadt  */
509df930be7Sderaadt protected el_action_t
ed_start_over(EditLine * el,wint_t c)510b2589f0bSschwarze ed_start_over(EditLine *el, wint_t c __attribute__((__unused__)))
511df930be7Sderaadt {
512d484b7d0Sotto 
5135161d913Sschwarze 	ch_reset(el);
51428d54ee8Sschwarze 	return CC_REFRESH;
515df930be7Sderaadt }
516df930be7Sderaadt 
517df930be7Sderaadt 
518df930be7Sderaadt /* ed_sequence_lead_in():
519df930be7Sderaadt  *	First character in a bound sequence
520df930be7Sderaadt  *	Placeholder for external keys
521df930be7Sderaadt  */
522df930be7Sderaadt protected el_action_t
ed_sequence_lead_in(EditLine * el,wint_t c)523d484b7d0Sotto ed_sequence_lead_in(EditLine *el __attribute__((__unused__)),
524b2589f0bSschwarze 		    wint_t c __attribute__((__unused__)))
525df930be7Sderaadt {
526d484b7d0Sotto 
52728d54ee8Sschwarze 	return CC_NORM;
528df930be7Sderaadt }
529df930be7Sderaadt 
530df930be7Sderaadt 
531df930be7Sderaadt /* ed_prev_history():
532df930be7Sderaadt  *	Move to the previous history line
533df930be7Sderaadt  *	[^P] [k]
534df930be7Sderaadt  */
535df930be7Sderaadt protected el_action_t
ed_prev_history(EditLine * el,wint_t c)536b2589f0bSschwarze ed_prev_history(EditLine *el, wint_t c __attribute__((__unused__)))
537df930be7Sderaadt {
538df930be7Sderaadt 	char beep = 0;
539d484b7d0Sotto 	int sv_event = el->el_history.eventno;
540df930be7Sderaadt 
541d484b7d0Sotto 	el->el_chared.c_undo.len = -1;
542df930be7Sderaadt 	*el->el_line.lastchar = '\0';		/* just in case */
543df930be7Sderaadt 
544d484b7d0Sotto 	if (el->el_history.eventno == 0) {	/* save the current buffer
545d484b7d0Sotto 						 * away */
5465c93237dSschwarze 		(void) wcsncpy(el->el_history.buf, el->el_line.buffer,
547d484b7d0Sotto 		    EL_BUFSIZ);
548df930be7Sderaadt 		el->el_history.last = el->el_history.buf +
549df930be7Sderaadt 		    (el->el_line.lastchar - el->el_line.buffer);
550df930be7Sderaadt 	}
551df930be7Sderaadt 	el->el_history.eventno += el->el_state.argument;
552df930be7Sderaadt 
553df930be7Sderaadt 	if (hist_get(el) == CC_ERROR) {
554d484b7d0Sotto 		if (el->el_map.type == MAP_VI) {
555d484b7d0Sotto 			el->el_history.eventno = sv_event;
556d484b7d0Sotto 		}
557df930be7Sderaadt 		beep = 1;
558df930be7Sderaadt 		/* el->el_history.eventno was fixed by first call */
559df930be7Sderaadt 		(void) hist_get(el);
560df930be7Sderaadt 	}
561df930be7Sderaadt 	if (beep)
562d484b7d0Sotto 		return CC_REFRESH_BEEP;
563d484b7d0Sotto 	return CC_REFRESH;
564df930be7Sderaadt }
565df930be7Sderaadt 
566df930be7Sderaadt 
567df930be7Sderaadt /* ed_next_history():
568df930be7Sderaadt  *	Move to the next history line
569df930be7Sderaadt  *	[^N] [j]
570df930be7Sderaadt  */
571df930be7Sderaadt protected el_action_t
ed_next_history(EditLine * el,wint_t c)572b2589f0bSschwarze ed_next_history(EditLine *el, wint_t c __attribute__((__unused__)))
573df930be7Sderaadt {
574d484b7d0Sotto 	el_action_t beep = CC_REFRESH, rval;
575d484b7d0Sotto 
576d484b7d0Sotto 	el->el_chared.c_undo.len = -1;
577df930be7Sderaadt 	*el->el_line.lastchar = '\0';	/* just in case */
578df930be7Sderaadt 
579df930be7Sderaadt 	el->el_history.eventno -= el->el_state.argument;
580df930be7Sderaadt 
581df930be7Sderaadt 	if (el->el_history.eventno < 0) {
582df930be7Sderaadt 		el->el_history.eventno = 0;
583d484b7d0Sotto 		beep = CC_REFRESH_BEEP;
584df930be7Sderaadt 	}
585d484b7d0Sotto 	rval = hist_get(el);
586d484b7d0Sotto 	if (rval == CC_REFRESH)
587d484b7d0Sotto 		return beep;
588d484b7d0Sotto 	return rval;
589df930be7Sderaadt 
590df930be7Sderaadt }
591df930be7Sderaadt 
592df930be7Sderaadt 
593df930be7Sderaadt /* ed_search_prev_history():
594df930be7Sderaadt  *	Search previous in history for a line matching the current
595df930be7Sderaadt  *	next search history [M-P] [K]
596df930be7Sderaadt  */
597df930be7Sderaadt protected el_action_t
ed_search_prev_history(EditLine * el,wint_t c)598b2589f0bSschwarze ed_search_prev_history(EditLine *el, wint_t c __attribute__((__unused__)))
599df930be7Sderaadt {
600e3191321Sschwarze 	const wchar_t *hp;
601df930be7Sderaadt 	int h;
6028df20b6bSschwarze 	int found = 0;
603df930be7Sderaadt 
604df930be7Sderaadt 	el->el_chared.c_vcmd.action = NOP;
605d484b7d0Sotto 	el->el_chared.c_undo.len = -1;
606df930be7Sderaadt 	*el->el_line.lastchar = '\0';	/* just in case */
607df930be7Sderaadt 	if (el->el_history.eventno < 0) {
608df930be7Sderaadt #ifdef DEBUG_EDIT
609d484b7d0Sotto 		(void) fprintf(el->el_errfile,
610d484b7d0Sotto 		    "e_prev_search_hist(): eventno < 0;\n");
611df930be7Sderaadt #endif
612df930be7Sderaadt 		el->el_history.eventno = 0;
61328d54ee8Sschwarze 		return CC_ERROR;
614df930be7Sderaadt 	}
615df930be7Sderaadt 	if (el->el_history.eventno == 0) {
6165c93237dSschwarze 		(void) wcsncpy(el->el_history.buf, el->el_line.buffer,
617d484b7d0Sotto 		    EL_BUFSIZ);
618df930be7Sderaadt 		el->el_history.last = el->el_history.buf +
619df930be7Sderaadt 		    (el->el_line.lastchar - el->el_line.buffer);
620df930be7Sderaadt 	}
621df930be7Sderaadt 	if (el->el_history.ref == NULL)
62228d54ee8Sschwarze 		return CC_ERROR;
623df930be7Sderaadt 
624df930be7Sderaadt 	hp = HIST_FIRST(el);
625df930be7Sderaadt 	if (hp == NULL)
62628d54ee8Sschwarze 		return CC_ERROR;
627df930be7Sderaadt 
628df930be7Sderaadt 	c_setpat(el);		/* Set search pattern !! */
629df930be7Sderaadt 
630df930be7Sderaadt 	for (h = 1; h <= el->el_history.eventno; h++)
631df930be7Sderaadt 		hp = HIST_NEXT(el);
632df930be7Sderaadt 
633df930be7Sderaadt 	while (hp != NULL) {
634df930be7Sderaadt #ifdef SDEBUG
635df930be7Sderaadt 		(void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
636df930be7Sderaadt #endif
6375c93237dSschwarze 		if ((wcsncmp(hp, el->el_line.buffer, (size_t)
638d484b7d0Sotto 			    (el->el_line.lastchar - el->el_line.buffer)) ||
639df930be7Sderaadt 			hp[el->el_line.lastchar - el->el_line.buffer]) &&
640df930be7Sderaadt 		    c_hmatch(el, hp)) {
6418df20b6bSschwarze 			found = 1;
642df930be7Sderaadt 			break;
643df930be7Sderaadt 		}
644df930be7Sderaadt 		h++;
645df930be7Sderaadt 		hp = HIST_NEXT(el);
646df930be7Sderaadt 	}
647df930be7Sderaadt 
648df930be7Sderaadt 	if (!found) {
649df930be7Sderaadt #ifdef SDEBUG
650df930be7Sderaadt 		(void) fprintf(el->el_errfile, "not found\n");
651df930be7Sderaadt #endif
65228d54ee8Sschwarze 		return CC_ERROR;
653df930be7Sderaadt 	}
654df930be7Sderaadt 	el->el_history.eventno = h;
655df930be7Sderaadt 
65628d54ee8Sschwarze 	return hist_get(el);
657df930be7Sderaadt }
658df930be7Sderaadt 
659df930be7Sderaadt 
660df930be7Sderaadt /* ed_search_next_history():
661df930be7Sderaadt  *	Search next in history for a line matching the current
662df930be7Sderaadt  *	[M-N] [J]
663df930be7Sderaadt  */
664df930be7Sderaadt protected el_action_t
ed_search_next_history(EditLine * el,wint_t c)665b2589f0bSschwarze ed_search_next_history(EditLine *el, wint_t c __attribute__((__unused__)))
666df930be7Sderaadt {
667e3191321Sschwarze 	const wchar_t *hp;
668df930be7Sderaadt 	int h;
6698df20b6bSschwarze 	int found = 0;
670df930be7Sderaadt 
671df930be7Sderaadt 	el->el_chared.c_vcmd.action = NOP;
672d484b7d0Sotto 	el->el_chared.c_undo.len = -1;
673df930be7Sderaadt 	*el->el_line.lastchar = '\0';	/* just in case */
674df930be7Sderaadt 
675df930be7Sderaadt 	if (el->el_history.eventno == 0)
67628d54ee8Sschwarze 		return CC_ERROR;
677df930be7Sderaadt 
678df930be7Sderaadt 	if (el->el_history.ref == NULL)
67928d54ee8Sschwarze 		return CC_ERROR;
680df930be7Sderaadt 
681df930be7Sderaadt 	hp = HIST_FIRST(el);
682df930be7Sderaadt 	if (hp == NULL)
68328d54ee8Sschwarze 		return CC_ERROR;
684df930be7Sderaadt 
685df930be7Sderaadt 	c_setpat(el);		/* Set search pattern !! */
686df930be7Sderaadt 
687df930be7Sderaadt 	for (h = 1; h < el->el_history.eventno && hp; h++) {
688df930be7Sderaadt #ifdef SDEBUG
689df930be7Sderaadt 		(void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
690df930be7Sderaadt #endif
6915c93237dSschwarze 		if ((wcsncmp(hp, el->el_line.buffer, (size_t)
692d484b7d0Sotto 			    (el->el_line.lastchar - el->el_line.buffer)) ||
693df930be7Sderaadt 			hp[el->el_line.lastchar - el->el_line.buffer]) &&
694df930be7Sderaadt 		    c_hmatch(el, hp))
695df930be7Sderaadt 			found = h;
696df930be7Sderaadt 		hp = HIST_NEXT(el);
697df930be7Sderaadt 	}
698df930be7Sderaadt 
699df930be7Sderaadt 	if (!found) {		/* is it the current history number? */
700df930be7Sderaadt 		if (!c_hmatch(el, el->el_history.buf)) {
701df930be7Sderaadt #ifdef SDEBUG
702df930be7Sderaadt 			(void) fprintf(el->el_errfile, "not found\n");
703df930be7Sderaadt #endif
70428d54ee8Sschwarze 			return CC_ERROR;
705df930be7Sderaadt 		}
706df930be7Sderaadt 	}
707df930be7Sderaadt 	el->el_history.eventno = found;
708df930be7Sderaadt 
70928d54ee8Sschwarze 	return hist_get(el);
710df930be7Sderaadt }
711df930be7Sderaadt 
712df930be7Sderaadt 
713df930be7Sderaadt /* ed_prev_line():
714df930be7Sderaadt  *	Move up one line
715df930be7Sderaadt  *	Could be [k] [^p]
716df930be7Sderaadt  */
717df930be7Sderaadt protected el_action_t
ed_prev_line(EditLine * el,wint_t c)718b2589f0bSschwarze ed_prev_line(EditLine *el, wint_t c __attribute__((__unused__)))
719df930be7Sderaadt {
720e3191321Sschwarze 	wchar_t *ptr;
721df930be7Sderaadt 	int nchars = c_hpos(el);
722df930be7Sderaadt 
723df930be7Sderaadt 	/*
724df930be7Sderaadt          * Move to the line requested
725df930be7Sderaadt          */
726df930be7Sderaadt 	if (*(ptr = el->el_line.cursor) == '\n')
727df930be7Sderaadt 		ptr--;
728df930be7Sderaadt 
729df930be7Sderaadt 	for (; ptr >= el->el_line.buffer; ptr--)
730df930be7Sderaadt 		if (*ptr == '\n' && --el->el_state.argument <= 0)
731df930be7Sderaadt 			break;
732df930be7Sderaadt 
733df930be7Sderaadt 	if (el->el_state.argument > 0)
73428d54ee8Sschwarze 		return CC_ERROR;
735df930be7Sderaadt 
736df930be7Sderaadt 	/*
737df930be7Sderaadt          * Move to the beginning of the line
738df930be7Sderaadt          */
739df930be7Sderaadt 	for (ptr--; ptr >= el->el_line.buffer && *ptr != '\n'; ptr--)
740df930be7Sderaadt 		continue;
741df930be7Sderaadt 
742df930be7Sderaadt 	/*
743df930be7Sderaadt          * Move to the character requested
744df930be7Sderaadt          */
745df930be7Sderaadt 	for (ptr++;
746df930be7Sderaadt 	    nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
747df930be7Sderaadt 	    ptr++)
748df930be7Sderaadt 		continue;
749df930be7Sderaadt 
750df930be7Sderaadt 	el->el_line.cursor = ptr;
75128d54ee8Sschwarze 	return CC_CURSOR;
752df930be7Sderaadt }
753df930be7Sderaadt 
754df930be7Sderaadt 
755df930be7Sderaadt /* ed_next_line():
756df930be7Sderaadt  *	Move down one line
757df930be7Sderaadt  *	Could be [j] [^n]
758df930be7Sderaadt  */
759df930be7Sderaadt protected el_action_t
ed_next_line(EditLine * el,wint_t c)760b2589f0bSschwarze ed_next_line(EditLine *el, wint_t c __attribute__((__unused__)))
761df930be7Sderaadt {
762e3191321Sschwarze 	wchar_t *ptr;
763df930be7Sderaadt 	int nchars = c_hpos(el);
764df930be7Sderaadt 
765df930be7Sderaadt 	/*
766df930be7Sderaadt          * Move to the line requested
767df930be7Sderaadt          */
768df930be7Sderaadt 	for (ptr = el->el_line.cursor; ptr < el->el_line.lastchar; ptr++)
769df930be7Sderaadt 		if (*ptr == '\n' && --el->el_state.argument <= 0)
770df930be7Sderaadt 			break;
771df930be7Sderaadt 
772df930be7Sderaadt 	if (el->el_state.argument > 0)
77328d54ee8Sschwarze 		return CC_ERROR;
774df930be7Sderaadt 
775df930be7Sderaadt 	/*
776df930be7Sderaadt          * Move to the character requested
777df930be7Sderaadt          */
778df930be7Sderaadt 	for (ptr++;
779df930be7Sderaadt 	    nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
780df930be7Sderaadt 	    ptr++)
781df930be7Sderaadt 		continue;
782df930be7Sderaadt 
783df930be7Sderaadt 	el->el_line.cursor = ptr;
78428d54ee8Sschwarze 	return CC_CURSOR;
785df930be7Sderaadt }
786df930be7Sderaadt 
787df930be7Sderaadt 
788df930be7Sderaadt /* ed_command():
789df930be7Sderaadt  *	Editline extended command
790df930be7Sderaadt  *	[M-X] [:]
791df930be7Sderaadt  */
792df930be7Sderaadt protected el_action_t
ed_command(EditLine * el,wint_t c)793b2589f0bSschwarze ed_command(EditLine *el, wint_t c __attribute__((__unused__)))
794df930be7Sderaadt {
795e3191321Sschwarze 	wchar_t tmpbuf[EL_BUFSIZ];
796df930be7Sderaadt 	int tmplen;
797df930be7Sderaadt 
7985c93237dSschwarze 	tmplen = c_gets(el, tmpbuf, L"\n: ");
799fd40972aSschwarze 	terminal__putc(el, '\n');
800df930be7Sderaadt 
801d484b7d0Sotto 	if (tmplen < 0 || (tmpbuf[tmplen] = 0, parse_line(el, tmpbuf)) == -1)
802fd40972aSschwarze 		terminal_beep(el);
803df930be7Sderaadt 
804d484b7d0Sotto 	el->el_map.current = el->el_map.key;
805d484b7d0Sotto 	re_clear_display(el);
806df930be7Sderaadt 	return CC_REFRESH;
807df930be7Sderaadt }
808