1*cdf8408cSAntonio Huete Jimenez /* $NetBSD: vi.c,v 1.64 2021/08/28 17:17:47 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 #if !defined(lint) && !defined(SCCSID)
3732fe07f8SJohn Marino #if 0
3832fe07f8SJohn Marino static char sccsid[] = "@(#)vi.c 8.1 (Berkeley) 6/4/93";
3932fe07f8SJohn Marino #else
40*cdf8408cSAntonio Huete Jimenez __RCSID("$NetBSD: vi.c,v 1.64 2021/08/28 17:17:47 christos Exp $");
4132fe07f8SJohn Marino #endif
4232fe07f8SJohn Marino #endif /* not lint && not SCCSID */
4332fe07f8SJohn Marino
4432fe07f8SJohn Marino /*
4532fe07f8SJohn Marino * vi.c: Vi mode commands.
4632fe07f8SJohn Marino */
4712db70c8Szrj #include <sys/wait.h>
4812db70c8Szrj #include <ctype.h>
4912db70c8Szrj #include <limits.h>
5012db70c8Szrj #include <stdlib.h>
5112db70c8Szrj #include <string.h>
5212db70c8Szrj #include <unistd.h>
5332fe07f8SJohn Marino
5412db70c8Szrj #include "el.h"
5512db70c8Szrj #include "common.h"
5612db70c8Szrj #include "emacs.h"
5712db70c8Szrj #include "fcns.h"
5812db70c8Szrj #include "vi.h"
5912db70c8Szrj
6012db70c8Szrj static el_action_t cv_action(EditLine *, wint_t);
6112db70c8Szrj static el_action_t cv_paste(EditLine *, wint_t);
6232fe07f8SJohn Marino
6332fe07f8SJohn Marino /* cv_action():
6432fe07f8SJohn Marino * Handle vi actions.
6532fe07f8SJohn Marino */
6612db70c8Szrj static el_action_t
cv_action(EditLine * el,wint_t c)6712db70c8Szrj cv_action(EditLine *el, wint_t c)
6832fe07f8SJohn Marino {
6932fe07f8SJohn Marino
7032fe07f8SJohn Marino if (el->el_chared.c_vcmd.action != NOP) {
7132fe07f8SJohn Marino /* 'cc', 'dd' and (possibly) friends */
7212db70c8Szrj if (c != (wint_t)el->el_chared.c_vcmd.action)
7332fe07f8SJohn Marino return CC_ERROR;
7432fe07f8SJohn Marino
7532fe07f8SJohn Marino if (!(c & YANK))
7632fe07f8SJohn Marino cv_undo(el);
7732fe07f8SJohn Marino cv_yank(el, el->el_line.buffer,
7832fe07f8SJohn Marino (int)(el->el_line.lastchar - el->el_line.buffer));
7932fe07f8SJohn Marino el->el_chared.c_vcmd.action = NOP;
8032fe07f8SJohn Marino el->el_chared.c_vcmd.pos = 0;
8132fe07f8SJohn Marino if (!(c & YANK)) {
8232fe07f8SJohn Marino el->el_line.lastchar = el->el_line.buffer;
8332fe07f8SJohn Marino el->el_line.cursor = el->el_line.buffer;
8432fe07f8SJohn Marino }
8532fe07f8SJohn Marino if (c & INSERT)
8632fe07f8SJohn Marino el->el_map.current = el->el_map.key;
8732fe07f8SJohn Marino
8832fe07f8SJohn Marino return CC_REFRESH;
8932fe07f8SJohn Marino }
9032fe07f8SJohn Marino el->el_chared.c_vcmd.pos = el->el_line.cursor;
9132fe07f8SJohn Marino el->el_chared.c_vcmd.action = c;
9232fe07f8SJohn Marino return CC_ARGHACK;
9332fe07f8SJohn Marino }
9432fe07f8SJohn Marino
9532fe07f8SJohn Marino /* cv_paste():
9632fe07f8SJohn Marino * Paste previous deletion before or after the cursor
9732fe07f8SJohn Marino */
9812db70c8Szrj static el_action_t
cv_paste(EditLine * el,wint_t c)9912db70c8Szrj cv_paste(EditLine *el, wint_t c)
10032fe07f8SJohn Marino {
10132fe07f8SJohn Marino c_kill_t *k = &el->el_chared.c_kill;
10232fe07f8SJohn Marino size_t len = (size_t)(k->last - k->buf);
10332fe07f8SJohn Marino
10432fe07f8SJohn Marino if (k->buf == NULL || len == 0)
10532fe07f8SJohn Marino return CC_ERROR;
10632fe07f8SJohn Marino #ifdef DEBUG_PASTE
10712db70c8Szrj (void) fprintf(el->el_errfile, "Paste: \"%.*ls\"\n", (int)len,
10812db70c8Szrj k->buf);
10932fe07f8SJohn Marino #endif
11032fe07f8SJohn Marino
11132fe07f8SJohn Marino cv_undo(el);
11232fe07f8SJohn Marino
11332fe07f8SJohn Marino if (!c && el->el_line.cursor < el->el_line.lastchar)
11432fe07f8SJohn Marino el->el_line.cursor++;
11532fe07f8SJohn Marino
11632fe07f8SJohn Marino c_insert(el, (int)len);
11732fe07f8SJohn Marino if (el->el_line.cursor + len > el->el_line.lastchar)
11832fe07f8SJohn Marino return CC_ERROR;
11932fe07f8SJohn Marino (void) memcpy(el->el_line.cursor, k->buf, len *
12032fe07f8SJohn Marino sizeof(*el->el_line.cursor));
12132fe07f8SJohn Marino
12232fe07f8SJohn Marino return CC_REFRESH;
12332fe07f8SJohn Marino }
12432fe07f8SJohn Marino
12532fe07f8SJohn Marino
12632fe07f8SJohn Marino /* vi_paste_next():
12732fe07f8SJohn Marino * Vi paste previous deletion to the right of the cursor
12832fe07f8SJohn Marino * [p]
12932fe07f8SJohn Marino */
13012db70c8Szrj libedit_private el_action_t
13132fe07f8SJohn Marino /*ARGSUSED*/
vi_paste_next(EditLine * el,wint_t c)13212db70c8Szrj vi_paste_next(EditLine *el, wint_t c __attribute__((__unused__)))
13332fe07f8SJohn Marino {
13432fe07f8SJohn Marino
13532fe07f8SJohn Marino return cv_paste(el, 0);
13632fe07f8SJohn Marino }
13732fe07f8SJohn Marino
13832fe07f8SJohn Marino
13932fe07f8SJohn Marino /* vi_paste_prev():
14032fe07f8SJohn Marino * Vi paste previous deletion to the left of the cursor
14132fe07f8SJohn Marino * [P]
14232fe07f8SJohn Marino */
14312db70c8Szrj libedit_private el_action_t
14432fe07f8SJohn Marino /*ARGSUSED*/
vi_paste_prev(EditLine * el,wint_t c)14512db70c8Szrj vi_paste_prev(EditLine *el, wint_t c __attribute__((__unused__)))
14632fe07f8SJohn Marino {
14732fe07f8SJohn Marino
14832fe07f8SJohn Marino return cv_paste(el, 1);
14932fe07f8SJohn Marino }
15032fe07f8SJohn Marino
15132fe07f8SJohn Marino
15232fe07f8SJohn Marino /* vi_prev_big_word():
15332fe07f8SJohn Marino * Vi move to the previous space delimited word
15432fe07f8SJohn Marino * [B]
15532fe07f8SJohn Marino */
15612db70c8Szrj libedit_private el_action_t
15732fe07f8SJohn Marino /*ARGSUSED*/
vi_prev_big_word(EditLine * el,wint_t c)15812db70c8Szrj vi_prev_big_word(EditLine *el, wint_t c __attribute__((__unused__)))
15932fe07f8SJohn Marino {
16032fe07f8SJohn Marino
16132fe07f8SJohn Marino if (el->el_line.cursor == el->el_line.buffer)
16232fe07f8SJohn Marino return CC_ERROR;
16332fe07f8SJohn Marino
16432fe07f8SJohn Marino el->el_line.cursor = cv_prev_word(el->el_line.cursor,
16532fe07f8SJohn Marino el->el_line.buffer,
16632fe07f8SJohn Marino el->el_state.argument,
16732fe07f8SJohn Marino cv__isWord);
16832fe07f8SJohn Marino
16932fe07f8SJohn Marino if (el->el_chared.c_vcmd.action != NOP) {
17032fe07f8SJohn Marino cv_delfini(el);
17132fe07f8SJohn Marino return CC_REFRESH;
17232fe07f8SJohn Marino }
17332fe07f8SJohn Marino return CC_CURSOR;
17432fe07f8SJohn Marino }
17532fe07f8SJohn Marino
17632fe07f8SJohn Marino
17732fe07f8SJohn Marino /* vi_prev_word():
17832fe07f8SJohn Marino * Vi move to the previous word
17932fe07f8SJohn Marino * [b]
18032fe07f8SJohn Marino */
18112db70c8Szrj libedit_private el_action_t
18232fe07f8SJohn Marino /*ARGSUSED*/
vi_prev_word(EditLine * el,wint_t c)18312db70c8Szrj vi_prev_word(EditLine *el, wint_t c __attribute__((__unused__)))
18432fe07f8SJohn Marino {
18532fe07f8SJohn Marino
18632fe07f8SJohn Marino if (el->el_line.cursor == el->el_line.buffer)
18732fe07f8SJohn Marino return CC_ERROR;
18832fe07f8SJohn Marino
18932fe07f8SJohn Marino el->el_line.cursor = cv_prev_word(el->el_line.cursor,
19032fe07f8SJohn Marino el->el_line.buffer,
19132fe07f8SJohn Marino el->el_state.argument,
19232fe07f8SJohn Marino cv__isword);
19332fe07f8SJohn Marino
19432fe07f8SJohn Marino if (el->el_chared.c_vcmd.action != NOP) {
19532fe07f8SJohn Marino cv_delfini(el);
19632fe07f8SJohn Marino return CC_REFRESH;
19732fe07f8SJohn Marino }
19832fe07f8SJohn Marino return CC_CURSOR;
19932fe07f8SJohn Marino }
20032fe07f8SJohn Marino
20132fe07f8SJohn Marino
20232fe07f8SJohn Marino /* vi_next_big_word():
20332fe07f8SJohn Marino * Vi move to the next space delimited word
20432fe07f8SJohn Marino * [W]
20532fe07f8SJohn Marino */
20612db70c8Szrj libedit_private el_action_t
20732fe07f8SJohn Marino /*ARGSUSED*/
vi_next_big_word(EditLine * el,wint_t c)20812db70c8Szrj vi_next_big_word(EditLine *el, wint_t c __attribute__((__unused__)))
20932fe07f8SJohn Marino {
21032fe07f8SJohn Marino
21132fe07f8SJohn Marino if (el->el_line.cursor >= el->el_line.lastchar - 1)
21232fe07f8SJohn Marino return CC_ERROR;
21332fe07f8SJohn Marino
21432fe07f8SJohn Marino el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
21532fe07f8SJohn Marino el->el_line.lastchar, el->el_state.argument, cv__isWord);
21632fe07f8SJohn Marino
21732fe07f8SJohn Marino if (el->el_map.type == MAP_VI)
21832fe07f8SJohn Marino if (el->el_chared.c_vcmd.action != NOP) {
21932fe07f8SJohn Marino cv_delfini(el);
22032fe07f8SJohn Marino return CC_REFRESH;
22132fe07f8SJohn Marino }
22232fe07f8SJohn Marino return CC_CURSOR;
22332fe07f8SJohn Marino }
22432fe07f8SJohn Marino
22532fe07f8SJohn Marino
22632fe07f8SJohn Marino /* vi_next_word():
22732fe07f8SJohn Marino * Vi move to the next word
22832fe07f8SJohn Marino * [w]
22932fe07f8SJohn Marino */
23012db70c8Szrj libedit_private el_action_t
23132fe07f8SJohn Marino /*ARGSUSED*/
vi_next_word(EditLine * el,wint_t c)23212db70c8Szrj vi_next_word(EditLine *el, wint_t c __attribute__((__unused__)))
23332fe07f8SJohn Marino {
23432fe07f8SJohn Marino
23532fe07f8SJohn Marino if (el->el_line.cursor >= el->el_line.lastchar - 1)
23632fe07f8SJohn Marino return CC_ERROR;
23732fe07f8SJohn Marino
23832fe07f8SJohn Marino el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
23932fe07f8SJohn Marino el->el_line.lastchar, el->el_state.argument, cv__isword);
24032fe07f8SJohn Marino
24132fe07f8SJohn Marino if (el->el_map.type == MAP_VI)
24232fe07f8SJohn Marino if (el->el_chared.c_vcmd.action != NOP) {
24332fe07f8SJohn Marino cv_delfini(el);
24432fe07f8SJohn Marino return CC_REFRESH;
24532fe07f8SJohn Marino }
24632fe07f8SJohn Marino return CC_CURSOR;
24732fe07f8SJohn Marino }
24832fe07f8SJohn Marino
24932fe07f8SJohn Marino
25032fe07f8SJohn Marino /* vi_change_case():
25132fe07f8SJohn Marino * Vi change case of character under the cursor and advance one character
25232fe07f8SJohn Marino * [~]
25332fe07f8SJohn Marino */
25412db70c8Szrj libedit_private el_action_t
vi_change_case(EditLine * el,wint_t c)25512db70c8Szrj vi_change_case(EditLine *el, wint_t c)
25632fe07f8SJohn Marino {
25732fe07f8SJohn Marino int i;
25832fe07f8SJohn Marino
25932fe07f8SJohn Marino if (el->el_line.cursor >= el->el_line.lastchar)
26032fe07f8SJohn Marino return CC_ERROR;
26132fe07f8SJohn Marino cv_undo(el);
26232fe07f8SJohn Marino for (i = 0; i < el->el_state.argument; i++) {
26332fe07f8SJohn Marino
26432fe07f8SJohn Marino c = *el->el_line.cursor;
26512db70c8Szrj if (iswupper(c))
26612db70c8Szrj *el->el_line.cursor = towlower(c);
26712db70c8Szrj else if (iswlower(c))
26812db70c8Szrj *el->el_line.cursor = towupper(c);
26932fe07f8SJohn Marino
27032fe07f8SJohn Marino if (++el->el_line.cursor >= el->el_line.lastchar) {
27132fe07f8SJohn Marino el->el_line.cursor--;
27232fe07f8SJohn Marino re_fastaddc(el);
27332fe07f8SJohn Marino break;
27432fe07f8SJohn Marino }
27532fe07f8SJohn Marino re_fastaddc(el);
27632fe07f8SJohn Marino }
27732fe07f8SJohn Marino return CC_NORM;
27832fe07f8SJohn Marino }
27932fe07f8SJohn Marino
28032fe07f8SJohn Marino
28132fe07f8SJohn Marino /* vi_change_meta():
28232fe07f8SJohn Marino * Vi change prefix command
28332fe07f8SJohn Marino * [c]
28432fe07f8SJohn Marino */
28512db70c8Szrj libedit_private el_action_t
28632fe07f8SJohn Marino /*ARGSUSED*/
vi_change_meta(EditLine * el,wint_t c)28712db70c8Szrj vi_change_meta(EditLine *el, wint_t c __attribute__((__unused__)))
28832fe07f8SJohn Marino {
28932fe07f8SJohn Marino
29032fe07f8SJohn Marino /*
29132fe07f8SJohn Marino * Delete with insert == change: first we delete and then we leave in
29232fe07f8SJohn Marino * insert mode.
29332fe07f8SJohn Marino */
29432fe07f8SJohn Marino return cv_action(el, DELETE | INSERT);
29532fe07f8SJohn Marino }
29632fe07f8SJohn Marino
29732fe07f8SJohn Marino
29832fe07f8SJohn Marino /* vi_insert_at_bol():
29932fe07f8SJohn Marino * Vi enter insert mode at the beginning of line
30032fe07f8SJohn Marino * [I]
30132fe07f8SJohn Marino */
30212db70c8Szrj libedit_private el_action_t
30332fe07f8SJohn Marino /*ARGSUSED*/
vi_insert_at_bol(EditLine * el,wint_t c)30412db70c8Szrj vi_insert_at_bol(EditLine *el, wint_t c __attribute__((__unused__)))
30532fe07f8SJohn Marino {
30632fe07f8SJohn Marino
30732fe07f8SJohn Marino el->el_line.cursor = el->el_line.buffer;
30832fe07f8SJohn Marino cv_undo(el);
30932fe07f8SJohn Marino el->el_map.current = el->el_map.key;
31032fe07f8SJohn Marino return CC_CURSOR;
31132fe07f8SJohn Marino }
31232fe07f8SJohn Marino
31332fe07f8SJohn Marino
31432fe07f8SJohn Marino /* vi_replace_char():
31532fe07f8SJohn Marino * Vi replace character under the cursor with the next character typed
31632fe07f8SJohn Marino * [r]
31732fe07f8SJohn Marino */
31812db70c8Szrj libedit_private el_action_t
31932fe07f8SJohn Marino /*ARGSUSED*/
vi_replace_char(EditLine * el,wint_t c)32012db70c8Szrj vi_replace_char(EditLine *el, wint_t c __attribute__((__unused__)))
32132fe07f8SJohn Marino {
32232fe07f8SJohn Marino
32332fe07f8SJohn Marino if (el->el_line.cursor >= el->el_line.lastchar)
32432fe07f8SJohn Marino return CC_ERROR;
32532fe07f8SJohn Marino
32632fe07f8SJohn Marino el->el_map.current = el->el_map.key;
32732fe07f8SJohn Marino el->el_state.inputmode = MODE_REPLACE_1;
32832fe07f8SJohn Marino cv_undo(el);
32932fe07f8SJohn Marino return CC_ARGHACK;
33032fe07f8SJohn Marino }
33132fe07f8SJohn Marino
33232fe07f8SJohn Marino
33332fe07f8SJohn Marino /* vi_replace_mode():
33432fe07f8SJohn Marino * Vi enter replace mode
33532fe07f8SJohn Marino * [R]
33632fe07f8SJohn Marino */
33712db70c8Szrj libedit_private el_action_t
33832fe07f8SJohn Marino /*ARGSUSED*/
vi_replace_mode(EditLine * el,wint_t c)33912db70c8Szrj vi_replace_mode(EditLine *el, wint_t c __attribute__((__unused__)))
34032fe07f8SJohn Marino {
34132fe07f8SJohn Marino
34232fe07f8SJohn Marino el->el_map.current = el->el_map.key;
34332fe07f8SJohn Marino el->el_state.inputmode = MODE_REPLACE;
34432fe07f8SJohn Marino cv_undo(el);
34532fe07f8SJohn Marino return CC_NORM;
34632fe07f8SJohn Marino }
34732fe07f8SJohn Marino
34832fe07f8SJohn Marino
34932fe07f8SJohn Marino /* vi_substitute_char():
35032fe07f8SJohn Marino * Vi replace character under the cursor and enter insert mode
35132fe07f8SJohn Marino * [s]
35232fe07f8SJohn Marino */
35312db70c8Szrj libedit_private el_action_t
35432fe07f8SJohn Marino /*ARGSUSED*/
vi_substitute_char(EditLine * el,wint_t c)35512db70c8Szrj vi_substitute_char(EditLine *el, wint_t c __attribute__((__unused__)))
35632fe07f8SJohn Marino {
35732fe07f8SJohn Marino
35832fe07f8SJohn Marino c_delafter(el, el->el_state.argument);
35932fe07f8SJohn Marino el->el_map.current = el->el_map.key;
36032fe07f8SJohn Marino return CC_REFRESH;
36132fe07f8SJohn Marino }
36232fe07f8SJohn Marino
36332fe07f8SJohn Marino
36432fe07f8SJohn Marino /* vi_substitute_line():
36532fe07f8SJohn Marino * Vi substitute entire line
36632fe07f8SJohn Marino * [S]
36732fe07f8SJohn Marino */
36812db70c8Szrj libedit_private el_action_t
36932fe07f8SJohn Marino /*ARGSUSED*/
vi_substitute_line(EditLine * el,wint_t c)37012db70c8Szrj vi_substitute_line(EditLine *el, wint_t c __attribute__((__unused__)))
37132fe07f8SJohn Marino {
37232fe07f8SJohn Marino
37332fe07f8SJohn Marino cv_undo(el);
37432fe07f8SJohn Marino cv_yank(el, el->el_line.buffer,
37532fe07f8SJohn Marino (int)(el->el_line.lastchar - el->el_line.buffer));
37632fe07f8SJohn Marino (void) em_kill_line(el, 0);
37732fe07f8SJohn Marino el->el_map.current = el->el_map.key;
37832fe07f8SJohn Marino return CC_REFRESH;
37932fe07f8SJohn Marino }
38032fe07f8SJohn Marino
38132fe07f8SJohn Marino
38232fe07f8SJohn Marino /* vi_change_to_eol():
38332fe07f8SJohn Marino * Vi change to end of line
38432fe07f8SJohn Marino * [C]
38532fe07f8SJohn Marino */
38612db70c8Szrj libedit_private el_action_t
38732fe07f8SJohn Marino /*ARGSUSED*/
vi_change_to_eol(EditLine * el,wint_t c)38812db70c8Szrj vi_change_to_eol(EditLine *el, wint_t c __attribute__((__unused__)))
38932fe07f8SJohn Marino {
39032fe07f8SJohn Marino
39132fe07f8SJohn Marino cv_undo(el);
39232fe07f8SJohn Marino cv_yank(el, el->el_line.cursor,
39332fe07f8SJohn Marino (int)(el->el_line.lastchar - el->el_line.cursor));
39432fe07f8SJohn Marino (void) ed_kill_line(el, 0);
39532fe07f8SJohn Marino el->el_map.current = el->el_map.key;
39632fe07f8SJohn Marino return CC_REFRESH;
39732fe07f8SJohn Marino }
39832fe07f8SJohn Marino
39932fe07f8SJohn Marino
40032fe07f8SJohn Marino /* vi_insert():
40132fe07f8SJohn Marino * Vi enter insert mode
40232fe07f8SJohn Marino * [i]
40332fe07f8SJohn Marino */
40412db70c8Szrj libedit_private el_action_t
40532fe07f8SJohn Marino /*ARGSUSED*/
vi_insert(EditLine * el,wint_t c)40612db70c8Szrj vi_insert(EditLine *el, wint_t c __attribute__((__unused__)))
40732fe07f8SJohn Marino {
40832fe07f8SJohn Marino
40932fe07f8SJohn Marino el->el_map.current = el->el_map.key;
41032fe07f8SJohn Marino cv_undo(el);
41132fe07f8SJohn Marino return CC_NORM;
41232fe07f8SJohn Marino }
41332fe07f8SJohn Marino
41432fe07f8SJohn Marino
41532fe07f8SJohn Marino /* vi_add():
41632fe07f8SJohn Marino * Vi enter insert mode after the cursor
41732fe07f8SJohn Marino * [a]
41832fe07f8SJohn Marino */
41912db70c8Szrj libedit_private el_action_t
42032fe07f8SJohn Marino /*ARGSUSED*/
vi_add(EditLine * el,wint_t c)42112db70c8Szrj vi_add(EditLine *el, wint_t c __attribute__((__unused__)))
42232fe07f8SJohn Marino {
42332fe07f8SJohn Marino int ret;
42432fe07f8SJohn Marino
42532fe07f8SJohn Marino el->el_map.current = el->el_map.key;
42632fe07f8SJohn Marino if (el->el_line.cursor < el->el_line.lastchar) {
42732fe07f8SJohn Marino el->el_line.cursor++;
42832fe07f8SJohn Marino if (el->el_line.cursor > el->el_line.lastchar)
42932fe07f8SJohn Marino el->el_line.cursor = el->el_line.lastchar;
43032fe07f8SJohn Marino ret = CC_CURSOR;
43132fe07f8SJohn Marino } else
43232fe07f8SJohn Marino ret = CC_NORM;
43332fe07f8SJohn Marino
43432fe07f8SJohn Marino cv_undo(el);
43532fe07f8SJohn Marino
43632fe07f8SJohn Marino return (el_action_t)ret;
43732fe07f8SJohn Marino }
43832fe07f8SJohn Marino
43932fe07f8SJohn Marino
44032fe07f8SJohn Marino /* vi_add_at_eol():
44132fe07f8SJohn Marino * Vi enter insert mode at end of line
44232fe07f8SJohn Marino * [A]
44332fe07f8SJohn Marino */
44412db70c8Szrj libedit_private el_action_t
44532fe07f8SJohn Marino /*ARGSUSED*/
vi_add_at_eol(EditLine * el,wint_t c)44612db70c8Szrj vi_add_at_eol(EditLine *el, wint_t c __attribute__((__unused__)))
44732fe07f8SJohn Marino {
44832fe07f8SJohn Marino
44932fe07f8SJohn Marino el->el_map.current = el->el_map.key;
45032fe07f8SJohn Marino el->el_line.cursor = el->el_line.lastchar;
45132fe07f8SJohn Marino cv_undo(el);
45232fe07f8SJohn Marino return CC_CURSOR;
45332fe07f8SJohn Marino }
45432fe07f8SJohn Marino
45532fe07f8SJohn Marino
45632fe07f8SJohn Marino /* vi_delete_meta():
45732fe07f8SJohn Marino * Vi delete prefix command
45832fe07f8SJohn Marino * [d]
45932fe07f8SJohn Marino */
46012db70c8Szrj libedit_private el_action_t
46132fe07f8SJohn Marino /*ARGSUSED*/
vi_delete_meta(EditLine * el,wint_t c)46212db70c8Szrj vi_delete_meta(EditLine *el, wint_t c __attribute__((__unused__)))
46332fe07f8SJohn Marino {
46432fe07f8SJohn Marino
46532fe07f8SJohn Marino return cv_action(el, DELETE);
46632fe07f8SJohn Marino }
46732fe07f8SJohn Marino
46832fe07f8SJohn Marino
46932fe07f8SJohn Marino /* vi_end_big_word():
47032fe07f8SJohn Marino * Vi move to the end of the current space delimited word
47132fe07f8SJohn Marino * [E]
47232fe07f8SJohn Marino */
47312db70c8Szrj libedit_private el_action_t
47432fe07f8SJohn Marino /*ARGSUSED*/
vi_end_big_word(EditLine * el,wint_t c)47512db70c8Szrj vi_end_big_word(EditLine *el, wint_t c __attribute__((__unused__)))
47632fe07f8SJohn Marino {
47732fe07f8SJohn Marino
47832fe07f8SJohn Marino if (el->el_line.cursor == el->el_line.lastchar)
47932fe07f8SJohn Marino return CC_ERROR;
48032fe07f8SJohn Marino
48132fe07f8SJohn Marino el->el_line.cursor = cv__endword(el->el_line.cursor,
48232fe07f8SJohn Marino el->el_line.lastchar, el->el_state.argument, cv__isWord);
48332fe07f8SJohn Marino
48432fe07f8SJohn Marino if (el->el_chared.c_vcmd.action != NOP) {
48532fe07f8SJohn Marino el->el_line.cursor++;
48632fe07f8SJohn Marino cv_delfini(el);
48732fe07f8SJohn Marino return CC_REFRESH;
48832fe07f8SJohn Marino }
48932fe07f8SJohn Marino return CC_CURSOR;
49032fe07f8SJohn Marino }
49132fe07f8SJohn Marino
49232fe07f8SJohn Marino
49332fe07f8SJohn Marino /* vi_end_word():
49432fe07f8SJohn Marino * Vi move to the end of the current word
49532fe07f8SJohn Marino * [e]
49632fe07f8SJohn Marino */
49712db70c8Szrj libedit_private el_action_t
49832fe07f8SJohn Marino /*ARGSUSED*/
vi_end_word(EditLine * el,wint_t c)49912db70c8Szrj vi_end_word(EditLine *el, wint_t c __attribute__((__unused__)))
50032fe07f8SJohn Marino {
50132fe07f8SJohn Marino
50232fe07f8SJohn Marino if (el->el_line.cursor == el->el_line.lastchar)
50332fe07f8SJohn Marino return CC_ERROR;
50432fe07f8SJohn Marino
50532fe07f8SJohn Marino el->el_line.cursor = cv__endword(el->el_line.cursor,
50632fe07f8SJohn Marino el->el_line.lastchar, el->el_state.argument, cv__isword);
50732fe07f8SJohn Marino
50832fe07f8SJohn Marino if (el->el_chared.c_vcmd.action != NOP) {
50932fe07f8SJohn Marino el->el_line.cursor++;
51032fe07f8SJohn Marino cv_delfini(el);
51132fe07f8SJohn Marino return CC_REFRESH;
51232fe07f8SJohn Marino }
51332fe07f8SJohn Marino return CC_CURSOR;
51432fe07f8SJohn Marino }
51532fe07f8SJohn Marino
51632fe07f8SJohn Marino
51732fe07f8SJohn Marino /* vi_undo():
51832fe07f8SJohn Marino * Vi undo last change
51932fe07f8SJohn Marino * [u]
52032fe07f8SJohn Marino */
52112db70c8Szrj libedit_private el_action_t
52232fe07f8SJohn Marino /*ARGSUSED*/
vi_undo(EditLine * el,wint_t c)52312db70c8Szrj vi_undo(EditLine *el, wint_t c __attribute__((__unused__)))
52432fe07f8SJohn Marino {
52532fe07f8SJohn Marino c_undo_t un = el->el_chared.c_undo;
52632fe07f8SJohn Marino
52732fe07f8SJohn Marino if (un.len == -1)
52832fe07f8SJohn Marino return CC_ERROR;
52932fe07f8SJohn Marino
53032fe07f8SJohn Marino /* switch line buffer and undo buffer */
53132fe07f8SJohn Marino el->el_chared.c_undo.buf = el->el_line.buffer;
53232fe07f8SJohn Marino el->el_chared.c_undo.len = el->el_line.lastchar - el->el_line.buffer;
53332fe07f8SJohn Marino el->el_chared.c_undo.cursor =
53432fe07f8SJohn Marino (int)(el->el_line.cursor - el->el_line.buffer);
53532fe07f8SJohn Marino el->el_line.limit = un.buf + (el->el_line.limit - el->el_line.buffer);
53632fe07f8SJohn Marino el->el_line.buffer = un.buf;
53732fe07f8SJohn Marino el->el_line.cursor = un.buf + un.cursor;
53832fe07f8SJohn Marino el->el_line.lastchar = un.buf + un.len;
53932fe07f8SJohn Marino
54032fe07f8SJohn Marino return CC_REFRESH;
54132fe07f8SJohn Marino }
54232fe07f8SJohn Marino
54332fe07f8SJohn Marino
54432fe07f8SJohn Marino /* vi_command_mode():
54532fe07f8SJohn Marino * Vi enter command mode (use alternative key bindings)
54632fe07f8SJohn Marino * [<ESC>]
54732fe07f8SJohn Marino */
54812db70c8Szrj libedit_private el_action_t
54932fe07f8SJohn Marino /*ARGSUSED*/
vi_command_mode(EditLine * el,wint_t c)55012db70c8Szrj vi_command_mode(EditLine *el, wint_t c __attribute__((__unused__)))
55132fe07f8SJohn Marino {
55232fe07f8SJohn Marino
55332fe07f8SJohn Marino /* [Esc] cancels pending action */
55432fe07f8SJohn Marino el->el_chared.c_vcmd.action = NOP;
55532fe07f8SJohn Marino el->el_chared.c_vcmd.pos = 0;
55632fe07f8SJohn Marino
55732fe07f8SJohn Marino el->el_state.doingarg = 0;
55832fe07f8SJohn Marino
55932fe07f8SJohn Marino el->el_state.inputmode = MODE_INSERT;
56032fe07f8SJohn Marino el->el_map.current = el->el_map.alt;
56132fe07f8SJohn Marino #ifdef VI_MOVE
56232fe07f8SJohn Marino if (el->el_line.cursor > el->el_line.buffer)
56332fe07f8SJohn Marino el->el_line.cursor--;
56432fe07f8SJohn Marino #endif
56532fe07f8SJohn Marino return CC_CURSOR;
56632fe07f8SJohn Marino }
56732fe07f8SJohn Marino
56832fe07f8SJohn Marino
56932fe07f8SJohn Marino /* vi_zero():
57032fe07f8SJohn Marino * Vi move to the beginning of line
57132fe07f8SJohn Marino * [0]
57232fe07f8SJohn Marino */
57312db70c8Szrj libedit_private el_action_t
vi_zero(EditLine * el,wint_t c)57412db70c8Szrj vi_zero(EditLine *el, wint_t c)
57532fe07f8SJohn Marino {
57632fe07f8SJohn Marino
57732fe07f8SJohn Marino if (el->el_state.doingarg)
57832fe07f8SJohn Marino return ed_argument_digit(el, c);
57932fe07f8SJohn Marino
58032fe07f8SJohn Marino el->el_line.cursor = el->el_line.buffer;
58132fe07f8SJohn Marino if (el->el_chared.c_vcmd.action != NOP) {
58232fe07f8SJohn Marino cv_delfini(el);
58332fe07f8SJohn Marino return CC_REFRESH;
58432fe07f8SJohn Marino }
58532fe07f8SJohn Marino return CC_CURSOR;
58632fe07f8SJohn Marino }
58732fe07f8SJohn Marino
58832fe07f8SJohn Marino
58932fe07f8SJohn Marino /* vi_delete_prev_char():
59032fe07f8SJohn Marino * Vi move to previous character (backspace)
59132fe07f8SJohn Marino * [^H] in insert mode only
59232fe07f8SJohn Marino */
59312db70c8Szrj libedit_private el_action_t
59432fe07f8SJohn Marino /*ARGSUSED*/
vi_delete_prev_char(EditLine * el,wint_t c)59512db70c8Szrj vi_delete_prev_char(EditLine *el, wint_t c __attribute__((__unused__)))
59632fe07f8SJohn Marino {
59732fe07f8SJohn Marino
59832fe07f8SJohn Marino if (el->el_line.cursor <= el->el_line.buffer)
59932fe07f8SJohn Marino return CC_ERROR;
60032fe07f8SJohn Marino
60132fe07f8SJohn Marino c_delbefore1(el);
60232fe07f8SJohn Marino el->el_line.cursor--;
60332fe07f8SJohn Marino return CC_REFRESH;
60432fe07f8SJohn Marino }
60532fe07f8SJohn Marino
60632fe07f8SJohn Marino
60732fe07f8SJohn Marino /* vi_list_or_eof():
60832fe07f8SJohn Marino * Vi list choices for completion or indicate end of file if empty line
60932fe07f8SJohn Marino * [^D]
61032fe07f8SJohn Marino */
61112db70c8Szrj libedit_private el_action_t
61232fe07f8SJohn Marino /*ARGSUSED*/
vi_list_or_eof(EditLine * el,wint_t c)61312db70c8Szrj vi_list_or_eof(EditLine *el, wint_t c)
61432fe07f8SJohn Marino {
61532fe07f8SJohn Marino
61632fe07f8SJohn Marino if (el->el_line.cursor == el->el_line.lastchar) {
61732fe07f8SJohn Marino if (el->el_line.cursor == el->el_line.buffer) {
61832fe07f8SJohn Marino terminal_writec(el, c); /* then do a EOF */
61932fe07f8SJohn Marino return CC_EOF;
62032fe07f8SJohn Marino } else {
62132fe07f8SJohn Marino /*
62232fe07f8SJohn Marino * Here we could list completions, but it is an
62332fe07f8SJohn Marino * error right now
62432fe07f8SJohn Marino */
62532fe07f8SJohn Marino terminal_beep(el);
62632fe07f8SJohn Marino return CC_ERROR;
62732fe07f8SJohn Marino }
62832fe07f8SJohn Marino } else {
62932fe07f8SJohn Marino #ifdef notyet
63032fe07f8SJohn Marino re_goto_bottom(el);
63132fe07f8SJohn Marino *el->el_line.lastchar = '\0'; /* just in case */
63232fe07f8SJohn Marino return CC_LIST_CHOICES;
63332fe07f8SJohn Marino #else
63432fe07f8SJohn Marino /*
63532fe07f8SJohn Marino * Just complain for now.
63632fe07f8SJohn Marino */
63732fe07f8SJohn Marino terminal_beep(el);
63832fe07f8SJohn Marino return CC_ERROR;
63932fe07f8SJohn Marino #endif
64032fe07f8SJohn Marino }
64132fe07f8SJohn Marino }
64232fe07f8SJohn Marino
64332fe07f8SJohn Marino
64432fe07f8SJohn Marino /* vi_kill_line_prev():
64532fe07f8SJohn Marino * Vi cut from beginning of line to cursor
64632fe07f8SJohn Marino * [^U]
64732fe07f8SJohn Marino */
64812db70c8Szrj libedit_private el_action_t
64932fe07f8SJohn Marino /*ARGSUSED*/
vi_kill_line_prev(EditLine * el,wint_t c)65012db70c8Szrj vi_kill_line_prev(EditLine *el, wint_t c __attribute__((__unused__)))
65132fe07f8SJohn Marino {
65212db70c8Szrj wchar_t *kp, *cp;
65332fe07f8SJohn Marino
65432fe07f8SJohn Marino cp = el->el_line.buffer;
65532fe07f8SJohn Marino kp = el->el_chared.c_kill.buf;
65632fe07f8SJohn Marino while (cp < el->el_line.cursor)
65732fe07f8SJohn Marino *kp++ = *cp++; /* copy it */
65832fe07f8SJohn Marino el->el_chared.c_kill.last = kp;
65932fe07f8SJohn Marino c_delbefore(el, (int)(el->el_line.cursor - el->el_line.buffer));
66032fe07f8SJohn Marino el->el_line.cursor = el->el_line.buffer; /* zap! */
66132fe07f8SJohn Marino return CC_REFRESH;
66232fe07f8SJohn Marino }
66332fe07f8SJohn Marino
66432fe07f8SJohn Marino
66532fe07f8SJohn Marino /* vi_search_prev():
66632fe07f8SJohn Marino * Vi search history previous
66732fe07f8SJohn Marino * [?]
66832fe07f8SJohn Marino */
66912db70c8Szrj libedit_private el_action_t
67032fe07f8SJohn Marino /*ARGSUSED*/
vi_search_prev(EditLine * el,wint_t c)67112db70c8Szrj vi_search_prev(EditLine *el, wint_t c __attribute__((__unused__)))
67232fe07f8SJohn Marino {
67332fe07f8SJohn Marino
67432fe07f8SJohn Marino return cv_search(el, ED_SEARCH_PREV_HISTORY);
67532fe07f8SJohn Marino }
67632fe07f8SJohn Marino
67732fe07f8SJohn Marino
67832fe07f8SJohn Marino /* vi_search_next():
67932fe07f8SJohn Marino * Vi search history next
68032fe07f8SJohn Marino * [/]
68132fe07f8SJohn Marino */
68212db70c8Szrj libedit_private el_action_t
68332fe07f8SJohn Marino /*ARGSUSED*/
vi_search_next(EditLine * el,wint_t c)68412db70c8Szrj vi_search_next(EditLine *el, wint_t c __attribute__((__unused__)))
68532fe07f8SJohn Marino {
68632fe07f8SJohn Marino
68732fe07f8SJohn Marino return cv_search(el, ED_SEARCH_NEXT_HISTORY);
68832fe07f8SJohn Marino }
68932fe07f8SJohn Marino
69032fe07f8SJohn Marino
69132fe07f8SJohn Marino /* vi_repeat_search_next():
69232fe07f8SJohn Marino * Vi repeat current search in the same search direction
69332fe07f8SJohn Marino * [n]
69432fe07f8SJohn Marino */
69512db70c8Szrj libedit_private el_action_t
69632fe07f8SJohn Marino /*ARGSUSED*/
vi_repeat_search_next(EditLine * el,wint_t c)69712db70c8Szrj vi_repeat_search_next(EditLine *el, wint_t c __attribute__((__unused__)))
69832fe07f8SJohn Marino {
69932fe07f8SJohn Marino
70032fe07f8SJohn Marino if (el->el_search.patlen == 0)
70132fe07f8SJohn Marino return CC_ERROR;
70232fe07f8SJohn Marino else
70332fe07f8SJohn Marino return cv_repeat_srch(el, el->el_search.patdir);
70432fe07f8SJohn Marino }
70532fe07f8SJohn Marino
70632fe07f8SJohn Marino
70732fe07f8SJohn Marino /* vi_repeat_search_prev():
70832fe07f8SJohn Marino * Vi repeat current search in the opposite search direction
70932fe07f8SJohn Marino * [N]
71032fe07f8SJohn Marino */
71132fe07f8SJohn Marino /*ARGSUSED*/
71212db70c8Szrj libedit_private el_action_t
vi_repeat_search_prev(EditLine * el,wint_t c)71312db70c8Szrj vi_repeat_search_prev(EditLine *el, wint_t c __attribute__((__unused__)))
71432fe07f8SJohn Marino {
71532fe07f8SJohn Marino
71632fe07f8SJohn Marino if (el->el_search.patlen == 0)
71732fe07f8SJohn Marino return CC_ERROR;
71832fe07f8SJohn Marino else
71932fe07f8SJohn Marino return (cv_repeat_srch(el,
72032fe07f8SJohn Marino el->el_search.patdir == ED_SEARCH_PREV_HISTORY ?
72132fe07f8SJohn Marino ED_SEARCH_NEXT_HISTORY : ED_SEARCH_PREV_HISTORY));
72232fe07f8SJohn Marino }
72332fe07f8SJohn Marino
72432fe07f8SJohn Marino
72532fe07f8SJohn Marino /* vi_next_char():
72632fe07f8SJohn Marino * Vi move to the character specified next
72732fe07f8SJohn Marino * [f]
72832fe07f8SJohn Marino */
72912db70c8Szrj libedit_private el_action_t
73032fe07f8SJohn Marino /*ARGSUSED*/
vi_next_char(EditLine * el,wint_t c)73112db70c8Szrj vi_next_char(EditLine *el, wint_t c __attribute__((__unused__)))
73232fe07f8SJohn Marino {
73332fe07f8SJohn Marino return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 0);
73432fe07f8SJohn Marino }
73532fe07f8SJohn Marino
73632fe07f8SJohn Marino
73732fe07f8SJohn Marino /* vi_prev_char():
73832fe07f8SJohn Marino * Vi move to the character specified previous
73932fe07f8SJohn Marino * [F]
74032fe07f8SJohn Marino */
74112db70c8Szrj libedit_private el_action_t
74232fe07f8SJohn Marino /*ARGSUSED*/
vi_prev_char(EditLine * el,wint_t c)74312db70c8Szrj vi_prev_char(EditLine *el, wint_t c __attribute__((__unused__)))
74432fe07f8SJohn Marino {
74532fe07f8SJohn Marino return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 0);
74632fe07f8SJohn Marino }
74732fe07f8SJohn Marino
74832fe07f8SJohn Marino
74932fe07f8SJohn Marino /* vi_to_next_char():
75032fe07f8SJohn Marino * Vi move up to the character specified next
75132fe07f8SJohn Marino * [t]
75232fe07f8SJohn Marino */
75312db70c8Szrj libedit_private el_action_t
75432fe07f8SJohn Marino /*ARGSUSED*/
vi_to_next_char(EditLine * el,wint_t c)75512db70c8Szrj vi_to_next_char(EditLine *el, wint_t c __attribute__((__unused__)))
75632fe07f8SJohn Marino {
75732fe07f8SJohn Marino return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 1);
75832fe07f8SJohn Marino }
75932fe07f8SJohn Marino
76032fe07f8SJohn Marino
76132fe07f8SJohn Marino /* vi_to_prev_char():
76232fe07f8SJohn Marino * Vi move up to the character specified previous
76332fe07f8SJohn Marino * [T]
76432fe07f8SJohn Marino */
76512db70c8Szrj libedit_private el_action_t
76632fe07f8SJohn Marino /*ARGSUSED*/
vi_to_prev_char(EditLine * el,wint_t c)76712db70c8Szrj vi_to_prev_char(EditLine *el, wint_t c __attribute__((__unused__)))
76832fe07f8SJohn Marino {
76932fe07f8SJohn Marino return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 1);
77032fe07f8SJohn Marino }
77132fe07f8SJohn Marino
77232fe07f8SJohn Marino
77332fe07f8SJohn Marino /* vi_repeat_next_char():
77432fe07f8SJohn Marino * Vi repeat current character search in the same search direction
77532fe07f8SJohn Marino * [;]
77632fe07f8SJohn Marino */
77712db70c8Szrj libedit_private el_action_t
77832fe07f8SJohn Marino /*ARGSUSED*/
vi_repeat_next_char(EditLine * el,wint_t c)77912db70c8Szrj vi_repeat_next_char(EditLine *el, wint_t c __attribute__((__unused__)))
78032fe07f8SJohn Marino {
78132fe07f8SJohn Marino
78232fe07f8SJohn Marino return cv_csearch(el, el->el_search.chadir, el->el_search.chacha,
78332fe07f8SJohn Marino el->el_state.argument, el->el_search.chatflg);
78432fe07f8SJohn Marino }
78532fe07f8SJohn Marino
78632fe07f8SJohn Marino
78732fe07f8SJohn Marino /* vi_repeat_prev_char():
78832fe07f8SJohn Marino * Vi repeat current character search in the opposite search direction
78932fe07f8SJohn Marino * [,]
79032fe07f8SJohn Marino */
79112db70c8Szrj libedit_private el_action_t
79232fe07f8SJohn Marino /*ARGSUSED*/
vi_repeat_prev_char(EditLine * el,wint_t c)79312db70c8Szrj vi_repeat_prev_char(EditLine *el, wint_t c __attribute__((__unused__)))
79432fe07f8SJohn Marino {
79532fe07f8SJohn Marino el_action_t r;
79632fe07f8SJohn Marino int dir = el->el_search.chadir;
79732fe07f8SJohn Marino
79832fe07f8SJohn Marino r = cv_csearch(el, -dir, el->el_search.chacha,
79932fe07f8SJohn Marino el->el_state.argument, el->el_search.chatflg);
80032fe07f8SJohn Marino el->el_search.chadir = dir;
80132fe07f8SJohn Marino return r;
80232fe07f8SJohn Marino }
80332fe07f8SJohn Marino
80432fe07f8SJohn Marino
80532fe07f8SJohn Marino /* vi_match():
80632fe07f8SJohn Marino * Vi go to matching () {} or []
80732fe07f8SJohn Marino * [%]
80832fe07f8SJohn Marino */
80912db70c8Szrj libedit_private el_action_t
81032fe07f8SJohn Marino /*ARGSUSED*/
vi_match(EditLine * el,wint_t c)81112db70c8Szrj vi_match(EditLine *el, wint_t c __attribute__((__unused__)))
81232fe07f8SJohn Marino {
81312db70c8Szrj const wchar_t match_chars[] = L"()[]{}";
81412db70c8Szrj wchar_t *cp;
81532fe07f8SJohn Marino size_t delta, i, count;
81612db70c8Szrj wchar_t o_ch, c_ch;
81732fe07f8SJohn Marino
81832fe07f8SJohn Marino *el->el_line.lastchar = '\0'; /* just in case */
81932fe07f8SJohn Marino
82012db70c8Szrj i = wcscspn(el->el_line.cursor, match_chars);
82132fe07f8SJohn Marino o_ch = el->el_line.cursor[i];
82232fe07f8SJohn Marino if (o_ch == 0)
82332fe07f8SJohn Marino return CC_ERROR;
82412db70c8Szrj delta = (size_t)(wcschr(match_chars, o_ch) - match_chars);
82532fe07f8SJohn Marino c_ch = match_chars[delta ^ 1];
82632fe07f8SJohn Marino count = 1;
82732fe07f8SJohn Marino delta = 1 - (delta & 1) * 2;
82832fe07f8SJohn Marino
82932fe07f8SJohn Marino for (cp = &el->el_line.cursor[i]; count; ) {
83032fe07f8SJohn Marino cp += delta;
83132fe07f8SJohn Marino if (cp < el->el_line.buffer || cp >= el->el_line.lastchar)
83232fe07f8SJohn Marino return CC_ERROR;
83332fe07f8SJohn Marino if (*cp == o_ch)
83432fe07f8SJohn Marino count++;
83532fe07f8SJohn Marino else if (*cp == c_ch)
83632fe07f8SJohn Marino count--;
83732fe07f8SJohn Marino }
83832fe07f8SJohn Marino
83932fe07f8SJohn Marino el->el_line.cursor = cp;
84032fe07f8SJohn Marino
84132fe07f8SJohn Marino if (el->el_chared.c_vcmd.action != NOP) {
84232fe07f8SJohn Marino /* NB posix says char under cursor should NOT be deleted
84332fe07f8SJohn Marino for -ve delta - this is different to netbsd vi. */
84432fe07f8SJohn Marino if (delta > 0)
84532fe07f8SJohn Marino el->el_line.cursor++;
84632fe07f8SJohn Marino cv_delfini(el);
84732fe07f8SJohn Marino return CC_REFRESH;
84832fe07f8SJohn Marino }
84932fe07f8SJohn Marino return CC_CURSOR;
85032fe07f8SJohn Marino }
85132fe07f8SJohn Marino
85232fe07f8SJohn Marino /* vi_undo_line():
85332fe07f8SJohn Marino * Vi undo all changes to line
85432fe07f8SJohn Marino * [U]
85532fe07f8SJohn Marino */
85612db70c8Szrj libedit_private el_action_t
85732fe07f8SJohn Marino /*ARGSUSED*/
vi_undo_line(EditLine * el,wint_t c)85812db70c8Szrj vi_undo_line(EditLine *el, wint_t c __attribute__((__unused__)))
85932fe07f8SJohn Marino {
86032fe07f8SJohn Marino
86132fe07f8SJohn Marino cv_undo(el);
86232fe07f8SJohn Marino return hist_get(el);
86332fe07f8SJohn Marino }
86432fe07f8SJohn Marino
86532fe07f8SJohn Marino /* vi_to_column():
86632fe07f8SJohn Marino * Vi go to specified column
86732fe07f8SJohn Marino * [|]
86832fe07f8SJohn Marino * NB netbsd vi goes to screen column 'n', posix says nth character
86932fe07f8SJohn Marino */
87012db70c8Szrj libedit_private el_action_t
87132fe07f8SJohn Marino /*ARGSUSED*/
vi_to_column(EditLine * el,wint_t c)87212db70c8Szrj vi_to_column(EditLine *el, wint_t c __attribute__((__unused__)))
87332fe07f8SJohn Marino {
87432fe07f8SJohn Marino
87532fe07f8SJohn Marino el->el_line.cursor = el->el_line.buffer;
87632fe07f8SJohn Marino el->el_state.argument--;
87732fe07f8SJohn Marino return ed_next_char(el, 0);
87832fe07f8SJohn Marino }
87932fe07f8SJohn Marino
88032fe07f8SJohn Marino /* vi_yank_end():
88132fe07f8SJohn Marino * Vi yank to end of line
88232fe07f8SJohn Marino * [Y]
88332fe07f8SJohn Marino */
88412db70c8Szrj libedit_private el_action_t
88532fe07f8SJohn Marino /*ARGSUSED*/
vi_yank_end(EditLine * el,wint_t c)88612db70c8Szrj vi_yank_end(EditLine *el, wint_t c __attribute__((__unused__)))
88732fe07f8SJohn Marino {
88832fe07f8SJohn Marino
88932fe07f8SJohn Marino cv_yank(el, el->el_line.cursor,
89032fe07f8SJohn Marino (int)(el->el_line.lastchar - el->el_line.cursor));
89132fe07f8SJohn Marino return CC_REFRESH;
89232fe07f8SJohn Marino }
89332fe07f8SJohn Marino
89432fe07f8SJohn Marino /* vi_yank():
89532fe07f8SJohn Marino * Vi yank
89632fe07f8SJohn Marino * [y]
89732fe07f8SJohn Marino */
89812db70c8Szrj libedit_private el_action_t
89932fe07f8SJohn Marino /*ARGSUSED*/
vi_yank(EditLine * el,wint_t c)90012db70c8Szrj vi_yank(EditLine *el, wint_t c __attribute__((__unused__)))
90132fe07f8SJohn Marino {
90232fe07f8SJohn Marino
90332fe07f8SJohn Marino return cv_action(el, YANK);
90432fe07f8SJohn Marino }
90532fe07f8SJohn Marino
90632fe07f8SJohn Marino /* vi_comment_out():
90732fe07f8SJohn Marino * Vi comment out current command
90832fe07f8SJohn Marino * [#]
90932fe07f8SJohn Marino */
91012db70c8Szrj libedit_private el_action_t
91132fe07f8SJohn Marino /*ARGSUSED*/
vi_comment_out(EditLine * el,wint_t c)91212db70c8Szrj vi_comment_out(EditLine *el, wint_t c __attribute__((__unused__)))
91332fe07f8SJohn Marino {
91432fe07f8SJohn Marino
91532fe07f8SJohn Marino el->el_line.cursor = el->el_line.buffer;
91632fe07f8SJohn Marino c_insert(el, 1);
91732fe07f8SJohn Marino *el->el_line.cursor = '#';
91832fe07f8SJohn Marino re_refresh(el);
91932fe07f8SJohn Marino return ed_newline(el, 0);
92032fe07f8SJohn Marino }
92132fe07f8SJohn Marino
92232fe07f8SJohn Marino /* vi_alias():
92332fe07f8SJohn Marino * Vi include shell alias
92432fe07f8SJohn Marino * [@]
92532fe07f8SJohn Marino * NB: posix implies that we should enter insert mode, however
92632fe07f8SJohn Marino * this is against historical precedent...
92732fe07f8SJohn Marino */
92812db70c8Szrj libedit_private el_action_t
92932fe07f8SJohn Marino /*ARGSUSED*/
vi_alias(EditLine * el,wint_t c)93012db70c8Szrj vi_alias(EditLine *el, wint_t c __attribute__((__unused__)))
93132fe07f8SJohn Marino {
93232fe07f8SJohn Marino char alias_name[3];
93384b940c1SJohn Marino const char *alias_text;
93432fe07f8SJohn Marino
93584b940c1SJohn Marino if (el->el_chared.c_aliasfun == NULL)
93632fe07f8SJohn Marino return CC_ERROR;
93732fe07f8SJohn Marino
93832fe07f8SJohn Marino alias_name[0] = '_';
93932fe07f8SJohn Marino alias_name[2] = 0;
94032fe07f8SJohn Marino if (el_getc(el, &alias_name[1]) != 1)
94132fe07f8SJohn Marino return CC_ERROR;
94232fe07f8SJohn Marino
94384b940c1SJohn Marino alias_text = (*el->el_chared.c_aliasfun)(el->el_chared.c_aliasarg,
94484b940c1SJohn Marino alias_name);
94532fe07f8SJohn Marino if (alias_text != NULL)
94612db70c8Szrj el_wpush(el, ct_decode_string(alias_text, &el->el_scratch));
94732fe07f8SJohn Marino return CC_NORM;
94832fe07f8SJohn Marino }
94932fe07f8SJohn Marino
95032fe07f8SJohn Marino /* vi_to_history_line():
95132fe07f8SJohn Marino * Vi go to specified history file line.
95232fe07f8SJohn Marino * [G]
95332fe07f8SJohn Marino */
95412db70c8Szrj libedit_private el_action_t
95532fe07f8SJohn Marino /*ARGSUSED*/
vi_to_history_line(EditLine * el,wint_t c)95612db70c8Szrj vi_to_history_line(EditLine *el, wint_t c __attribute__((__unused__)))
95732fe07f8SJohn Marino {
95832fe07f8SJohn Marino int sv_event_no = el->el_history.eventno;
95932fe07f8SJohn Marino el_action_t rval;
96032fe07f8SJohn Marino
96132fe07f8SJohn Marino
96232fe07f8SJohn Marino if (el->el_history.eventno == 0) {
96312db70c8Szrj (void) wcsncpy(el->el_history.buf, el->el_line.buffer,
96432fe07f8SJohn Marino EL_BUFSIZ);
96532fe07f8SJohn Marino el->el_history.last = el->el_history.buf +
96632fe07f8SJohn Marino (el->el_line.lastchar - el->el_line.buffer);
96732fe07f8SJohn Marino }
96832fe07f8SJohn Marino
96932fe07f8SJohn Marino /* Lack of a 'count' means oldest, not 1 */
97032fe07f8SJohn Marino if (!el->el_state.doingarg) {
97132fe07f8SJohn Marino el->el_history.eventno = 0x7fffffff;
97232fe07f8SJohn Marino hist_get(el);
97332fe07f8SJohn Marino } else {
97432fe07f8SJohn Marino /* This is brain dead, all the rest of this code counts
97532fe07f8SJohn Marino * upwards going into the past. Here we need count in the
97632fe07f8SJohn Marino * other direction (to match the output of fc -l).
97732fe07f8SJohn Marino * I could change the world, but this seems to suffice.
97832fe07f8SJohn Marino */
97932fe07f8SJohn Marino el->el_history.eventno = 1;
98032fe07f8SJohn Marino if (hist_get(el) == CC_ERROR)
98132fe07f8SJohn Marino return CC_ERROR;
98232fe07f8SJohn Marino el->el_history.eventno = 1 + el->el_history.ev.num
98332fe07f8SJohn Marino - el->el_state.argument;
98432fe07f8SJohn Marino if (el->el_history.eventno < 0) {
98532fe07f8SJohn Marino el->el_history.eventno = sv_event_no;
98632fe07f8SJohn Marino return CC_ERROR;
98732fe07f8SJohn Marino }
98832fe07f8SJohn Marino }
98932fe07f8SJohn Marino rval = hist_get(el);
99032fe07f8SJohn Marino if (rval == CC_ERROR)
99132fe07f8SJohn Marino el->el_history.eventno = sv_event_no;
99232fe07f8SJohn Marino return rval;
99332fe07f8SJohn Marino }
99432fe07f8SJohn Marino
99532fe07f8SJohn Marino /* vi_histedit():
99632fe07f8SJohn Marino * Vi edit history line with vi
99732fe07f8SJohn Marino * [v]
99832fe07f8SJohn Marino */
99912db70c8Szrj libedit_private el_action_t
100032fe07f8SJohn Marino /*ARGSUSED*/
vi_histedit(EditLine * el,wint_t c)100112db70c8Szrj vi_histedit(EditLine *el, wint_t c __attribute__((__unused__)))
100232fe07f8SJohn Marino {
100332fe07f8SJohn Marino int fd;
100432fe07f8SJohn Marino pid_t pid;
100532fe07f8SJohn Marino ssize_t st;
100632fe07f8SJohn Marino int status;
100732fe07f8SJohn Marino char tempfile[] = "/tmp/histedit.XXXXXXXXXX";
100832fe07f8SJohn Marino char *cp = NULL;
100932fe07f8SJohn Marino size_t len;
101012db70c8Szrj wchar_t *line = NULL;
1011*cdf8408cSAntonio Huete Jimenez const char *editor;
101232fe07f8SJohn Marino
101332fe07f8SJohn Marino if (el->el_state.doingarg) {
101432fe07f8SJohn Marino if (vi_to_history_line(el, 0) == CC_ERROR)
101532fe07f8SJohn Marino return CC_ERROR;
101632fe07f8SJohn Marino }
101732fe07f8SJohn Marino
1018*cdf8408cSAntonio Huete Jimenez if ((editor = getenv("EDITOR")) == NULL)
1019*cdf8408cSAntonio Huete Jimenez editor = "vi";
102032fe07f8SJohn Marino fd = mkstemp(tempfile);
102132fe07f8SJohn Marino if (fd < 0)
102232fe07f8SJohn Marino return CC_ERROR;
102332fe07f8SJohn Marino len = (size_t)(el->el_line.lastchar - el->el_line.buffer);
102432fe07f8SJohn Marino #define TMP_BUFSIZ (EL_BUFSIZ * MB_LEN_MAX)
102560ecde0cSDaniel Fojt cp = el_calloc(TMP_BUFSIZ, sizeof(*cp));
102632fe07f8SJohn Marino if (cp == NULL)
102732fe07f8SJohn Marino goto error;
102860ecde0cSDaniel Fojt line = el_calloc(len + 1, sizeof(*line));
102932fe07f8SJohn Marino if (line == NULL)
103032fe07f8SJohn Marino goto error;
103112db70c8Szrj wcsncpy(line, el->el_line.buffer, len);
103232fe07f8SJohn Marino line[len] = '\0';
103312db70c8Szrj wcstombs(cp, line, TMP_BUFSIZ - 1);
103432fe07f8SJohn Marino cp[TMP_BUFSIZ - 1] = '\0';
103532fe07f8SJohn Marino len = strlen(cp);
103632fe07f8SJohn Marino write(fd, cp, len);
103732fe07f8SJohn Marino write(fd, "\n", (size_t)1);
103832fe07f8SJohn Marino pid = fork();
103932fe07f8SJohn Marino switch (pid) {
104032fe07f8SJohn Marino case -1:
104132fe07f8SJohn Marino goto error;
104232fe07f8SJohn Marino case 0:
104332fe07f8SJohn Marino close(fd);
1044*cdf8408cSAntonio Huete Jimenez execlp(editor, editor, tempfile, (char *)NULL);
104532fe07f8SJohn Marino exit(0);
104632fe07f8SJohn Marino /*NOTREACHED*/
104732fe07f8SJohn Marino default:
104832fe07f8SJohn Marino while (waitpid(pid, &status, 0) != pid)
104932fe07f8SJohn Marino continue;
105032fe07f8SJohn Marino lseek(fd, (off_t)0, SEEK_SET);
105112db70c8Szrj st = read(fd, cp, TMP_BUFSIZ - 1);
105232fe07f8SJohn Marino if (st > 0) {
105312db70c8Szrj cp[st] = '\0';
105412db70c8Szrj len = (size_t)(el->el_line.limit - el->el_line.buffer);
105512db70c8Szrj len = mbstowcs(el->el_line.buffer, cp, len);
105632fe07f8SJohn Marino if (len > 0 && el->el_line.buffer[len - 1] == '\n')
105732fe07f8SJohn Marino --len;
105832fe07f8SJohn Marino }
105932fe07f8SJohn Marino else
106032fe07f8SJohn Marino len = 0;
106132fe07f8SJohn Marino el->el_line.cursor = el->el_line.buffer;
106232fe07f8SJohn Marino el->el_line.lastchar = el->el_line.buffer + len;
106332fe07f8SJohn Marino el_free(cp);
106432fe07f8SJohn Marino el_free(line);
106532fe07f8SJohn Marino break;
106632fe07f8SJohn Marino }
106732fe07f8SJohn Marino
106832fe07f8SJohn Marino close(fd);
106932fe07f8SJohn Marino unlink(tempfile);
107032fe07f8SJohn Marino /* return CC_REFRESH; */
107132fe07f8SJohn Marino return ed_newline(el, 0);
107232fe07f8SJohn Marino error:
107332fe07f8SJohn Marino el_free(line);
107432fe07f8SJohn Marino el_free(cp);
107532fe07f8SJohn Marino close(fd);
107632fe07f8SJohn Marino unlink(tempfile);
107732fe07f8SJohn Marino return CC_ERROR;
107832fe07f8SJohn Marino }
107932fe07f8SJohn Marino
108032fe07f8SJohn Marino /* vi_history_word():
108132fe07f8SJohn Marino * Vi append word from previous input line
108232fe07f8SJohn Marino * [_]
108332fe07f8SJohn Marino * Who knows where this one came from!
108432fe07f8SJohn Marino * '_' in vi means 'entire current line', so 'cc' is a synonym for 'c_'
108532fe07f8SJohn Marino */
108612db70c8Szrj libedit_private el_action_t
108732fe07f8SJohn Marino /*ARGSUSED*/
vi_history_word(EditLine * el,wint_t c)108812db70c8Szrj vi_history_word(EditLine *el, wint_t c __attribute__((__unused__)))
108932fe07f8SJohn Marino {
109012db70c8Szrj const wchar_t *wp = HIST_FIRST(el);
109112db70c8Szrj const wchar_t *wep, *wsp;
109232fe07f8SJohn Marino int len;
109312db70c8Szrj wchar_t *cp;
109412db70c8Szrj const wchar_t *lim;
109532fe07f8SJohn Marino
109632fe07f8SJohn Marino if (wp == NULL)
109732fe07f8SJohn Marino return CC_ERROR;
109832fe07f8SJohn Marino
109912db70c8Szrj wep = wsp = NULL;
110032fe07f8SJohn Marino do {
110112db70c8Szrj while (iswspace(*wp))
110232fe07f8SJohn Marino wp++;
110332fe07f8SJohn Marino if (*wp == 0)
110432fe07f8SJohn Marino break;
110532fe07f8SJohn Marino wsp = wp;
110612db70c8Szrj while (*wp && !iswspace(*wp))
110732fe07f8SJohn Marino wp++;
110832fe07f8SJohn Marino wep = wp;
110932fe07f8SJohn Marino } while ((!el->el_state.doingarg || --el->el_state.argument > 0)
111032fe07f8SJohn Marino && *wp != 0);
111132fe07f8SJohn Marino
111212db70c8Szrj if (wsp == NULL || (el->el_state.doingarg && el->el_state.argument != 0))
111332fe07f8SJohn Marino return CC_ERROR;
111432fe07f8SJohn Marino
111532fe07f8SJohn Marino cv_undo(el);
111632fe07f8SJohn Marino len = (int)(wep - wsp);
111732fe07f8SJohn Marino if (el->el_line.cursor < el->el_line.lastchar)
111832fe07f8SJohn Marino el->el_line.cursor++;
111932fe07f8SJohn Marino c_insert(el, len + 1);
112032fe07f8SJohn Marino cp = el->el_line.cursor;
112132fe07f8SJohn Marino lim = el->el_line.limit;
112232fe07f8SJohn Marino if (cp < lim)
112332fe07f8SJohn Marino *cp++ = ' ';
112432fe07f8SJohn Marino while (wsp < wep && cp < lim)
112532fe07f8SJohn Marino *cp++ = *wsp++;
112632fe07f8SJohn Marino el->el_line.cursor = cp;
112732fe07f8SJohn Marino
112832fe07f8SJohn Marino el->el_map.current = el->el_map.key;
112932fe07f8SJohn Marino return CC_REFRESH;
113032fe07f8SJohn Marino }
113132fe07f8SJohn Marino
113232fe07f8SJohn Marino /* vi_redo():
113332fe07f8SJohn Marino * Vi redo last non-motion command
113432fe07f8SJohn Marino * [.]
113532fe07f8SJohn Marino */
113612db70c8Szrj libedit_private el_action_t
113732fe07f8SJohn Marino /*ARGSUSED*/
vi_redo(EditLine * el,wint_t c)113812db70c8Szrj vi_redo(EditLine *el, wint_t c __attribute__((__unused__)))
113932fe07f8SJohn Marino {
114032fe07f8SJohn Marino c_redo_t *r = &el->el_chared.c_redo;
114132fe07f8SJohn Marino
114232fe07f8SJohn Marino if (!el->el_state.doingarg && r->count) {
114332fe07f8SJohn Marino el->el_state.doingarg = 1;
114432fe07f8SJohn Marino el->el_state.argument = r->count;
114532fe07f8SJohn Marino }
114632fe07f8SJohn Marino
114732fe07f8SJohn Marino el->el_chared.c_vcmd.pos = el->el_line.cursor;
114832fe07f8SJohn Marino el->el_chared.c_vcmd.action = r->action;
114932fe07f8SJohn Marino if (r->pos != r->buf) {
115032fe07f8SJohn Marino if (r->pos + 1 > r->lim)
115132fe07f8SJohn Marino /* sanity */
115232fe07f8SJohn Marino r->pos = r->lim - 1;
115332fe07f8SJohn Marino r->pos[0] = 0;
115412db70c8Szrj el_wpush(el, r->buf);
115532fe07f8SJohn Marino }
115632fe07f8SJohn Marino
115732fe07f8SJohn Marino el->el_state.thiscmd = r->cmd;
115832fe07f8SJohn Marino el->el_state.thisch = r->ch;
115932fe07f8SJohn Marino return (*el->el_map.func[r->cmd])(el, r->ch);
116032fe07f8SJohn Marino }
1161