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