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