xref: /freebsd/contrib/libedit/vi.c (revision d0ef721ed3dc99bddc1e48605a6921ec60322efc)
1*d0ef721eSBaptiste Daroussin /*	$NetBSD: vi.c,v 1.63 2019/07/23 10:18:52 christos Exp $	*/
2*d0ef721eSBaptiste Daroussin 
3*d0ef721eSBaptiste Daroussin /*-
4*d0ef721eSBaptiste Daroussin  * Copyright (c) 1992, 1993
5*d0ef721eSBaptiste Daroussin  *	The Regents of the University of California.  All rights reserved.
6*d0ef721eSBaptiste Daroussin  *
7*d0ef721eSBaptiste Daroussin  * This code is derived from software contributed to Berkeley by
8*d0ef721eSBaptiste Daroussin  * Christos Zoulas of Cornell University.
9*d0ef721eSBaptiste Daroussin  *
10*d0ef721eSBaptiste Daroussin  * Redistribution and use in source and binary forms, with or without
11*d0ef721eSBaptiste Daroussin  * modification, are permitted provided that the following conditions
12*d0ef721eSBaptiste Daroussin  * are met:
13*d0ef721eSBaptiste Daroussin  * 1. Redistributions of source code must retain the above copyright
14*d0ef721eSBaptiste Daroussin  *    notice, this list of conditions and the following disclaimer.
15*d0ef721eSBaptiste Daroussin  * 2. Redistributions in binary form must reproduce the above copyright
16*d0ef721eSBaptiste Daroussin  *    notice, this list of conditions and the following disclaimer in the
17*d0ef721eSBaptiste Daroussin  *    documentation and/or other materials provided with the distribution.
18*d0ef721eSBaptiste Daroussin  * 3. Neither the name of the University nor the names of its contributors
19*d0ef721eSBaptiste Daroussin  *    may be used to endorse or promote products derived from this software
20*d0ef721eSBaptiste Daroussin  *    without specific prior written permission.
21*d0ef721eSBaptiste Daroussin  *
22*d0ef721eSBaptiste Daroussin  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23*d0ef721eSBaptiste Daroussin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24*d0ef721eSBaptiste Daroussin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25*d0ef721eSBaptiste Daroussin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26*d0ef721eSBaptiste Daroussin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27*d0ef721eSBaptiste Daroussin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28*d0ef721eSBaptiste Daroussin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29*d0ef721eSBaptiste Daroussin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30*d0ef721eSBaptiste Daroussin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31*d0ef721eSBaptiste Daroussin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32*d0ef721eSBaptiste Daroussin  * SUCH DAMAGE.
33*d0ef721eSBaptiste Daroussin  */
34*d0ef721eSBaptiste Daroussin 
35*d0ef721eSBaptiste Daroussin #include "config.h"
36*d0ef721eSBaptiste Daroussin #if !defined(lint) && !defined(SCCSID)
37*d0ef721eSBaptiste Daroussin #if 0
38*d0ef721eSBaptiste Daroussin static char sccsid[] = "@(#)vi.c	8.1 (Berkeley) 6/4/93";
39*d0ef721eSBaptiste Daroussin #else
40*d0ef721eSBaptiste Daroussin __RCSID("$NetBSD: vi.c,v 1.63 2019/07/23 10:18:52 christos Exp $");
41*d0ef721eSBaptiste Daroussin #endif
42*d0ef721eSBaptiste Daroussin #endif /* not lint && not SCCSID */
43*d0ef721eSBaptiste Daroussin 
44*d0ef721eSBaptiste Daroussin /*
45*d0ef721eSBaptiste Daroussin  * vi.c: Vi mode commands.
46*d0ef721eSBaptiste Daroussin  */
47*d0ef721eSBaptiste Daroussin #include <sys/wait.h>
48*d0ef721eSBaptiste Daroussin #include <ctype.h>
49*d0ef721eSBaptiste Daroussin #include <limits.h>
50*d0ef721eSBaptiste Daroussin #include <stdlib.h>
51*d0ef721eSBaptiste Daroussin #include <string.h>
52*d0ef721eSBaptiste Daroussin #include <unistd.h>
53*d0ef721eSBaptiste Daroussin 
54*d0ef721eSBaptiste Daroussin #include "el.h"
55*d0ef721eSBaptiste Daroussin #include "common.h"
56*d0ef721eSBaptiste Daroussin #include "emacs.h"
57*d0ef721eSBaptiste Daroussin #include "fcns.h"
58*d0ef721eSBaptiste Daroussin #include "vi.h"
59*d0ef721eSBaptiste Daroussin 
60*d0ef721eSBaptiste Daroussin static el_action_t	cv_action(EditLine *, wint_t);
61*d0ef721eSBaptiste Daroussin static el_action_t	cv_paste(EditLine *, wint_t);
62*d0ef721eSBaptiste Daroussin 
63*d0ef721eSBaptiste Daroussin /* cv_action():
64*d0ef721eSBaptiste Daroussin  *	Handle vi actions.
65*d0ef721eSBaptiste Daroussin  */
66*d0ef721eSBaptiste Daroussin static el_action_t
67*d0ef721eSBaptiste Daroussin cv_action(EditLine *el, wint_t c)
68*d0ef721eSBaptiste Daroussin {
69*d0ef721eSBaptiste Daroussin 
70*d0ef721eSBaptiste Daroussin 	if (el->el_chared.c_vcmd.action != NOP) {
71*d0ef721eSBaptiste Daroussin 		/* 'cc', 'dd' and (possibly) friends */
72*d0ef721eSBaptiste Daroussin 		if (c != (wint_t)el->el_chared.c_vcmd.action)
73*d0ef721eSBaptiste Daroussin 			return CC_ERROR;
74*d0ef721eSBaptiste Daroussin 
75*d0ef721eSBaptiste Daroussin 		if (!(c & YANK))
76*d0ef721eSBaptiste Daroussin 			cv_undo(el);
77*d0ef721eSBaptiste Daroussin 		cv_yank(el, el->el_line.buffer,
78*d0ef721eSBaptiste Daroussin 		    (int)(el->el_line.lastchar - el->el_line.buffer));
79*d0ef721eSBaptiste Daroussin 		el->el_chared.c_vcmd.action = NOP;
80*d0ef721eSBaptiste Daroussin 		el->el_chared.c_vcmd.pos = 0;
81*d0ef721eSBaptiste Daroussin 		if (!(c & YANK)) {
82*d0ef721eSBaptiste Daroussin 			el->el_line.lastchar = el->el_line.buffer;
83*d0ef721eSBaptiste Daroussin 			el->el_line.cursor = el->el_line.buffer;
84*d0ef721eSBaptiste Daroussin 		}
85*d0ef721eSBaptiste Daroussin 		if (c & INSERT)
86*d0ef721eSBaptiste Daroussin 			el->el_map.current = el->el_map.key;
87*d0ef721eSBaptiste Daroussin 
88*d0ef721eSBaptiste Daroussin 		return CC_REFRESH;
89*d0ef721eSBaptiste Daroussin 	}
90*d0ef721eSBaptiste Daroussin 	el->el_chared.c_vcmd.pos = el->el_line.cursor;
91*d0ef721eSBaptiste Daroussin 	el->el_chared.c_vcmd.action = c;
92*d0ef721eSBaptiste Daroussin 	return CC_ARGHACK;
93*d0ef721eSBaptiste Daroussin }
94*d0ef721eSBaptiste Daroussin 
95*d0ef721eSBaptiste Daroussin /* cv_paste():
96*d0ef721eSBaptiste Daroussin  *	Paste previous deletion before or after the cursor
97*d0ef721eSBaptiste Daroussin  */
98*d0ef721eSBaptiste Daroussin static el_action_t
99*d0ef721eSBaptiste Daroussin cv_paste(EditLine *el, wint_t c)
100*d0ef721eSBaptiste Daroussin {
101*d0ef721eSBaptiste Daroussin 	c_kill_t *k = &el->el_chared.c_kill;
102*d0ef721eSBaptiste Daroussin 	size_t len = (size_t)(k->last - k->buf);
103*d0ef721eSBaptiste Daroussin 
104*d0ef721eSBaptiste Daroussin 	if (k->buf == NULL || len == 0)
105*d0ef721eSBaptiste Daroussin 		return CC_ERROR;
106*d0ef721eSBaptiste Daroussin #ifdef DEBUG_PASTE
107*d0ef721eSBaptiste Daroussin 	(void) fprintf(el->el_errfile, "Paste: \"%.*ls\"\n", (int)len,
108*d0ef721eSBaptiste Daroussin 	    k->buf);
109*d0ef721eSBaptiste Daroussin #endif
110*d0ef721eSBaptiste Daroussin 
111*d0ef721eSBaptiste Daroussin 	cv_undo(el);
112*d0ef721eSBaptiste Daroussin 
113*d0ef721eSBaptiste Daroussin 	if (!c && el->el_line.cursor < el->el_line.lastchar)
114*d0ef721eSBaptiste Daroussin 		el->el_line.cursor++;
115*d0ef721eSBaptiste Daroussin 
116*d0ef721eSBaptiste Daroussin 	c_insert(el, (int)len);
117*d0ef721eSBaptiste Daroussin 	if (el->el_line.cursor + len > el->el_line.lastchar)
118*d0ef721eSBaptiste Daroussin 		return CC_ERROR;
119*d0ef721eSBaptiste Daroussin 	(void) memcpy(el->el_line.cursor, k->buf, len *
120*d0ef721eSBaptiste Daroussin 	    sizeof(*el->el_line.cursor));
121*d0ef721eSBaptiste Daroussin 
122*d0ef721eSBaptiste Daroussin 	return CC_REFRESH;
123*d0ef721eSBaptiste Daroussin }
124*d0ef721eSBaptiste Daroussin 
125*d0ef721eSBaptiste Daroussin 
126*d0ef721eSBaptiste Daroussin /* vi_paste_next():
127*d0ef721eSBaptiste Daroussin  *	Vi paste previous deletion to the right of the cursor
128*d0ef721eSBaptiste Daroussin  *	[p]
129*d0ef721eSBaptiste Daroussin  */
130*d0ef721eSBaptiste Daroussin libedit_private el_action_t
131*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
132*d0ef721eSBaptiste Daroussin vi_paste_next(EditLine *el, wint_t c __attribute__((__unused__)))
133*d0ef721eSBaptiste Daroussin {
134*d0ef721eSBaptiste Daroussin 
135*d0ef721eSBaptiste Daroussin 	return cv_paste(el, 0);
136*d0ef721eSBaptiste Daroussin }
137*d0ef721eSBaptiste Daroussin 
138*d0ef721eSBaptiste Daroussin 
139*d0ef721eSBaptiste Daroussin /* vi_paste_prev():
140*d0ef721eSBaptiste Daroussin  *	Vi paste previous deletion to the left of the cursor
141*d0ef721eSBaptiste Daroussin  *	[P]
142*d0ef721eSBaptiste Daroussin  */
143*d0ef721eSBaptiste Daroussin libedit_private el_action_t
144*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
145*d0ef721eSBaptiste Daroussin vi_paste_prev(EditLine *el, wint_t c __attribute__((__unused__)))
146*d0ef721eSBaptiste Daroussin {
147*d0ef721eSBaptiste Daroussin 
148*d0ef721eSBaptiste Daroussin 	return cv_paste(el, 1);
149*d0ef721eSBaptiste Daroussin }
150*d0ef721eSBaptiste Daroussin 
151*d0ef721eSBaptiste Daroussin 
152*d0ef721eSBaptiste Daroussin /* vi_prev_big_word():
153*d0ef721eSBaptiste Daroussin  *	Vi move to the previous space delimited word
154*d0ef721eSBaptiste Daroussin  *	[B]
155*d0ef721eSBaptiste Daroussin  */
156*d0ef721eSBaptiste Daroussin libedit_private el_action_t
157*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
158*d0ef721eSBaptiste Daroussin vi_prev_big_word(EditLine *el, wint_t c __attribute__((__unused__)))
159*d0ef721eSBaptiste Daroussin {
160*d0ef721eSBaptiste Daroussin 
161*d0ef721eSBaptiste Daroussin 	if (el->el_line.cursor == el->el_line.buffer)
162*d0ef721eSBaptiste Daroussin 		return CC_ERROR;
163*d0ef721eSBaptiste Daroussin 
164*d0ef721eSBaptiste Daroussin 	el->el_line.cursor = cv_prev_word(el->el_line.cursor,
165*d0ef721eSBaptiste Daroussin 	    el->el_line.buffer,
166*d0ef721eSBaptiste Daroussin 	    el->el_state.argument,
167*d0ef721eSBaptiste Daroussin 	    cv__isWord);
168*d0ef721eSBaptiste Daroussin 
169*d0ef721eSBaptiste Daroussin 	if (el->el_chared.c_vcmd.action != NOP) {
170*d0ef721eSBaptiste Daroussin 		cv_delfini(el);
171*d0ef721eSBaptiste Daroussin 		return CC_REFRESH;
172*d0ef721eSBaptiste Daroussin 	}
173*d0ef721eSBaptiste Daroussin 	return CC_CURSOR;
174*d0ef721eSBaptiste Daroussin }
175*d0ef721eSBaptiste Daroussin 
176*d0ef721eSBaptiste Daroussin 
177*d0ef721eSBaptiste Daroussin /* vi_prev_word():
178*d0ef721eSBaptiste Daroussin  *	Vi move to the previous word
179*d0ef721eSBaptiste Daroussin  *	[b]
180*d0ef721eSBaptiste Daroussin  */
181*d0ef721eSBaptiste Daroussin libedit_private el_action_t
182*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
183*d0ef721eSBaptiste Daroussin vi_prev_word(EditLine *el, wint_t c __attribute__((__unused__)))
184*d0ef721eSBaptiste Daroussin {
185*d0ef721eSBaptiste Daroussin 
186*d0ef721eSBaptiste Daroussin 	if (el->el_line.cursor == el->el_line.buffer)
187*d0ef721eSBaptiste Daroussin 		return CC_ERROR;
188*d0ef721eSBaptiste Daroussin 
189*d0ef721eSBaptiste Daroussin 	el->el_line.cursor = cv_prev_word(el->el_line.cursor,
190*d0ef721eSBaptiste Daroussin 	    el->el_line.buffer,
191*d0ef721eSBaptiste Daroussin 	    el->el_state.argument,
192*d0ef721eSBaptiste Daroussin 	    cv__isword);
193*d0ef721eSBaptiste Daroussin 
194*d0ef721eSBaptiste Daroussin 	if (el->el_chared.c_vcmd.action != NOP) {
195*d0ef721eSBaptiste Daroussin 		cv_delfini(el);
196*d0ef721eSBaptiste Daroussin 		return CC_REFRESH;
197*d0ef721eSBaptiste Daroussin 	}
198*d0ef721eSBaptiste Daroussin 	return CC_CURSOR;
199*d0ef721eSBaptiste Daroussin }
200*d0ef721eSBaptiste Daroussin 
201*d0ef721eSBaptiste Daroussin 
202*d0ef721eSBaptiste Daroussin /* vi_next_big_word():
203*d0ef721eSBaptiste Daroussin  *	Vi move to the next space delimited word
204*d0ef721eSBaptiste Daroussin  *	[W]
205*d0ef721eSBaptiste Daroussin  */
206*d0ef721eSBaptiste Daroussin libedit_private el_action_t
207*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
208*d0ef721eSBaptiste Daroussin vi_next_big_word(EditLine *el, wint_t c __attribute__((__unused__)))
209*d0ef721eSBaptiste Daroussin {
210*d0ef721eSBaptiste Daroussin 
211*d0ef721eSBaptiste Daroussin 	if (el->el_line.cursor >= el->el_line.lastchar - 1)
212*d0ef721eSBaptiste Daroussin 		return CC_ERROR;
213*d0ef721eSBaptiste Daroussin 
214*d0ef721eSBaptiste Daroussin 	el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
215*d0ef721eSBaptiste Daroussin 	    el->el_line.lastchar, el->el_state.argument, cv__isWord);
216*d0ef721eSBaptiste Daroussin 
217*d0ef721eSBaptiste Daroussin 	if (el->el_map.type == MAP_VI)
218*d0ef721eSBaptiste Daroussin 		if (el->el_chared.c_vcmd.action != NOP) {
219*d0ef721eSBaptiste Daroussin 			cv_delfini(el);
220*d0ef721eSBaptiste Daroussin 			return CC_REFRESH;
221*d0ef721eSBaptiste Daroussin 		}
222*d0ef721eSBaptiste Daroussin 	return CC_CURSOR;
223*d0ef721eSBaptiste Daroussin }
224*d0ef721eSBaptiste Daroussin 
225*d0ef721eSBaptiste Daroussin 
226*d0ef721eSBaptiste Daroussin /* vi_next_word():
227*d0ef721eSBaptiste Daroussin  *	Vi move to the next word
228*d0ef721eSBaptiste Daroussin  *	[w]
229*d0ef721eSBaptiste Daroussin  */
230*d0ef721eSBaptiste Daroussin libedit_private el_action_t
231*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
232*d0ef721eSBaptiste Daroussin vi_next_word(EditLine *el, wint_t c __attribute__((__unused__)))
233*d0ef721eSBaptiste Daroussin {
234*d0ef721eSBaptiste Daroussin 
235*d0ef721eSBaptiste Daroussin 	if (el->el_line.cursor >= el->el_line.lastchar - 1)
236*d0ef721eSBaptiste Daroussin 		return CC_ERROR;
237*d0ef721eSBaptiste Daroussin 
238*d0ef721eSBaptiste Daroussin 	el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
239*d0ef721eSBaptiste Daroussin 	    el->el_line.lastchar, el->el_state.argument, cv__isword);
240*d0ef721eSBaptiste Daroussin 
241*d0ef721eSBaptiste Daroussin 	if (el->el_map.type == MAP_VI)
242*d0ef721eSBaptiste Daroussin 		if (el->el_chared.c_vcmd.action != NOP) {
243*d0ef721eSBaptiste Daroussin 			cv_delfini(el);
244*d0ef721eSBaptiste Daroussin 			return CC_REFRESH;
245*d0ef721eSBaptiste Daroussin 		}
246*d0ef721eSBaptiste Daroussin 	return CC_CURSOR;
247*d0ef721eSBaptiste Daroussin }
248*d0ef721eSBaptiste Daroussin 
249*d0ef721eSBaptiste Daroussin 
250*d0ef721eSBaptiste Daroussin /* vi_change_case():
251*d0ef721eSBaptiste Daroussin  *	Vi change case of character under the cursor and advance one character
252*d0ef721eSBaptiste Daroussin  *	[~]
253*d0ef721eSBaptiste Daroussin  */
254*d0ef721eSBaptiste Daroussin libedit_private el_action_t
255*d0ef721eSBaptiste Daroussin vi_change_case(EditLine *el, wint_t c)
256*d0ef721eSBaptiste Daroussin {
257*d0ef721eSBaptiste Daroussin 	int i;
258*d0ef721eSBaptiste Daroussin 
259*d0ef721eSBaptiste Daroussin 	if (el->el_line.cursor >= el->el_line.lastchar)
260*d0ef721eSBaptiste Daroussin 		return CC_ERROR;
261*d0ef721eSBaptiste Daroussin 	cv_undo(el);
262*d0ef721eSBaptiste Daroussin 	for (i = 0; i < el->el_state.argument; i++) {
263*d0ef721eSBaptiste Daroussin 
264*d0ef721eSBaptiste Daroussin 		c = *el->el_line.cursor;
265*d0ef721eSBaptiste Daroussin 		if (iswupper(c))
266*d0ef721eSBaptiste Daroussin 			*el->el_line.cursor = towlower(c);
267*d0ef721eSBaptiste Daroussin 		else if (iswlower(c))
268*d0ef721eSBaptiste Daroussin 			*el->el_line.cursor = towupper(c);
269*d0ef721eSBaptiste Daroussin 
270*d0ef721eSBaptiste Daroussin 		if (++el->el_line.cursor >= el->el_line.lastchar) {
271*d0ef721eSBaptiste Daroussin 			el->el_line.cursor--;
272*d0ef721eSBaptiste Daroussin 			re_fastaddc(el);
273*d0ef721eSBaptiste Daroussin 			break;
274*d0ef721eSBaptiste Daroussin 		}
275*d0ef721eSBaptiste Daroussin 		re_fastaddc(el);
276*d0ef721eSBaptiste Daroussin 	}
277*d0ef721eSBaptiste Daroussin 	return CC_NORM;
278*d0ef721eSBaptiste Daroussin }
279*d0ef721eSBaptiste Daroussin 
280*d0ef721eSBaptiste Daroussin 
281*d0ef721eSBaptiste Daroussin /* vi_change_meta():
282*d0ef721eSBaptiste Daroussin  *	Vi change prefix command
283*d0ef721eSBaptiste Daroussin  *	[c]
284*d0ef721eSBaptiste Daroussin  */
285*d0ef721eSBaptiste Daroussin libedit_private el_action_t
286*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
287*d0ef721eSBaptiste Daroussin vi_change_meta(EditLine *el, wint_t c __attribute__((__unused__)))
288*d0ef721eSBaptiste Daroussin {
289*d0ef721eSBaptiste Daroussin 
290*d0ef721eSBaptiste Daroussin 	/*
291*d0ef721eSBaptiste Daroussin          * Delete with insert == change: first we delete and then we leave in
292*d0ef721eSBaptiste Daroussin          * insert mode.
293*d0ef721eSBaptiste Daroussin          */
294*d0ef721eSBaptiste Daroussin 	return cv_action(el, DELETE | INSERT);
295*d0ef721eSBaptiste Daroussin }
296*d0ef721eSBaptiste Daroussin 
297*d0ef721eSBaptiste Daroussin 
298*d0ef721eSBaptiste Daroussin /* vi_insert_at_bol():
299*d0ef721eSBaptiste Daroussin  *	Vi enter insert mode at the beginning of line
300*d0ef721eSBaptiste Daroussin  *	[I]
301*d0ef721eSBaptiste Daroussin  */
302*d0ef721eSBaptiste Daroussin libedit_private el_action_t
303*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
304*d0ef721eSBaptiste Daroussin vi_insert_at_bol(EditLine *el, wint_t c __attribute__((__unused__)))
305*d0ef721eSBaptiste Daroussin {
306*d0ef721eSBaptiste Daroussin 
307*d0ef721eSBaptiste Daroussin 	el->el_line.cursor = el->el_line.buffer;
308*d0ef721eSBaptiste Daroussin 	cv_undo(el);
309*d0ef721eSBaptiste Daroussin 	el->el_map.current = el->el_map.key;
310*d0ef721eSBaptiste Daroussin 	return CC_CURSOR;
311*d0ef721eSBaptiste Daroussin }
312*d0ef721eSBaptiste Daroussin 
313*d0ef721eSBaptiste Daroussin 
314*d0ef721eSBaptiste Daroussin /* vi_replace_char():
315*d0ef721eSBaptiste Daroussin  *	Vi replace character under the cursor with the next character typed
316*d0ef721eSBaptiste Daroussin  *	[r]
317*d0ef721eSBaptiste Daroussin  */
318*d0ef721eSBaptiste Daroussin libedit_private el_action_t
319*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
320*d0ef721eSBaptiste Daroussin vi_replace_char(EditLine *el, wint_t c __attribute__((__unused__)))
321*d0ef721eSBaptiste Daroussin {
322*d0ef721eSBaptiste Daroussin 
323*d0ef721eSBaptiste Daroussin 	if (el->el_line.cursor >= el->el_line.lastchar)
324*d0ef721eSBaptiste Daroussin 		return CC_ERROR;
325*d0ef721eSBaptiste Daroussin 
326*d0ef721eSBaptiste Daroussin 	el->el_map.current = el->el_map.key;
327*d0ef721eSBaptiste Daroussin 	el->el_state.inputmode = MODE_REPLACE_1;
328*d0ef721eSBaptiste Daroussin 	cv_undo(el);
329*d0ef721eSBaptiste Daroussin 	return CC_ARGHACK;
330*d0ef721eSBaptiste Daroussin }
331*d0ef721eSBaptiste Daroussin 
332*d0ef721eSBaptiste Daroussin 
333*d0ef721eSBaptiste Daroussin /* vi_replace_mode():
334*d0ef721eSBaptiste Daroussin  *	Vi enter replace mode
335*d0ef721eSBaptiste Daroussin  *	[R]
336*d0ef721eSBaptiste Daroussin  */
337*d0ef721eSBaptiste Daroussin libedit_private el_action_t
338*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
339*d0ef721eSBaptiste Daroussin vi_replace_mode(EditLine *el, wint_t c __attribute__((__unused__)))
340*d0ef721eSBaptiste Daroussin {
341*d0ef721eSBaptiste Daroussin 
342*d0ef721eSBaptiste Daroussin 	el->el_map.current = el->el_map.key;
343*d0ef721eSBaptiste Daroussin 	el->el_state.inputmode = MODE_REPLACE;
344*d0ef721eSBaptiste Daroussin 	cv_undo(el);
345*d0ef721eSBaptiste Daroussin 	return CC_NORM;
346*d0ef721eSBaptiste Daroussin }
347*d0ef721eSBaptiste Daroussin 
348*d0ef721eSBaptiste Daroussin 
349*d0ef721eSBaptiste Daroussin /* vi_substitute_char():
350*d0ef721eSBaptiste Daroussin  *	Vi replace character under the cursor and enter insert mode
351*d0ef721eSBaptiste Daroussin  *	[s]
352*d0ef721eSBaptiste Daroussin  */
353*d0ef721eSBaptiste Daroussin libedit_private el_action_t
354*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
355*d0ef721eSBaptiste Daroussin vi_substitute_char(EditLine *el, wint_t c __attribute__((__unused__)))
356*d0ef721eSBaptiste Daroussin {
357*d0ef721eSBaptiste Daroussin 
358*d0ef721eSBaptiste Daroussin 	c_delafter(el, el->el_state.argument);
359*d0ef721eSBaptiste Daroussin 	el->el_map.current = el->el_map.key;
360*d0ef721eSBaptiste Daroussin 	return CC_REFRESH;
361*d0ef721eSBaptiste Daroussin }
362*d0ef721eSBaptiste Daroussin 
363*d0ef721eSBaptiste Daroussin 
364*d0ef721eSBaptiste Daroussin /* vi_substitute_line():
365*d0ef721eSBaptiste Daroussin  *	Vi substitute entire line
366*d0ef721eSBaptiste Daroussin  *	[S]
367*d0ef721eSBaptiste Daroussin  */
368*d0ef721eSBaptiste Daroussin libedit_private el_action_t
369*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
370*d0ef721eSBaptiste Daroussin vi_substitute_line(EditLine *el, wint_t c __attribute__((__unused__)))
371*d0ef721eSBaptiste Daroussin {
372*d0ef721eSBaptiste Daroussin 
373*d0ef721eSBaptiste Daroussin 	cv_undo(el);
374*d0ef721eSBaptiste Daroussin 	cv_yank(el, el->el_line.buffer,
375*d0ef721eSBaptiste Daroussin 	    (int)(el->el_line.lastchar - el->el_line.buffer));
376*d0ef721eSBaptiste Daroussin 	(void) em_kill_line(el, 0);
377*d0ef721eSBaptiste Daroussin 	el->el_map.current = el->el_map.key;
378*d0ef721eSBaptiste Daroussin 	return CC_REFRESH;
379*d0ef721eSBaptiste Daroussin }
380*d0ef721eSBaptiste Daroussin 
381*d0ef721eSBaptiste Daroussin 
382*d0ef721eSBaptiste Daroussin /* vi_change_to_eol():
383*d0ef721eSBaptiste Daroussin  *	Vi change to end of line
384*d0ef721eSBaptiste Daroussin  *	[C]
385*d0ef721eSBaptiste Daroussin  */
386*d0ef721eSBaptiste Daroussin libedit_private el_action_t
387*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
388*d0ef721eSBaptiste Daroussin vi_change_to_eol(EditLine *el, wint_t c __attribute__((__unused__)))
389*d0ef721eSBaptiste Daroussin {
390*d0ef721eSBaptiste Daroussin 
391*d0ef721eSBaptiste Daroussin 	cv_undo(el);
392*d0ef721eSBaptiste Daroussin 	cv_yank(el, el->el_line.cursor,
393*d0ef721eSBaptiste Daroussin 	    (int)(el->el_line.lastchar - el->el_line.cursor));
394*d0ef721eSBaptiste Daroussin 	(void) ed_kill_line(el, 0);
395*d0ef721eSBaptiste Daroussin 	el->el_map.current = el->el_map.key;
396*d0ef721eSBaptiste Daroussin 	return CC_REFRESH;
397*d0ef721eSBaptiste Daroussin }
398*d0ef721eSBaptiste Daroussin 
399*d0ef721eSBaptiste Daroussin 
400*d0ef721eSBaptiste Daroussin /* vi_insert():
401*d0ef721eSBaptiste Daroussin  *	Vi enter insert mode
402*d0ef721eSBaptiste Daroussin  *	[i]
403*d0ef721eSBaptiste Daroussin  */
404*d0ef721eSBaptiste Daroussin libedit_private el_action_t
405*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
406*d0ef721eSBaptiste Daroussin vi_insert(EditLine *el, wint_t c __attribute__((__unused__)))
407*d0ef721eSBaptiste Daroussin {
408*d0ef721eSBaptiste Daroussin 
409*d0ef721eSBaptiste Daroussin 	el->el_map.current = el->el_map.key;
410*d0ef721eSBaptiste Daroussin 	cv_undo(el);
411*d0ef721eSBaptiste Daroussin 	return CC_NORM;
412*d0ef721eSBaptiste Daroussin }
413*d0ef721eSBaptiste Daroussin 
414*d0ef721eSBaptiste Daroussin 
415*d0ef721eSBaptiste Daroussin /* vi_add():
416*d0ef721eSBaptiste Daroussin  *	Vi enter insert mode after the cursor
417*d0ef721eSBaptiste Daroussin  *	[a]
418*d0ef721eSBaptiste Daroussin  */
419*d0ef721eSBaptiste Daroussin libedit_private el_action_t
420*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
421*d0ef721eSBaptiste Daroussin vi_add(EditLine *el, wint_t c __attribute__((__unused__)))
422*d0ef721eSBaptiste Daroussin {
423*d0ef721eSBaptiste Daroussin 	int ret;
424*d0ef721eSBaptiste Daroussin 
425*d0ef721eSBaptiste Daroussin 	el->el_map.current = el->el_map.key;
426*d0ef721eSBaptiste Daroussin 	if (el->el_line.cursor < el->el_line.lastchar) {
427*d0ef721eSBaptiste Daroussin 		el->el_line.cursor++;
428*d0ef721eSBaptiste Daroussin 		if (el->el_line.cursor > el->el_line.lastchar)
429*d0ef721eSBaptiste Daroussin 			el->el_line.cursor = el->el_line.lastchar;
430*d0ef721eSBaptiste Daroussin 		ret = CC_CURSOR;
431*d0ef721eSBaptiste Daroussin 	} else
432*d0ef721eSBaptiste Daroussin 		ret = CC_NORM;
433*d0ef721eSBaptiste Daroussin 
434*d0ef721eSBaptiste Daroussin 	cv_undo(el);
435*d0ef721eSBaptiste Daroussin 
436*d0ef721eSBaptiste Daroussin 	return (el_action_t)ret;
437*d0ef721eSBaptiste Daroussin }
438*d0ef721eSBaptiste Daroussin 
439*d0ef721eSBaptiste Daroussin 
440*d0ef721eSBaptiste Daroussin /* vi_add_at_eol():
441*d0ef721eSBaptiste Daroussin  *	Vi enter insert mode at end of line
442*d0ef721eSBaptiste Daroussin  *	[A]
443*d0ef721eSBaptiste Daroussin  */
444*d0ef721eSBaptiste Daroussin libedit_private el_action_t
445*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
446*d0ef721eSBaptiste Daroussin vi_add_at_eol(EditLine *el, wint_t c __attribute__((__unused__)))
447*d0ef721eSBaptiste Daroussin {
448*d0ef721eSBaptiste Daroussin 
449*d0ef721eSBaptiste Daroussin 	el->el_map.current = el->el_map.key;
450*d0ef721eSBaptiste Daroussin 	el->el_line.cursor = el->el_line.lastchar;
451*d0ef721eSBaptiste Daroussin 	cv_undo(el);
452*d0ef721eSBaptiste Daroussin 	return CC_CURSOR;
453*d0ef721eSBaptiste Daroussin }
454*d0ef721eSBaptiste Daroussin 
455*d0ef721eSBaptiste Daroussin 
456*d0ef721eSBaptiste Daroussin /* vi_delete_meta():
457*d0ef721eSBaptiste Daroussin  *	Vi delete prefix command
458*d0ef721eSBaptiste Daroussin  *	[d]
459*d0ef721eSBaptiste Daroussin  */
460*d0ef721eSBaptiste Daroussin libedit_private el_action_t
461*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
462*d0ef721eSBaptiste Daroussin vi_delete_meta(EditLine *el, wint_t c __attribute__((__unused__)))
463*d0ef721eSBaptiste Daroussin {
464*d0ef721eSBaptiste Daroussin 
465*d0ef721eSBaptiste Daroussin 	return cv_action(el, DELETE);
466*d0ef721eSBaptiste Daroussin }
467*d0ef721eSBaptiste Daroussin 
468*d0ef721eSBaptiste Daroussin 
469*d0ef721eSBaptiste Daroussin /* vi_end_big_word():
470*d0ef721eSBaptiste Daroussin  *	Vi move to the end of the current space delimited word
471*d0ef721eSBaptiste Daroussin  *	[E]
472*d0ef721eSBaptiste Daroussin  */
473*d0ef721eSBaptiste Daroussin libedit_private el_action_t
474*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
475*d0ef721eSBaptiste Daroussin vi_end_big_word(EditLine *el, wint_t c __attribute__((__unused__)))
476*d0ef721eSBaptiste Daroussin {
477*d0ef721eSBaptiste Daroussin 
478*d0ef721eSBaptiste Daroussin 	if (el->el_line.cursor == el->el_line.lastchar)
479*d0ef721eSBaptiste Daroussin 		return CC_ERROR;
480*d0ef721eSBaptiste Daroussin 
481*d0ef721eSBaptiste Daroussin 	el->el_line.cursor = cv__endword(el->el_line.cursor,
482*d0ef721eSBaptiste Daroussin 	    el->el_line.lastchar, el->el_state.argument, cv__isWord);
483*d0ef721eSBaptiste Daroussin 
484*d0ef721eSBaptiste Daroussin 	if (el->el_chared.c_vcmd.action != NOP) {
485*d0ef721eSBaptiste Daroussin 		el->el_line.cursor++;
486*d0ef721eSBaptiste Daroussin 		cv_delfini(el);
487*d0ef721eSBaptiste Daroussin 		return CC_REFRESH;
488*d0ef721eSBaptiste Daroussin 	}
489*d0ef721eSBaptiste Daroussin 	return CC_CURSOR;
490*d0ef721eSBaptiste Daroussin }
491*d0ef721eSBaptiste Daroussin 
492*d0ef721eSBaptiste Daroussin 
493*d0ef721eSBaptiste Daroussin /* vi_end_word():
494*d0ef721eSBaptiste Daroussin  *	Vi move to the end of the current word
495*d0ef721eSBaptiste Daroussin  *	[e]
496*d0ef721eSBaptiste Daroussin  */
497*d0ef721eSBaptiste Daroussin libedit_private el_action_t
498*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
499*d0ef721eSBaptiste Daroussin vi_end_word(EditLine *el, wint_t c __attribute__((__unused__)))
500*d0ef721eSBaptiste Daroussin {
501*d0ef721eSBaptiste Daroussin 
502*d0ef721eSBaptiste Daroussin 	if (el->el_line.cursor == el->el_line.lastchar)
503*d0ef721eSBaptiste Daroussin 		return CC_ERROR;
504*d0ef721eSBaptiste Daroussin 
505*d0ef721eSBaptiste Daroussin 	el->el_line.cursor = cv__endword(el->el_line.cursor,
506*d0ef721eSBaptiste Daroussin 	    el->el_line.lastchar, el->el_state.argument, cv__isword);
507*d0ef721eSBaptiste Daroussin 
508*d0ef721eSBaptiste Daroussin 	if (el->el_chared.c_vcmd.action != NOP) {
509*d0ef721eSBaptiste Daroussin 		el->el_line.cursor++;
510*d0ef721eSBaptiste Daroussin 		cv_delfini(el);
511*d0ef721eSBaptiste Daroussin 		return CC_REFRESH;
512*d0ef721eSBaptiste Daroussin 	}
513*d0ef721eSBaptiste Daroussin 	return CC_CURSOR;
514*d0ef721eSBaptiste Daroussin }
515*d0ef721eSBaptiste Daroussin 
516*d0ef721eSBaptiste Daroussin 
517*d0ef721eSBaptiste Daroussin /* vi_undo():
518*d0ef721eSBaptiste Daroussin  *	Vi undo last change
519*d0ef721eSBaptiste Daroussin  *	[u]
520*d0ef721eSBaptiste Daroussin  */
521*d0ef721eSBaptiste Daroussin libedit_private el_action_t
522*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
523*d0ef721eSBaptiste Daroussin vi_undo(EditLine *el, wint_t c __attribute__((__unused__)))
524*d0ef721eSBaptiste Daroussin {
525*d0ef721eSBaptiste Daroussin 	c_undo_t un = el->el_chared.c_undo;
526*d0ef721eSBaptiste Daroussin 
527*d0ef721eSBaptiste Daroussin 	if (un.len == -1)
528*d0ef721eSBaptiste Daroussin 		return CC_ERROR;
529*d0ef721eSBaptiste Daroussin 
530*d0ef721eSBaptiste Daroussin 	/* switch line buffer and undo buffer */
531*d0ef721eSBaptiste Daroussin 	el->el_chared.c_undo.buf = el->el_line.buffer;
532*d0ef721eSBaptiste Daroussin 	el->el_chared.c_undo.len = el->el_line.lastchar - el->el_line.buffer;
533*d0ef721eSBaptiste Daroussin 	el->el_chared.c_undo.cursor =
534*d0ef721eSBaptiste Daroussin 	    (int)(el->el_line.cursor - el->el_line.buffer);
535*d0ef721eSBaptiste Daroussin 	el->el_line.limit = un.buf + (el->el_line.limit - el->el_line.buffer);
536*d0ef721eSBaptiste Daroussin 	el->el_line.buffer = un.buf;
537*d0ef721eSBaptiste Daroussin 	el->el_line.cursor = un.buf + un.cursor;
538*d0ef721eSBaptiste Daroussin 	el->el_line.lastchar = un.buf + un.len;
539*d0ef721eSBaptiste Daroussin 
540*d0ef721eSBaptiste Daroussin 	return CC_REFRESH;
541*d0ef721eSBaptiste Daroussin }
542*d0ef721eSBaptiste Daroussin 
543*d0ef721eSBaptiste Daroussin 
544*d0ef721eSBaptiste Daroussin /* vi_command_mode():
545*d0ef721eSBaptiste Daroussin  *	Vi enter command mode (use alternative key bindings)
546*d0ef721eSBaptiste Daroussin  *	[<ESC>]
547*d0ef721eSBaptiste Daroussin  */
548*d0ef721eSBaptiste Daroussin libedit_private el_action_t
549*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
550*d0ef721eSBaptiste Daroussin vi_command_mode(EditLine *el, wint_t c __attribute__((__unused__)))
551*d0ef721eSBaptiste Daroussin {
552*d0ef721eSBaptiste Daroussin 
553*d0ef721eSBaptiste Daroussin 	/* [Esc] cancels pending action */
554*d0ef721eSBaptiste Daroussin 	el->el_chared.c_vcmd.action = NOP;
555*d0ef721eSBaptiste Daroussin 	el->el_chared.c_vcmd.pos = 0;
556*d0ef721eSBaptiste Daroussin 
557*d0ef721eSBaptiste Daroussin 	el->el_state.doingarg = 0;
558*d0ef721eSBaptiste Daroussin 
559*d0ef721eSBaptiste Daroussin 	el->el_state.inputmode = MODE_INSERT;
560*d0ef721eSBaptiste Daroussin 	el->el_map.current = el->el_map.alt;
561*d0ef721eSBaptiste Daroussin #ifdef VI_MOVE
562*d0ef721eSBaptiste Daroussin 	if (el->el_line.cursor > el->el_line.buffer)
563*d0ef721eSBaptiste Daroussin 		el->el_line.cursor--;
564*d0ef721eSBaptiste Daroussin #endif
565*d0ef721eSBaptiste Daroussin 	return CC_CURSOR;
566*d0ef721eSBaptiste Daroussin }
567*d0ef721eSBaptiste Daroussin 
568*d0ef721eSBaptiste Daroussin 
569*d0ef721eSBaptiste Daroussin /* vi_zero():
570*d0ef721eSBaptiste Daroussin  *	Vi move to the beginning of line
571*d0ef721eSBaptiste Daroussin  *	[0]
572*d0ef721eSBaptiste Daroussin  */
573*d0ef721eSBaptiste Daroussin libedit_private el_action_t
574*d0ef721eSBaptiste Daroussin vi_zero(EditLine *el, wint_t c)
575*d0ef721eSBaptiste Daroussin {
576*d0ef721eSBaptiste Daroussin 
577*d0ef721eSBaptiste Daroussin 	if (el->el_state.doingarg)
578*d0ef721eSBaptiste Daroussin 		return ed_argument_digit(el, c);
579*d0ef721eSBaptiste Daroussin 
580*d0ef721eSBaptiste Daroussin 	el->el_line.cursor = el->el_line.buffer;
581*d0ef721eSBaptiste Daroussin 	if (el->el_chared.c_vcmd.action != NOP) {
582*d0ef721eSBaptiste Daroussin 		cv_delfini(el);
583*d0ef721eSBaptiste Daroussin 		return CC_REFRESH;
584*d0ef721eSBaptiste Daroussin 	}
585*d0ef721eSBaptiste Daroussin 	return CC_CURSOR;
586*d0ef721eSBaptiste Daroussin }
587*d0ef721eSBaptiste Daroussin 
588*d0ef721eSBaptiste Daroussin 
589*d0ef721eSBaptiste Daroussin /* vi_delete_prev_char():
590*d0ef721eSBaptiste Daroussin  *	Vi move to previous character (backspace)
591*d0ef721eSBaptiste Daroussin  *	[^H] in insert mode only
592*d0ef721eSBaptiste Daroussin  */
593*d0ef721eSBaptiste Daroussin libedit_private el_action_t
594*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
595*d0ef721eSBaptiste Daroussin vi_delete_prev_char(EditLine *el, wint_t c __attribute__((__unused__)))
596*d0ef721eSBaptiste Daroussin {
597*d0ef721eSBaptiste Daroussin 
598*d0ef721eSBaptiste Daroussin 	if (el->el_line.cursor <= el->el_line.buffer)
599*d0ef721eSBaptiste Daroussin 		return CC_ERROR;
600*d0ef721eSBaptiste Daroussin 
601*d0ef721eSBaptiste Daroussin 	c_delbefore1(el);
602*d0ef721eSBaptiste Daroussin 	el->el_line.cursor--;
603*d0ef721eSBaptiste Daroussin 	return CC_REFRESH;
604*d0ef721eSBaptiste Daroussin }
605*d0ef721eSBaptiste Daroussin 
606*d0ef721eSBaptiste Daroussin 
607*d0ef721eSBaptiste Daroussin /* vi_list_or_eof():
608*d0ef721eSBaptiste Daroussin  *	Vi list choices for completion or indicate end of file if empty line
609*d0ef721eSBaptiste Daroussin  *	[^D]
610*d0ef721eSBaptiste Daroussin  */
611*d0ef721eSBaptiste Daroussin libedit_private el_action_t
612*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
613*d0ef721eSBaptiste Daroussin vi_list_or_eof(EditLine *el, wint_t c)
614*d0ef721eSBaptiste Daroussin {
615*d0ef721eSBaptiste Daroussin 
616*d0ef721eSBaptiste Daroussin 	if (el->el_line.cursor == el->el_line.lastchar) {
617*d0ef721eSBaptiste Daroussin 		if (el->el_line.cursor == el->el_line.buffer) {
618*d0ef721eSBaptiste Daroussin 			terminal_writec(el, c);	/* then do a EOF */
619*d0ef721eSBaptiste Daroussin 			return CC_EOF;
620*d0ef721eSBaptiste Daroussin 		} else {
621*d0ef721eSBaptiste Daroussin 			/*
622*d0ef721eSBaptiste Daroussin 			 * Here we could list completions, but it is an
623*d0ef721eSBaptiste Daroussin 			 * error right now
624*d0ef721eSBaptiste Daroussin 			 */
625*d0ef721eSBaptiste Daroussin 			terminal_beep(el);
626*d0ef721eSBaptiste Daroussin 			return CC_ERROR;
627*d0ef721eSBaptiste Daroussin 		}
628*d0ef721eSBaptiste Daroussin 	} else {
629*d0ef721eSBaptiste Daroussin #ifdef notyet
630*d0ef721eSBaptiste Daroussin 		re_goto_bottom(el);
631*d0ef721eSBaptiste Daroussin 		*el->el_line.lastchar = '\0';	/* just in case */
632*d0ef721eSBaptiste Daroussin 		return CC_LIST_CHOICES;
633*d0ef721eSBaptiste Daroussin #else
634*d0ef721eSBaptiste Daroussin 		/*
635*d0ef721eSBaptiste Daroussin 		 * Just complain for now.
636*d0ef721eSBaptiste Daroussin 		 */
637*d0ef721eSBaptiste Daroussin 		terminal_beep(el);
638*d0ef721eSBaptiste Daroussin 		return CC_ERROR;
639*d0ef721eSBaptiste Daroussin #endif
640*d0ef721eSBaptiste Daroussin 	}
641*d0ef721eSBaptiste Daroussin }
642*d0ef721eSBaptiste Daroussin 
643*d0ef721eSBaptiste Daroussin 
644*d0ef721eSBaptiste Daroussin /* vi_kill_line_prev():
645*d0ef721eSBaptiste Daroussin  *	Vi cut from beginning of line to cursor
646*d0ef721eSBaptiste Daroussin  *	[^U]
647*d0ef721eSBaptiste Daroussin  */
648*d0ef721eSBaptiste Daroussin libedit_private el_action_t
649*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
650*d0ef721eSBaptiste Daroussin vi_kill_line_prev(EditLine *el, wint_t c __attribute__((__unused__)))
651*d0ef721eSBaptiste Daroussin {
652*d0ef721eSBaptiste Daroussin 	wchar_t *kp, *cp;
653*d0ef721eSBaptiste Daroussin 
654*d0ef721eSBaptiste Daroussin 	cp = el->el_line.buffer;
655*d0ef721eSBaptiste Daroussin 	kp = el->el_chared.c_kill.buf;
656*d0ef721eSBaptiste Daroussin 	while (cp < el->el_line.cursor)
657*d0ef721eSBaptiste Daroussin 		*kp++ = *cp++;	/* copy it */
658*d0ef721eSBaptiste Daroussin 	el->el_chared.c_kill.last = kp;
659*d0ef721eSBaptiste Daroussin 	c_delbefore(el, (int)(el->el_line.cursor - el->el_line.buffer));
660*d0ef721eSBaptiste Daroussin 	el->el_line.cursor = el->el_line.buffer;	/* zap! */
661*d0ef721eSBaptiste Daroussin 	return CC_REFRESH;
662*d0ef721eSBaptiste Daroussin }
663*d0ef721eSBaptiste Daroussin 
664*d0ef721eSBaptiste Daroussin 
665*d0ef721eSBaptiste Daroussin /* vi_search_prev():
666*d0ef721eSBaptiste Daroussin  *	Vi search history previous
667*d0ef721eSBaptiste Daroussin  *	[?]
668*d0ef721eSBaptiste Daroussin  */
669*d0ef721eSBaptiste Daroussin libedit_private el_action_t
670*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
671*d0ef721eSBaptiste Daroussin vi_search_prev(EditLine *el, wint_t c __attribute__((__unused__)))
672*d0ef721eSBaptiste Daroussin {
673*d0ef721eSBaptiste Daroussin 
674*d0ef721eSBaptiste Daroussin 	return cv_search(el, ED_SEARCH_PREV_HISTORY);
675*d0ef721eSBaptiste Daroussin }
676*d0ef721eSBaptiste Daroussin 
677*d0ef721eSBaptiste Daroussin 
678*d0ef721eSBaptiste Daroussin /* vi_search_next():
679*d0ef721eSBaptiste Daroussin  *	Vi search history next
680*d0ef721eSBaptiste Daroussin  *	[/]
681*d0ef721eSBaptiste Daroussin  */
682*d0ef721eSBaptiste Daroussin libedit_private el_action_t
683*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
684*d0ef721eSBaptiste Daroussin vi_search_next(EditLine *el, wint_t c __attribute__((__unused__)))
685*d0ef721eSBaptiste Daroussin {
686*d0ef721eSBaptiste Daroussin 
687*d0ef721eSBaptiste Daroussin 	return cv_search(el, ED_SEARCH_NEXT_HISTORY);
688*d0ef721eSBaptiste Daroussin }
689*d0ef721eSBaptiste Daroussin 
690*d0ef721eSBaptiste Daroussin 
691*d0ef721eSBaptiste Daroussin /* vi_repeat_search_next():
692*d0ef721eSBaptiste Daroussin  *	Vi repeat current search in the same search direction
693*d0ef721eSBaptiste Daroussin  *	[n]
694*d0ef721eSBaptiste Daroussin  */
695*d0ef721eSBaptiste Daroussin libedit_private el_action_t
696*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
697*d0ef721eSBaptiste Daroussin vi_repeat_search_next(EditLine *el, wint_t c __attribute__((__unused__)))
698*d0ef721eSBaptiste Daroussin {
699*d0ef721eSBaptiste Daroussin 
700*d0ef721eSBaptiste Daroussin 	if (el->el_search.patlen == 0)
701*d0ef721eSBaptiste Daroussin 		return CC_ERROR;
702*d0ef721eSBaptiste Daroussin 	else
703*d0ef721eSBaptiste Daroussin 		return cv_repeat_srch(el, el->el_search.patdir);
704*d0ef721eSBaptiste Daroussin }
705*d0ef721eSBaptiste Daroussin 
706*d0ef721eSBaptiste Daroussin 
707*d0ef721eSBaptiste Daroussin /* vi_repeat_search_prev():
708*d0ef721eSBaptiste Daroussin  *	Vi repeat current search in the opposite search direction
709*d0ef721eSBaptiste Daroussin  *	[N]
710*d0ef721eSBaptiste Daroussin  */
711*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
712*d0ef721eSBaptiste Daroussin libedit_private el_action_t
713*d0ef721eSBaptiste Daroussin vi_repeat_search_prev(EditLine *el, wint_t c __attribute__((__unused__)))
714*d0ef721eSBaptiste Daroussin {
715*d0ef721eSBaptiste Daroussin 
716*d0ef721eSBaptiste Daroussin 	if (el->el_search.patlen == 0)
717*d0ef721eSBaptiste Daroussin 		return CC_ERROR;
718*d0ef721eSBaptiste Daroussin 	else
719*d0ef721eSBaptiste Daroussin 		return (cv_repeat_srch(el,
720*d0ef721eSBaptiste Daroussin 		    el->el_search.patdir == ED_SEARCH_PREV_HISTORY ?
721*d0ef721eSBaptiste Daroussin 		    ED_SEARCH_NEXT_HISTORY : ED_SEARCH_PREV_HISTORY));
722*d0ef721eSBaptiste Daroussin }
723*d0ef721eSBaptiste Daroussin 
724*d0ef721eSBaptiste Daroussin 
725*d0ef721eSBaptiste Daroussin /* vi_next_char():
726*d0ef721eSBaptiste Daroussin  *	Vi move to the character specified next
727*d0ef721eSBaptiste Daroussin  *	[f]
728*d0ef721eSBaptiste Daroussin  */
729*d0ef721eSBaptiste Daroussin libedit_private el_action_t
730*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
731*d0ef721eSBaptiste Daroussin vi_next_char(EditLine *el, wint_t c __attribute__((__unused__)))
732*d0ef721eSBaptiste Daroussin {
733*d0ef721eSBaptiste Daroussin 	return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 0);
734*d0ef721eSBaptiste Daroussin }
735*d0ef721eSBaptiste Daroussin 
736*d0ef721eSBaptiste Daroussin 
737*d0ef721eSBaptiste Daroussin /* vi_prev_char():
738*d0ef721eSBaptiste Daroussin  *	Vi move to the character specified previous
739*d0ef721eSBaptiste Daroussin  *	[F]
740*d0ef721eSBaptiste Daroussin  */
741*d0ef721eSBaptiste Daroussin libedit_private el_action_t
742*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
743*d0ef721eSBaptiste Daroussin vi_prev_char(EditLine *el, wint_t c __attribute__((__unused__)))
744*d0ef721eSBaptiste Daroussin {
745*d0ef721eSBaptiste Daroussin 	return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 0);
746*d0ef721eSBaptiste Daroussin }
747*d0ef721eSBaptiste Daroussin 
748*d0ef721eSBaptiste Daroussin 
749*d0ef721eSBaptiste Daroussin /* vi_to_next_char():
750*d0ef721eSBaptiste Daroussin  *	Vi move up to the character specified next
751*d0ef721eSBaptiste Daroussin  *	[t]
752*d0ef721eSBaptiste Daroussin  */
753*d0ef721eSBaptiste Daroussin libedit_private el_action_t
754*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
755*d0ef721eSBaptiste Daroussin vi_to_next_char(EditLine *el, wint_t c __attribute__((__unused__)))
756*d0ef721eSBaptiste Daroussin {
757*d0ef721eSBaptiste Daroussin 	return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 1);
758*d0ef721eSBaptiste Daroussin }
759*d0ef721eSBaptiste Daroussin 
760*d0ef721eSBaptiste Daroussin 
761*d0ef721eSBaptiste Daroussin /* vi_to_prev_char():
762*d0ef721eSBaptiste Daroussin  *	Vi move up to the character specified previous
763*d0ef721eSBaptiste Daroussin  *	[T]
764*d0ef721eSBaptiste Daroussin  */
765*d0ef721eSBaptiste Daroussin libedit_private el_action_t
766*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
767*d0ef721eSBaptiste Daroussin vi_to_prev_char(EditLine *el, wint_t c __attribute__((__unused__)))
768*d0ef721eSBaptiste Daroussin {
769*d0ef721eSBaptiste Daroussin 	return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 1);
770*d0ef721eSBaptiste Daroussin }
771*d0ef721eSBaptiste Daroussin 
772*d0ef721eSBaptiste Daroussin 
773*d0ef721eSBaptiste Daroussin /* vi_repeat_next_char():
774*d0ef721eSBaptiste Daroussin  *	Vi repeat current character search in the same search direction
775*d0ef721eSBaptiste Daroussin  *	[;]
776*d0ef721eSBaptiste Daroussin  */
777*d0ef721eSBaptiste Daroussin libedit_private el_action_t
778*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
779*d0ef721eSBaptiste Daroussin vi_repeat_next_char(EditLine *el, wint_t c __attribute__((__unused__)))
780*d0ef721eSBaptiste Daroussin {
781*d0ef721eSBaptiste Daroussin 
782*d0ef721eSBaptiste Daroussin 	return cv_csearch(el, el->el_search.chadir, el->el_search.chacha,
783*d0ef721eSBaptiste Daroussin 		el->el_state.argument, el->el_search.chatflg);
784*d0ef721eSBaptiste Daroussin }
785*d0ef721eSBaptiste Daroussin 
786*d0ef721eSBaptiste Daroussin 
787*d0ef721eSBaptiste Daroussin /* vi_repeat_prev_char():
788*d0ef721eSBaptiste Daroussin  *	Vi repeat current character search in the opposite search direction
789*d0ef721eSBaptiste Daroussin  *	[,]
790*d0ef721eSBaptiste Daroussin  */
791*d0ef721eSBaptiste Daroussin libedit_private el_action_t
792*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
793*d0ef721eSBaptiste Daroussin vi_repeat_prev_char(EditLine *el, wint_t c __attribute__((__unused__)))
794*d0ef721eSBaptiste Daroussin {
795*d0ef721eSBaptiste Daroussin 	el_action_t r;
796*d0ef721eSBaptiste Daroussin 	int dir = el->el_search.chadir;
797*d0ef721eSBaptiste Daroussin 
798*d0ef721eSBaptiste Daroussin 	r = cv_csearch(el, -dir, el->el_search.chacha,
799*d0ef721eSBaptiste Daroussin 		el->el_state.argument, el->el_search.chatflg);
800*d0ef721eSBaptiste Daroussin 	el->el_search.chadir = dir;
801*d0ef721eSBaptiste Daroussin 	return r;
802*d0ef721eSBaptiste Daroussin }
803*d0ef721eSBaptiste Daroussin 
804*d0ef721eSBaptiste Daroussin 
805*d0ef721eSBaptiste Daroussin /* vi_match():
806*d0ef721eSBaptiste Daroussin  *	Vi go to matching () {} or []
807*d0ef721eSBaptiste Daroussin  *	[%]
808*d0ef721eSBaptiste Daroussin  */
809*d0ef721eSBaptiste Daroussin libedit_private el_action_t
810*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
811*d0ef721eSBaptiste Daroussin vi_match(EditLine *el, wint_t c __attribute__((__unused__)))
812*d0ef721eSBaptiste Daroussin {
813*d0ef721eSBaptiste Daroussin 	const wchar_t match_chars[] = L"()[]{}";
814*d0ef721eSBaptiste Daroussin 	wchar_t *cp;
815*d0ef721eSBaptiste Daroussin 	size_t delta, i, count;
816*d0ef721eSBaptiste Daroussin 	wchar_t o_ch, c_ch;
817*d0ef721eSBaptiste Daroussin 
818*d0ef721eSBaptiste Daroussin 	*el->el_line.lastchar = '\0';		/* just in case */
819*d0ef721eSBaptiste Daroussin 
820*d0ef721eSBaptiste Daroussin 	i = wcscspn(el->el_line.cursor, match_chars);
821*d0ef721eSBaptiste Daroussin 	o_ch = el->el_line.cursor[i];
822*d0ef721eSBaptiste Daroussin 	if (o_ch == 0)
823*d0ef721eSBaptiste Daroussin 		return CC_ERROR;
824*d0ef721eSBaptiste Daroussin 	delta = (size_t)(wcschr(match_chars, o_ch) - match_chars);
825*d0ef721eSBaptiste Daroussin 	c_ch = match_chars[delta ^ 1];
826*d0ef721eSBaptiste Daroussin 	count = 1;
827*d0ef721eSBaptiste Daroussin 	delta = 1 - (delta & 1) * 2;
828*d0ef721eSBaptiste Daroussin 
829*d0ef721eSBaptiste Daroussin 	for (cp = &el->el_line.cursor[i]; count; ) {
830*d0ef721eSBaptiste Daroussin 		cp += delta;
831*d0ef721eSBaptiste Daroussin 		if (cp < el->el_line.buffer || cp >= el->el_line.lastchar)
832*d0ef721eSBaptiste Daroussin 			return CC_ERROR;
833*d0ef721eSBaptiste Daroussin 		if (*cp == o_ch)
834*d0ef721eSBaptiste Daroussin 			count++;
835*d0ef721eSBaptiste Daroussin 		else if (*cp == c_ch)
836*d0ef721eSBaptiste Daroussin 			count--;
837*d0ef721eSBaptiste Daroussin 	}
838*d0ef721eSBaptiste Daroussin 
839*d0ef721eSBaptiste Daroussin 	el->el_line.cursor = cp;
840*d0ef721eSBaptiste Daroussin 
841*d0ef721eSBaptiste Daroussin 	if (el->el_chared.c_vcmd.action != NOP) {
842*d0ef721eSBaptiste Daroussin 		/* NB posix says char under cursor should NOT be deleted
843*d0ef721eSBaptiste Daroussin 		   for -ve delta - this is different to netbsd vi. */
844*d0ef721eSBaptiste Daroussin 		if (delta > 0)
845*d0ef721eSBaptiste Daroussin 			el->el_line.cursor++;
846*d0ef721eSBaptiste Daroussin 		cv_delfini(el);
847*d0ef721eSBaptiste Daroussin 		return CC_REFRESH;
848*d0ef721eSBaptiste Daroussin 	}
849*d0ef721eSBaptiste Daroussin 	return CC_CURSOR;
850*d0ef721eSBaptiste Daroussin }
851*d0ef721eSBaptiste Daroussin 
852*d0ef721eSBaptiste Daroussin /* vi_undo_line():
853*d0ef721eSBaptiste Daroussin  *	Vi undo all changes to line
854*d0ef721eSBaptiste Daroussin  *	[U]
855*d0ef721eSBaptiste Daroussin  */
856*d0ef721eSBaptiste Daroussin libedit_private el_action_t
857*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
858*d0ef721eSBaptiste Daroussin vi_undo_line(EditLine *el, wint_t c __attribute__((__unused__)))
859*d0ef721eSBaptiste Daroussin {
860*d0ef721eSBaptiste Daroussin 
861*d0ef721eSBaptiste Daroussin 	cv_undo(el);
862*d0ef721eSBaptiste Daroussin 	return hist_get(el);
863*d0ef721eSBaptiste Daroussin }
864*d0ef721eSBaptiste Daroussin 
865*d0ef721eSBaptiste Daroussin /* vi_to_column():
866*d0ef721eSBaptiste Daroussin  *	Vi go to specified column
867*d0ef721eSBaptiste Daroussin  *	[|]
868*d0ef721eSBaptiste Daroussin  * NB netbsd vi goes to screen column 'n', posix says nth character
869*d0ef721eSBaptiste Daroussin  */
870*d0ef721eSBaptiste Daroussin libedit_private el_action_t
871*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
872*d0ef721eSBaptiste Daroussin vi_to_column(EditLine *el, wint_t c __attribute__((__unused__)))
873*d0ef721eSBaptiste Daroussin {
874*d0ef721eSBaptiste Daroussin 
875*d0ef721eSBaptiste Daroussin 	el->el_line.cursor = el->el_line.buffer;
876*d0ef721eSBaptiste Daroussin 	el->el_state.argument--;
877*d0ef721eSBaptiste Daroussin 	return ed_next_char(el, 0);
878*d0ef721eSBaptiste Daroussin }
879*d0ef721eSBaptiste Daroussin 
880*d0ef721eSBaptiste Daroussin /* vi_yank_end():
881*d0ef721eSBaptiste Daroussin  *	Vi yank to end of line
882*d0ef721eSBaptiste Daroussin  *	[Y]
883*d0ef721eSBaptiste Daroussin  */
884*d0ef721eSBaptiste Daroussin libedit_private el_action_t
885*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
886*d0ef721eSBaptiste Daroussin vi_yank_end(EditLine *el, wint_t c __attribute__((__unused__)))
887*d0ef721eSBaptiste Daroussin {
888*d0ef721eSBaptiste Daroussin 
889*d0ef721eSBaptiste Daroussin 	cv_yank(el, el->el_line.cursor,
890*d0ef721eSBaptiste Daroussin 	    (int)(el->el_line.lastchar - el->el_line.cursor));
891*d0ef721eSBaptiste Daroussin 	return CC_REFRESH;
892*d0ef721eSBaptiste Daroussin }
893*d0ef721eSBaptiste Daroussin 
894*d0ef721eSBaptiste Daroussin /* vi_yank():
895*d0ef721eSBaptiste Daroussin  *	Vi yank
896*d0ef721eSBaptiste Daroussin  *	[y]
897*d0ef721eSBaptiste Daroussin  */
898*d0ef721eSBaptiste Daroussin libedit_private el_action_t
899*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
900*d0ef721eSBaptiste Daroussin vi_yank(EditLine *el, wint_t c __attribute__((__unused__)))
901*d0ef721eSBaptiste Daroussin {
902*d0ef721eSBaptiste Daroussin 
903*d0ef721eSBaptiste Daroussin 	return cv_action(el, YANK);
904*d0ef721eSBaptiste Daroussin }
905*d0ef721eSBaptiste Daroussin 
906*d0ef721eSBaptiste Daroussin /* vi_comment_out():
907*d0ef721eSBaptiste Daroussin  *	Vi comment out current command
908*d0ef721eSBaptiste Daroussin  *	[#]
909*d0ef721eSBaptiste Daroussin  */
910*d0ef721eSBaptiste Daroussin libedit_private el_action_t
911*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
912*d0ef721eSBaptiste Daroussin vi_comment_out(EditLine *el, wint_t c __attribute__((__unused__)))
913*d0ef721eSBaptiste Daroussin {
914*d0ef721eSBaptiste Daroussin 
915*d0ef721eSBaptiste Daroussin 	el->el_line.cursor = el->el_line.buffer;
916*d0ef721eSBaptiste Daroussin 	c_insert(el, 1);
917*d0ef721eSBaptiste Daroussin 	*el->el_line.cursor = '#';
918*d0ef721eSBaptiste Daroussin 	re_refresh(el);
919*d0ef721eSBaptiste Daroussin 	return ed_newline(el, 0);
920*d0ef721eSBaptiste Daroussin }
921*d0ef721eSBaptiste Daroussin 
922*d0ef721eSBaptiste Daroussin /* vi_alias():
923*d0ef721eSBaptiste Daroussin  *	Vi include shell alias
924*d0ef721eSBaptiste Daroussin  *	[@]
925*d0ef721eSBaptiste Daroussin  * NB: posix implies that we should enter insert mode, however
926*d0ef721eSBaptiste Daroussin  * this is against historical precedent...
927*d0ef721eSBaptiste Daroussin  */
928*d0ef721eSBaptiste Daroussin libedit_private el_action_t
929*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
930*d0ef721eSBaptiste Daroussin vi_alias(EditLine *el, wint_t c __attribute__((__unused__)))
931*d0ef721eSBaptiste Daroussin {
932*d0ef721eSBaptiste Daroussin 	char alias_name[3];
933*d0ef721eSBaptiste Daroussin 	const char *alias_text;
934*d0ef721eSBaptiste Daroussin 
935*d0ef721eSBaptiste Daroussin 	if (el->el_chared.c_aliasfun == NULL)
936*d0ef721eSBaptiste Daroussin 		return CC_ERROR;
937*d0ef721eSBaptiste Daroussin 
938*d0ef721eSBaptiste Daroussin 	alias_name[0] = '_';
939*d0ef721eSBaptiste Daroussin 	alias_name[2] = 0;
940*d0ef721eSBaptiste Daroussin 	if (el_getc(el, &alias_name[1]) != 1)
941*d0ef721eSBaptiste Daroussin 		return CC_ERROR;
942*d0ef721eSBaptiste Daroussin 
943*d0ef721eSBaptiste Daroussin 	alias_text = (*el->el_chared.c_aliasfun)(el->el_chared.c_aliasarg,
944*d0ef721eSBaptiste Daroussin 	    alias_name);
945*d0ef721eSBaptiste Daroussin 	if (alias_text != NULL)
946*d0ef721eSBaptiste Daroussin 		el_wpush(el, ct_decode_string(alias_text, &el->el_scratch));
947*d0ef721eSBaptiste Daroussin 	return CC_NORM;
948*d0ef721eSBaptiste Daroussin }
949*d0ef721eSBaptiste Daroussin 
950*d0ef721eSBaptiste Daroussin /* vi_to_history_line():
951*d0ef721eSBaptiste Daroussin  *	Vi go to specified history file line.
952*d0ef721eSBaptiste Daroussin  *	[G]
953*d0ef721eSBaptiste Daroussin  */
954*d0ef721eSBaptiste Daroussin libedit_private el_action_t
955*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
956*d0ef721eSBaptiste Daroussin vi_to_history_line(EditLine *el, wint_t c __attribute__((__unused__)))
957*d0ef721eSBaptiste Daroussin {
958*d0ef721eSBaptiste Daroussin 	int sv_event_no = el->el_history.eventno;
959*d0ef721eSBaptiste Daroussin 	el_action_t rval;
960*d0ef721eSBaptiste Daroussin 
961*d0ef721eSBaptiste Daroussin 
962*d0ef721eSBaptiste Daroussin 	if (el->el_history.eventno == 0) {
963*d0ef721eSBaptiste Daroussin 		 (void) wcsncpy(el->el_history.buf, el->el_line.buffer,
964*d0ef721eSBaptiste Daroussin 		     EL_BUFSIZ);
965*d0ef721eSBaptiste Daroussin 		 el->el_history.last = el->el_history.buf +
966*d0ef721eSBaptiste Daroussin 			 (el->el_line.lastchar - el->el_line.buffer);
967*d0ef721eSBaptiste Daroussin 	}
968*d0ef721eSBaptiste Daroussin 
969*d0ef721eSBaptiste Daroussin 	/* Lack of a 'count' means oldest, not 1 */
970*d0ef721eSBaptiste Daroussin 	if (!el->el_state.doingarg) {
971*d0ef721eSBaptiste Daroussin 		el->el_history.eventno = 0x7fffffff;
972*d0ef721eSBaptiste Daroussin 		hist_get(el);
973*d0ef721eSBaptiste Daroussin 	} else {
974*d0ef721eSBaptiste Daroussin 		/* This is brain dead, all the rest of this code counts
975*d0ef721eSBaptiste Daroussin 		 * upwards going into the past.  Here we need count in the
976*d0ef721eSBaptiste Daroussin 		 * other direction (to match the output of fc -l).
977*d0ef721eSBaptiste Daroussin 		 * I could change the world, but this seems to suffice.
978*d0ef721eSBaptiste Daroussin 		 */
979*d0ef721eSBaptiste Daroussin 		el->el_history.eventno = 1;
980*d0ef721eSBaptiste Daroussin 		if (hist_get(el) == CC_ERROR)
981*d0ef721eSBaptiste Daroussin 			return CC_ERROR;
982*d0ef721eSBaptiste Daroussin 		el->el_history.eventno = 1 + el->el_history.ev.num
983*d0ef721eSBaptiste Daroussin 					- el->el_state.argument;
984*d0ef721eSBaptiste Daroussin 		if (el->el_history.eventno < 0) {
985*d0ef721eSBaptiste Daroussin 			el->el_history.eventno = sv_event_no;
986*d0ef721eSBaptiste Daroussin 			return CC_ERROR;
987*d0ef721eSBaptiste Daroussin 		}
988*d0ef721eSBaptiste Daroussin 	}
989*d0ef721eSBaptiste Daroussin 	rval = hist_get(el);
990*d0ef721eSBaptiste Daroussin 	if (rval == CC_ERROR)
991*d0ef721eSBaptiste Daroussin 		el->el_history.eventno = sv_event_no;
992*d0ef721eSBaptiste Daroussin 	return rval;
993*d0ef721eSBaptiste Daroussin }
994*d0ef721eSBaptiste Daroussin 
995*d0ef721eSBaptiste Daroussin /* vi_histedit():
996*d0ef721eSBaptiste Daroussin  *	Vi edit history line with vi
997*d0ef721eSBaptiste Daroussin  *	[v]
998*d0ef721eSBaptiste Daroussin  */
999*d0ef721eSBaptiste Daroussin libedit_private el_action_t
1000*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
1001*d0ef721eSBaptiste Daroussin vi_histedit(EditLine *el, wint_t c __attribute__((__unused__)))
1002*d0ef721eSBaptiste Daroussin {
1003*d0ef721eSBaptiste Daroussin 	int fd;
1004*d0ef721eSBaptiste Daroussin 	pid_t pid;
1005*d0ef721eSBaptiste Daroussin 	ssize_t st;
1006*d0ef721eSBaptiste Daroussin 	int status;
1007*d0ef721eSBaptiste Daroussin 	char tempfile[] = "/tmp/histedit.XXXXXXXXXX";
1008*d0ef721eSBaptiste Daroussin 	char *cp = NULL;
1009*d0ef721eSBaptiste Daroussin 	size_t len;
1010*d0ef721eSBaptiste Daroussin 	wchar_t *line = NULL;
1011*d0ef721eSBaptiste Daroussin 
1012*d0ef721eSBaptiste Daroussin 	if (el->el_state.doingarg) {
1013*d0ef721eSBaptiste Daroussin 		if (vi_to_history_line(el, 0) == CC_ERROR)
1014*d0ef721eSBaptiste Daroussin 			return CC_ERROR;
1015*d0ef721eSBaptiste Daroussin 	}
1016*d0ef721eSBaptiste Daroussin 
1017*d0ef721eSBaptiste Daroussin 	fd = mkstemp(tempfile);
1018*d0ef721eSBaptiste Daroussin 	if (fd < 0)
1019*d0ef721eSBaptiste Daroussin 		return CC_ERROR;
1020*d0ef721eSBaptiste Daroussin 	len = (size_t)(el->el_line.lastchar - el->el_line.buffer);
1021*d0ef721eSBaptiste Daroussin #define TMP_BUFSIZ (EL_BUFSIZ * MB_LEN_MAX)
1022*d0ef721eSBaptiste Daroussin 	cp = el_calloc(TMP_BUFSIZ, sizeof(*cp));
1023*d0ef721eSBaptiste Daroussin 	if (cp == NULL)
1024*d0ef721eSBaptiste Daroussin 		goto error;
1025*d0ef721eSBaptiste Daroussin 	line = el_calloc(len + 1, sizeof(*line));
1026*d0ef721eSBaptiste Daroussin 	if (line == NULL)
1027*d0ef721eSBaptiste Daroussin 		goto error;
1028*d0ef721eSBaptiste Daroussin 	wcsncpy(line, el->el_line.buffer, len);
1029*d0ef721eSBaptiste Daroussin 	line[len] = '\0';
1030*d0ef721eSBaptiste Daroussin 	wcstombs(cp, line, TMP_BUFSIZ - 1);
1031*d0ef721eSBaptiste Daroussin 	cp[TMP_BUFSIZ - 1] = '\0';
1032*d0ef721eSBaptiste Daroussin 	len = strlen(cp);
1033*d0ef721eSBaptiste Daroussin 	write(fd, cp, len);
1034*d0ef721eSBaptiste Daroussin 	write(fd, "\n", (size_t)1);
1035*d0ef721eSBaptiste Daroussin 	pid = fork();
1036*d0ef721eSBaptiste Daroussin 	switch (pid) {
1037*d0ef721eSBaptiste Daroussin 	case -1:
1038*d0ef721eSBaptiste Daroussin 		goto error;
1039*d0ef721eSBaptiste Daroussin 	case 0:
1040*d0ef721eSBaptiste Daroussin 		close(fd);
1041*d0ef721eSBaptiste Daroussin 		execlp("vi", "vi", tempfile, (char *)NULL);
1042*d0ef721eSBaptiste Daroussin 		exit(0);
1043*d0ef721eSBaptiste Daroussin 		/*NOTREACHED*/
1044*d0ef721eSBaptiste Daroussin 	default:
1045*d0ef721eSBaptiste Daroussin 		while (waitpid(pid, &status, 0) != pid)
1046*d0ef721eSBaptiste Daroussin 			continue;
1047*d0ef721eSBaptiste Daroussin 		lseek(fd, (off_t)0, SEEK_SET);
1048*d0ef721eSBaptiste Daroussin 		st = read(fd, cp, TMP_BUFSIZ - 1);
1049*d0ef721eSBaptiste Daroussin 		if (st > 0) {
1050*d0ef721eSBaptiste Daroussin 			cp[st] = '\0';
1051*d0ef721eSBaptiste Daroussin 			len = (size_t)(el->el_line.limit - el->el_line.buffer);
1052*d0ef721eSBaptiste Daroussin 			len = mbstowcs(el->el_line.buffer, cp, len);
1053*d0ef721eSBaptiste Daroussin 			if (len > 0 && el->el_line.buffer[len - 1] == '\n')
1054*d0ef721eSBaptiste Daroussin 				--len;
1055*d0ef721eSBaptiste Daroussin 		}
1056*d0ef721eSBaptiste Daroussin 		else
1057*d0ef721eSBaptiste Daroussin 			len = 0;
1058*d0ef721eSBaptiste Daroussin                 el->el_line.cursor = el->el_line.buffer;
1059*d0ef721eSBaptiste Daroussin                 el->el_line.lastchar = el->el_line.buffer + len;
1060*d0ef721eSBaptiste Daroussin 		el_free(cp);
1061*d0ef721eSBaptiste Daroussin                 el_free(line);
1062*d0ef721eSBaptiste Daroussin 		break;
1063*d0ef721eSBaptiste Daroussin 	}
1064*d0ef721eSBaptiste Daroussin 
1065*d0ef721eSBaptiste Daroussin 	close(fd);
1066*d0ef721eSBaptiste Daroussin 	unlink(tempfile);
1067*d0ef721eSBaptiste Daroussin 	/* return CC_REFRESH; */
1068*d0ef721eSBaptiste Daroussin 	return ed_newline(el, 0);
1069*d0ef721eSBaptiste Daroussin error:
1070*d0ef721eSBaptiste Daroussin 	el_free(line);
1071*d0ef721eSBaptiste Daroussin 	el_free(cp);
1072*d0ef721eSBaptiste Daroussin 	close(fd);
1073*d0ef721eSBaptiste Daroussin 	unlink(tempfile);
1074*d0ef721eSBaptiste Daroussin 	return CC_ERROR;
1075*d0ef721eSBaptiste Daroussin }
1076*d0ef721eSBaptiste Daroussin 
1077*d0ef721eSBaptiste Daroussin /* vi_history_word():
1078*d0ef721eSBaptiste Daroussin  *	Vi append word from previous input line
1079*d0ef721eSBaptiste Daroussin  *	[_]
1080*d0ef721eSBaptiste Daroussin  * Who knows where this one came from!
1081*d0ef721eSBaptiste Daroussin  * '_' in vi means 'entire current line', so 'cc' is a synonym for 'c_'
1082*d0ef721eSBaptiste Daroussin  */
1083*d0ef721eSBaptiste Daroussin libedit_private el_action_t
1084*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
1085*d0ef721eSBaptiste Daroussin vi_history_word(EditLine *el, wint_t c __attribute__((__unused__)))
1086*d0ef721eSBaptiste Daroussin {
1087*d0ef721eSBaptiste Daroussin 	const wchar_t *wp = HIST_FIRST(el);
1088*d0ef721eSBaptiste Daroussin 	const wchar_t *wep, *wsp;
1089*d0ef721eSBaptiste Daroussin 	int len;
1090*d0ef721eSBaptiste Daroussin 	wchar_t *cp;
1091*d0ef721eSBaptiste Daroussin 	const wchar_t *lim;
1092*d0ef721eSBaptiste Daroussin 
1093*d0ef721eSBaptiste Daroussin 	if (wp == NULL)
1094*d0ef721eSBaptiste Daroussin 		return CC_ERROR;
1095*d0ef721eSBaptiste Daroussin 
1096*d0ef721eSBaptiste Daroussin 	wep = wsp = NULL;
1097*d0ef721eSBaptiste Daroussin 	do {
1098*d0ef721eSBaptiste Daroussin 		while (iswspace(*wp))
1099*d0ef721eSBaptiste Daroussin 			wp++;
1100*d0ef721eSBaptiste Daroussin 		if (*wp == 0)
1101*d0ef721eSBaptiste Daroussin 			break;
1102*d0ef721eSBaptiste Daroussin 		wsp = wp;
1103*d0ef721eSBaptiste Daroussin 		while (*wp && !iswspace(*wp))
1104*d0ef721eSBaptiste Daroussin 			wp++;
1105*d0ef721eSBaptiste Daroussin 		wep = wp;
1106*d0ef721eSBaptiste Daroussin 	} while ((!el->el_state.doingarg || --el->el_state.argument > 0)
1107*d0ef721eSBaptiste Daroussin 	    && *wp != 0);
1108*d0ef721eSBaptiste Daroussin 
1109*d0ef721eSBaptiste Daroussin 	if (wsp == NULL || (el->el_state.doingarg && el->el_state.argument != 0))
1110*d0ef721eSBaptiste Daroussin 		return CC_ERROR;
1111*d0ef721eSBaptiste Daroussin 
1112*d0ef721eSBaptiste Daroussin 	cv_undo(el);
1113*d0ef721eSBaptiste Daroussin 	len = (int)(wep - wsp);
1114*d0ef721eSBaptiste Daroussin 	if (el->el_line.cursor < el->el_line.lastchar)
1115*d0ef721eSBaptiste Daroussin 		el->el_line.cursor++;
1116*d0ef721eSBaptiste Daroussin 	c_insert(el, len + 1);
1117*d0ef721eSBaptiste Daroussin 	cp = el->el_line.cursor;
1118*d0ef721eSBaptiste Daroussin 	lim = el->el_line.limit;
1119*d0ef721eSBaptiste Daroussin 	if (cp < lim)
1120*d0ef721eSBaptiste Daroussin 		*cp++ = ' ';
1121*d0ef721eSBaptiste Daroussin 	while (wsp < wep && cp < lim)
1122*d0ef721eSBaptiste Daroussin 		*cp++ = *wsp++;
1123*d0ef721eSBaptiste Daroussin 	el->el_line.cursor = cp;
1124*d0ef721eSBaptiste Daroussin 
1125*d0ef721eSBaptiste Daroussin 	el->el_map.current = el->el_map.key;
1126*d0ef721eSBaptiste Daroussin 	return CC_REFRESH;
1127*d0ef721eSBaptiste Daroussin }
1128*d0ef721eSBaptiste Daroussin 
1129*d0ef721eSBaptiste Daroussin /* vi_redo():
1130*d0ef721eSBaptiste Daroussin  *	Vi redo last non-motion command
1131*d0ef721eSBaptiste Daroussin  *	[.]
1132*d0ef721eSBaptiste Daroussin  */
1133*d0ef721eSBaptiste Daroussin libedit_private el_action_t
1134*d0ef721eSBaptiste Daroussin /*ARGSUSED*/
1135*d0ef721eSBaptiste Daroussin vi_redo(EditLine *el, wint_t c __attribute__((__unused__)))
1136*d0ef721eSBaptiste Daroussin {
1137*d0ef721eSBaptiste Daroussin 	c_redo_t *r = &el->el_chared.c_redo;
1138*d0ef721eSBaptiste Daroussin 
1139*d0ef721eSBaptiste Daroussin 	if (!el->el_state.doingarg && r->count) {
1140*d0ef721eSBaptiste Daroussin 		el->el_state.doingarg = 1;
1141*d0ef721eSBaptiste Daroussin 		el->el_state.argument = r->count;
1142*d0ef721eSBaptiste Daroussin 	}
1143*d0ef721eSBaptiste Daroussin 
1144*d0ef721eSBaptiste Daroussin 	el->el_chared.c_vcmd.pos = el->el_line.cursor;
1145*d0ef721eSBaptiste Daroussin 	el->el_chared.c_vcmd.action = r->action;
1146*d0ef721eSBaptiste Daroussin 	if (r->pos != r->buf) {
1147*d0ef721eSBaptiste Daroussin 		if (r->pos + 1 > r->lim)
1148*d0ef721eSBaptiste Daroussin 			/* sanity */
1149*d0ef721eSBaptiste Daroussin 			r->pos = r->lim - 1;
1150*d0ef721eSBaptiste Daroussin 		r->pos[0] = 0;
1151*d0ef721eSBaptiste Daroussin 		el_wpush(el, r->buf);
1152*d0ef721eSBaptiste Daroussin 	}
1153*d0ef721eSBaptiste Daroussin 
1154*d0ef721eSBaptiste Daroussin 	el->el_state.thiscmd = r->cmd;
1155*d0ef721eSBaptiste Daroussin 	el->el_state.thisch = r->ch;
1156*d0ef721eSBaptiste Daroussin 	return (*el->el_map.func[r->cmd])(el, r->ch);
1157*d0ef721eSBaptiste Daroussin }
1158