Home | History | Annotate | Line # | Download | only in libedit
vi.c revision 1.1
      1 /*-
      2  * Copyright (c) 1992, 1993
      3  *	The Regents of the University of California.  All rights reserved.
      4  *
      5  * This code is derived from software contributed to Berkeley by
      6  * Christos Zoulas of Cornell University.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  * 3. All advertising materials mentioning features or use of this software
     17  *    must display the following acknowledgement:
     18  *	This product includes software developed by the University of
     19  *	California, Berkeley and its contributors.
     20  * 4. Neither the name of the University nor the names of its contributors
     21  *    may be used to endorse or promote products derived from this software
     22  *    without specific prior written permission.
     23  *
     24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     34  * SUCH DAMAGE.
     35  */
     36 
     37 #if !defined(lint) && !defined(SCCSID)
     38 static char sccsid[] = "@(#)vi.c	8.1 (Berkeley) 6/4/93";
     39 #endif /* not lint && not SCCSID */
     40 
     41 /*
     42  * vi.c: Vi mode commands.
     43  */
     44 #include "sys.h"
     45 #include "el.h"
     46 
     47 private el_action_t cv_action __P((EditLine *, int));
     48 
     49 /* cv_action():
     50  *	Handle vi actions.
     51  */
     52 private el_action_t
     53 cv_action(el, c)
     54     EditLine *el;
     55     int c;
     56 {
     57     register char *cp, *kp;
     58 
     59     if (el->el_chared.c_vcmd.action & DELETE) {
     60 	el->el_chared.c_vcmd.action = NOP;
     61 	el->el_chared.c_vcmd.pos = 0;
     62 
     63 	el->el_chared.c_undo.isize = 0;
     64 	el->el_chared.c_undo.dsize = 0;
     65 	kp = el->el_chared.c_undo.buf;
     66 	for (cp = el->el_line.buffer; cp < el->el_line.lastchar; cp++) {
     67 	    *kp++ = *cp;
     68 	    el->el_chared.c_undo.dsize++;
     69 	}
     70 
     71 	el->el_chared.c_undo.action = INSERT;
     72 	el->el_chared.c_undo.ptr  = el->el_line.buffer;
     73 	el->el_line.lastchar = el->el_line.buffer;
     74 	el->el_line.cursor   = el->el_line.buffer;
     75 	if (c & INSERT)
     76 	    el->el_map.current = el->el_map.key;
     77 
     78 	return CC_REFRESH;
     79     }
     80 
     81     el->el_chared.c_vcmd.pos = el->el_line.cursor;
     82     el->el_chared.c_vcmd.action = c;
     83     return CC_ARGHACK;
     84 
     85 #ifdef notdef
     86     /*
     87      * I don't think that this is needed. But we keep it for now
     88      */
     89     else if (el_chared.c_vcmd.action == NOP) {
     90 	el->el_chared.c_vcmd.pos = el->el_line.cursor;
     91 	el->el_chared.c_vcmd.action = c;
     92 	return CC_ARGHACK;
     93     }
     94     else {
     95 	el->el_chared.c_vcmd.action = 0;
     96 	el->el_chared.c_vcmd.pos = 0;
     97 	return CC_ERROR;
     98     }
     99 #endif
    100 }
    101 
    102 
    103 /* cv_paste():
    104  *	Paste previous deletion before or after the cursor
    105  */
    106 protected el_action_t
    107 cv_paste(el, c)
    108     EditLine *el;
    109     int c;
    110 {
    111     char *ptr;
    112     c_undo_t *un = &el->el_chared.c_undo;
    113 #ifdef DEBUG_PASTE
    114     (void) fprintf(el->el_errfile, "Paste: %x \"%s\" +%d -%d\n",
    115 		   un->action, un->buf, un->isize, un->dsize);
    116 #endif
    117     if (un->isize == 0)
    118 	return CC_ERROR;
    119 
    120     if (!c && el->el_line.cursor < el->el_line.lastchar)
    121 	el->el_line.cursor++;
    122     ptr = el->el_line.cursor;
    123 
    124     c_insert(el, un->isize);
    125     if (el->el_line.cursor + un->isize > el->el_line.lastchar)
    126 	return CC_ERROR;
    127     (void) memcpy(ptr, un->buf, un->isize);
    128     return CC_REFRESH;
    129 }
    130 
    131 
    132 /* vi_paste_next():
    133  *	Vi paste previous deletion to the right of the cursor
    134  *	[p]
    135  */
    136 protected el_action_t
    137 /*ARGSUSED*/
    138 vi_paste_next(el, c)
    139     EditLine *el;
    140     int c;
    141 {
    142     return cv_paste(el, 0);
    143 }
    144 
    145 
    146 /* vi_paste_prev():
    147  *	Vi paste previous deletion to the left of the cursor
    148  *	[P]
    149  */
    150 protected el_action_t
    151 /*ARGSUSED*/
    152 vi_paste_prev(el, c)
    153     EditLine *el;
    154     int c;
    155 {
    156     return cv_paste(el, 1);
    157 }
    158 
    159 
    160 /* vi_prev_space_word():
    161  *	Vi move to the previous space delimited word
    162  *	[B]
    163  */
    164 protected el_action_t
    165 /*ARGSUSED*/
    166 vi_prev_space_word(el, c)
    167     EditLine *el;
    168     int c;
    169 {
    170     if (el->el_line.cursor == el->el_line.buffer)
    171 	return CC_ERROR;
    172 
    173     el->el_line.cursor = cv_prev_word(el, el->el_line.cursor,
    174 				      el->el_line.buffer,
    175 			 	      el->el_state.argument,
    176 				      cv__isword);
    177 
    178     if (el->el_chared.c_vcmd.action & DELETE) {
    179 	cv_delfini(el);
    180 	return CC_REFRESH;
    181     }
    182 
    183     return CC_CURSOR;
    184 }
    185 
    186 
    187 /* vi_prev_word():
    188  *	Vi move to the previous word
    189  *	[B]
    190  */
    191 protected el_action_t
    192 /*ARGSUSED*/
    193 vi_prev_word(el, c)
    194     EditLine *el;
    195     int c;
    196 {
    197     if (el->el_line.cursor == el->el_line.buffer)
    198 	return CC_ERROR;
    199 
    200     el->el_line.cursor = cv_prev_word(el, el->el_line.cursor,
    201 				      el->el_line.buffer,
    202 			 	      el->el_state.argument,
    203 				      ce__isword);
    204 
    205     if (el->el_chared.c_vcmd.action & DELETE) {
    206 	cv_delfini(el);
    207 	return CC_REFRESH;
    208     }
    209 
    210     return CC_CURSOR;
    211 }
    212 
    213 
    214 /* vi_next_space_word():
    215  *	Vi move to the next space delimited word
    216  *	[W]
    217  */
    218 protected el_action_t
    219 /*ARGSUSED*/
    220 vi_next_space_word(el, c)
    221     EditLine *el;
    222     int c;
    223 {
    224     if (el->el_line.cursor == el->el_line.lastchar)
    225 	return CC_ERROR;
    226 
    227     el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
    228 				      el->el_line.lastchar,
    229 				      el->el_state.argument,
    230 				      cv__isword);
    231 
    232     if (el->el_map.type == MAP_VI)
    233 	if (el->el_chared.c_vcmd.action & DELETE) {
    234 	    cv_delfini(el);
    235 	    return CC_REFRESH;
    236 	}
    237 
    238     return CC_CURSOR;
    239 }
    240 
    241 /* vi_next_word():
    242  *	Vi move to the next word
    243  *	[w]
    244  */
    245 protected el_action_t
    246 /*ARGSUSED*/
    247 vi_next_word(el, c)
    248     EditLine *el;
    249     int c;
    250 {
    251     if (el->el_line.cursor == el->el_line.lastchar)
    252 	return CC_ERROR;
    253 
    254     el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
    255 				      el->el_line.lastchar,
    256 				      el->el_state.argument,
    257 				      ce__isword);
    258 
    259     if (el->el_map.type == MAP_VI)
    260 	if (el->el_chared.c_vcmd.action & DELETE) {
    261 	    cv_delfini(el);
    262 	    return CC_REFRESH;
    263 	}
    264 
    265     return CC_CURSOR;
    266 }
    267 
    268 
    269 
    270 /* vi_change_case():
    271  *	Vi change case of character under the cursor and advance one character
    272  *	[~]
    273  */
    274 protected el_action_t
    275 vi_change_case(el, c)
    276     EditLine *el;
    277     int c;
    278 {
    279     if (el->el_line.cursor < el->el_line.lastchar) {
    280 	c = *el->el_line.cursor;
    281 	if (isupper(c))
    282 	    *el->el_line.cursor++ = tolower(c);
    283 	else if (islower(c))
    284 	    *el->el_line.cursor++ = toupper(c);
    285 	else
    286 	    el->el_line.cursor++;
    287 	re_fastaddc(el);
    288 	return CC_NORM;
    289     }
    290     return CC_ERROR;
    291 }
    292 
    293 
    294 /* vi_change_meta():
    295  *	Vi change prefix command
    296  *	[c]
    297  */
    298 protected el_action_t
    299 /*ARGSUSED*/
    300 vi_change_meta(el, c)
    301     EditLine *el;
    302     int c;
    303 {
    304     /*
    305      * Delete with insert == change: first we delete and then we leave in
    306      * insert mode.
    307      */
    308     return cv_action(el, DELETE|INSERT);
    309 }
    310 
    311 
    312 /* vi_insert_at_bol():
    313  *	Vi enter insert mode at the beginning of line
    314  *	[I]
    315  */
    316 protected el_action_t
    317 /*ARGSUSED*/
    318 vi_insert_at_bol(el, c)
    319     EditLine *el;
    320     int c;
    321 {
    322     el->el_line.cursor = el->el_line.buffer;
    323     el->el_chared.c_vcmd.ins = el->el_line.cursor;
    324 
    325     el->el_chared.c_undo.ptr = el->el_line.cursor;
    326     el->el_chared.c_undo.action = DELETE;
    327 
    328     el->el_map.current = el->el_map.key;
    329     return CC_CURSOR;
    330 }
    331 
    332 
    333 /* vi_replace_char():
    334  *	Vi replace character under the cursor with the next character typed
    335  *	[r]
    336  */
    337 protected el_action_t
    338 /*ARGSUSED*/
    339 vi_replace_char(el, c)
    340     EditLine *el;
    341     int c;
    342 {
    343     el->el_map.current = el->el_map.key;
    344     el->el_state.inputmode = MODE_REPLACE_1;
    345     el->el_chared.c_undo.action = CHANGE;
    346     el->el_chared.c_undo.ptr = el->el_line.cursor;
    347     el->el_chared.c_undo.isize = 0;
    348     el->el_chared.c_undo.dsize = 0;
    349     return CC_NORM;
    350 }
    351 
    352 
    353 /* vi_replace_mode():
    354  *	Vi enter replace mode
    355  *	[R]
    356  */
    357 protected el_action_t
    358 /*ARGSUSED*/
    359 vi_replace_mode(el, c)
    360     EditLine *el;
    361     int c;
    362 {
    363     el->el_map.current = el->el_map.key;
    364     el->el_state.inputmode = MODE_REPLACE;
    365     el->el_chared.c_undo.action = CHANGE;
    366     el->el_chared.c_undo.ptr = el->el_line.cursor;
    367     el->el_chared.c_undo.isize = 0;
    368     el->el_chared.c_undo.dsize = 0;
    369     return CC_NORM;
    370 }
    371 
    372 
    373 /* vi_substitute_char():
    374  *	Vi replace character under the cursor and enter insert mode
    375  *	[r]
    376  */
    377 protected el_action_t
    378 /*ARGSUSED*/
    379 vi_substitute_char(el, c)
    380     EditLine *el;
    381     int c;
    382 {
    383     c_delafter(el, el->el_state.argument);
    384     el->el_map.current = el->el_map.key;
    385     return CC_REFRESH;
    386 }
    387 
    388 
    389 /* vi_substitute_line():
    390  *	Vi substitute entire line
    391  *	[S]
    392  */
    393 protected el_action_t
    394 /*ARGSUSED*/
    395 vi_substitute_line(el, c)
    396     EditLine *el;
    397     int c;
    398 {
    399     (void) em_kill_line(el, 0);
    400     el->el_map.current = el->el_map.key;
    401     return CC_REFRESH;
    402 }
    403 
    404 
    405 /* vi_change_to_eol():
    406  *	Vi change to end of line
    407  *	[C]
    408  */
    409 protected el_action_t
    410 /*ARGSUSED*/
    411 vi_change_to_eol(el, c)
    412     EditLine *el;
    413     int c;
    414 {
    415     (void) ed_kill_line(el, 0);
    416     el->el_map.current = el->el_map.key;
    417     return CC_REFRESH;
    418 }
    419 
    420 
    421 /* vi_insert():
    422  *	Vi enter insert mode
    423  *	[i]
    424  */
    425 protected el_action_t
    426 /*ARGSUSED*/
    427 vi_insert(el, c)
    428     EditLine *el;
    429     int c;
    430 {
    431     el->el_map.current = el->el_map.key;
    432 
    433     el->el_chared.c_vcmd.ins = el->el_line.cursor;
    434     el->el_chared.c_undo.ptr = el->el_line.cursor;
    435     el->el_chared.c_undo.action = DELETE;
    436 
    437     return CC_NORM;
    438 }
    439 
    440 
    441 /* vi_add():
    442  *	Vi enter insert mode after the cursor
    443  *	[a]
    444  */
    445 protected el_action_t
    446 /*ARGSUSED*/
    447 vi_add(el, c)
    448     EditLine *el;
    449     int c;
    450 {
    451     int ret;
    452     el->el_map.current = el->el_map.key;
    453     if (el->el_line.cursor < el->el_line.lastchar) {
    454 	el->el_line.cursor++;
    455 	if (el->el_line.cursor > el->el_line.lastchar)
    456 	    el->el_line.cursor = el->el_line.lastchar;
    457 	ret = CC_CURSOR;
    458     }
    459     else
    460 	ret = CC_NORM;
    461 
    462     el->el_chared.c_vcmd.ins = el->el_line.cursor;
    463     el->el_chared.c_undo.ptr = el->el_line.cursor;
    464     el->el_chared.c_undo.action = DELETE;
    465 
    466     return ret;
    467 }
    468 
    469 
    470 /* vi_add_at_eol():
    471  *	Vi enter insert mode at end of line
    472  *	[A]
    473  */
    474 protected el_action_t
    475 /*ARGSUSED*/
    476 vi_add_at_eol(el, c)
    477     EditLine *el;
    478     int c;
    479 {
    480     el->el_map.current = el->el_map.key;
    481     el->el_line.cursor = el->el_line.lastchar;
    482 
    483     /* Mark where insertion begins */
    484     el->el_chared.c_vcmd.ins = el->el_line.lastchar;
    485     el->el_chared.c_undo.ptr = el->el_line.lastchar;
    486     el->el_chared.c_undo.action = DELETE;
    487     return CC_CURSOR;
    488 }
    489 
    490 
    491 /* vi_delete_meta():
    492  *	Vi delete prefix command
    493  *	[d]
    494  */
    495 protected el_action_t
    496 /*ARGSUSED*/
    497 vi_delete_meta(el, c)
    498     EditLine *el;
    499     int c;
    500 {
    501     return cv_action(el, DELETE);
    502 }
    503 
    504 
    505 /* vi_end_word():
    506  *	Vi move to the end of the current space delimited word
    507  *	[E]
    508  */
    509 protected el_action_t
    510 /*ARGSUSED*/
    511 vi_end_word(el, c)
    512     EditLine *el;
    513     int c;
    514 {
    515     if (el->el_line.cursor == el->el_line.lastchar)
    516 	return CC_ERROR;
    517 
    518     el->el_line.cursor = cv__endword(el->el_line.cursor, el->el_line.lastchar,
    519 				     el->el_state.argument);
    520 
    521     if (el->el_chared.c_vcmd.action & DELETE) {
    522 	el->el_line.cursor++;
    523 	cv_delfini(el);
    524 	return CC_REFRESH;
    525     }
    526 
    527     return CC_CURSOR;
    528 }
    529 
    530 
    531 /* vi_to_end_word():
    532  *	Vi move to the end of the current word
    533  *	[e]
    534  */
    535 protected el_action_t
    536 /*ARGSUSED*/
    537 vi_to_end_word(el, c)
    538     EditLine *el;
    539     int c;
    540 {
    541     if (el->el_line.cursor == el->el_line.lastchar)
    542 	return CC_ERROR;
    543 
    544     el->el_line.cursor = cv__endword(el->el_line.cursor, el->el_line.lastchar,
    545 				     el->el_state.argument);
    546 
    547     if (el->el_chared.c_vcmd.action & DELETE) {
    548 	el->el_line.cursor++;
    549 	cv_delfini(el);
    550 	return CC_REFRESH;
    551     }
    552 
    553     return CC_CURSOR;
    554 }
    555 
    556 
    557 /* vi_undo():
    558  *	Vi undo last change
    559  *	[u]
    560  */
    561 protected el_action_t
    562 /*ARGSUSED*/
    563 vi_undo(el, c)
    564     EditLine *el;
    565     int c;
    566 {
    567     char *cp, *kp;
    568     char temp;
    569     int	 i, size;
    570     c_undo_t *un = &el->el_chared.c_undo;
    571 
    572 #ifdef DEBUG_UNDO
    573     (void) fprintf(el->el_errfile, "Undo: %x \"%s\" +%d -%d\n",
    574 		   un->action, un->buf, un->isize, un->dsize);
    575 #endif
    576     switch (un->action) {
    577     case DELETE:
    578 	if (un->dsize == 0)
    579 	    return CC_NORM;
    580 
    581 	(void) memcpy(un->buf, un->ptr, un->dsize);
    582 	for (cp = un->ptr; cp <= el->el_line.lastchar; cp++)
    583 	    *cp = cp[un->dsize];
    584 
    585 	el->el_line.lastchar -= un->dsize;
    586 	el->el_line.cursor   =  un->ptr;
    587 
    588 	un->action = INSERT;
    589 	un->isize = un->dsize;
    590 	un->dsize = 0;
    591 	break;
    592 
    593     case DELETE|INSERT:
    594 	size = un->isize - un->dsize;
    595 	if (size > 0)
    596 	    i = un->dsize;
    597 	else
    598 	    i = un->isize;
    599 	cp = un->ptr;
    600 	kp = un->buf;
    601 	while (i-- > 0) {
    602 	    temp = *kp;
    603 	    *kp++ = *cp;
    604 	    *cp++ = temp;
    605 	}
    606 	if (size > 0) {
    607 	    el->el_line.cursor = cp;
    608 	    c_insert(el, size);
    609 	    while (size-- > 0 && cp < el->el_line.lastchar) {
    610 		temp = *kp;
    611 		*kp++ = *cp;
    612 		*cp++ = temp;
    613 	    }
    614 	}
    615 	else if (size < 0) {
    616 	    size = -size;
    617 	    for (; cp <= el->el_line.lastchar; cp++) {
    618 		*kp++ = *cp;
    619 		*cp = cp[size];
    620 	    }
    621 	    el->el_line.lastchar -= size;
    622 	}
    623 	el->el_line.cursor = un->ptr;
    624 	i = un->dsize;
    625 	un->dsize = un->isize;
    626 	un->isize = i;
    627 	break;
    628 
    629     case INSERT:
    630 	if (un->isize == 0)
    631 	    return CC_NORM;
    632 
    633 	el->el_line.cursor = un->ptr;
    634 	c_insert(el, un->isize);
    635 	memcpy(un->ptr, un->buf, un->isize);
    636 	un->action = DELETE;
    637 	un->dsize = un->isize;
    638 	un->isize = 0;
    639 	break;
    640 
    641     case CHANGE:
    642 	if (un->isize == 0)
    643 	    return CC_NORM;
    644 
    645 	el->el_line.cursor = un->ptr;
    646 	size = (int) (el->el_line.cursor - el->el_line.lastchar);
    647 	if (size < un->isize)
    648 	    size = un->isize;
    649 	cp = un->ptr;
    650 	kp = un->buf;
    651 	for(i = 0; i < size; i++) {
    652 	    temp = *kp;
    653 	    *kp++ = *cp;
    654 	    *cp++ = temp;
    655 	}
    656 	un->dsize = 0;
    657 	break;
    658 
    659     default:
    660 	return CC_ERROR;
    661     }
    662 
    663     return CC_REFRESH;
    664 }
    665 
    666 
    667 /* vi_command_mode():
    668  *	Vi enter command mode (use alternative key bindings)
    669  *	[<ESC>]
    670  */
    671 protected el_action_t
    672 /*ARGSUSED*/
    673 vi_command_mode(el, c)
    674     EditLine *el;
    675     int c;
    676 {
    677     int size;
    678     /* [Esc] cancels pending action */
    679     el->el_chared.c_vcmd.ins = 0;
    680     el->el_chared.c_vcmd.action = NOP;
    681     el->el_chared.c_vcmd.pos = 0;
    682 
    683     el->el_state.doingarg = 0;
    684     size = el->el_chared.c_undo.ptr - el->el_line.cursor;
    685     if (size < 0)
    686 	size = -size;
    687     if (el->el_chared.c_undo.action == (INSERT|DELETE) ||
    688         el->el_chared.c_undo.action == DELETE)
    689 	el->el_chared.c_undo.dsize = size;
    690     else
    691 	el->el_chared.c_undo.isize = size;
    692 
    693     el->el_state.inputmode = MODE_INSERT;
    694     el->el_map.current = el->el_map.alt;
    695 #ifdef VI_MOVE
    696     if (el->el_line.cursor > el->el_line.buffer)
    697 	el->el_line.cursor--;
    698 #endif
    699     return CC_CURSOR;
    700 }
    701 
    702 /* vi_zero():
    703  *	Vi move to the beginning of line
    704  *	[0]
    705  */
    706 protected el_action_t
    707 vi_zero(el, c)
    708     EditLine *el;
    709     int c;
    710 {
    711     if (el->el_state.doingarg) {
    712 	if (el->el_state.argument > 1000000)
    713 	    return CC_ERROR;
    714 	el->el_state.argument =
    715 		(el->el_state.argument * 10) + (c - '0');
    716 	return CC_ARGHACK;
    717     }
    718     else {
    719 	el->el_line.cursor = el->el_line.buffer;
    720 	if (el->el_chared.c_vcmd.action & DELETE) {
    721 	   cv_delfini(el);
    722 	   return CC_REFRESH;
    723         }
    724 	return CC_CURSOR;
    725     }
    726 }
    727 
    728 
    729 /* vi_delete_prev_char():
    730  * 	Vi move to previous character (backspace)
    731  *	[^H]
    732  */
    733 protected el_action_t
    734 /*ARGSUSED*/
    735 vi_delete_prev_char(el, c)
    736     EditLine *el;
    737     int c;
    738 {
    739     if (el->el_chared.c_vcmd.ins == 0)
    740 	return CC_ERROR;
    741 
    742     if (el->el_chared.c_vcmd.ins >
    743 	el->el_line.cursor - el->el_state.argument)
    744 	return CC_ERROR;
    745 
    746     c_delbefore(el, el->el_state.argument);
    747     el->el_line.cursor -= el->el_state.argument;
    748 
    749     return CC_REFRESH;
    750 } /* end v_del_char_prev  */
    751 
    752 
    753 /* vi_list_or_eof():
    754  *	Vi list choices for completion or indicate end of file if empty line
    755  *	[^D]
    756  */
    757 protected el_action_t
    758 /*ARGSUSED*/
    759 vi_list_or_eof(el, c)
    760     EditLine *el;
    761     int c;
    762 {
    763 #ifdef notyet
    764     if (el->el_line.cursor == el->el_line.lastchar &&
    765 	el->el_line.cursor == el->el_line.buffer) {
    766 #endif
    767 	term_overwrite(el, STReof, 4);	/* then do a EOF */
    768 	term__flush();
    769 	return CC_EOF;
    770 #ifdef notyet
    771     }
    772     else {
    773 	re_goto_bottom(el);
    774 	*el->el_line.lastchar = '\0';	/* just in case */
    775 	return CC_LIST_CHOICES;
    776     }
    777 #endif
    778 }
    779 
    780 
    781 /* vi_kill_line_prev():
    782  *	Vi cut from beginning of line to cursor
    783  *	[^U]
    784  */
    785 protected el_action_t
    786 /*ARGSUSED*/
    787 vi_kill_line_prev(el, c)
    788     EditLine *el;
    789     int c;
    790 {
    791     char *kp, *cp;
    792 
    793     cp = el->el_line.buffer;
    794     kp = el->el_chared.c_kill.buf;
    795     while (cp < el->el_line.cursor)
    796 	*kp++ = *cp++;		/* copy it */
    797     el->el_chared.c_kill.last = kp;
    798     c_delbefore(el, el->el_line.cursor - el->el_line.buffer);
    799     el->el_line.cursor = el->el_line.buffer;		/* zap! */
    800     return CC_REFRESH;
    801 }
    802 
    803 
    804 /* vi_search_prev():
    805  *	Vi search history previous
    806  *	[?]
    807  */
    808 protected el_action_t
    809 /*ARGSUSED*/
    810 vi_search_prev(el, c)
    811     EditLine *el;
    812     int c;
    813 {
    814     return cv_search(el, ED_SEARCH_PREV_HISTORY);
    815 }
    816 
    817 
    818 /* vi_search_next():
    819  *	Vi search history next
    820  *	[/]
    821  */
    822 protected el_action_t
    823 /*ARGSUSED*/
    824 vi_search_next(el, c)
    825     EditLine *el;
    826     int c;
    827 {
    828     return cv_search(el, ED_SEARCH_NEXT_HISTORY);
    829 }
    830 
    831 
    832 /* vi_repeat_search_next():
    833  *	Vi repeat current search in the same search direction
    834  *	[n]
    835  */
    836 protected el_action_t
    837 /*ARGSUSED*/
    838 vi_repeat_search_next(el, c)
    839     EditLine *el;
    840     int c;
    841 {
    842     if (el->el_search.patlen == 0)
    843 	return CC_ERROR;
    844     else
    845 	return cv_repeat_srch(el, el->el_search.patdir);
    846 }
    847 
    848 
    849 /* vi_repeat_search_prev():
    850  *	Vi repeat current search in the opposite search direction
    851  *	[N]
    852  */
    853 /*ARGSUSED*/
    854 protected el_action_t
    855 vi_repeat_search_prev(el, c)
    856     EditLine *el;
    857     int c;
    858 {
    859     if (el->el_search.patlen == 0)
    860 	return CC_ERROR;
    861     else
    862 	return cv_repeat_srch(el,
    863 			      el->el_search.patdir == ED_SEARCH_PREV_HISTORY ?
    864 			      ED_SEARCH_NEXT_HISTORY : ED_SEARCH_PREV_HISTORY);
    865 }
    866 
    867 
    868 /* vi_next_char():
    869  *	Vi move to the character specified next
    870  *	[f]
    871  */
    872 protected el_action_t
    873 /*ARGSUSED*/
    874 vi_next_char(el, c)
    875     EditLine *el;
    876     int c;
    877 {
    878     char ch;
    879 
    880     if (el_getc(el, &ch) != 1)
    881 	return ed_end_of_file(el, 0);
    882 
    883     el->el_search.chadir = CHAR_FWD;
    884     el->el_search.chacha = ch;
    885 
    886     return cv_csearch_fwd(el, ch, el->el_state.argument, 0);
    887 
    888 }
    889 
    890 
    891 /* vi_prev_char():
    892  *	Vi move to the character specified previous
    893  *	[F]
    894  */
    895 protected el_action_t
    896 /*ARGSUSED*/
    897 vi_prev_char(el, c)
    898     EditLine *el;
    899     int c;
    900 {
    901     char ch;
    902 
    903     if (el_getc(el, &ch) != 1)
    904 	return ed_end_of_file(el, 0);
    905 
    906     el->el_search.chadir = CHAR_BACK;
    907     el->el_search.chacha = ch;
    908 
    909     return cv_csearch_back(el, ch, el->el_state.argument, 0);
    910 }
    911 
    912 
    913 /* vi_to_next_char():
    914  *	Vi move up to the character specified next
    915  *	[t]
    916  */
    917 protected el_action_t
    918 /*ARGSUSED*/
    919 vi_to_next_char(el, c)
    920     EditLine *el;
    921     int c;
    922 {
    923     char ch;
    924 
    925     if (el_getc(el, &ch) != 1)
    926 	return ed_end_of_file(el, 0);
    927 
    928     return cv_csearch_fwd(el, ch, el->el_state.argument, 1);
    929 
    930 }
    931 
    932 
    933 /* vi_to_prev_char():
    934  *	Vi move up to the character specified previous
    935  *	[T]
    936  */
    937 protected el_action_t
    938 /*ARGSUSED*/
    939 vi_to_prev_char(el, c)
    940     EditLine *el;
    941     int c;
    942 {
    943     char ch;
    944     if (el_getc(el, &ch) != 1)
    945 	return ed_end_of_file(el, 0);
    946 
    947     return cv_csearch_back(el, ch, el->el_state.argument, 1);
    948 }
    949 
    950 
    951 /* vi_repeat_next_char():
    952  *	Vi repeat current character search in the same search direction
    953  *	[;]
    954  */
    955 protected el_action_t
    956 /*ARGSUSED*/
    957 vi_repeat_next_char(el, c)
    958     EditLine *el;
    959     int c;
    960 {
    961     if (el->el_search.chacha == 0)
    962 	return CC_ERROR;
    963 
    964     return el->el_search.chadir == CHAR_FWD ?
    965 	cv_csearch_fwd(el, el->el_search.chacha, el->el_state.argument, 0) :
    966         cv_csearch_back(el, el->el_search.chacha, el->el_state.argument, 0);
    967 }
    968 
    969 
    970 /* vi_repeat_prev_char():
    971  *	Vi repeat current character search in the opposite search direction
    972  *	[,]
    973  */
    974 protected el_action_t
    975 /*ARGSUSED*/
    976 vi_repeat_prev_char(el, c)
    977     EditLine *el;
    978     int c;
    979 {
    980     if (el->el_search.chacha == 0)
    981 	return CC_ERROR;
    982 
    983     return el->el_search.chadir == CHAR_BACK ?
    984 	cv_csearch_fwd(el, el->el_search.chacha, el->el_state.argument, 0) :
    985         cv_csearch_back(el, el->el_search.chacha, el->el_state.argument, 0);
    986 }
    987