vi.c revision 37199
11573Srgrimes/*-
21573Srgrimes * Copyright (c) 1992, 1993
31573Srgrimes *	The Regents of the University of California.  All rights reserved.
41573Srgrimes *
51573Srgrimes * This code is derived from software contributed to Berkeley by
61573Srgrimes * Christos Zoulas of Cornell University.
71573Srgrimes *
81573Srgrimes * Redistribution and use in source and binary forms, with or without
91573Srgrimes * modification, are permitted provided that the following conditions
101573Srgrimes * are met:
111573Srgrimes * 1. Redistributions of source code must retain the above copyright
121573Srgrimes *    notice, this list of conditions and the following disclaimer.
131573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
141573Srgrimes *    notice, this list of conditions and the following disclaimer in the
151573Srgrimes *    documentation and/or other materials provided with the distribution.
161573Srgrimes * 3. All advertising materials mentioning features or use of this software
171573Srgrimes *    must display the following acknowledgement:
181573Srgrimes *	This product includes software developed by the University of
191573Srgrimes *	California, Berkeley and its contributors.
201573Srgrimes * 4. Neither the name of the University nor the names of its contributors
211573Srgrimes *    may be used to endorse or promote products derived from this software
221573Srgrimes *    without specific prior written permission.
231573Srgrimes *
241573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
251573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
261573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
271573Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
281573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
291573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
301573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
311573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
321573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
331573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
341573Srgrimes * SUCH DAMAGE.
351573Srgrimes */
361573Srgrimes
371573Srgrimes#if !defined(lint) && !defined(SCCSID)
381573Srgrimesstatic char sccsid[] = "@(#)vi.c	8.1 (Berkeley) 6/4/93";
391573Srgrimes#endif /* not lint && not SCCSID */
401573Srgrimes
411573Srgrimes/*
421573Srgrimes * vi.c: Vi mode commands.
431573Srgrimes */
441573Srgrimes#include "sys.h"
451573Srgrimes#include "el.h"
461573Srgrimes
471573Srgrimesprivate el_action_t cv_action __P((EditLine *, int));
481573Srgrimes
491573Srgrimes/* cv_action():
501573Srgrimes *	Handle vi actions.
511573Srgrimes */
521573Srgrimesprivate el_action_t
531573Srgrimescv_action(el, c)
541573Srgrimes    EditLine *el;
551573Srgrimes    int c;
561573Srgrimes{
571573Srgrimes    register char *cp, *kp;
581573Srgrimes
591573Srgrimes    if (el->el_chared.c_vcmd.action & DELETE) {
601573Srgrimes	el->el_chared.c_vcmd.action = NOP;
611573Srgrimes	el->el_chared.c_vcmd.pos = 0;
628870Srgrimes
631573Srgrimes	el->el_chared.c_undo.isize = 0;
641573Srgrimes	el->el_chared.c_undo.dsize = 0;
651573Srgrimes	kp = el->el_chared.c_undo.buf;
661573Srgrimes	for (cp = el->el_line.buffer; cp < el->el_line.lastchar; cp++) {
671573Srgrimes	    *kp++ = *cp;
681573Srgrimes	    el->el_chared.c_undo.dsize++;
691573Srgrimes	}
708870Srgrimes
711573Srgrimes	el->el_chared.c_undo.action = INSERT;
721573Srgrimes	el->el_chared.c_undo.ptr  = el->el_line.buffer;
731573Srgrimes	el->el_line.lastchar = el->el_line.buffer;
741573Srgrimes	el->el_line.cursor   = el->el_line.buffer;
751573Srgrimes	if (c & INSERT)
761573Srgrimes	    el->el_map.current = el->el_map.key;
778870Srgrimes
781573Srgrimes	return CC_REFRESH;
791573Srgrimes    }
801573Srgrimes
811573Srgrimes    el->el_chared.c_vcmd.pos = el->el_line.cursor;
821573Srgrimes    el->el_chared.c_vcmd.action = c;
831573Srgrimes    return CC_ARGHACK;
841573Srgrimes
851573Srgrimes#ifdef notdef
861573Srgrimes    /*
871573Srgrimes     * I don't think that this is needed. But we keep it for now
881573Srgrimes     */
891573Srgrimes    else if (el_chared.c_vcmd.action == NOP) {
901573Srgrimes	el->el_chared.c_vcmd.pos = el->el_line.cursor;
911573Srgrimes	el->el_chared.c_vcmd.action = c;
921573Srgrimes	return CC_ARGHACK;
931573Srgrimes    }
941573Srgrimes    else {
951573Srgrimes	el->el_chared.c_vcmd.action = 0;
961573Srgrimes	el->el_chared.c_vcmd.pos = 0;
971573Srgrimes	return CC_ERROR;
981573Srgrimes    }
991573Srgrimes#endif
1001573Srgrimes}
1011573Srgrimes
1021573Srgrimes
1031573Srgrimes/* cv_paste():
1041573Srgrimes *	Paste previous deletion before or after the cursor
1051573Srgrimes */
1061573Srgrimesprotected el_action_t
1071573Srgrimescv_paste(el, c)
1081573Srgrimes    EditLine *el;
1091573Srgrimes    int c;
1101573Srgrimes{
1111573Srgrimes    char *ptr;
1121573Srgrimes    c_undo_t *un = &el->el_chared.c_undo;
1131573Srgrimes#ifdef DEBUG_PASTE
1148870Srgrimes    (void) fprintf(el->el_errfile, "Paste: %x \"%s\" +%d -%d\n",
1151573Srgrimes		   un->action, un->buf, un->isize, un->dsize);
1161573Srgrimes#endif
1171573Srgrimes    if (un->isize == 0)
1181573Srgrimes	return CC_ERROR;
1191573Srgrimes
1201573Srgrimes    if (!c && el->el_line.cursor < el->el_line.lastchar)
1211573Srgrimes	el->el_line.cursor++;
1221573Srgrimes    ptr = el->el_line.cursor;
1238870Srgrimes
1241573Srgrimes    c_insert(el, un->isize);
1251573Srgrimes    if (el->el_line.cursor + un->isize > el->el_line.lastchar)
1261573Srgrimes	return CC_ERROR;
1271573Srgrimes    (void) memcpy(ptr, un->buf, un->isize);
1281573Srgrimes    return CC_REFRESH;
1291573Srgrimes}
1301573Srgrimes
1311573Srgrimes
1328870Srgrimes/* vi_paste_next():
1331573Srgrimes *	Vi paste previous deletion to the right of the cursor
1341573Srgrimes *	[p]
1351573Srgrimes */
1361573Srgrimesprotected el_action_t
1371573Srgrimes/*ARGSUSED*/
1381573Srgrimesvi_paste_next(el, c)
1391573Srgrimes    EditLine *el;
1401573Srgrimes    int c;
1411573Srgrimes{
1421573Srgrimes    return cv_paste(el, 0);
1431573Srgrimes}
1441573Srgrimes
1451573Srgrimes
1468870Srgrimes/* vi_paste_prev():
1471573Srgrimes *	Vi paste previous deletion to the left of the cursor
1481573Srgrimes *	[P]
1491573Srgrimes */
1501573Srgrimesprotected el_action_t
1511573Srgrimes/*ARGSUSED*/
1521573Srgrimesvi_paste_prev(el, c)
1531573Srgrimes    EditLine *el;
1541573Srgrimes    int c;
1551573Srgrimes{
1561573Srgrimes    return cv_paste(el, 1);
1571573Srgrimes}
1581573Srgrimes
1591573Srgrimes
1608870Srgrimes/* vi_prev_space_word():
1611573Srgrimes *	Vi move to the previous space delimited word
1621573Srgrimes *	[B]
1631573Srgrimes */
1641573Srgrimesprotected el_action_t
1651573Srgrimes/*ARGSUSED*/
1661573Srgrimesvi_prev_space_word(el, c)
1671573Srgrimes    EditLine *el;
1681573Srgrimes    int c;
1691573Srgrimes{
1701573Srgrimes    if (el->el_line.cursor == el->el_line.buffer)
1711573Srgrimes	return CC_ERROR;
1721573Srgrimes
1738870Srgrimes    el->el_line.cursor = cv_prev_word(el, el->el_line.cursor,
1748870Srgrimes				      el->el_line.buffer,
1758870Srgrimes			 	      el->el_state.argument,
17637199Sbrian				      c___isword);
1771573Srgrimes
1781573Srgrimes    if (el->el_chared.c_vcmd.action & DELETE) {
1791573Srgrimes	cv_delfini(el);
1801573Srgrimes	return CC_REFRESH;
1811573Srgrimes    }
1821573Srgrimes
1831573Srgrimes    return CC_CURSOR;
1841573Srgrimes}
1851573Srgrimes
1861573Srgrimes
1878870Srgrimes/* vi_prev_word():
1881573Srgrimes *	Vi move to the previous word
18937199Sbrian *	[b]
1901573Srgrimes */
1911573Srgrimesprotected el_action_t
1921573Srgrimes/*ARGSUSED*/
1931573Srgrimesvi_prev_word(el, c)
1941573Srgrimes    EditLine *el;
1951573Srgrimes    int c;
1961573Srgrimes{
1971573Srgrimes    if (el->el_line.cursor == el->el_line.buffer)
1981573Srgrimes	return CC_ERROR;
1991573Srgrimes
2008870Srgrimes    el->el_line.cursor = cv_prev_word(el, el->el_line.cursor,
2018870Srgrimes				      el->el_line.buffer,
2028870Srgrimes			 	      el->el_state.argument,
20337199Sbrian				      cv__isword);
2041573Srgrimes
2051573Srgrimes    if (el->el_chared.c_vcmd.action & DELETE) {
2061573Srgrimes	cv_delfini(el);
2071573Srgrimes	return CC_REFRESH;
2081573Srgrimes    }
2091573Srgrimes
2101573Srgrimes    return CC_CURSOR;
2111573Srgrimes}
2121573Srgrimes
2131573Srgrimes
2148870Srgrimes/* vi_next_space_word():
2151573Srgrimes *	Vi move to the next space delimited word
2161573Srgrimes *	[W]
2171573Srgrimes */
2181573Srgrimesprotected el_action_t
2191573Srgrimes/*ARGSUSED*/
2201573Srgrimesvi_next_space_word(el, c)
2211573Srgrimes    EditLine *el;
2221573Srgrimes    int c;
2231573Srgrimes{
2241573Srgrimes    if (el->el_line.cursor == el->el_line.lastchar)
2251573Srgrimes	return CC_ERROR;
2261573Srgrimes
2278870Srgrimes    el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
2288870Srgrimes				      el->el_line.lastchar,
2298870Srgrimes				      el->el_state.argument,
23037199Sbrian				      c___isword);
2311573Srgrimes
2321573Srgrimes    if (el->el_map.type == MAP_VI)
2331573Srgrimes	if (el->el_chared.c_vcmd.action & DELETE) {
2341573Srgrimes	    cv_delfini(el);
2351573Srgrimes	    return CC_REFRESH;
2361573Srgrimes	}
2371573Srgrimes
2381573Srgrimes    return CC_CURSOR;
2391573Srgrimes}
2401573Srgrimes
2418870Srgrimes/* vi_next_word():
2421573Srgrimes *	Vi move to the next word
2431573Srgrimes *	[w]
2441573Srgrimes */
2451573Srgrimesprotected el_action_t
2461573Srgrimes/*ARGSUSED*/
2471573Srgrimesvi_next_word(el, c)
2481573Srgrimes    EditLine *el;
2491573Srgrimes    int c;
2501573Srgrimes{
2511573Srgrimes    if (el->el_line.cursor == el->el_line.lastchar)
2521573Srgrimes	return CC_ERROR;
2531573Srgrimes
2548870Srgrimes    el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
2558870Srgrimes				      el->el_line.lastchar,
2561573Srgrimes				      el->el_state.argument,
25737199Sbrian				      cv__isword);
2581573Srgrimes
2591573Srgrimes    if (el->el_map.type == MAP_VI)
2601573Srgrimes	if (el->el_chared.c_vcmd.action & DELETE) {
2611573Srgrimes	    cv_delfini(el);
2621573Srgrimes	    return CC_REFRESH;
2631573Srgrimes	}
2641573Srgrimes
2651573Srgrimes    return CC_CURSOR;
2661573Srgrimes}
2671573Srgrimes
2681573Srgrimes
2691573Srgrimes
2708870Srgrimes/* vi_change_case():
2711573Srgrimes *	Vi change case of character under the cursor and advance one character
2721573Srgrimes *	[~]
2731573Srgrimes */
2741573Srgrimesprotected el_action_t
2751573Srgrimesvi_change_case(el, c)
2761573Srgrimes    EditLine *el;
2771573Srgrimes    int c;
2781573Srgrimes{
2791573Srgrimes    if (el->el_line.cursor < el->el_line.lastchar) {
28026982Sache	c = (unsigned char)*el->el_line.cursor;
2811573Srgrimes	if (isupper(c))
2821573Srgrimes	    *el->el_line.cursor++ = tolower(c);
2831573Srgrimes	else if (islower(c))
2841573Srgrimes	    *el->el_line.cursor++ = toupper(c);
2851573Srgrimes	else
2861573Srgrimes	    el->el_line.cursor++;
2871573Srgrimes	re_fastaddc(el);
2881573Srgrimes	return CC_NORM;
2891573Srgrimes    }
2901573Srgrimes    return CC_ERROR;
2911573Srgrimes}
2921573Srgrimes
2931573Srgrimes
2948870Srgrimes/* vi_change_meta():
2951573Srgrimes *	Vi change prefix command
2961573Srgrimes *	[c]
2971573Srgrimes */
2981573Srgrimesprotected el_action_t
2991573Srgrimes/*ARGSUSED*/
3001573Srgrimesvi_change_meta(el, c)
3011573Srgrimes    EditLine *el;
3021573Srgrimes    int c;
3031573Srgrimes{
3041573Srgrimes    /*
3051573Srgrimes     * Delete with insert == change: first we delete and then we leave in
3061573Srgrimes     * insert mode.
3071573Srgrimes     */
3081573Srgrimes    return cv_action(el, DELETE|INSERT);
3091573Srgrimes}
3101573Srgrimes
3111573Srgrimes
3128870Srgrimes/* vi_insert_at_bol():
3131573Srgrimes *	Vi enter insert mode at the beginning of line
3141573Srgrimes *	[I]
3151573Srgrimes */
3161573Srgrimesprotected el_action_t
3171573Srgrimes/*ARGSUSED*/
3181573Srgrimesvi_insert_at_bol(el, c)
3191573Srgrimes    EditLine *el;
3201573Srgrimes    int c;
3211573Srgrimes{
3221573Srgrimes    el->el_line.cursor = el->el_line.buffer;
3231573Srgrimes    el->el_chared.c_vcmd.ins = el->el_line.cursor;
3241573Srgrimes
3251573Srgrimes    el->el_chared.c_undo.ptr = el->el_line.cursor;
3261573Srgrimes    el->el_chared.c_undo.action = DELETE;
3271573Srgrimes
3281573Srgrimes    el->el_map.current = el->el_map.key;
3291573Srgrimes    return CC_CURSOR;
3301573Srgrimes}
3311573Srgrimes
3321573Srgrimes
3338870Srgrimes/* vi_replace_char():
3341573Srgrimes *	Vi replace character under the cursor with the next character typed
3351573Srgrimes *	[r]
3361573Srgrimes */
3371573Srgrimesprotected el_action_t
3381573Srgrimes/*ARGSUSED*/
3391573Srgrimesvi_replace_char(el, c)
3401573Srgrimes    EditLine *el;
3411573Srgrimes    int c;
3421573Srgrimes{
3431573Srgrimes    el->el_map.current = el->el_map.key;
3441573Srgrimes    el->el_state.inputmode = MODE_REPLACE_1;
3451573Srgrimes    el->el_chared.c_undo.action = CHANGE;
3461573Srgrimes    el->el_chared.c_undo.ptr = el->el_line.cursor;
3471573Srgrimes    el->el_chared.c_undo.isize = 0;
3481573Srgrimes    el->el_chared.c_undo.dsize = 0;
34937199Sbrian    return CC_ARGHACK;
3501573Srgrimes}
3511573Srgrimes
3521573Srgrimes
3538870Srgrimes/* vi_replace_mode():
3541573Srgrimes *	Vi enter replace mode
3551573Srgrimes *	[R]
3561573Srgrimes */
3571573Srgrimesprotected el_action_t
3581573Srgrimes/*ARGSUSED*/
3591573Srgrimesvi_replace_mode(el, c)
3601573Srgrimes    EditLine *el;
3611573Srgrimes    int c;
3621573Srgrimes{
3631573Srgrimes    el->el_map.current = el->el_map.key;
3641573Srgrimes    el->el_state.inputmode = MODE_REPLACE;
3651573Srgrimes    el->el_chared.c_undo.action = CHANGE;
3661573Srgrimes    el->el_chared.c_undo.ptr = el->el_line.cursor;
3671573Srgrimes    el->el_chared.c_undo.isize = 0;
3681573Srgrimes    el->el_chared.c_undo.dsize = 0;
36937199Sbrian    return CC_ARGHACK;
3701573Srgrimes}
3711573Srgrimes
3721573Srgrimes
3738870Srgrimes/* vi_substitute_char():
3741573Srgrimes *	Vi replace character under the cursor and enter insert mode
37537199Sbrian *	[s]
3761573Srgrimes */
3771573Srgrimesprotected el_action_t
3781573Srgrimes/*ARGSUSED*/
3791573Srgrimesvi_substitute_char(el, c)
3801573Srgrimes    EditLine *el;
3811573Srgrimes    int c;
3821573Srgrimes{
3831573Srgrimes    c_delafter(el, el->el_state.argument);
3841573Srgrimes    el->el_map.current = el->el_map.key;
3851573Srgrimes    return CC_REFRESH;
3861573Srgrimes}
3871573Srgrimes
3881573Srgrimes
3898870Srgrimes/* vi_substitute_line():
3901573Srgrimes *	Vi substitute entire line
3911573Srgrimes *	[S]
3921573Srgrimes */
3931573Srgrimesprotected el_action_t
3941573Srgrimes/*ARGSUSED*/
3951573Srgrimesvi_substitute_line(el, c)
3961573Srgrimes    EditLine *el;
3971573Srgrimes    int c;
3981573Srgrimes{
3991573Srgrimes    (void) em_kill_line(el, 0);
4001573Srgrimes    el->el_map.current = el->el_map.key;
4011573Srgrimes    return CC_REFRESH;
4021573Srgrimes}
4031573Srgrimes
4041573Srgrimes
4058870Srgrimes/* vi_change_to_eol():
4061573Srgrimes *	Vi change to end of line
4071573Srgrimes *	[C]
4081573Srgrimes */
4091573Srgrimesprotected el_action_t
4101573Srgrimes/*ARGSUSED*/
4111573Srgrimesvi_change_to_eol(el, c)
4121573Srgrimes    EditLine *el;
4131573Srgrimes    int c;
4141573Srgrimes{
4151573Srgrimes    (void) ed_kill_line(el, 0);
4161573Srgrimes    el->el_map.current = el->el_map.key;
4171573Srgrimes    return CC_REFRESH;
4181573Srgrimes}
4191573Srgrimes
4201573Srgrimes
4211573Srgrimes/* vi_insert():
4221573Srgrimes *	Vi enter insert mode
4231573Srgrimes *	[i]
4241573Srgrimes */
4251573Srgrimesprotected el_action_t
4261573Srgrimes/*ARGSUSED*/
4271573Srgrimesvi_insert(el, c)
4281573Srgrimes    EditLine *el;
4291573Srgrimes    int c;
4301573Srgrimes{
4311573Srgrimes    el->el_map.current = el->el_map.key;
4321573Srgrimes
4331573Srgrimes    el->el_chared.c_vcmd.ins = el->el_line.cursor;
4341573Srgrimes    el->el_chared.c_undo.ptr = el->el_line.cursor;
4351573Srgrimes    el->el_chared.c_undo.action = DELETE;
4361573Srgrimes
4371573Srgrimes    return CC_NORM;
4381573Srgrimes}
4391573Srgrimes
4401573Srgrimes
4411573Srgrimes/* vi_add():
4428870Srgrimes *	Vi enter insert mode after the cursor
4431573Srgrimes *	[a]
4441573Srgrimes */
4451573Srgrimesprotected el_action_t
4461573Srgrimes/*ARGSUSED*/
4471573Srgrimesvi_add(el, c)
4481573Srgrimes    EditLine *el;
4491573Srgrimes    int c;
4501573Srgrimes{
45137199Sbrian    el_action_t ret;
45237199Sbrian
4531573Srgrimes    el->el_map.current = el->el_map.key;
4541573Srgrimes    if (el->el_line.cursor < el->el_line.lastchar) {
4551573Srgrimes	el->el_line.cursor++;
4561573Srgrimes	if (el->el_line.cursor > el->el_line.lastchar)
4571573Srgrimes	    el->el_line.cursor = el->el_line.lastchar;
4581573Srgrimes	ret = CC_CURSOR;
4591573Srgrimes    }
4601573Srgrimes    else
4611573Srgrimes	ret = CC_NORM;
4621573Srgrimes
4631573Srgrimes    el->el_chared.c_vcmd.ins = el->el_line.cursor;
4641573Srgrimes    el->el_chared.c_undo.ptr = el->el_line.cursor;
4651573Srgrimes    el->el_chared.c_undo.action = DELETE;
4661573Srgrimes
4671573Srgrimes    return ret;
4681573Srgrimes}
4691573Srgrimes
4701573Srgrimes
4711573Srgrimes/* vi_add_at_eol():
4721573Srgrimes *	Vi enter insert mode at end of line
4731573Srgrimes *	[A]
4741573Srgrimes */
4751573Srgrimesprotected el_action_t
4761573Srgrimes/*ARGSUSED*/
4771573Srgrimesvi_add_at_eol(el, c)
4781573Srgrimes    EditLine *el;
4791573Srgrimes    int c;
4801573Srgrimes{
4811573Srgrimes    el->el_map.current = el->el_map.key;
4821573Srgrimes    el->el_line.cursor = el->el_line.lastchar;
4831573Srgrimes
4841573Srgrimes    /* Mark where insertion begins */
4858870Srgrimes    el->el_chared.c_vcmd.ins = el->el_line.lastchar;
4861573Srgrimes    el->el_chared.c_undo.ptr = el->el_line.lastchar;
4871573Srgrimes    el->el_chared.c_undo.action = DELETE;
4881573Srgrimes    return CC_CURSOR;
4891573Srgrimes}
4901573Srgrimes
4911573Srgrimes
4921573Srgrimes/* vi_delete_meta():
4938870Srgrimes *	Vi delete prefix command
4941573Srgrimes *	[d]
4951573Srgrimes */
4961573Srgrimesprotected el_action_t
4971573Srgrimes/*ARGSUSED*/
4981573Srgrimesvi_delete_meta(el, c)
4991573Srgrimes    EditLine *el;
5001573Srgrimes    int c;
5011573Srgrimes{
5021573Srgrimes    return cv_action(el, DELETE);
5031573Srgrimes}
5041573Srgrimes
5051573Srgrimes
5061573Srgrimes/* vi_end_word():
5078870Srgrimes *	Vi move to the end of the current space delimited word
5088870Srgrimes *	[E]
5091573Srgrimes */
5101573Srgrimesprotected el_action_t
5111573Srgrimes/*ARGSUSED*/
5121573Srgrimesvi_end_word(el, c)
5131573Srgrimes    EditLine *el;
5141573Srgrimes    int c;
5151573Srgrimes{
5161573Srgrimes    if (el->el_line.cursor == el->el_line.lastchar)
5171573Srgrimes	return CC_ERROR;
5181573Srgrimes
5198870Srgrimes    el->el_line.cursor = cv__endword(el->el_line.cursor, el->el_line.lastchar,
5201573Srgrimes				     el->el_state.argument);
5211573Srgrimes
5221573Srgrimes    if (el->el_chared.c_vcmd.action & DELETE) {
5231573Srgrimes	el->el_line.cursor++;
5241573Srgrimes	cv_delfini(el);
5251573Srgrimes	return CC_REFRESH;
5261573Srgrimes    }
5271573Srgrimes
5281573Srgrimes    return CC_CURSOR;
5291573Srgrimes}
5301573Srgrimes
5311573Srgrimes
5321573Srgrimes/* vi_to_end_word():
5331573Srgrimes *	Vi move to the end of the current word
5341573Srgrimes *	[e]
5351573Srgrimes */
5361573Srgrimesprotected el_action_t
5371573Srgrimes/*ARGSUSED*/
5381573Srgrimesvi_to_end_word(el, c)
5391573Srgrimes    EditLine *el;
5401573Srgrimes    int c;
5411573Srgrimes{
5421573Srgrimes    if (el->el_line.cursor == el->el_line.lastchar)
5431573Srgrimes	return CC_ERROR;
5441573Srgrimes
5458870Srgrimes    el->el_line.cursor = cv__endword(el->el_line.cursor, el->el_line.lastchar,
5461573Srgrimes				     el->el_state.argument);
5471573Srgrimes
5481573Srgrimes    if (el->el_chared.c_vcmd.action & DELETE) {
5491573Srgrimes	el->el_line.cursor++;
5501573Srgrimes	cv_delfini(el);
5511573Srgrimes	return CC_REFRESH;
5521573Srgrimes    }
5531573Srgrimes
5541573Srgrimes    return CC_CURSOR;
5551573Srgrimes}
5561573Srgrimes
5571573Srgrimes
5581573Srgrimes/* vi_undo():
5591573Srgrimes *	Vi undo last change
5601573Srgrimes *	[u]
5611573Srgrimes */
5621573Srgrimesprotected el_action_t
5631573Srgrimes/*ARGSUSED*/
5641573Srgrimesvi_undo(el, c)
5651573Srgrimes    EditLine *el;
5661573Srgrimes    int c;
5671573Srgrimes{
5681573Srgrimes    char *cp, *kp;
5691573Srgrimes    char temp;
5701573Srgrimes    int	 i, size;
5711573Srgrimes    c_undo_t *un = &el->el_chared.c_undo;
5721573Srgrimes
5731573Srgrimes#ifdef DEBUG_UNDO
5748870Srgrimes    (void) fprintf(el->el_errfile, "Undo: %x \"%s\" +%d -%d\n",
5751573Srgrimes		   un->action, un->buf, un->isize, un->dsize);
5761573Srgrimes#endif
5771573Srgrimes    switch (un->action) {
5781573Srgrimes    case DELETE:
5798870Srgrimes	if (un->dsize == 0)
5801573Srgrimes	    return CC_NORM;
5811573Srgrimes
5821573Srgrimes	(void) memcpy(un->buf, un->ptr, un->dsize);
5831573Srgrimes	for (cp = un->ptr; cp <= el->el_line.lastchar; cp++)
5841573Srgrimes	    *cp = cp[un->dsize];
5851573Srgrimes
5861573Srgrimes	el->el_line.lastchar -= un->dsize;
5871573Srgrimes	el->el_line.cursor   =  un->ptr;
5888870Srgrimes
5891573Srgrimes	un->action = INSERT;
5901573Srgrimes	un->isize = un->dsize;
5911573Srgrimes	un->dsize = 0;
5921573Srgrimes	break;
5931573Srgrimes
5941573Srgrimes    case DELETE|INSERT:
5951573Srgrimes	size = un->isize - un->dsize;
5968870Srgrimes	if (size > 0)
5971573Srgrimes	    i = un->dsize;
5988870Srgrimes	else
5991573Srgrimes	    i = un->isize;
6001573Srgrimes	cp = un->ptr;
6011573Srgrimes	kp = un->buf;
6021573Srgrimes	while (i-- > 0) {
6031573Srgrimes	    temp = *kp;
6041573Srgrimes	    *kp++ = *cp;
6051573Srgrimes	    *cp++ = temp;
6061573Srgrimes	}
6071573Srgrimes	if (size > 0) {
6081573Srgrimes	    el->el_line.cursor = cp;
6091573Srgrimes	    c_insert(el, size);
6101573Srgrimes	    while (size-- > 0 && cp < el->el_line.lastchar) {
6111573Srgrimes		temp = *kp;
6121573Srgrimes		*kp++ = *cp;
6131573Srgrimes		*cp++ = temp;
6141573Srgrimes	    }
6151573Srgrimes	}
6161573Srgrimes	else if (size < 0) {
6171573Srgrimes	    size = -size;
6181573Srgrimes	    for (; cp <= el->el_line.lastchar; cp++) {
6191573Srgrimes		*kp++ = *cp;
6201573Srgrimes		*cp = cp[size];
6211573Srgrimes	    }
6221573Srgrimes	    el->el_line.lastchar -= size;
6231573Srgrimes	}
6241573Srgrimes	el->el_line.cursor = un->ptr;
6251573Srgrimes	i = un->dsize;
6261573Srgrimes	un->dsize = un->isize;
6271573Srgrimes	un->isize = i;
6281573Srgrimes	break;
6291573Srgrimes
6301573Srgrimes    case INSERT:
6318870Srgrimes	if (un->isize == 0)
6321573Srgrimes	    return CC_NORM;
6331573Srgrimes
6341573Srgrimes	el->el_line.cursor = un->ptr;
6351573Srgrimes	c_insert(el, un->isize);
6361573Srgrimes	memcpy(un->ptr, un->buf, un->isize);
6371573Srgrimes	un->action = DELETE;
6381573Srgrimes	un->dsize = un->isize;
6391573Srgrimes	un->isize = 0;
6401573Srgrimes	break;
6411573Srgrimes
6421573Srgrimes    case CHANGE:
6438870Srgrimes	if (un->isize == 0)
6441573Srgrimes	    return CC_NORM;
6451573Srgrimes
6461573Srgrimes	el->el_line.cursor = un->ptr;
6478870Srgrimes	size = (int) (el->el_line.cursor - el->el_line.lastchar);
6481573Srgrimes	if (size < un->isize)
6491573Srgrimes	    size = un->isize;
6501573Srgrimes	cp = un->ptr;
6511573Srgrimes	kp = un->buf;
6521573Srgrimes	for(i = 0; i < size; i++) {
6531573Srgrimes	    temp = *kp;
6541573Srgrimes	    *kp++ = *cp;
6551573Srgrimes	    *cp++ = temp;
6561573Srgrimes	}
6571573Srgrimes	un->dsize = 0;
6581573Srgrimes	break;
6591573Srgrimes
6601573Srgrimes    default:
6611573Srgrimes	return CC_ERROR;
6621573Srgrimes    }
6631573Srgrimes
6641573Srgrimes    return CC_REFRESH;
6651573Srgrimes}
6661573Srgrimes
6671573Srgrimes
66837199Sbrian/* vi_undo_line():
66937199Sbrian *	Vi undo all changes
67037199Sbrian *	[U]
67137199Sbrian */
67237199Sbrianprotected el_action_t
67337199Sbrian/*ARGSUSED*/
67437199Sbrianvi_undo_line(el, c)
67537199Sbrian    EditLine *el;
67637199Sbrian    int c;
67737199Sbrian{
67837199Sbrian
67937199Sbrian    return hist_get(el);
68037199Sbrian}
68137199Sbrian
68237199Sbrian
6831573Srgrimes/* vi_command_mode():
6841573Srgrimes *	Vi enter command mode (use alternative key bindings)
6851573Srgrimes *	[<ESC>]
6861573Srgrimes */
6871573Srgrimesprotected el_action_t
6881573Srgrimes/*ARGSUSED*/
6891573Srgrimesvi_command_mode(el, c)
6901573Srgrimes    EditLine *el;
6911573Srgrimes    int c;
6921573Srgrimes{
6931573Srgrimes    int size;
6941573Srgrimes    /* [Esc] cancels pending action */
6951573Srgrimes    el->el_chared.c_vcmd.ins = 0;
6968870Srgrimes    el->el_chared.c_vcmd.action = NOP;
6971573Srgrimes    el->el_chared.c_vcmd.pos = 0;
6981573Srgrimes
6991573Srgrimes    el->el_state.doingarg = 0;
7001573Srgrimes    size = el->el_chared.c_undo.ptr - el->el_line.cursor;
7011573Srgrimes    if (size < 0)
7021573Srgrimes	size = -size;
7031573Srgrimes    if (el->el_chared.c_undo.action == (INSERT|DELETE) ||
7041573Srgrimes        el->el_chared.c_undo.action == DELETE)
7051573Srgrimes	el->el_chared.c_undo.dsize = size;
7061573Srgrimes    else
7071573Srgrimes	el->el_chared.c_undo.isize = size;
7081573Srgrimes
7091573Srgrimes    el->el_state.inputmode = MODE_INSERT;
7101573Srgrimes    el->el_map.current = el->el_map.alt;
7111573Srgrimes#ifdef VI_MOVE
7121573Srgrimes    if (el->el_line.cursor > el->el_line.buffer)
7131573Srgrimes	el->el_line.cursor--;
7141573Srgrimes#endif
7151573Srgrimes    return CC_CURSOR;
7161573Srgrimes}
7171573Srgrimes
7181573Srgrimes/* vi_zero():
7198870Srgrimes *	Vi move to the beginning of line
7201573Srgrimes *	[0]
7211573Srgrimes */
7221573Srgrimesprotected el_action_t
7231573Srgrimesvi_zero(el, c)
7241573Srgrimes    EditLine *el;
7251573Srgrimes    int c;
7261573Srgrimes{
7271573Srgrimes    if (el->el_state.doingarg) {
7281573Srgrimes	if (el->el_state.argument > 1000000)
7291573Srgrimes	    return CC_ERROR;
7308870Srgrimes	el->el_state.argument =
7311573Srgrimes		(el->el_state.argument * 10) + (c - '0');
7321573Srgrimes	return CC_ARGHACK;
7331573Srgrimes    }
7341573Srgrimes    else {
7351573Srgrimes	el->el_line.cursor = el->el_line.buffer;
7361573Srgrimes	if (el->el_chared.c_vcmd.action & DELETE) {
7371573Srgrimes	   cv_delfini(el);
7381573Srgrimes	   return CC_REFRESH;
7391573Srgrimes        }
7401573Srgrimes	return CC_CURSOR;
7411573Srgrimes    }
7421573Srgrimes}
7431573Srgrimes
7441573Srgrimes
7451573Srgrimes/* vi_delete_prev_char():
7468870Srgrimes * 	Vi move to previous character (backspace)
7471573Srgrimes *	[^H]
7488870Srgrimes */
7491573Srgrimesprotected el_action_t
7501573Srgrimes/*ARGSUSED*/
7511573Srgrimesvi_delete_prev_char(el, c)
7521573Srgrimes    EditLine *el;
7531573Srgrimes    int c;
7541573Srgrimes{
7558870Srgrimes    if (el->el_chared.c_vcmd.ins == 0)
7561573Srgrimes	return CC_ERROR;
7571573Srgrimes
7588870Srgrimes    if (el->el_chared.c_vcmd.ins >
7591573Srgrimes	el->el_line.cursor - el->el_state.argument)
7601573Srgrimes	return CC_ERROR;
7611573Srgrimes
7628870Srgrimes    c_delbefore(el, el->el_state.argument);
7631573Srgrimes    el->el_line.cursor -= el->el_state.argument;
7641573Srgrimes
7651573Srgrimes    return CC_REFRESH;
7661573Srgrimes} /* end v_del_char_prev  */
7671573Srgrimes
7681573Srgrimes
7691573Srgrimes/* vi_list_or_eof():
7701573Srgrimes *	Vi list choices for completion or indicate end of file if empty line
7711573Srgrimes *	[^D]
7721573Srgrimes */
7731573Srgrimesprotected el_action_t
7741573Srgrimes/*ARGSUSED*/
7751573Srgrimesvi_list_or_eof(el, c)
7761573Srgrimes    EditLine *el;
7771573Srgrimes    int c;
7781573Srgrimes{
7791573Srgrimes#ifdef notyet
7808870Srgrimes    if (el->el_line.cursor == el->el_line.lastchar &&
7811573Srgrimes	el->el_line.cursor == el->el_line.buffer) {
7821573Srgrimes#endif
7831573Srgrimes	term_overwrite(el, STReof, 4);	/* then do a EOF */
7841573Srgrimes	term__flush();
7851573Srgrimes	return CC_EOF;
7861573Srgrimes#ifdef notyet
7871573Srgrimes    }
7881573Srgrimes    else {
7891573Srgrimes	re_goto_bottom(el);
7901573Srgrimes	*el->el_line.lastchar = '\0';	/* just in case */
7911573Srgrimes	return CC_LIST_CHOICES;
7921573Srgrimes    }
7931573Srgrimes#endif
7941573Srgrimes}
7951573Srgrimes
7961573Srgrimes
7971573Srgrimes/* vi_kill_line_prev():
7988870Srgrimes *	Vi cut from beginning of line to cursor
7991573Srgrimes *	[^U]
8001573Srgrimes */
8011573Srgrimesprotected el_action_t
8021573Srgrimes/*ARGSUSED*/
8031573Srgrimesvi_kill_line_prev(el, c)
8041573Srgrimes    EditLine *el;
8051573Srgrimes    int c;
8061573Srgrimes{
8071573Srgrimes    char *kp, *cp;
8081573Srgrimes
8091573Srgrimes    cp = el->el_line.buffer;
8101573Srgrimes    kp = el->el_chared.c_kill.buf;
8111573Srgrimes    while (cp < el->el_line.cursor)
8121573Srgrimes	*kp++ = *cp++;		/* copy it */
8131573Srgrimes    el->el_chared.c_kill.last = kp;
8141573Srgrimes    c_delbefore(el, el->el_line.cursor - el->el_line.buffer);
8151573Srgrimes    el->el_line.cursor = el->el_line.buffer;		/* zap! */
8161573Srgrimes    return CC_REFRESH;
8171573Srgrimes}
8181573Srgrimes
8191573Srgrimes
8201573Srgrimes/* vi_search_prev():
8211573Srgrimes *	Vi search history previous
8221573Srgrimes *	[?]
8231573Srgrimes */
8241573Srgrimesprotected el_action_t
8251573Srgrimes/*ARGSUSED*/
8261573Srgrimesvi_search_prev(el, c)
8271573Srgrimes    EditLine *el;
8281573Srgrimes    int c;
8291573Srgrimes{
8301573Srgrimes    return cv_search(el, ED_SEARCH_PREV_HISTORY);
8311573Srgrimes}
8321573Srgrimes
8331573Srgrimes
8341573Srgrimes/* vi_search_next():
8351573Srgrimes *	Vi search history next
8361573Srgrimes *	[/]
8371573Srgrimes */
8381573Srgrimesprotected el_action_t
8391573Srgrimes/*ARGSUSED*/
8401573Srgrimesvi_search_next(el, c)
8411573Srgrimes    EditLine *el;
8421573Srgrimes    int c;
8431573Srgrimes{
8441573Srgrimes    return cv_search(el, ED_SEARCH_NEXT_HISTORY);
8451573Srgrimes}
8461573Srgrimes
8471573Srgrimes
8481573Srgrimes/* vi_repeat_search_next():
8491573Srgrimes *	Vi repeat current search in the same search direction
8501573Srgrimes *	[n]
8511573Srgrimes */
8521573Srgrimesprotected el_action_t
8531573Srgrimes/*ARGSUSED*/
8541573Srgrimesvi_repeat_search_next(el, c)
8551573Srgrimes    EditLine *el;
8561573Srgrimes    int c;
8571573Srgrimes{
8588870Srgrimes    if (el->el_search.patlen == 0)
8591573Srgrimes	return CC_ERROR;
8601573Srgrimes    else
8611573Srgrimes	return cv_repeat_srch(el, el->el_search.patdir);
8621573Srgrimes}
8631573Srgrimes
8641573Srgrimes
8651573Srgrimes/* vi_repeat_search_prev():
8661573Srgrimes *	Vi repeat current search in the opposite search direction
8671573Srgrimes *	[N]
8681573Srgrimes */
8691573Srgrimes/*ARGSUSED*/
8701573Srgrimesprotected el_action_t
8711573Srgrimesvi_repeat_search_prev(el, c)
8721573Srgrimes    EditLine *el;
8731573Srgrimes    int c;
8741573Srgrimes{
8758870Srgrimes    if (el->el_search.patlen == 0)
8761573Srgrimes	return CC_ERROR;
8771573Srgrimes    else
8788870Srgrimes	return cv_repeat_srch(el,
8791573Srgrimes			      el->el_search.patdir == ED_SEARCH_PREV_HISTORY ?
8801573Srgrimes			      ED_SEARCH_NEXT_HISTORY : ED_SEARCH_PREV_HISTORY);
8811573Srgrimes}
8821573Srgrimes
8831573Srgrimes
8841573Srgrimes/* vi_next_char():
8851573Srgrimes *	Vi move to the character specified next
8861573Srgrimes *	[f]
8871573Srgrimes */
8881573Srgrimesprotected el_action_t
8891573Srgrimes/*ARGSUSED*/
8901573Srgrimesvi_next_char(el, c)
8911573Srgrimes    EditLine *el;
8921573Srgrimes    int c;
8931573Srgrimes{
8941573Srgrimes    char ch;
8951573Srgrimes
8961573Srgrimes    if (el_getc(el, &ch) != 1)
8971573Srgrimes	return ed_end_of_file(el, 0);
8981573Srgrimes
8991573Srgrimes    el->el_search.chadir = CHAR_FWD;
9001573Srgrimes    el->el_search.chacha = ch;
9011573Srgrimes
9021573Srgrimes    return cv_csearch_fwd(el, ch, el->el_state.argument, 0);
9031573Srgrimes
9041573Srgrimes}
9051573Srgrimes
9061573Srgrimes
9071573Srgrimes/* vi_prev_char():
9081573Srgrimes *	Vi move to the character specified previous
9091573Srgrimes *	[F]
9101573Srgrimes */
9111573Srgrimesprotected el_action_t
9121573Srgrimes/*ARGSUSED*/
9131573Srgrimesvi_prev_char(el, c)
9141573Srgrimes    EditLine *el;
9151573Srgrimes    int c;
9161573Srgrimes{
9171573Srgrimes    char ch;
9181573Srgrimes
9191573Srgrimes    if (el_getc(el, &ch) != 1)
9201573Srgrimes	return ed_end_of_file(el, 0);
9211573Srgrimes
9221573Srgrimes    el->el_search.chadir = CHAR_BACK;
9231573Srgrimes    el->el_search.chacha = ch;
9241573Srgrimes
9251573Srgrimes    return cv_csearch_back(el, ch, el->el_state.argument, 0);
9261573Srgrimes}
9271573Srgrimes
9281573Srgrimes
9291573Srgrimes/* vi_to_next_char():
9301573Srgrimes *	Vi move up to the character specified next
9311573Srgrimes *	[t]
9321573Srgrimes */
9331573Srgrimesprotected el_action_t
9341573Srgrimes/*ARGSUSED*/
9351573Srgrimesvi_to_next_char(el, c)
9361573Srgrimes    EditLine *el;
9371573Srgrimes    int c;
9381573Srgrimes{
9391573Srgrimes    char ch;
9401573Srgrimes
9411573Srgrimes    if (el_getc(el, &ch) != 1)
9421573Srgrimes	return ed_end_of_file(el, 0);
9431573Srgrimes
9441573Srgrimes    return cv_csearch_fwd(el, ch, el->el_state.argument, 1);
9451573Srgrimes
9461573Srgrimes}
9471573Srgrimes
9481573Srgrimes
9491573Srgrimes/* vi_to_prev_char():
9501573Srgrimes *	Vi move up to the character specified previous
9511573Srgrimes *	[T]
9521573Srgrimes */
9531573Srgrimesprotected el_action_t
9541573Srgrimes/*ARGSUSED*/
9551573Srgrimesvi_to_prev_char(el, c)
9561573Srgrimes    EditLine *el;
9571573Srgrimes    int c;
9581573Srgrimes{
9591573Srgrimes    char ch;
9601573Srgrimes    if (el_getc(el, &ch) != 1)
9611573Srgrimes	return ed_end_of_file(el, 0);
9621573Srgrimes
9631573Srgrimes    return cv_csearch_back(el, ch, el->el_state.argument, 1);
9641573Srgrimes}
9651573Srgrimes
9661573Srgrimes
9671573Srgrimes/* vi_repeat_next_char():
9681573Srgrimes *	Vi repeat current character search in the same search direction
9691573Srgrimes *	[;]
9701573Srgrimes */
9711573Srgrimesprotected el_action_t
9721573Srgrimes/*ARGSUSED*/
9731573Srgrimesvi_repeat_next_char(el, c)
9741573Srgrimes    EditLine *el;
9751573Srgrimes    int c;
9761573Srgrimes{
9771573Srgrimes    if (el->el_search.chacha == 0)
9781573Srgrimes	return CC_ERROR;
9791573Srgrimes
9808870Srgrimes    return el->el_search.chadir == CHAR_FWD ?
9818870Srgrimes	cv_csearch_fwd(el, el->el_search.chacha, el->el_state.argument, 0) :
9821573Srgrimes        cv_csearch_back(el, el->el_search.chacha, el->el_state.argument, 0);
9831573Srgrimes}
9841573Srgrimes
9851573Srgrimes
9861573Srgrimes/* vi_repeat_prev_char():
9871573Srgrimes *	Vi repeat current character search in the opposite search direction
9881573Srgrimes *	[,]
9891573Srgrimes */
9901573Srgrimesprotected el_action_t
9911573Srgrimes/*ARGSUSED*/
9921573Srgrimesvi_repeat_prev_char(el, c)
9931573Srgrimes    EditLine *el;
9941573Srgrimes    int c;
9951573Srgrimes{
9961573Srgrimes    if (el->el_search.chacha == 0)
9971573Srgrimes	return CC_ERROR;
9981573Srgrimes
9998870Srgrimes    return el->el_search.chadir == CHAR_BACK ?
10008870Srgrimes	cv_csearch_fwd(el, el->el_search.chacha, el->el_state.argument, 0) :
10011573Srgrimes        cv_csearch_back(el, el->el_search.chacha, el->el_state.argument, 0);
10021573Srgrimes}
1003