xref: /dflybsd-src/contrib/libedit/src/vi.c (revision 84b940c191e90f5c2d8200c25de3ef0a4f427e9b)
1*84b940c1SJohn Marino /*	$NetBSD: vi.c,v 1.45 2014/06/18 18:12:28 christos Exp $	*/
232fe07f8SJohn Marino 
332fe07f8SJohn Marino /*-
432fe07f8SJohn Marino  * Copyright (c) 1992, 1993
532fe07f8SJohn Marino  *	The Regents of the University of California.  All rights reserved.
632fe07f8SJohn Marino  *
732fe07f8SJohn Marino  * This code is derived from software contributed to Berkeley by
832fe07f8SJohn Marino  * Christos Zoulas of Cornell University.
932fe07f8SJohn Marino  *
1032fe07f8SJohn Marino  * Redistribution and use in source and binary forms, with or without
1132fe07f8SJohn Marino  * modification, are permitted provided that the following conditions
1232fe07f8SJohn Marino  * are met:
1332fe07f8SJohn Marino  * 1. Redistributions of source code must retain the above copyright
1432fe07f8SJohn Marino  *    notice, this list of conditions and the following disclaimer.
1532fe07f8SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
1632fe07f8SJohn Marino  *    notice, this list of conditions and the following disclaimer in the
1732fe07f8SJohn Marino  *    documentation and/or other materials provided with the distribution.
1832fe07f8SJohn Marino  * 3. Neither the name of the University nor the names of its contributors
1932fe07f8SJohn Marino  *    may be used to endorse or promote products derived from this software
2032fe07f8SJohn Marino  *    without specific prior written permission.
2132fe07f8SJohn Marino  *
2232fe07f8SJohn Marino  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2332fe07f8SJohn Marino  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2432fe07f8SJohn Marino  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2532fe07f8SJohn Marino  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2632fe07f8SJohn Marino  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2732fe07f8SJohn Marino  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2832fe07f8SJohn Marino  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2932fe07f8SJohn Marino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3032fe07f8SJohn Marino  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3132fe07f8SJohn Marino  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3232fe07f8SJohn Marino  * SUCH DAMAGE.
3332fe07f8SJohn Marino  */
3432fe07f8SJohn Marino 
3532fe07f8SJohn Marino #include "config.h"
3632fe07f8SJohn Marino #include <stdlib.h>
3732fe07f8SJohn Marino #include <unistd.h>
3832fe07f8SJohn Marino #include <limits.h>
3932fe07f8SJohn Marino #include <sys/wait.h>
4032fe07f8SJohn Marino 
4132fe07f8SJohn Marino #if !defined(lint) && !defined(SCCSID)
4232fe07f8SJohn Marino #if 0
4332fe07f8SJohn Marino static char sccsid[] = "@(#)vi.c	8.1 (Berkeley) 6/4/93";
4432fe07f8SJohn Marino #else
45*84b940c1SJohn Marino __RCSID("$NetBSD: vi.c,v 1.45 2014/06/18 18:12:28 christos Exp $");
4632fe07f8SJohn Marino #endif
4732fe07f8SJohn Marino #endif /* not lint && not SCCSID */
4832fe07f8SJohn Marino 
4932fe07f8SJohn Marino /*
5032fe07f8SJohn Marino  * vi.c: Vi mode commands.
5132fe07f8SJohn Marino  */
5232fe07f8SJohn Marino #include "el.h"
5332fe07f8SJohn Marino 
5432fe07f8SJohn Marino private el_action_t	cv_action(EditLine *, Int);
5532fe07f8SJohn Marino private el_action_t	cv_paste(EditLine *, Int);
5632fe07f8SJohn Marino 
5732fe07f8SJohn Marino /* cv_action():
5832fe07f8SJohn Marino  *	Handle vi actions.
5932fe07f8SJohn Marino  */
6032fe07f8SJohn Marino private el_action_t
6132fe07f8SJohn Marino cv_action(EditLine *el, Int c)
6232fe07f8SJohn Marino {
6332fe07f8SJohn Marino 
6432fe07f8SJohn Marino 	if (el->el_chared.c_vcmd.action != NOP) {
6532fe07f8SJohn Marino 		/* 'cc', 'dd' and (possibly) friends */
6632fe07f8SJohn Marino 		if (c != (Int)el->el_chared.c_vcmd.action)
6732fe07f8SJohn Marino 			return CC_ERROR;
6832fe07f8SJohn Marino 
6932fe07f8SJohn Marino 		if (!(c & YANK))
7032fe07f8SJohn Marino 			cv_undo(el);
7132fe07f8SJohn Marino 		cv_yank(el, el->el_line.buffer,
7232fe07f8SJohn Marino 		    (int)(el->el_line.lastchar - el->el_line.buffer));
7332fe07f8SJohn Marino 		el->el_chared.c_vcmd.action = NOP;
7432fe07f8SJohn Marino 		el->el_chared.c_vcmd.pos = 0;
7532fe07f8SJohn Marino 		if (!(c & YANK)) {
7632fe07f8SJohn Marino 			el->el_line.lastchar = el->el_line.buffer;
7732fe07f8SJohn Marino 			el->el_line.cursor = el->el_line.buffer;
7832fe07f8SJohn Marino 		}
7932fe07f8SJohn Marino 		if (c & INSERT)
8032fe07f8SJohn Marino 			el->el_map.current = el->el_map.key;
8132fe07f8SJohn Marino 
8232fe07f8SJohn Marino 		return CC_REFRESH;
8332fe07f8SJohn Marino 	}
8432fe07f8SJohn Marino 	el->el_chared.c_vcmd.pos = el->el_line.cursor;
8532fe07f8SJohn Marino 	el->el_chared.c_vcmd.action = c;
8632fe07f8SJohn Marino 	return CC_ARGHACK;
8732fe07f8SJohn Marino }
8832fe07f8SJohn Marino 
8932fe07f8SJohn Marino /* cv_paste():
9032fe07f8SJohn Marino  *	Paste previous deletion before or after the cursor
9132fe07f8SJohn Marino  */
9232fe07f8SJohn Marino private el_action_t
9332fe07f8SJohn Marino cv_paste(EditLine *el, Int c)
9432fe07f8SJohn Marino {
9532fe07f8SJohn Marino 	c_kill_t *k = &el->el_chared.c_kill;
9632fe07f8SJohn Marino 	size_t len = (size_t)(k->last - k->buf);
9732fe07f8SJohn Marino 
9832fe07f8SJohn Marino 	if (k->buf == NULL || len == 0)
9932fe07f8SJohn Marino 		return CC_ERROR;
10032fe07f8SJohn Marino #ifdef DEBUG_PASTE
10132fe07f8SJohn Marino 	(void) fprintf(el->el_errfile, "Paste: \"%.*s\"\n", (int)len, k->buf);
10232fe07f8SJohn Marino #endif
10332fe07f8SJohn Marino 
10432fe07f8SJohn Marino 	cv_undo(el);
10532fe07f8SJohn Marino 
10632fe07f8SJohn Marino 	if (!c && el->el_line.cursor < el->el_line.lastchar)
10732fe07f8SJohn Marino 		el->el_line.cursor++;
10832fe07f8SJohn Marino 
10932fe07f8SJohn Marino 	c_insert(el, (int)len);
11032fe07f8SJohn Marino 	if (el->el_line.cursor + len > el->el_line.lastchar)
11132fe07f8SJohn Marino 		return CC_ERROR;
11232fe07f8SJohn Marino 	(void) memcpy(el->el_line.cursor, k->buf, len *
11332fe07f8SJohn Marino 	    sizeof(*el->el_line.cursor));
11432fe07f8SJohn Marino 
11532fe07f8SJohn Marino 	return CC_REFRESH;
11632fe07f8SJohn Marino }
11732fe07f8SJohn Marino 
11832fe07f8SJohn Marino 
11932fe07f8SJohn Marino /* vi_paste_next():
12032fe07f8SJohn Marino  *	Vi paste previous deletion to the right of the cursor
12132fe07f8SJohn Marino  *	[p]
12232fe07f8SJohn Marino  */
12332fe07f8SJohn Marino protected el_action_t
12432fe07f8SJohn Marino /*ARGSUSED*/
12532fe07f8SJohn Marino vi_paste_next(EditLine *el, Int c __attribute__((__unused__)))
12632fe07f8SJohn Marino {
12732fe07f8SJohn Marino 
12832fe07f8SJohn Marino 	return cv_paste(el, 0);
12932fe07f8SJohn Marino }
13032fe07f8SJohn Marino 
13132fe07f8SJohn Marino 
13232fe07f8SJohn Marino /* vi_paste_prev():
13332fe07f8SJohn Marino  *	Vi paste previous deletion to the left of the cursor
13432fe07f8SJohn Marino  *	[P]
13532fe07f8SJohn Marino  */
13632fe07f8SJohn Marino protected el_action_t
13732fe07f8SJohn Marino /*ARGSUSED*/
13832fe07f8SJohn Marino vi_paste_prev(EditLine *el, Int c __attribute__((__unused__)))
13932fe07f8SJohn Marino {
14032fe07f8SJohn Marino 
14132fe07f8SJohn Marino 	return cv_paste(el, 1);
14232fe07f8SJohn Marino }
14332fe07f8SJohn Marino 
14432fe07f8SJohn Marino 
14532fe07f8SJohn Marino /* vi_prev_big_word():
14632fe07f8SJohn Marino  *	Vi move to the previous space delimited word
14732fe07f8SJohn Marino  *	[B]
14832fe07f8SJohn Marino  */
14932fe07f8SJohn Marino protected el_action_t
15032fe07f8SJohn Marino /*ARGSUSED*/
15132fe07f8SJohn Marino vi_prev_big_word(EditLine *el, Int c __attribute__((__unused__)))
15232fe07f8SJohn Marino {
15332fe07f8SJohn Marino 
15432fe07f8SJohn Marino 	if (el->el_line.cursor == el->el_line.buffer)
15532fe07f8SJohn Marino 		return CC_ERROR;
15632fe07f8SJohn Marino 
15732fe07f8SJohn Marino 	el->el_line.cursor = cv_prev_word(el->el_line.cursor,
15832fe07f8SJohn Marino 	    el->el_line.buffer,
15932fe07f8SJohn Marino 	    el->el_state.argument,
16032fe07f8SJohn Marino 	    cv__isWord);
16132fe07f8SJohn Marino 
16232fe07f8SJohn Marino 	if (el->el_chared.c_vcmd.action != NOP) {
16332fe07f8SJohn Marino 		cv_delfini(el);
16432fe07f8SJohn Marino 		return CC_REFRESH;
16532fe07f8SJohn Marino 	}
16632fe07f8SJohn Marino 	return CC_CURSOR;
16732fe07f8SJohn Marino }
16832fe07f8SJohn Marino 
16932fe07f8SJohn Marino 
17032fe07f8SJohn Marino /* vi_prev_word():
17132fe07f8SJohn Marino  *	Vi move to the previous word
17232fe07f8SJohn Marino  *	[b]
17332fe07f8SJohn Marino  */
17432fe07f8SJohn Marino protected el_action_t
17532fe07f8SJohn Marino /*ARGSUSED*/
17632fe07f8SJohn Marino vi_prev_word(EditLine *el, Int c __attribute__((__unused__)))
17732fe07f8SJohn Marino {
17832fe07f8SJohn Marino 
17932fe07f8SJohn Marino 	if (el->el_line.cursor == el->el_line.buffer)
18032fe07f8SJohn Marino 		return CC_ERROR;
18132fe07f8SJohn Marino 
18232fe07f8SJohn Marino 	el->el_line.cursor = cv_prev_word(el->el_line.cursor,
18332fe07f8SJohn Marino 	    el->el_line.buffer,
18432fe07f8SJohn Marino 	    el->el_state.argument,
18532fe07f8SJohn Marino 	    cv__isword);
18632fe07f8SJohn Marino 
18732fe07f8SJohn Marino 	if (el->el_chared.c_vcmd.action != NOP) {
18832fe07f8SJohn Marino 		cv_delfini(el);
18932fe07f8SJohn Marino 		return CC_REFRESH;
19032fe07f8SJohn Marino 	}
19132fe07f8SJohn Marino 	return CC_CURSOR;
19232fe07f8SJohn Marino }
19332fe07f8SJohn Marino 
19432fe07f8SJohn Marino 
19532fe07f8SJohn Marino /* vi_next_big_word():
19632fe07f8SJohn Marino  *	Vi move to the next space delimited word
19732fe07f8SJohn Marino  *	[W]
19832fe07f8SJohn Marino  */
19932fe07f8SJohn Marino protected el_action_t
20032fe07f8SJohn Marino /*ARGSUSED*/
20132fe07f8SJohn Marino vi_next_big_word(EditLine *el, Int c __attribute__((__unused__)))
20232fe07f8SJohn Marino {
20332fe07f8SJohn Marino 
20432fe07f8SJohn Marino 	if (el->el_line.cursor >= el->el_line.lastchar - 1)
20532fe07f8SJohn Marino 		return CC_ERROR;
20632fe07f8SJohn Marino 
20732fe07f8SJohn Marino 	el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
20832fe07f8SJohn Marino 	    el->el_line.lastchar, el->el_state.argument, cv__isWord);
20932fe07f8SJohn Marino 
21032fe07f8SJohn Marino 	if (el->el_map.type == MAP_VI)
21132fe07f8SJohn Marino 		if (el->el_chared.c_vcmd.action != NOP) {
21232fe07f8SJohn Marino 			cv_delfini(el);
21332fe07f8SJohn Marino 			return CC_REFRESH;
21432fe07f8SJohn Marino 		}
21532fe07f8SJohn Marino 	return CC_CURSOR;
21632fe07f8SJohn Marino }
21732fe07f8SJohn Marino 
21832fe07f8SJohn Marino 
21932fe07f8SJohn Marino /* vi_next_word():
22032fe07f8SJohn Marino  *	Vi move to the next word
22132fe07f8SJohn Marino  *	[w]
22232fe07f8SJohn Marino  */
22332fe07f8SJohn Marino protected el_action_t
22432fe07f8SJohn Marino /*ARGSUSED*/
22532fe07f8SJohn Marino vi_next_word(EditLine *el, Int c __attribute__((__unused__)))
22632fe07f8SJohn Marino {
22732fe07f8SJohn Marino 
22832fe07f8SJohn Marino 	if (el->el_line.cursor >= el->el_line.lastchar - 1)
22932fe07f8SJohn Marino 		return CC_ERROR;
23032fe07f8SJohn Marino 
23132fe07f8SJohn Marino 	el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
23232fe07f8SJohn Marino 	    el->el_line.lastchar, el->el_state.argument, cv__isword);
23332fe07f8SJohn Marino 
23432fe07f8SJohn Marino 	if (el->el_map.type == MAP_VI)
23532fe07f8SJohn Marino 		if (el->el_chared.c_vcmd.action != NOP) {
23632fe07f8SJohn Marino 			cv_delfini(el);
23732fe07f8SJohn Marino 			return CC_REFRESH;
23832fe07f8SJohn Marino 		}
23932fe07f8SJohn Marino 	return CC_CURSOR;
24032fe07f8SJohn Marino }
24132fe07f8SJohn Marino 
24232fe07f8SJohn Marino 
24332fe07f8SJohn Marino /* vi_change_case():
24432fe07f8SJohn Marino  *	Vi change case of character under the cursor and advance one character
24532fe07f8SJohn Marino  *	[~]
24632fe07f8SJohn Marino  */
24732fe07f8SJohn Marino protected el_action_t
24832fe07f8SJohn Marino vi_change_case(EditLine *el, Int c)
24932fe07f8SJohn Marino {
25032fe07f8SJohn Marino 	int i;
25132fe07f8SJohn Marino 
25232fe07f8SJohn Marino 	if (el->el_line.cursor >= el->el_line.lastchar)
25332fe07f8SJohn Marino 		return CC_ERROR;
25432fe07f8SJohn Marino 	cv_undo(el);
25532fe07f8SJohn Marino 	for (i = 0; i < el->el_state.argument; i++) {
25632fe07f8SJohn Marino 
25732fe07f8SJohn Marino 		c = *el->el_line.cursor;
25832fe07f8SJohn Marino 		if (Isupper(c))
25932fe07f8SJohn Marino 			*el->el_line.cursor = Tolower(c);
26032fe07f8SJohn Marino 		else if (Islower(c))
26132fe07f8SJohn Marino 			*el->el_line.cursor = Toupper(c);
26232fe07f8SJohn Marino 
26332fe07f8SJohn Marino 		if (++el->el_line.cursor >= el->el_line.lastchar) {
26432fe07f8SJohn Marino 			el->el_line.cursor--;
26532fe07f8SJohn Marino 			re_fastaddc(el);
26632fe07f8SJohn Marino 			break;
26732fe07f8SJohn Marino 		}
26832fe07f8SJohn Marino 		re_fastaddc(el);
26932fe07f8SJohn Marino 	}
27032fe07f8SJohn Marino 	return CC_NORM;
27132fe07f8SJohn Marino }
27232fe07f8SJohn Marino 
27332fe07f8SJohn Marino 
27432fe07f8SJohn Marino /* vi_change_meta():
27532fe07f8SJohn Marino  *	Vi change prefix command
27632fe07f8SJohn Marino  *	[c]
27732fe07f8SJohn Marino  */
27832fe07f8SJohn Marino protected el_action_t
27932fe07f8SJohn Marino /*ARGSUSED*/
28032fe07f8SJohn Marino vi_change_meta(EditLine *el, Int c __attribute__((__unused__)))
28132fe07f8SJohn Marino {
28232fe07f8SJohn Marino 
28332fe07f8SJohn Marino 	/*
28432fe07f8SJohn Marino          * Delete with insert == change: first we delete and then we leave in
28532fe07f8SJohn Marino          * insert mode.
28632fe07f8SJohn Marino          */
28732fe07f8SJohn Marino 	return cv_action(el, DELETE | INSERT);
28832fe07f8SJohn Marino }
28932fe07f8SJohn Marino 
29032fe07f8SJohn Marino 
29132fe07f8SJohn Marino /* vi_insert_at_bol():
29232fe07f8SJohn Marino  *	Vi enter insert mode at the beginning of line
29332fe07f8SJohn Marino  *	[I]
29432fe07f8SJohn Marino  */
29532fe07f8SJohn Marino protected el_action_t
29632fe07f8SJohn Marino /*ARGSUSED*/
29732fe07f8SJohn Marino vi_insert_at_bol(EditLine *el, Int c __attribute__((__unused__)))
29832fe07f8SJohn Marino {
29932fe07f8SJohn Marino 
30032fe07f8SJohn Marino 	el->el_line.cursor = el->el_line.buffer;
30132fe07f8SJohn Marino 	cv_undo(el);
30232fe07f8SJohn Marino 	el->el_map.current = el->el_map.key;
30332fe07f8SJohn Marino 	return CC_CURSOR;
30432fe07f8SJohn Marino }
30532fe07f8SJohn Marino 
30632fe07f8SJohn Marino 
30732fe07f8SJohn Marino /* vi_replace_char():
30832fe07f8SJohn Marino  *	Vi replace character under the cursor with the next character typed
30932fe07f8SJohn Marino  *	[r]
31032fe07f8SJohn Marino  */
31132fe07f8SJohn Marino protected el_action_t
31232fe07f8SJohn Marino /*ARGSUSED*/
31332fe07f8SJohn Marino vi_replace_char(EditLine *el, Int c __attribute__((__unused__)))
31432fe07f8SJohn Marino {
31532fe07f8SJohn Marino 
31632fe07f8SJohn Marino 	if (el->el_line.cursor >= el->el_line.lastchar)
31732fe07f8SJohn Marino 		return CC_ERROR;
31832fe07f8SJohn Marino 
31932fe07f8SJohn Marino 	el->el_map.current = el->el_map.key;
32032fe07f8SJohn Marino 	el->el_state.inputmode = MODE_REPLACE_1;
32132fe07f8SJohn Marino 	cv_undo(el);
32232fe07f8SJohn Marino 	return CC_ARGHACK;
32332fe07f8SJohn Marino }
32432fe07f8SJohn Marino 
32532fe07f8SJohn Marino 
32632fe07f8SJohn Marino /* vi_replace_mode():
32732fe07f8SJohn Marino  *	Vi enter replace mode
32832fe07f8SJohn Marino  *	[R]
32932fe07f8SJohn Marino  */
33032fe07f8SJohn Marino protected el_action_t
33132fe07f8SJohn Marino /*ARGSUSED*/
33232fe07f8SJohn Marino vi_replace_mode(EditLine *el, Int c __attribute__((__unused__)))
33332fe07f8SJohn Marino {
33432fe07f8SJohn Marino 
33532fe07f8SJohn Marino 	el->el_map.current = el->el_map.key;
33632fe07f8SJohn Marino 	el->el_state.inputmode = MODE_REPLACE;
33732fe07f8SJohn Marino 	cv_undo(el);
33832fe07f8SJohn Marino 	return CC_NORM;
33932fe07f8SJohn Marino }
34032fe07f8SJohn Marino 
34132fe07f8SJohn Marino 
34232fe07f8SJohn Marino /* vi_substitute_char():
34332fe07f8SJohn Marino  *	Vi replace character under the cursor and enter insert mode
34432fe07f8SJohn Marino  *	[s]
34532fe07f8SJohn Marino  */
34632fe07f8SJohn Marino protected el_action_t
34732fe07f8SJohn Marino /*ARGSUSED*/
34832fe07f8SJohn Marino vi_substitute_char(EditLine *el, Int c __attribute__((__unused__)))
34932fe07f8SJohn Marino {
35032fe07f8SJohn Marino 
35132fe07f8SJohn Marino 	c_delafter(el, el->el_state.argument);
35232fe07f8SJohn Marino 	el->el_map.current = el->el_map.key;
35332fe07f8SJohn Marino 	return CC_REFRESH;
35432fe07f8SJohn Marino }
35532fe07f8SJohn Marino 
35632fe07f8SJohn Marino 
35732fe07f8SJohn Marino /* vi_substitute_line():
35832fe07f8SJohn Marino  *	Vi substitute entire line
35932fe07f8SJohn Marino  *	[S]
36032fe07f8SJohn Marino  */
36132fe07f8SJohn Marino protected el_action_t
36232fe07f8SJohn Marino /*ARGSUSED*/
36332fe07f8SJohn Marino vi_substitute_line(EditLine *el, Int c __attribute__((__unused__)))
36432fe07f8SJohn Marino {
36532fe07f8SJohn Marino 
36632fe07f8SJohn Marino 	cv_undo(el);
36732fe07f8SJohn Marino 	cv_yank(el, el->el_line.buffer,
36832fe07f8SJohn Marino 	    (int)(el->el_line.lastchar - el->el_line.buffer));
36932fe07f8SJohn Marino 	(void) em_kill_line(el, 0);
37032fe07f8SJohn Marino 	el->el_map.current = el->el_map.key;
37132fe07f8SJohn Marino 	return CC_REFRESH;
37232fe07f8SJohn Marino }
37332fe07f8SJohn Marino 
37432fe07f8SJohn Marino 
37532fe07f8SJohn Marino /* vi_change_to_eol():
37632fe07f8SJohn Marino  *	Vi change to end of line
37732fe07f8SJohn Marino  *	[C]
37832fe07f8SJohn Marino  */
37932fe07f8SJohn Marino protected el_action_t
38032fe07f8SJohn Marino /*ARGSUSED*/
38132fe07f8SJohn Marino vi_change_to_eol(EditLine *el, Int c __attribute__((__unused__)))
38232fe07f8SJohn Marino {
38332fe07f8SJohn Marino 
38432fe07f8SJohn Marino 	cv_undo(el);
38532fe07f8SJohn Marino 	cv_yank(el, el->el_line.cursor,
38632fe07f8SJohn Marino 	    (int)(el->el_line.lastchar - el->el_line.cursor));
38732fe07f8SJohn Marino 	(void) ed_kill_line(el, 0);
38832fe07f8SJohn Marino 	el->el_map.current = el->el_map.key;
38932fe07f8SJohn Marino 	return CC_REFRESH;
39032fe07f8SJohn Marino }
39132fe07f8SJohn Marino 
39232fe07f8SJohn Marino 
39332fe07f8SJohn Marino /* vi_insert():
39432fe07f8SJohn Marino  *	Vi enter insert mode
39532fe07f8SJohn Marino  *	[i]
39632fe07f8SJohn Marino  */
39732fe07f8SJohn Marino protected el_action_t
39832fe07f8SJohn Marino /*ARGSUSED*/
39932fe07f8SJohn Marino vi_insert(EditLine *el, Int c __attribute__((__unused__)))
40032fe07f8SJohn Marino {
40132fe07f8SJohn Marino 
40232fe07f8SJohn Marino 	el->el_map.current = el->el_map.key;
40332fe07f8SJohn Marino 	cv_undo(el);
40432fe07f8SJohn Marino 	return CC_NORM;
40532fe07f8SJohn Marino }
40632fe07f8SJohn Marino 
40732fe07f8SJohn Marino 
40832fe07f8SJohn Marino /* vi_add():
40932fe07f8SJohn Marino  *	Vi enter insert mode after the cursor
41032fe07f8SJohn Marino  *	[a]
41132fe07f8SJohn Marino  */
41232fe07f8SJohn Marino protected el_action_t
41332fe07f8SJohn Marino /*ARGSUSED*/
41432fe07f8SJohn Marino vi_add(EditLine *el, Int c __attribute__((__unused__)))
41532fe07f8SJohn Marino {
41632fe07f8SJohn Marino 	int ret;
41732fe07f8SJohn Marino 
41832fe07f8SJohn Marino 	el->el_map.current = el->el_map.key;
41932fe07f8SJohn Marino 	if (el->el_line.cursor < el->el_line.lastchar) {
42032fe07f8SJohn Marino 		el->el_line.cursor++;
42132fe07f8SJohn Marino 		if (el->el_line.cursor > el->el_line.lastchar)
42232fe07f8SJohn Marino 			el->el_line.cursor = el->el_line.lastchar;
42332fe07f8SJohn Marino 		ret = CC_CURSOR;
42432fe07f8SJohn Marino 	} else
42532fe07f8SJohn Marino 		ret = CC_NORM;
42632fe07f8SJohn Marino 
42732fe07f8SJohn Marino 	cv_undo(el);
42832fe07f8SJohn Marino 
42932fe07f8SJohn Marino 	return (el_action_t)ret;
43032fe07f8SJohn Marino }
43132fe07f8SJohn Marino 
43232fe07f8SJohn Marino 
43332fe07f8SJohn Marino /* vi_add_at_eol():
43432fe07f8SJohn Marino  *	Vi enter insert mode at end of line
43532fe07f8SJohn Marino  *	[A]
43632fe07f8SJohn Marino  */
43732fe07f8SJohn Marino protected el_action_t
43832fe07f8SJohn Marino /*ARGSUSED*/
43932fe07f8SJohn Marino vi_add_at_eol(EditLine *el, Int c __attribute__((__unused__)))
44032fe07f8SJohn Marino {
44132fe07f8SJohn Marino 
44232fe07f8SJohn Marino 	el->el_map.current = el->el_map.key;
44332fe07f8SJohn Marino 	el->el_line.cursor = el->el_line.lastchar;
44432fe07f8SJohn Marino 	cv_undo(el);
44532fe07f8SJohn Marino 	return CC_CURSOR;
44632fe07f8SJohn Marino }
44732fe07f8SJohn Marino 
44832fe07f8SJohn Marino 
44932fe07f8SJohn Marino /* vi_delete_meta():
45032fe07f8SJohn Marino  *	Vi delete prefix command
45132fe07f8SJohn Marino  *	[d]
45232fe07f8SJohn Marino  */
45332fe07f8SJohn Marino protected el_action_t
45432fe07f8SJohn Marino /*ARGSUSED*/
45532fe07f8SJohn Marino vi_delete_meta(EditLine *el, Int c __attribute__((__unused__)))
45632fe07f8SJohn Marino {
45732fe07f8SJohn Marino 
45832fe07f8SJohn Marino 	return cv_action(el, DELETE);
45932fe07f8SJohn Marino }
46032fe07f8SJohn Marino 
46132fe07f8SJohn Marino 
46232fe07f8SJohn Marino /* vi_end_big_word():
46332fe07f8SJohn Marino  *	Vi move to the end of the current space delimited word
46432fe07f8SJohn Marino  *	[E]
46532fe07f8SJohn Marino  */
46632fe07f8SJohn Marino protected el_action_t
46732fe07f8SJohn Marino /*ARGSUSED*/
46832fe07f8SJohn Marino vi_end_big_word(EditLine *el, Int c __attribute__((__unused__)))
46932fe07f8SJohn Marino {
47032fe07f8SJohn Marino 
47132fe07f8SJohn Marino 	if (el->el_line.cursor == el->el_line.lastchar)
47232fe07f8SJohn Marino 		return CC_ERROR;
47332fe07f8SJohn Marino 
47432fe07f8SJohn Marino 	el->el_line.cursor = cv__endword(el->el_line.cursor,
47532fe07f8SJohn Marino 	    el->el_line.lastchar, el->el_state.argument, cv__isWord);
47632fe07f8SJohn Marino 
47732fe07f8SJohn Marino 	if (el->el_chared.c_vcmd.action != NOP) {
47832fe07f8SJohn Marino 		el->el_line.cursor++;
47932fe07f8SJohn Marino 		cv_delfini(el);
48032fe07f8SJohn Marino 		return CC_REFRESH;
48132fe07f8SJohn Marino 	}
48232fe07f8SJohn Marino 	return CC_CURSOR;
48332fe07f8SJohn Marino }
48432fe07f8SJohn Marino 
48532fe07f8SJohn Marino 
48632fe07f8SJohn Marino /* vi_end_word():
48732fe07f8SJohn Marino  *	Vi move to the end of the current word
48832fe07f8SJohn Marino  *	[e]
48932fe07f8SJohn Marino  */
49032fe07f8SJohn Marino protected el_action_t
49132fe07f8SJohn Marino /*ARGSUSED*/
49232fe07f8SJohn Marino vi_end_word(EditLine *el, Int c __attribute__((__unused__)))
49332fe07f8SJohn Marino {
49432fe07f8SJohn Marino 
49532fe07f8SJohn Marino 	if (el->el_line.cursor == el->el_line.lastchar)
49632fe07f8SJohn Marino 		return CC_ERROR;
49732fe07f8SJohn Marino 
49832fe07f8SJohn Marino 	el->el_line.cursor = cv__endword(el->el_line.cursor,
49932fe07f8SJohn Marino 	    el->el_line.lastchar, el->el_state.argument, cv__isword);
50032fe07f8SJohn Marino 
50132fe07f8SJohn Marino 	if (el->el_chared.c_vcmd.action != NOP) {
50232fe07f8SJohn Marino 		el->el_line.cursor++;
50332fe07f8SJohn Marino 		cv_delfini(el);
50432fe07f8SJohn Marino 		return CC_REFRESH;
50532fe07f8SJohn Marino 	}
50632fe07f8SJohn Marino 	return CC_CURSOR;
50732fe07f8SJohn Marino }
50832fe07f8SJohn Marino 
50932fe07f8SJohn Marino 
51032fe07f8SJohn Marino /* vi_undo():
51132fe07f8SJohn Marino  *	Vi undo last change
51232fe07f8SJohn Marino  *	[u]
51332fe07f8SJohn Marino  */
51432fe07f8SJohn Marino protected el_action_t
51532fe07f8SJohn Marino /*ARGSUSED*/
51632fe07f8SJohn Marino vi_undo(EditLine *el, Int c __attribute__((__unused__)))
51732fe07f8SJohn Marino {
51832fe07f8SJohn Marino 	c_undo_t un = el->el_chared.c_undo;
51932fe07f8SJohn Marino 
52032fe07f8SJohn Marino 	if (un.len == -1)
52132fe07f8SJohn Marino 		return CC_ERROR;
52232fe07f8SJohn Marino 
52332fe07f8SJohn Marino 	/* switch line buffer and undo buffer */
52432fe07f8SJohn Marino 	el->el_chared.c_undo.buf = el->el_line.buffer;
52532fe07f8SJohn Marino 	el->el_chared.c_undo.len = el->el_line.lastchar - el->el_line.buffer;
52632fe07f8SJohn Marino 	el->el_chared.c_undo.cursor =
52732fe07f8SJohn Marino 	    (int)(el->el_line.cursor - el->el_line.buffer);
52832fe07f8SJohn Marino 	el->el_line.limit = un.buf + (el->el_line.limit - el->el_line.buffer);
52932fe07f8SJohn Marino 	el->el_line.buffer = un.buf;
53032fe07f8SJohn Marino 	el->el_line.cursor = un.buf + un.cursor;
53132fe07f8SJohn Marino 	el->el_line.lastchar = un.buf + un.len;
53232fe07f8SJohn Marino 
53332fe07f8SJohn Marino 	return CC_REFRESH;
53432fe07f8SJohn Marino }
53532fe07f8SJohn Marino 
53632fe07f8SJohn Marino 
53732fe07f8SJohn Marino /* vi_command_mode():
53832fe07f8SJohn Marino  *	Vi enter command mode (use alternative key bindings)
53932fe07f8SJohn Marino  *	[<ESC>]
54032fe07f8SJohn Marino  */
54132fe07f8SJohn Marino protected el_action_t
54232fe07f8SJohn Marino /*ARGSUSED*/
54332fe07f8SJohn Marino vi_command_mode(EditLine *el, Int c __attribute__((__unused__)))
54432fe07f8SJohn Marino {
54532fe07f8SJohn Marino 
54632fe07f8SJohn Marino 	/* [Esc] cancels pending action */
54732fe07f8SJohn Marino 	el->el_chared.c_vcmd.action = NOP;
54832fe07f8SJohn Marino 	el->el_chared.c_vcmd.pos = 0;
54932fe07f8SJohn Marino 
55032fe07f8SJohn Marino 	el->el_state.doingarg = 0;
55132fe07f8SJohn Marino 
55232fe07f8SJohn Marino 	el->el_state.inputmode = MODE_INSERT;
55332fe07f8SJohn Marino 	el->el_map.current = el->el_map.alt;
55432fe07f8SJohn Marino #ifdef VI_MOVE
55532fe07f8SJohn Marino 	if (el->el_line.cursor > el->el_line.buffer)
55632fe07f8SJohn Marino 		el->el_line.cursor--;
55732fe07f8SJohn Marino #endif
55832fe07f8SJohn Marino 	return CC_CURSOR;
55932fe07f8SJohn Marino }
56032fe07f8SJohn Marino 
56132fe07f8SJohn Marino 
56232fe07f8SJohn Marino /* vi_zero():
56332fe07f8SJohn Marino  *	Vi move to the beginning of line
56432fe07f8SJohn Marino  *	[0]
56532fe07f8SJohn Marino  */
56632fe07f8SJohn Marino protected el_action_t
56732fe07f8SJohn Marino vi_zero(EditLine *el, Int c)
56832fe07f8SJohn Marino {
56932fe07f8SJohn Marino 
57032fe07f8SJohn Marino 	if (el->el_state.doingarg)
57132fe07f8SJohn Marino 		return ed_argument_digit(el, c);
57232fe07f8SJohn Marino 
57332fe07f8SJohn Marino 	el->el_line.cursor = el->el_line.buffer;
57432fe07f8SJohn Marino 	if (el->el_chared.c_vcmd.action != NOP) {
57532fe07f8SJohn Marino 		cv_delfini(el);
57632fe07f8SJohn Marino 		return CC_REFRESH;
57732fe07f8SJohn Marino 	}
57832fe07f8SJohn Marino 	return CC_CURSOR;
57932fe07f8SJohn Marino }
58032fe07f8SJohn Marino 
58132fe07f8SJohn Marino 
58232fe07f8SJohn Marino /* vi_delete_prev_char():
58332fe07f8SJohn Marino  * 	Vi move to previous character (backspace)
58432fe07f8SJohn Marino  *	[^H] in insert mode only
58532fe07f8SJohn Marino  */
58632fe07f8SJohn Marino protected el_action_t
58732fe07f8SJohn Marino /*ARGSUSED*/
58832fe07f8SJohn Marino vi_delete_prev_char(EditLine *el, Int c __attribute__((__unused__)))
58932fe07f8SJohn Marino {
59032fe07f8SJohn Marino 
59132fe07f8SJohn Marino 	if (el->el_line.cursor <= el->el_line.buffer)
59232fe07f8SJohn Marino 		return CC_ERROR;
59332fe07f8SJohn Marino 
59432fe07f8SJohn Marino 	c_delbefore1(el);
59532fe07f8SJohn Marino 	el->el_line.cursor--;
59632fe07f8SJohn Marino 	return CC_REFRESH;
59732fe07f8SJohn Marino }
59832fe07f8SJohn Marino 
59932fe07f8SJohn Marino 
60032fe07f8SJohn Marino /* vi_list_or_eof():
60132fe07f8SJohn Marino  *	Vi list choices for completion or indicate end of file if empty line
60232fe07f8SJohn Marino  *	[^D]
60332fe07f8SJohn Marino  */
60432fe07f8SJohn Marino protected el_action_t
60532fe07f8SJohn Marino /*ARGSUSED*/
60632fe07f8SJohn Marino vi_list_or_eof(EditLine *el, Int c)
60732fe07f8SJohn Marino {
60832fe07f8SJohn Marino 
60932fe07f8SJohn Marino 	if (el->el_line.cursor == el->el_line.lastchar) {
61032fe07f8SJohn Marino 		if (el->el_line.cursor == el->el_line.buffer) {
61132fe07f8SJohn Marino 			terminal_writec(el, c);	/* then do a EOF */
61232fe07f8SJohn Marino 			return CC_EOF;
61332fe07f8SJohn Marino 		} else {
61432fe07f8SJohn Marino 			/*
61532fe07f8SJohn Marino 			 * Here we could list completions, but it is an
61632fe07f8SJohn Marino 			 * error right now
61732fe07f8SJohn Marino 			 */
61832fe07f8SJohn Marino 			terminal_beep(el);
61932fe07f8SJohn Marino 			return CC_ERROR;
62032fe07f8SJohn Marino 		}
62132fe07f8SJohn Marino 	} else {
62232fe07f8SJohn Marino #ifdef notyet
62332fe07f8SJohn Marino 		re_goto_bottom(el);
62432fe07f8SJohn Marino 		*el->el_line.lastchar = '\0';	/* just in case */
62532fe07f8SJohn Marino 		return CC_LIST_CHOICES;
62632fe07f8SJohn Marino #else
62732fe07f8SJohn Marino 		/*
62832fe07f8SJohn Marino 		 * Just complain for now.
62932fe07f8SJohn Marino 		 */
63032fe07f8SJohn Marino 		terminal_beep(el);
63132fe07f8SJohn Marino 		return CC_ERROR;
63232fe07f8SJohn Marino #endif
63332fe07f8SJohn Marino 	}
63432fe07f8SJohn Marino }
63532fe07f8SJohn Marino 
63632fe07f8SJohn Marino 
63732fe07f8SJohn Marino /* vi_kill_line_prev():
63832fe07f8SJohn Marino  *	Vi cut from beginning of line to cursor
63932fe07f8SJohn Marino  *	[^U]
64032fe07f8SJohn Marino  */
64132fe07f8SJohn Marino protected el_action_t
64232fe07f8SJohn Marino /*ARGSUSED*/
64332fe07f8SJohn Marino vi_kill_line_prev(EditLine *el, Int c __attribute__((__unused__)))
64432fe07f8SJohn Marino {
64532fe07f8SJohn Marino 	Char *kp, *cp;
64632fe07f8SJohn Marino 
64732fe07f8SJohn Marino 	cp = el->el_line.buffer;
64832fe07f8SJohn Marino 	kp = el->el_chared.c_kill.buf;
64932fe07f8SJohn Marino 	while (cp < el->el_line.cursor)
65032fe07f8SJohn Marino 		*kp++ = *cp++;	/* copy it */
65132fe07f8SJohn Marino 	el->el_chared.c_kill.last = kp;
65232fe07f8SJohn Marino 	c_delbefore(el, (int)(el->el_line.cursor - el->el_line.buffer));
65332fe07f8SJohn Marino 	el->el_line.cursor = el->el_line.buffer;	/* zap! */
65432fe07f8SJohn Marino 	return CC_REFRESH;
65532fe07f8SJohn Marino }
65632fe07f8SJohn Marino 
65732fe07f8SJohn Marino 
65832fe07f8SJohn Marino /* vi_search_prev():
65932fe07f8SJohn Marino  *	Vi search history previous
66032fe07f8SJohn Marino  *	[?]
66132fe07f8SJohn Marino  */
66232fe07f8SJohn Marino protected el_action_t
66332fe07f8SJohn Marino /*ARGSUSED*/
66432fe07f8SJohn Marino vi_search_prev(EditLine *el, Int c __attribute__((__unused__)))
66532fe07f8SJohn Marino {
66632fe07f8SJohn Marino 
66732fe07f8SJohn Marino 	return cv_search(el, ED_SEARCH_PREV_HISTORY);
66832fe07f8SJohn Marino }
66932fe07f8SJohn Marino 
67032fe07f8SJohn Marino 
67132fe07f8SJohn Marino /* vi_search_next():
67232fe07f8SJohn Marino  *	Vi search history next
67332fe07f8SJohn Marino  *	[/]
67432fe07f8SJohn Marino  */
67532fe07f8SJohn Marino protected el_action_t
67632fe07f8SJohn Marino /*ARGSUSED*/
67732fe07f8SJohn Marino vi_search_next(EditLine *el, Int c __attribute__((__unused__)))
67832fe07f8SJohn Marino {
67932fe07f8SJohn Marino 
68032fe07f8SJohn Marino 	return cv_search(el, ED_SEARCH_NEXT_HISTORY);
68132fe07f8SJohn Marino }
68232fe07f8SJohn Marino 
68332fe07f8SJohn Marino 
68432fe07f8SJohn Marino /* vi_repeat_search_next():
68532fe07f8SJohn Marino  *	Vi repeat current search in the same search direction
68632fe07f8SJohn Marino  *	[n]
68732fe07f8SJohn Marino  */
68832fe07f8SJohn Marino protected el_action_t
68932fe07f8SJohn Marino /*ARGSUSED*/
69032fe07f8SJohn Marino vi_repeat_search_next(EditLine *el, Int c __attribute__((__unused__)))
69132fe07f8SJohn Marino {
69232fe07f8SJohn Marino 
69332fe07f8SJohn Marino 	if (el->el_search.patlen == 0)
69432fe07f8SJohn Marino 		return CC_ERROR;
69532fe07f8SJohn Marino 	else
69632fe07f8SJohn Marino 		return cv_repeat_srch(el, el->el_search.patdir);
69732fe07f8SJohn Marino }
69832fe07f8SJohn Marino 
69932fe07f8SJohn Marino 
70032fe07f8SJohn Marino /* vi_repeat_search_prev():
70132fe07f8SJohn Marino  *	Vi repeat current search in the opposite search direction
70232fe07f8SJohn Marino  *	[N]
70332fe07f8SJohn Marino  */
70432fe07f8SJohn Marino /*ARGSUSED*/
70532fe07f8SJohn Marino protected el_action_t
70632fe07f8SJohn Marino vi_repeat_search_prev(EditLine *el, Int c __attribute__((__unused__)))
70732fe07f8SJohn Marino {
70832fe07f8SJohn Marino 
70932fe07f8SJohn Marino 	if (el->el_search.patlen == 0)
71032fe07f8SJohn Marino 		return CC_ERROR;
71132fe07f8SJohn Marino 	else
71232fe07f8SJohn Marino 		return (cv_repeat_srch(el,
71332fe07f8SJohn Marino 		    el->el_search.patdir == ED_SEARCH_PREV_HISTORY ?
71432fe07f8SJohn Marino 		    ED_SEARCH_NEXT_HISTORY : ED_SEARCH_PREV_HISTORY));
71532fe07f8SJohn Marino }
71632fe07f8SJohn Marino 
71732fe07f8SJohn Marino 
71832fe07f8SJohn Marino /* vi_next_char():
71932fe07f8SJohn Marino  *	Vi move to the character specified next
72032fe07f8SJohn Marino  *	[f]
72132fe07f8SJohn Marino  */
72232fe07f8SJohn Marino protected el_action_t
72332fe07f8SJohn Marino /*ARGSUSED*/
72432fe07f8SJohn Marino vi_next_char(EditLine *el, Int c __attribute__((__unused__)))
72532fe07f8SJohn Marino {
72632fe07f8SJohn Marino 	return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 0);
72732fe07f8SJohn Marino }
72832fe07f8SJohn Marino 
72932fe07f8SJohn Marino 
73032fe07f8SJohn Marino /* vi_prev_char():
73132fe07f8SJohn Marino  *	Vi move to the character specified previous
73232fe07f8SJohn Marino  *	[F]
73332fe07f8SJohn Marino  */
73432fe07f8SJohn Marino protected el_action_t
73532fe07f8SJohn Marino /*ARGSUSED*/
73632fe07f8SJohn Marino vi_prev_char(EditLine *el, Int c __attribute__((__unused__)))
73732fe07f8SJohn Marino {
73832fe07f8SJohn Marino 	return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 0);
73932fe07f8SJohn Marino }
74032fe07f8SJohn Marino 
74132fe07f8SJohn Marino 
74232fe07f8SJohn Marino /* vi_to_next_char():
74332fe07f8SJohn Marino  *	Vi move up to the character specified next
74432fe07f8SJohn Marino  *	[t]
74532fe07f8SJohn Marino  */
74632fe07f8SJohn Marino protected el_action_t
74732fe07f8SJohn Marino /*ARGSUSED*/
74832fe07f8SJohn Marino vi_to_next_char(EditLine *el, Int c __attribute__((__unused__)))
74932fe07f8SJohn Marino {
75032fe07f8SJohn Marino 	return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 1);
75132fe07f8SJohn Marino }
75232fe07f8SJohn Marino 
75332fe07f8SJohn Marino 
75432fe07f8SJohn Marino /* vi_to_prev_char():
75532fe07f8SJohn Marino  *	Vi move up to the character specified previous
75632fe07f8SJohn Marino  *	[T]
75732fe07f8SJohn Marino  */
75832fe07f8SJohn Marino protected el_action_t
75932fe07f8SJohn Marino /*ARGSUSED*/
76032fe07f8SJohn Marino vi_to_prev_char(EditLine *el, Int c __attribute__((__unused__)))
76132fe07f8SJohn Marino {
76232fe07f8SJohn Marino 	return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 1);
76332fe07f8SJohn Marino }
76432fe07f8SJohn Marino 
76532fe07f8SJohn Marino 
76632fe07f8SJohn Marino /* vi_repeat_next_char():
76732fe07f8SJohn Marino  *	Vi repeat current character search in the same search direction
76832fe07f8SJohn Marino  *	[;]
76932fe07f8SJohn Marino  */
77032fe07f8SJohn Marino protected el_action_t
77132fe07f8SJohn Marino /*ARGSUSED*/
77232fe07f8SJohn Marino vi_repeat_next_char(EditLine *el, Int c __attribute__((__unused__)))
77332fe07f8SJohn Marino {
77432fe07f8SJohn Marino 
77532fe07f8SJohn Marino 	return cv_csearch(el, el->el_search.chadir, el->el_search.chacha,
77632fe07f8SJohn Marino 		el->el_state.argument, el->el_search.chatflg);
77732fe07f8SJohn Marino }
77832fe07f8SJohn Marino 
77932fe07f8SJohn Marino 
78032fe07f8SJohn Marino /* vi_repeat_prev_char():
78132fe07f8SJohn Marino  *	Vi repeat current character search in the opposite search direction
78232fe07f8SJohn Marino  *	[,]
78332fe07f8SJohn Marino  */
78432fe07f8SJohn Marino protected el_action_t
78532fe07f8SJohn Marino /*ARGSUSED*/
78632fe07f8SJohn Marino vi_repeat_prev_char(EditLine *el, Int c __attribute__((__unused__)))
78732fe07f8SJohn Marino {
78832fe07f8SJohn Marino 	el_action_t r;
78932fe07f8SJohn Marino 	int dir = el->el_search.chadir;
79032fe07f8SJohn Marino 
79132fe07f8SJohn Marino 	r = cv_csearch(el, -dir, el->el_search.chacha,
79232fe07f8SJohn Marino 		el->el_state.argument, el->el_search.chatflg);
79332fe07f8SJohn Marino 	el->el_search.chadir = dir;
79432fe07f8SJohn Marino 	return r;
79532fe07f8SJohn Marino }
79632fe07f8SJohn Marino 
79732fe07f8SJohn Marino 
79832fe07f8SJohn Marino /* vi_match():
79932fe07f8SJohn Marino  *	Vi go to matching () {} or []
80032fe07f8SJohn Marino  *	[%]
80132fe07f8SJohn Marino  */
80232fe07f8SJohn Marino protected el_action_t
80332fe07f8SJohn Marino /*ARGSUSED*/
80432fe07f8SJohn Marino vi_match(EditLine *el, Int c __attribute__((__unused__)))
80532fe07f8SJohn Marino {
80632fe07f8SJohn Marino 	const Char match_chars[] = STR("()[]{}");
80732fe07f8SJohn Marino 	Char *cp;
80832fe07f8SJohn Marino 	size_t delta, i, count;
80932fe07f8SJohn Marino 	Char o_ch, c_ch;
81032fe07f8SJohn Marino 
81132fe07f8SJohn Marino 	*el->el_line.lastchar = '\0';		/* just in case */
81232fe07f8SJohn Marino 
81332fe07f8SJohn Marino 	i = Strcspn(el->el_line.cursor, match_chars);
81432fe07f8SJohn Marino 	o_ch = el->el_line.cursor[i];
81532fe07f8SJohn Marino 	if (o_ch == 0)
81632fe07f8SJohn Marino 		return CC_ERROR;
81732fe07f8SJohn Marino 	delta = (size_t)(Strchr(match_chars, o_ch) - match_chars);
81832fe07f8SJohn Marino 	c_ch = match_chars[delta ^ 1];
81932fe07f8SJohn Marino 	count = 1;
82032fe07f8SJohn Marino 	delta = 1 - (delta & 1) * 2;
82132fe07f8SJohn Marino 
82232fe07f8SJohn Marino 	for (cp = &el->el_line.cursor[i]; count; ) {
82332fe07f8SJohn Marino 		cp += delta;
82432fe07f8SJohn Marino 		if (cp < el->el_line.buffer || cp >= el->el_line.lastchar)
82532fe07f8SJohn Marino 			return CC_ERROR;
82632fe07f8SJohn Marino 		if (*cp == o_ch)
82732fe07f8SJohn Marino 			count++;
82832fe07f8SJohn Marino 		else if (*cp == c_ch)
82932fe07f8SJohn Marino 			count--;
83032fe07f8SJohn Marino 	}
83132fe07f8SJohn Marino 
83232fe07f8SJohn Marino 	el->el_line.cursor = cp;
83332fe07f8SJohn Marino 
83432fe07f8SJohn Marino 	if (el->el_chared.c_vcmd.action != NOP) {
83532fe07f8SJohn Marino 		/* NB posix says char under cursor should NOT be deleted
83632fe07f8SJohn Marino 		   for -ve delta - this is different to netbsd vi. */
83732fe07f8SJohn Marino 		if (delta > 0)
83832fe07f8SJohn Marino 			el->el_line.cursor++;
83932fe07f8SJohn Marino 		cv_delfini(el);
84032fe07f8SJohn Marino 		return CC_REFRESH;
84132fe07f8SJohn Marino 	}
84232fe07f8SJohn Marino 	return CC_CURSOR;
84332fe07f8SJohn Marino }
84432fe07f8SJohn Marino 
84532fe07f8SJohn Marino /* vi_undo_line():
84632fe07f8SJohn Marino  *	Vi undo all changes to line
84732fe07f8SJohn Marino  *	[U]
84832fe07f8SJohn Marino  */
84932fe07f8SJohn Marino protected el_action_t
85032fe07f8SJohn Marino /*ARGSUSED*/
85132fe07f8SJohn Marino vi_undo_line(EditLine *el, Int c __attribute__((__unused__)))
85232fe07f8SJohn Marino {
85332fe07f8SJohn Marino 
85432fe07f8SJohn Marino 	cv_undo(el);
85532fe07f8SJohn Marino 	return hist_get(el);
85632fe07f8SJohn Marino }
85732fe07f8SJohn Marino 
85832fe07f8SJohn Marino /* vi_to_column():
85932fe07f8SJohn Marino  *	Vi go to specified column
86032fe07f8SJohn Marino  *	[|]
86132fe07f8SJohn Marino  * NB netbsd vi goes to screen column 'n', posix says nth character
86232fe07f8SJohn Marino  */
86332fe07f8SJohn Marino protected el_action_t
86432fe07f8SJohn Marino /*ARGSUSED*/
86532fe07f8SJohn Marino vi_to_column(EditLine *el, Int c __attribute__((__unused__)))
86632fe07f8SJohn Marino {
86732fe07f8SJohn Marino 
86832fe07f8SJohn Marino 	el->el_line.cursor = el->el_line.buffer;
86932fe07f8SJohn Marino 	el->el_state.argument--;
87032fe07f8SJohn Marino 	return ed_next_char(el, 0);
87132fe07f8SJohn Marino }
87232fe07f8SJohn Marino 
87332fe07f8SJohn Marino /* vi_yank_end():
87432fe07f8SJohn Marino  *	Vi yank to end of line
87532fe07f8SJohn Marino  *	[Y]
87632fe07f8SJohn Marino  */
87732fe07f8SJohn Marino protected el_action_t
87832fe07f8SJohn Marino /*ARGSUSED*/
87932fe07f8SJohn Marino vi_yank_end(EditLine *el, Int c __attribute__((__unused__)))
88032fe07f8SJohn Marino {
88132fe07f8SJohn Marino 
88232fe07f8SJohn Marino 	cv_yank(el, el->el_line.cursor,
88332fe07f8SJohn Marino 	    (int)(el->el_line.lastchar - el->el_line.cursor));
88432fe07f8SJohn Marino 	return CC_REFRESH;
88532fe07f8SJohn Marino }
88632fe07f8SJohn Marino 
88732fe07f8SJohn Marino /* vi_yank():
88832fe07f8SJohn Marino  *	Vi yank
88932fe07f8SJohn Marino  *	[y]
89032fe07f8SJohn Marino  */
89132fe07f8SJohn Marino protected el_action_t
89232fe07f8SJohn Marino /*ARGSUSED*/
89332fe07f8SJohn Marino vi_yank(EditLine *el, Int c __attribute__((__unused__)))
89432fe07f8SJohn Marino {
89532fe07f8SJohn Marino 
89632fe07f8SJohn Marino 	return cv_action(el, YANK);
89732fe07f8SJohn Marino }
89832fe07f8SJohn Marino 
89932fe07f8SJohn Marino /* vi_comment_out():
90032fe07f8SJohn Marino  *	Vi comment out current command
90132fe07f8SJohn Marino  *	[#]
90232fe07f8SJohn Marino  */
90332fe07f8SJohn Marino protected el_action_t
90432fe07f8SJohn Marino /*ARGSUSED*/
90532fe07f8SJohn Marino vi_comment_out(EditLine *el, Int c __attribute__((__unused__)))
90632fe07f8SJohn Marino {
90732fe07f8SJohn Marino 
90832fe07f8SJohn Marino 	el->el_line.cursor = el->el_line.buffer;
90932fe07f8SJohn Marino 	c_insert(el, 1);
91032fe07f8SJohn Marino 	*el->el_line.cursor = '#';
91132fe07f8SJohn Marino 	re_refresh(el);
91232fe07f8SJohn Marino 	return ed_newline(el, 0);
91332fe07f8SJohn Marino }
91432fe07f8SJohn Marino 
91532fe07f8SJohn Marino /* vi_alias():
91632fe07f8SJohn Marino  *	Vi include shell alias
91732fe07f8SJohn Marino  *	[@]
91832fe07f8SJohn Marino  * NB: posix implies that we should enter insert mode, however
91932fe07f8SJohn Marino  * this is against historical precedent...
92032fe07f8SJohn Marino  */
92132fe07f8SJohn Marino protected el_action_t
92232fe07f8SJohn Marino /*ARGSUSED*/
923*84b940c1SJohn Marino vi_alias(EditLine *el __attribute__((__unused__)), Int c __attribute__((__unused__)))
92432fe07f8SJohn Marino {
92532fe07f8SJohn Marino 	char alias_name[3];
926*84b940c1SJohn Marino 	const char *alias_text;
92732fe07f8SJohn Marino 
928*84b940c1SJohn Marino 	if (el->el_chared.c_aliasfun == NULL)
92932fe07f8SJohn Marino 		return CC_ERROR;
93032fe07f8SJohn Marino 
93132fe07f8SJohn Marino 	alias_name[0] = '_';
93232fe07f8SJohn Marino 	alias_name[2] = 0;
93332fe07f8SJohn Marino 	if (el_getc(el, &alias_name[1]) != 1)
93432fe07f8SJohn Marino 		return CC_ERROR;
93532fe07f8SJohn Marino 
936*84b940c1SJohn Marino 	alias_text = (*el->el_chared.c_aliasfun)(el->el_chared.c_aliasarg,
937*84b940c1SJohn Marino 	    alias_name);
93832fe07f8SJohn Marino 	if (alias_text != NULL)
93932fe07f8SJohn Marino 		FUN(el,push)(el, ct_decode_string(alias_text, &el->el_scratch));
94032fe07f8SJohn Marino 	return CC_NORM;
94132fe07f8SJohn Marino }
94232fe07f8SJohn Marino 
94332fe07f8SJohn Marino /* vi_to_history_line():
94432fe07f8SJohn Marino  *	Vi go to specified history file line.
94532fe07f8SJohn Marino  *	[G]
94632fe07f8SJohn Marino  */
94732fe07f8SJohn Marino protected el_action_t
94832fe07f8SJohn Marino /*ARGSUSED*/
94932fe07f8SJohn Marino vi_to_history_line(EditLine *el, Int c __attribute__((__unused__)))
95032fe07f8SJohn Marino {
95132fe07f8SJohn Marino 	int sv_event_no = el->el_history.eventno;
95232fe07f8SJohn Marino 	el_action_t rval;
95332fe07f8SJohn Marino 
95432fe07f8SJohn Marino 
95532fe07f8SJohn Marino 	if (el->el_history.eventno == 0) {
95632fe07f8SJohn Marino 		 (void) Strncpy(el->el_history.buf, el->el_line.buffer,
95732fe07f8SJohn Marino 		     EL_BUFSIZ);
95832fe07f8SJohn Marino 		 el->el_history.last = el->el_history.buf +
95932fe07f8SJohn Marino 			 (el->el_line.lastchar - el->el_line.buffer);
96032fe07f8SJohn Marino 	}
96132fe07f8SJohn Marino 
96232fe07f8SJohn Marino 	/* Lack of a 'count' means oldest, not 1 */
96332fe07f8SJohn Marino 	if (!el->el_state.doingarg) {
96432fe07f8SJohn Marino 		el->el_history.eventno = 0x7fffffff;
96532fe07f8SJohn Marino 		hist_get(el);
96632fe07f8SJohn Marino 	} else {
96732fe07f8SJohn Marino 		/* This is brain dead, all the rest of this code counts
96832fe07f8SJohn Marino 		 * upwards going into the past.  Here we need count in the
96932fe07f8SJohn Marino 		 * other direction (to match the output of fc -l).
97032fe07f8SJohn Marino 		 * I could change the world, but this seems to suffice.
97132fe07f8SJohn Marino 		 */
97232fe07f8SJohn Marino 		el->el_history.eventno = 1;
97332fe07f8SJohn Marino 		if (hist_get(el) == CC_ERROR)
97432fe07f8SJohn Marino 			return CC_ERROR;
97532fe07f8SJohn Marino 		el->el_history.eventno = 1 + el->el_history.ev.num
97632fe07f8SJohn Marino 					- el->el_state.argument;
97732fe07f8SJohn Marino 		if (el->el_history.eventno < 0) {
97832fe07f8SJohn Marino 			el->el_history.eventno = sv_event_no;
97932fe07f8SJohn Marino 			return CC_ERROR;
98032fe07f8SJohn Marino 		}
98132fe07f8SJohn Marino 	}
98232fe07f8SJohn Marino 	rval = hist_get(el);
98332fe07f8SJohn Marino 	if (rval == CC_ERROR)
98432fe07f8SJohn Marino 		el->el_history.eventno = sv_event_no;
98532fe07f8SJohn Marino 	return rval;
98632fe07f8SJohn Marino }
98732fe07f8SJohn Marino 
98832fe07f8SJohn Marino /* vi_histedit():
98932fe07f8SJohn Marino  *	Vi edit history line with vi
99032fe07f8SJohn Marino  *	[v]
99132fe07f8SJohn Marino  */
99232fe07f8SJohn Marino protected el_action_t
99332fe07f8SJohn Marino /*ARGSUSED*/
99432fe07f8SJohn Marino vi_histedit(EditLine *el, Int c __attribute__((__unused__)))
99532fe07f8SJohn Marino {
99632fe07f8SJohn Marino 	int fd;
99732fe07f8SJohn Marino 	pid_t pid;
99832fe07f8SJohn Marino 	ssize_t st;
99932fe07f8SJohn Marino 	int status;
100032fe07f8SJohn Marino 	char tempfile[] = "/tmp/histedit.XXXXXXXXXX";
100132fe07f8SJohn Marino 	char *cp = NULL;
100232fe07f8SJohn Marino 	size_t len;
100332fe07f8SJohn Marino 	Char *line = NULL;
100432fe07f8SJohn Marino 
100532fe07f8SJohn Marino 	if (el->el_state.doingarg) {
100632fe07f8SJohn Marino 		if (vi_to_history_line(el, 0) == CC_ERROR)
100732fe07f8SJohn Marino 			return CC_ERROR;
100832fe07f8SJohn Marino 	}
100932fe07f8SJohn Marino 
101032fe07f8SJohn Marino 	fd = mkstemp(tempfile);
101132fe07f8SJohn Marino 	if (fd < 0)
101232fe07f8SJohn Marino 		return CC_ERROR;
101332fe07f8SJohn Marino 	len = (size_t)(el->el_line.lastchar - el->el_line.buffer);
101432fe07f8SJohn Marino #define TMP_BUFSIZ (EL_BUFSIZ * MB_LEN_MAX)
101532fe07f8SJohn Marino 	cp = el_malloc(TMP_BUFSIZ * sizeof(*cp));
101632fe07f8SJohn Marino 	if (cp == NULL)
101732fe07f8SJohn Marino 		goto error;
101832fe07f8SJohn Marino 	line = el_malloc(len * sizeof(*line) + 1);
101932fe07f8SJohn Marino 	if (line == NULL)
102032fe07f8SJohn Marino 		goto error;
102132fe07f8SJohn Marino 	Strncpy(line, el->el_line.buffer, len);
102232fe07f8SJohn Marino 	line[len] = '\0';
102332fe07f8SJohn Marino 	ct_wcstombs(cp, line, TMP_BUFSIZ - 1);
102432fe07f8SJohn Marino 	cp[TMP_BUFSIZ - 1] = '\0';
102532fe07f8SJohn Marino 	len = strlen(cp);
102632fe07f8SJohn Marino 	write(fd, cp, len);
102732fe07f8SJohn Marino 	write(fd, "\n", (size_t)1);
102832fe07f8SJohn Marino 	pid = fork();
102932fe07f8SJohn Marino 	switch (pid) {
103032fe07f8SJohn Marino 	case -1:
103132fe07f8SJohn Marino 		goto error;
103232fe07f8SJohn Marino 	case 0:
103332fe07f8SJohn Marino 		close(fd);
103432fe07f8SJohn Marino 		execlp("vi", "vi", tempfile, (char *)NULL);
103532fe07f8SJohn Marino 		exit(0);
103632fe07f8SJohn Marino 		/*NOTREACHED*/
103732fe07f8SJohn Marino 	default:
103832fe07f8SJohn Marino 		while (waitpid(pid, &status, 0) != pid)
103932fe07f8SJohn Marino 			continue;
104032fe07f8SJohn Marino 		lseek(fd, (off_t)0, SEEK_SET);
104132fe07f8SJohn Marino 		st = read(fd, cp, TMP_BUFSIZ);
104232fe07f8SJohn Marino 		if (st > 0) {
104332fe07f8SJohn Marino 			len = (size_t)(el->el_line.lastchar -
104432fe07f8SJohn Marino 			    el->el_line.buffer);
104532fe07f8SJohn Marino 			len = ct_mbstowcs(el->el_line.buffer, cp, len);
104632fe07f8SJohn Marino 			if (len > 0 && el->el_line.buffer[len -1] == '\n')
104732fe07f8SJohn Marino 				--len;
104832fe07f8SJohn Marino 		}
104932fe07f8SJohn Marino 		else
105032fe07f8SJohn Marino 			len = 0;
105132fe07f8SJohn Marino                 el->el_line.cursor = el->el_line.buffer;
105232fe07f8SJohn Marino                 el->el_line.lastchar = el->el_line.buffer + len;
105332fe07f8SJohn Marino 		el_free(cp);
105432fe07f8SJohn Marino                 el_free(line);
105532fe07f8SJohn Marino 		break;
105632fe07f8SJohn Marino 	}
105732fe07f8SJohn Marino 
105832fe07f8SJohn Marino 	close(fd);
105932fe07f8SJohn Marino 	unlink(tempfile);
106032fe07f8SJohn Marino 	/* return CC_REFRESH; */
106132fe07f8SJohn Marino 	return ed_newline(el, 0);
106232fe07f8SJohn Marino error:
106332fe07f8SJohn Marino 	el_free(line);
106432fe07f8SJohn Marino 	el_free(cp);
106532fe07f8SJohn Marino 	close(fd);
106632fe07f8SJohn Marino 	unlink(tempfile);
106732fe07f8SJohn Marino 	return CC_ERROR;
106832fe07f8SJohn Marino }
106932fe07f8SJohn Marino 
107032fe07f8SJohn Marino /* vi_history_word():
107132fe07f8SJohn Marino  *	Vi append word from previous input line
107232fe07f8SJohn Marino  *	[_]
107332fe07f8SJohn Marino  * Who knows where this one came from!
107432fe07f8SJohn Marino  * '_' in vi means 'entire current line', so 'cc' is a synonym for 'c_'
107532fe07f8SJohn Marino  */
107632fe07f8SJohn Marino protected el_action_t
107732fe07f8SJohn Marino /*ARGSUSED*/
107832fe07f8SJohn Marino vi_history_word(EditLine *el, Int c __attribute__((__unused__)))
107932fe07f8SJohn Marino {
108032fe07f8SJohn Marino 	const Char *wp = HIST_FIRST(el);
108132fe07f8SJohn Marino 	const Char *wep, *wsp;
108232fe07f8SJohn Marino 	int len;
108332fe07f8SJohn Marino 	Char *cp;
108432fe07f8SJohn Marino 	const Char *lim;
108532fe07f8SJohn Marino 
108632fe07f8SJohn Marino 	if (wp == NULL)
108732fe07f8SJohn Marino 		return CC_ERROR;
108832fe07f8SJohn Marino 
108932fe07f8SJohn Marino 	wep = wsp = 0;
109032fe07f8SJohn Marino 	do {
109132fe07f8SJohn Marino 		while (Isspace(*wp))
109232fe07f8SJohn Marino 			wp++;
109332fe07f8SJohn Marino 		if (*wp == 0)
109432fe07f8SJohn Marino 			break;
109532fe07f8SJohn Marino 		wsp = wp;
109632fe07f8SJohn Marino 		while (*wp && !Isspace(*wp))
109732fe07f8SJohn Marino 			wp++;
109832fe07f8SJohn Marino 		wep = wp;
109932fe07f8SJohn Marino 	} while ((!el->el_state.doingarg || --el->el_state.argument > 0)
110032fe07f8SJohn Marino 	    && *wp != 0);
110132fe07f8SJohn Marino 
110232fe07f8SJohn Marino 	if (wsp == 0 || (el->el_state.doingarg && el->el_state.argument != 0))
110332fe07f8SJohn Marino 		return CC_ERROR;
110432fe07f8SJohn Marino 
110532fe07f8SJohn Marino 	cv_undo(el);
110632fe07f8SJohn Marino 	len = (int)(wep - wsp);
110732fe07f8SJohn Marino 	if (el->el_line.cursor < el->el_line.lastchar)
110832fe07f8SJohn Marino 		el->el_line.cursor++;
110932fe07f8SJohn Marino 	c_insert(el, len + 1);
111032fe07f8SJohn Marino 	cp = el->el_line.cursor;
111132fe07f8SJohn Marino 	lim = el->el_line.limit;
111232fe07f8SJohn Marino 	if (cp < lim)
111332fe07f8SJohn Marino 		*cp++ = ' ';
111432fe07f8SJohn Marino 	while (wsp < wep && cp < lim)
111532fe07f8SJohn Marino 		*cp++ = *wsp++;
111632fe07f8SJohn Marino 	el->el_line.cursor = cp;
111732fe07f8SJohn Marino 
111832fe07f8SJohn Marino 	el->el_map.current = el->el_map.key;
111932fe07f8SJohn Marino 	return CC_REFRESH;
112032fe07f8SJohn Marino }
112132fe07f8SJohn Marino 
112232fe07f8SJohn Marino /* vi_redo():
112332fe07f8SJohn Marino  *	Vi redo last non-motion command
112432fe07f8SJohn Marino  *	[.]
112532fe07f8SJohn Marino  */
112632fe07f8SJohn Marino protected el_action_t
112732fe07f8SJohn Marino /*ARGSUSED*/
112832fe07f8SJohn Marino vi_redo(EditLine *el, Int c __attribute__((__unused__)))
112932fe07f8SJohn Marino {
113032fe07f8SJohn Marino 	c_redo_t *r = &el->el_chared.c_redo;
113132fe07f8SJohn Marino 
113232fe07f8SJohn Marino 	if (!el->el_state.doingarg && r->count) {
113332fe07f8SJohn Marino 		el->el_state.doingarg = 1;
113432fe07f8SJohn Marino 		el->el_state.argument = r->count;
113532fe07f8SJohn Marino 	}
113632fe07f8SJohn Marino 
113732fe07f8SJohn Marino 	el->el_chared.c_vcmd.pos = el->el_line.cursor;
113832fe07f8SJohn Marino 	el->el_chared.c_vcmd.action = r->action;
113932fe07f8SJohn Marino 	if (r->pos != r->buf) {
114032fe07f8SJohn Marino 		if (r->pos + 1 > r->lim)
114132fe07f8SJohn Marino 			/* sanity */
114232fe07f8SJohn Marino 			r->pos = r->lim - 1;
114332fe07f8SJohn Marino 		r->pos[0] = 0;
114432fe07f8SJohn Marino 		FUN(el,push)(el, r->buf);
114532fe07f8SJohn Marino 	}
114632fe07f8SJohn Marino 
114732fe07f8SJohn Marino 	el->el_state.thiscmd = r->cmd;
114832fe07f8SJohn Marino 	el->el_state.thisch = r->ch;
114932fe07f8SJohn Marino 	return (*el->el_map.func[r->cmd])(el, r->ch);
115032fe07f8SJohn Marino }
1151