From 6ff1c1765c2b4495f0292fe730d9bb9a5daef063 Mon Sep 17 00:00:00 2001 From: Otto Moerbeek Date: Fri, 31 Oct 2003 08:42:25 +0000 Subject: Update to NetBSD libedit (from Oct 1, 2003), adding some string cleaning and history bug fixes. The code includes GNU libreadline functionality, but the corresponding header files are not installed, since some libreadline functions are missing. There are some minor API changes, notably: old: EditLine *el_init(const char *, FILE *, FILE *); new: EditLine *el_init(const char *, FILE *, FILE *, FILE *); old: HistEvent *history(History *h, int op, ...); new: int history(History *h, HistEvent *ev, int op, ...); plus some changes in operation names. See editline(3) for details. Tested by djm@, mouring@, jmc@. ok deraadt@ --- lib/libedit/vi.c | 1254 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 698 insertions(+), 556 deletions(-) (limited to 'lib/libedit/vi.c') diff --git a/lib/libedit/vi.c b/lib/libedit/vi.c index d0d289f20e4..888c1469381 100644 --- a/lib/libedit/vi.c +++ b/lib/libedit/vi.c @@ -1,5 +1,5 @@ -/* $OpenBSD: vi.c,v 1.6 2003/06/02 20:18:40 millert Exp $ */ -/* $NetBSD: vi.c,v 1.2 1997/01/11 06:48:19 lukem Exp $ */ +/* $OpenBSD: vi.c,v 1.7 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: vi.c,v 1.19 2003/08/07 16:44:35 agc Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -33,391 +33,358 @@ * SUCH DAMAGE. */ +#include "config.h" +#include +#include +#include + #if !defined(lint) && !defined(SCCSID) #if 0 static char sccsid[] = "@(#)vi.c 8.1 (Berkeley) 6/4/93"; #else -static const char rcsid[] = "$OpenBSD: vi.c,v 1.6 2003/06/02 20:18:40 millert Exp $"; +static const char rcsid[] = "$OpenBSD: vi.c,v 1.7 2003/10/31 08:42:24 otto Exp $"; #endif #endif /* not lint && not SCCSID */ /* * vi.c: Vi mode commands. */ -#include "sys.h" #include "el.h" -private el_action_t cv_action(EditLine *, int); +private el_action_t cv_action(EditLine *, int); +private el_action_t cv_paste(EditLine *, int); /* cv_action(): * Handle vi actions. */ private el_action_t -cv_action(el, c) - EditLine *el; - int c; +cv_action(EditLine *el, int c) { - register char *cp, *kp; - if (el->el_chared.c_vcmd.action & DELETE) { - el->el_chared.c_vcmd.action = NOP; - el->el_chared.c_vcmd.pos = 0; - - el->el_chared.c_undo.isize = 0; - el->el_chared.c_undo.dsize = 0; - kp = el->el_chared.c_undo.buf; - for (cp = el->el_line.buffer; cp < el->el_line.lastchar; cp++) { - *kp++ = *cp; - el->el_chared.c_undo.dsize++; + if (el->el_chared.c_vcmd.action != NOP) { + /* 'cc', 'dd' and (possibly) friends */ + if (c != el->el_chared.c_vcmd.action) + return CC_ERROR; + + if (!(c & YANK)) + cv_undo(el); + cv_yank(el, el->el_line.buffer, + el->el_line.lastchar - el->el_line.buffer); + el->el_chared.c_vcmd.action = NOP; + el->el_chared.c_vcmd.pos = 0; + el->el_line.lastchar = el->el_line.buffer; + el->el_line.cursor = el->el_line.buffer; + if (c & INSERT) + el->el_map.current = el->el_map.key; + + return (CC_REFRESH); } - - el->el_chared.c_undo.action = INSERT; - el->el_chared.c_undo.ptr = el->el_line.buffer; - el->el_line.lastchar = el->el_line.buffer; - el->el_line.cursor = el->el_line.buffer; - if (c & INSERT) - el->el_map.current = el->el_map.key; - - return CC_REFRESH; - } - - el->el_chared.c_vcmd.pos = el->el_line.cursor; - el->el_chared.c_vcmd.action = c; - return CC_ARGHACK; - -#ifdef notdef - /* - * I don't think that this is needed. But we keep it for now - */ - else if (el_chared.c_vcmd.action == NOP) { el->el_chared.c_vcmd.pos = el->el_line.cursor; el->el_chared.c_vcmd.action = c; - return CC_ARGHACK; - } - else { - el->el_chared.c_vcmd.action = 0; - el->el_chared.c_vcmd.pos = 0; - return CC_ERROR; - } -#endif + return (CC_ARGHACK); } - /* cv_paste(): * Paste previous deletion before or after the cursor */ -protected el_action_t -cv_paste(el, c) - EditLine *el; - int c; +private el_action_t +cv_paste(EditLine *el, int c) { - char *ptr; - c_undo_t *un = &el->el_chared.c_undo; + char *ptr; + c_kill_t *k = &el->el_chared.c_kill; + int len = k->last - k->buf; + + if (k->buf == NULL || len == 0) + return (CC_ERROR); #ifdef DEBUG_PASTE - (void)fprintf(el->el_errfile, "Paste: %x \"%s\" +%d -%d\n", - un->action, un->buf, un->isize, un->dsize); + (void) fprintf(el->el_errfile, "Paste: \"%.*s\"\n", len, k->buf); #endif - if (un->isize == 0) - return CC_ERROR; - if (!c && el->el_line.cursor < el->el_line.lastchar) - el->el_line.cursor++; - ptr = el->el_line.cursor; - - c_insert(el, un->isize); - if (el->el_line.cursor + un->isize > el->el_line.lastchar) - return CC_ERROR; - (void)memcpy(ptr, un->buf, un->isize); - return CC_REFRESH; + cv_undo(el); + + if (!c && el->el_line.cursor < el->el_line.lastchar) + el->el_line.cursor++; + ptr = el->el_line.cursor; + + c_insert(el, len); + if (el->el_line.cursor + len > el->el_line.lastchar) + return (CC_ERROR); + (void) memcpy(ptr, k->buf, len +0u); + return (CC_REFRESH); } -/* vi_paste_next(): +/* vi_paste_next(): * Vi paste previous deletion to the right of the cursor * [p] */ protected el_action_t /*ARGSUSED*/ -vi_paste_next(el, c) - EditLine *el; - int c; +vi_paste_next(EditLine *el, int c __attribute__((__unused__))) { - return cv_paste(el, 0); + + return (cv_paste(el, 0)); } -/* vi_paste_prev(): +/* vi_paste_prev(): * Vi paste previous deletion to the left of the cursor * [P] */ protected el_action_t /*ARGSUSED*/ -vi_paste_prev(el, c) - EditLine *el; - int c; +vi_paste_prev(EditLine *el, int c __attribute__((__unused__))) { - return cv_paste(el, 1); + + return (cv_paste(el, 1)); } -/* vi_prev_space_word(): +/* vi_prev_big_word(): * Vi move to the previous space delimited word * [B] */ protected el_action_t /*ARGSUSED*/ -vi_prev_space_word(el, c) - EditLine *el; - int c; +vi_prev_big_word(EditLine *el, int c) { - if (el->el_line.cursor == el->el_line.buffer) - return CC_ERROR; - el->el_line.cursor = cv_prev_word(el, el->el_line.cursor, - el->el_line.buffer, - el->el_state.argument, - cv__isword); + if (el->el_line.cursor == el->el_line.buffer) + return (CC_ERROR); - if (el->el_chared.c_vcmd.action & DELETE) { - cv_delfini(el); - return CC_REFRESH; - } + el->el_line.cursor = cv_prev_word(el->el_line.cursor, + el->el_line.buffer, + el->el_state.argument, + cv__isWord); - return CC_CURSOR; + if (el->el_chared.c_vcmd.action != NOP) { + cv_delfini(el); + return (CC_REFRESH); + } + return (CC_CURSOR); } -/* vi_prev_word(): +/* vi_prev_word(): * Vi move to the previous word - * [B] + * [b] */ protected el_action_t /*ARGSUSED*/ -vi_prev_word(el, c) - EditLine *el; - int c; +vi_prev_word(EditLine *el, int c __attribute__((__unused__))) { - if (el->el_line.cursor == el->el_line.buffer) - return CC_ERROR; - el->el_line.cursor = cv_prev_word(el, el->el_line.cursor, - el->el_line.buffer, - el->el_state.argument, - ce__isword); + if (el->el_line.cursor == el->el_line.buffer) + return (CC_ERROR); - if (el->el_chared.c_vcmd.action & DELETE) { - cv_delfini(el); - return CC_REFRESH; - } + el->el_line.cursor = cv_prev_word(el->el_line.cursor, + el->el_line.buffer, + el->el_state.argument, + cv__isword); - return CC_CURSOR; + if (el->el_chared.c_vcmd.action != NOP) { + cv_delfini(el); + return (CC_REFRESH); + } + return (CC_CURSOR); } -/* vi_next_space_word(): +/* vi_next_big_word(): * Vi move to the next space delimited word * [W] */ protected el_action_t /*ARGSUSED*/ -vi_next_space_word(el, c) - EditLine *el; - int c; +vi_next_big_word(EditLine *el, int c) { - if (el->el_line.cursor == el->el_line.lastchar) - return CC_ERROR; - el->el_line.cursor = cv_next_word(el, el->el_line.cursor, - el->el_line.lastchar, - el->el_state.argument, - cv__isword); + if (el->el_line.cursor >= el->el_line.lastchar - 1) + return (CC_ERROR); - if (el->el_map.type == MAP_VI) - if (el->el_chared.c_vcmd.action & DELETE) { - cv_delfini(el); - return CC_REFRESH; - } + el->el_line.cursor = cv_next_word(el, el->el_line.cursor, + el->el_line.lastchar, el->el_state.argument, cv__isWord); - return CC_CURSOR; + if (el->el_map.type == MAP_VI) + if (el->el_chared.c_vcmd.action != NOP) { + cv_delfini(el); + return (CC_REFRESH); + } + return (CC_CURSOR); } -/* vi_next_word(): + +/* vi_next_word(): * Vi move to the next word * [w] */ protected el_action_t /*ARGSUSED*/ -vi_next_word(el, c) - EditLine *el; - int c; +vi_next_word(EditLine *el, int c __attribute__((__unused__))) { - if (el->el_line.cursor == el->el_line.lastchar) - return CC_ERROR; - el->el_line.cursor = cv_next_word(el, el->el_line.cursor, - el->el_line.lastchar, - el->el_state.argument, - ce__isword); + if (el->el_line.cursor >= el->el_line.lastchar - 1) + return (CC_ERROR); - if (el->el_map.type == MAP_VI) - if (el->el_chared.c_vcmd.action & DELETE) { - cv_delfini(el); - return CC_REFRESH; - } + el->el_line.cursor = cv_next_word(el, el->el_line.cursor, + el->el_line.lastchar, el->el_state.argument, cv__isword); - return CC_CURSOR; + if (el->el_map.type == MAP_VI) + if (el->el_chared.c_vcmd.action != NOP) { + cv_delfini(el); + return (CC_REFRESH); + } + return (CC_CURSOR); } - -/* vi_change_case(): +/* vi_change_case(): * Vi change case of character under the cursor and advance one character * [~] */ protected el_action_t -vi_change_case(el, c) - EditLine *el; - int c; +vi_change_case(EditLine *el, int c) { - if (el->el_line.cursor < el->el_line.lastchar) { - c = *el->el_line.cursor; - if (isupper(c)) - *el->el_line.cursor++ = tolower(c); - else if (islower(c)) - *el->el_line.cursor++ = toupper(c); - else - el->el_line.cursor++; - re_fastaddc(el); + int i; + + if (el->el_line.cursor >= el->el_line.lastchar) + return (CC_ERROR); + cv_undo(el); + for (i = 0; i < el->el_state.argument; i++) { + + c = *(unsigned char *)el->el_line.cursor; + if (isupper(c)) + *el->el_line.cursor = tolower(c); + else if (islower(c)) + *el->el_line.cursor = toupper(c); + + if (++el->el_line.cursor >= el->el_line.lastchar) { + el->el_line.cursor--; + re_fastaddc(el); + break; + } + re_fastaddc(el); + } return CC_NORM; - } - return CC_ERROR; } -/* vi_change_meta(): +/* vi_change_meta(): * Vi change prefix command * [c] */ protected el_action_t /*ARGSUSED*/ -vi_change_meta(el, c) - EditLine *el; - int c; +vi_change_meta(EditLine *el, int c __attribute__((__unused__))) { - /* - * Delete with insert == change: first we delete and then we leave in - * insert mode. - */ - return cv_action(el, DELETE|INSERT); + + /* + * Delete with insert == change: first we delete and then we leave in + * insert mode. + */ + return (cv_action(el, DELETE | INSERT)); } -/* vi_insert_at_bol(): +/* vi_insert_at_bol(): * Vi enter insert mode at the beginning of line * [I] */ protected el_action_t /*ARGSUSED*/ -vi_insert_at_bol(el, c) - EditLine *el; - int c; +vi_insert_at_bol(EditLine *el, int c __attribute__((__unused__))) { - el->el_line.cursor = el->el_line.buffer; - el->el_chared.c_vcmd.ins = el->el_line.cursor; - el->el_chared.c_undo.ptr = el->el_line.cursor; - el->el_chared.c_undo.action = DELETE; - - el->el_map.current = el->el_map.key; - return CC_CURSOR; + el->el_line.cursor = el->el_line.buffer; + cv_undo(el); + el->el_map.current = el->el_map.key; + return (CC_CURSOR); } -/* vi_replace_char(): +/* vi_replace_char(): * Vi replace character under the cursor with the next character typed * [r] */ protected el_action_t /*ARGSUSED*/ -vi_replace_char(el, c) - EditLine *el; - int c; +vi_replace_char(EditLine *el, int c __attribute__((__unused__))) { - el->el_map.current = el->el_map.key; - el->el_state.inputmode = MODE_REPLACE_1; - el->el_chared.c_undo.action = CHANGE; - el->el_chared.c_undo.ptr = el->el_line.cursor; - el->el_chared.c_undo.isize = 0; - el->el_chared.c_undo.dsize = 0; - return CC_NORM; + + if (el->el_line.cursor >= el->el_line.lastchar) + return CC_ERROR; + + el->el_map.current = el->el_map.key; + el->el_state.inputmode = MODE_REPLACE_1; + cv_undo(el); + return (CC_ARGHACK); } -/* vi_replace_mode(): +/* vi_replace_mode(): * Vi enter replace mode * [R] */ protected el_action_t /*ARGSUSED*/ -vi_replace_mode(el, c) - EditLine *el; - int c; +vi_replace_mode(EditLine *el, int c __attribute__((__unused__))) { - el->el_map.current = el->el_map.key; - el->el_state.inputmode = MODE_REPLACE; - el->el_chared.c_undo.action = CHANGE; - el->el_chared.c_undo.ptr = el->el_line.cursor; - el->el_chared.c_undo.isize = 0; - el->el_chared.c_undo.dsize = 0; - return CC_NORM; + + el->el_map.current = el->el_map.key; + el->el_state.inputmode = MODE_REPLACE; + cv_undo(el); + return (CC_NORM); } -/* vi_substitute_char(): +/* vi_substitute_char(): * Vi replace character under the cursor and enter insert mode - * [r] + * [s] */ protected el_action_t /*ARGSUSED*/ -vi_substitute_char(el, c) - EditLine *el; - int c; +vi_substitute_char(EditLine *el, int c __attribute__((__unused__))) { - c_delafter(el, el->el_state.argument); - el->el_map.current = el->el_map.key; - return CC_REFRESH; + + c_delafter(el, el->el_state.argument); + el->el_map.current = el->el_map.key; + return (CC_REFRESH); } -/* vi_substitute_line(): +/* vi_substitute_line(): * Vi substitute entire line * [S] */ protected el_action_t /*ARGSUSED*/ -vi_substitute_line(el, c) - EditLine *el; - int c; +vi_substitute_line(EditLine *el, int c __attribute__((__unused__))) { - (void)em_kill_line(el, 0); - el->el_map.current = el->el_map.key; - return CC_REFRESH; + + cv_undo(el); + cv_yank(el, el->el_line.buffer, + el->el_line.lastchar - el->el_line.buffer); + (void) em_kill_line(el, 0); + el->el_map.current = el->el_map.key; + return (CC_REFRESH); } -/* vi_change_to_eol(): +/* vi_change_to_eol(): * Vi change to end of line * [C] */ protected el_action_t /*ARGSUSED*/ -vi_change_to_eol(el, c) - EditLine *el; - int c; +vi_change_to_eol(EditLine *el, int c __attribute__((__unused__))) { - (void)ed_kill_line(el, 0); - el->el_map.current = el->el_map.key; - return CC_REFRESH; + + cv_undo(el); + cv_yank(el, el->el_line.cursor, + el->el_line.lastchar - el->el_line.cursor); + (void) ed_kill_line(el, 0); + el->el_map.current = el->el_map.key; + return (CC_REFRESH); } @@ -427,46 +394,37 @@ vi_change_to_eol(el, c) */ protected el_action_t /*ARGSUSED*/ -vi_insert(el, c) - EditLine *el; - int c; +vi_insert(EditLine *el, int c __attribute__((__unused__))) { - el->el_map.current = el->el_map.key; - el->el_chared.c_vcmd.ins = el->el_line.cursor; - el->el_chared.c_undo.ptr = el->el_line.cursor; - el->el_chared.c_undo.action = DELETE; - - return CC_NORM; + el->el_map.current = el->el_map.key; + cv_undo(el); + return (CC_NORM); } /* vi_add(): - * Vi enter insert mode after the cursor + * Vi enter insert mode after the cursor * [a] */ protected el_action_t /*ARGSUSED*/ -vi_add(el, c) - EditLine *el; - int c; +vi_add(EditLine *el, int c __attribute__((__unused__))) { - int ret; - el->el_map.current = el->el_map.key; - if (el->el_line.cursor < el->el_line.lastchar) { - el->el_line.cursor++; - if (el->el_line.cursor > el->el_line.lastchar) - el->el_line.cursor = el->el_line.lastchar; - ret = CC_CURSOR; - } - else - ret = CC_NORM; + int ret; + + el->el_map.current = el->el_map.key; + if (el->el_line.cursor < el->el_line.lastchar) { + el->el_line.cursor++; + if (el->el_line.cursor > el->el_line.lastchar) + el->el_line.cursor = el->el_line.lastchar; + ret = CC_CURSOR; + } else + ret = CC_NORM; - el->el_chared.c_vcmd.ins = el->el_line.cursor; - el->el_chared.c_undo.ptr = el->el_line.cursor; - el->el_chared.c_undo.action = DELETE; + cv_undo(el); - return ret; + return (ret); } @@ -476,84 +434,74 @@ vi_add(el, c) */ protected el_action_t /*ARGSUSED*/ -vi_add_at_eol(el, c) - EditLine *el; - int c; +vi_add_at_eol(EditLine *el, int c __attribute__((__unused__))) { - el->el_map.current = el->el_map.key; - el->el_line.cursor = el->el_line.lastchar; - /* Mark where insertion begins */ - el->el_chared.c_vcmd.ins = el->el_line.lastchar; - el->el_chared.c_undo.ptr = el->el_line.lastchar; - el->el_chared.c_undo.action = DELETE; - return CC_CURSOR; + el->el_map.current = el->el_map.key; + el->el_line.cursor = el->el_line.lastchar; + cv_undo(el); + return (CC_CURSOR); } /* vi_delete_meta(): - * Vi delete prefix command + * Vi delete prefix command * [d] */ protected el_action_t /*ARGSUSED*/ -vi_delete_meta(el, c) - EditLine *el; - int c; +vi_delete_meta(EditLine *el, int c __attribute__((__unused__))) { - return cv_action(el, DELETE); + + return (cv_action(el, DELETE)); } -/* vi_end_word(): - * Vi move to the end of the current space delimited word - * [E] +/* vi_end_big_word(): + * Vi move to the end of the current space delimited word + * [E] */ protected el_action_t /*ARGSUSED*/ -vi_end_word(el, c) - EditLine *el; - int c; +vi_end_big_word(EditLine *el, int c) { - if (el->el_line.cursor == el->el_line.lastchar) - return CC_ERROR; - el->el_line.cursor = cv__endword(el->el_line.cursor, el->el_line.lastchar, - el->el_state.argument); + if (el->el_line.cursor == el->el_line.lastchar) + return (CC_ERROR); - if (el->el_chared.c_vcmd.action & DELETE) { - el->el_line.cursor++; - cv_delfini(el); - return CC_REFRESH; - } + el->el_line.cursor = cv__endword(el->el_line.cursor, + el->el_line.lastchar, el->el_state.argument, cv__isWord); - return CC_CURSOR; + if (el->el_chared.c_vcmd.action != NOP) { + el->el_line.cursor++; + cv_delfini(el); + return (CC_REFRESH); + } + return (CC_CURSOR); } -/* vi_to_end_word(): +/* vi_end_word(): * Vi move to the end of the current word * [e] */ protected el_action_t /*ARGSUSED*/ -vi_to_end_word(el, c) - EditLine *el; - int c; +vi_end_word(EditLine *el, int c __attribute__((__unused__))) { - if (el->el_line.cursor == el->el_line.lastchar) - return CC_ERROR; - el->el_line.cursor = cv__endword(el->el_line.cursor, el->el_line.lastchar, - el->el_state.argument); + if (el->el_line.cursor == el->el_line.lastchar) + return (CC_ERROR); - if (el->el_chared.c_vcmd.action & DELETE) { - el->el_line.cursor++; - cv_delfini(el); - return CC_REFRESH; - } + el->el_line.cursor = cv__endword(el->el_line.cursor, + el->el_line.lastchar, el->el_state.argument, cv__isword); - return CC_CURSOR; + if (el->el_chared.c_vcmd.action != NOP) { + el->el_line.cursor++; + cv_delfini(el); + return (CC_REFRESH); + } + return (CC_CURSOR); } @@ -563,107 +511,23 @@ vi_to_end_word(el, c) */ protected el_action_t /*ARGSUSED*/ -vi_undo(el, c) - EditLine *el; - int c; +vi_undo(EditLine *el, int c __attribute__((__unused__))) { - char *cp, *kp; - char temp; - int i, size; - c_undo_t *un = &el->el_chared.c_undo; + c_undo_t un = el->el_chared.c_undo; -#ifdef DEBUG_UNDO - (void)fprintf(el->el_errfile, "Undo: %x \"%s\" +%d -%d\n", - un->action, un->buf, un->isize, un->dsize); -#endif - switch (un->action) { - case DELETE: - if (un->dsize == 0) - return CC_NORM; - - (void)memcpy(un->buf, un->ptr, un->dsize); - for (cp = un->ptr; cp <= el->el_line.lastchar; cp++) - *cp = cp[un->dsize]; - - el->el_line.lastchar -= un->dsize; - el->el_line.cursor = un->ptr; - - un->action = INSERT; - un->isize = un->dsize; - un->dsize = 0; - break; - - case DELETE|INSERT: - size = un->isize - un->dsize; - if (size > 0) - i = un->dsize; - else - i = un->isize; - cp = un->ptr; - kp = un->buf; - while (i-- > 0) { - temp = *kp; - *kp++ = *cp; - *cp++ = temp; - } - if (size > 0) { - el->el_line.cursor = cp; - c_insert(el, size); - while (size-- > 0 && cp < el->el_line.lastchar) { - temp = *kp; - *kp++ = *cp; - *cp++ = temp; - } - } - else if (size < 0) { - size = -size; - for (; cp <= el->el_line.lastchar; cp++) { - *kp++ = *cp; - *cp = cp[size]; - } - el->el_line.lastchar -= size; - } - el->el_line.cursor = un->ptr; - i = un->dsize; - un->dsize = un->isize; - un->isize = i; - break; - - case INSERT: - if (un->isize == 0) - return CC_NORM; - - el->el_line.cursor = un->ptr; - c_insert(el, un->isize); - memcpy(un->ptr, un->buf, un->isize); - un->action = DELETE; - un->dsize = un->isize; - un->isize = 0; - break; - - case CHANGE: - if (un->isize == 0) - return CC_NORM; - - el->el_line.cursor = un->ptr; - size = (int) (el->el_line.cursor - el->el_line.lastchar); - if (size < un->isize) - size = un->isize; - cp = un->ptr; - kp = un->buf; - for(i = 0; i < size; i++) { - temp = *kp; - *kp++ = *cp; - *cp++ = temp; - } - un->dsize = 0; - break; + if (un.len == -1) + return CC_ERROR; - default: - return CC_ERROR; - } + /* switch line buffer and undo buffer */ + el->el_chared.c_undo.buf = el->el_line.buffer; + el->el_chared.c_undo.len = el->el_line.lastchar - el->el_line.buffer; + el->el_chared.c_undo.cursor = el->el_line.cursor - el->el_line.buffer; + el->el_line.limit = un.buf + (el->el_line.limit - el->el_line.buffer); + el->el_line.buffer = un.buf; + el->el_line.cursor = un.buf + un.cursor; + el->el_line.lastchar = un.buf + un.len; - return CC_REFRESH; + return (CC_REFRESH); } @@ -673,84 +537,67 @@ vi_undo(el, c) */ protected el_action_t /*ARGSUSED*/ -vi_command_mode(el, c) - EditLine *el; - int c; +vi_command_mode(EditLine *el, int c __attribute__((__unused__))) { - int size; - /* [Esc] cancels pending action */ - el->el_chared.c_vcmd.ins = 0; - el->el_chared.c_vcmd.action = NOP; - el->el_chared.c_vcmd.pos = 0; - el->el_state.doingarg = 0; - size = el->el_chared.c_undo.ptr - el->el_line.cursor; - if (size < 0) - size = -size; - if (el->el_chared.c_undo.action == (INSERT|DELETE) || - el->el_chared.c_undo.action == DELETE) - el->el_chared.c_undo.dsize = size; - else - el->el_chared.c_undo.isize = size; + /* [Esc] cancels pending action */ + el->el_chared.c_vcmd.action = NOP; + el->el_chared.c_vcmd.pos = 0; - el->el_state.inputmode = MODE_INSERT; - el->el_map.current = el->el_map.alt; + el->el_state.doingarg = 0; + + el->el_state.inputmode = MODE_INSERT; + el->el_map.current = el->el_map.alt; #ifdef VI_MOVE - if (el->el_line.cursor > el->el_line.buffer) - el->el_line.cursor--; + if (el->el_line.cursor > el->el_line.buffer) + el->el_line.cursor--; #endif - return CC_CURSOR; + return (CC_CURSOR); } + /* vi_zero(): - * Vi move to the beginning of line + * Vi move to the beginning of line * [0] */ protected el_action_t -vi_zero(el, c) - EditLine *el; - int c; +vi_zero(EditLine *el, int c) { - if (el->el_state.doingarg) { - if (el->el_state.argument > 1000000) - return CC_ERROR; - el->el_state.argument = - (el->el_state.argument * 10) + (c - '0'); - return CC_ARGHACK; - } - else { + + if (el->el_state.doingarg) + return ed_argument_digit(el, c); + el->el_line.cursor = el->el_line.buffer; - if (el->el_chared.c_vcmd.action & DELETE) { - cv_delfini(el); - return CC_REFRESH; - } - return CC_CURSOR; - } + if (el->el_chared.c_vcmd.action != NOP) { + cv_delfini(el); + return (CC_REFRESH); + } + return (CC_CURSOR); } /* vi_delete_prev_char(): - * Vi move to previous character (backspace) - * [^H] - */ + * Vi move to previous character (backspace) + * [^H] in insert mode only + */ protected el_action_t /*ARGSUSED*/ -vi_delete_prev_char(el, c) - EditLine *el; - int c; +vi_delete_prev_char(EditLine *el, int c __attribute__((__unused__))) { - if (el->el_chared.c_vcmd.ins == 0) - return CC_ERROR; + char *cp; - if (el->el_chared.c_vcmd.ins > - el->el_line.cursor - el->el_state.argument) - return CC_ERROR; + cp = el->el_line.cursor; + if (cp <= el->el_line.buffer) + return (CC_ERROR); - c_delbefore(el, el->el_state.argument); - el->el_line.cursor -= el->el_state.argument; + /* do the delete here so we dont mess up the undo and paste buffers */ + el->el_line.cursor = --cp; + for (; cp < el->el_line.lastchar; cp++) + cp[0] = cp[1]; + el->el_line.lastchar = cp - 1; - return CC_REFRESH; -} /* end v_del_char_prev */ + return (CC_REFRESH); +} /* vi_list_or_eof(): @@ -759,48 +606,56 @@ vi_delete_prev_char(el, c) */ protected el_action_t /*ARGSUSED*/ -vi_list_or_eof(el, c) - EditLine *el; - int c; +vi_list_or_eof(EditLine *el, int c __attribute__((__unused__))) { + + if (el->el_line.cursor == el->el_line.lastchar) { + if (el->el_line.cursor == el->el_line.buffer) { + term_overwrite(el, STReof, 4); /* then do a EOF */ + term__flush(); + return (CC_EOF); + } else { + /* + * Here we could list completions, but it is an + * error right now + */ + term_beep(el); + return (CC_ERROR); + } + } else { #ifdef notyet - if (el->el_line.cursor == el->el_line.lastchar && - el->el_line.cursor == el->el_line.buffer) { -#endif - term_overwrite(el, STReof, 4); /* then do a EOF */ - term__flush(); - return CC_EOF; -#ifdef notyet - } - else { - re_goto_bottom(el); - *el->el_line.lastchar = '\0'; /* just in case */ - return CC_LIST_CHOICES; - } + re_goto_bottom(el); + *el->el_line.lastchar = '\0'; /* just in case */ + return (CC_LIST_CHOICES); +#else + /* + * Just complain for now. + */ + term_beep(el); + return (CC_ERROR); #endif + } } /* vi_kill_line_prev(): - * Vi cut from beginning of line to cursor + * Vi cut from beginning of line to cursor * [^U] */ protected el_action_t /*ARGSUSED*/ -vi_kill_line_prev(el, c) - EditLine *el; - int c; +vi_kill_line_prev(EditLine *el, int c __attribute__((__unused__))) { - char *kp, *cp; - - cp = el->el_line.buffer; - kp = el->el_chared.c_kill.buf; - while (cp < el->el_line.cursor) - *kp++ = *cp++; /* copy it */ - el->el_chared.c_kill.last = kp; - c_delbefore(el, el->el_line.cursor - el->el_line.buffer); - el->el_line.cursor = el->el_line.buffer; /* zap! */ - return CC_REFRESH; + char *kp, *cp; + + cp = el->el_line.buffer; + kp = el->el_chared.c_kill.buf; + while (cp < el->el_line.cursor) + *kp++ = *cp++; /* copy it */ + el->el_chared.c_kill.last = kp; + c_delbefore(el, el->el_line.cursor - el->el_line.buffer); + el->el_line.cursor = el->el_line.buffer; /* zap! */ + return (CC_REFRESH); } @@ -810,11 +665,10 @@ vi_kill_line_prev(el, c) */ protected el_action_t /*ARGSUSED*/ -vi_search_prev(el, c) - EditLine *el; - int c; +vi_search_prev(EditLine *el, int c __attribute__((__unused__))) { - return cv_search(el, ED_SEARCH_PREV_HISTORY); + + return (cv_search(el, ED_SEARCH_PREV_HISTORY)); } @@ -824,11 +678,10 @@ vi_search_prev(el, c) */ protected el_action_t /*ARGSUSED*/ -vi_search_next(el, c) - EditLine *el; - int c; +vi_search_next(EditLine *el, int c __attribute__((__unused__))) { - return cv_search(el, ED_SEARCH_NEXT_HISTORY); + + return (cv_search(el, ED_SEARCH_NEXT_HISTORY)); } @@ -838,14 +691,13 @@ vi_search_next(el, c) */ protected el_action_t /*ARGSUSED*/ -vi_repeat_search_next(el, c) - EditLine *el; - int c; +vi_repeat_search_next(EditLine *el, int c __attribute__((__unused__))) { - if (el->el_search.patlen == 0) - return CC_ERROR; - else - return cv_repeat_srch(el, el->el_search.patdir); + + if (el->el_search.patlen == 0) + return (CC_ERROR); + else + return (cv_repeat_srch(el, el->el_search.patdir)); } @@ -855,16 +707,15 @@ vi_repeat_search_next(el, c) */ /*ARGSUSED*/ protected el_action_t -vi_repeat_search_prev(el, c) - EditLine *el; - int c; +vi_repeat_search_prev(EditLine *el, int c __attribute__((__unused__))) { - if (el->el_search.patlen == 0) - return CC_ERROR; - else - return cv_repeat_srch(el, - el->el_search.patdir == ED_SEARCH_PREV_HISTORY ? - ED_SEARCH_NEXT_HISTORY : ED_SEARCH_PREV_HISTORY); + + if (el->el_search.patlen == 0) + return (CC_ERROR); + else + return (cv_repeat_srch(el, + el->el_search.patdir == ED_SEARCH_PREV_HISTORY ? + ED_SEARCH_NEXT_HISTORY : ED_SEARCH_PREV_HISTORY)); } @@ -874,20 +725,9 @@ vi_repeat_search_prev(el, c) */ protected el_action_t /*ARGSUSED*/ -vi_next_char(el, c) - EditLine *el; - int c; +vi_next_char(EditLine *el, int c __attribute__((__unused__))) { - char ch; - - if (el_getc(el, &ch) != 1) - return ed_end_of_file(el, 0); - - el->el_search.chadir = CHAR_FWD; - el->el_search.chacha = ch; - - return cv_csearch_fwd(el, ch, el->el_state.argument, 0); - + return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 0); } @@ -897,19 +737,9 @@ vi_next_char(el, c) */ protected el_action_t /*ARGSUSED*/ -vi_prev_char(el, c) - EditLine *el; - int c; +vi_prev_char(EditLine *el, int c __attribute__((__unused__))) { - char ch; - - if (el_getc(el, &ch) != 1) - return ed_end_of_file(el, 0); - - el->el_search.chadir = CHAR_BACK; - el->el_search.chacha = ch; - - return cv_csearch_back(el, ch, el->el_state.argument, 0); + return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 0); } @@ -919,17 +749,9 @@ vi_prev_char(el, c) */ protected el_action_t /*ARGSUSED*/ -vi_to_next_char(el, c) - EditLine *el; - int c; +vi_to_next_char(EditLine *el, int c __attribute__((__unused__))) { - char ch; - - if (el_getc(el, &ch) != 1) - return ed_end_of_file(el, 0); - - return cv_csearch_fwd(el, ch, el->el_state.argument, 1); - + return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 1); } @@ -939,15 +761,9 @@ vi_to_next_char(el, c) */ protected el_action_t /*ARGSUSED*/ -vi_to_prev_char(el, c) - EditLine *el; - int c; +vi_to_prev_char(EditLine *el, int c __attribute__((__unused__))) { - char ch; - if (el_getc(el, &ch) != 1) - return ed_end_of_file(el, 0); - - return cv_csearch_back(el, ch, el->el_state.argument, 1); + return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 1); } @@ -957,16 +773,11 @@ vi_to_prev_char(el, c) */ protected el_action_t /*ARGSUSED*/ -vi_repeat_next_char(el, c) - EditLine *el; - int c; +vi_repeat_next_char(EditLine *el, int c __attribute__((__unused__))) { - if (el->el_search.chacha == 0) - return CC_ERROR; - return el->el_search.chadir == CHAR_FWD ? - cv_csearch_fwd(el, el->el_search.chacha, el->el_state.argument, 0) : - cv_csearch_back(el, el->el_search.chacha, el->el_state.argument, 0); + return cv_csearch(el, el->el_search.chadir, el->el_search.chacha, + el->el_state.argument, el->el_search.chatflg); } @@ -976,14 +787,345 @@ vi_repeat_next_char(el, c) */ protected el_action_t /*ARGSUSED*/ -vi_repeat_prev_char(el, c) - EditLine *el; - int c; +vi_repeat_prev_char(EditLine *el, int c __attribute__((__unused__))) +{ + el_action_t r; + int dir = el->el_search.chadir; + + r = cv_csearch(el, -dir, el->el_search.chacha, + el->el_state.argument, el->el_search.chatflg); + el->el_search.chadir = dir; + return r; +} + + +/* vi_match(): + * Vi go to matching () {} or [] + * [%] + */ +protected el_action_t +/*ARGSUSED*/ +vi_match(EditLine *el, int c) +{ + const char match_chars[] = "()[]{}"; + char *cp; + int delta, i, count; + char o_ch, c_ch; + + *el->el_line.lastchar = '\0'; /* just in case */ + + i = strcspn(el->el_line.cursor, match_chars); + o_ch = el->el_line.cursor[i]; + if (o_ch == 0) + return CC_ERROR; + delta = strchr(match_chars, o_ch) - match_chars; + c_ch = match_chars[delta ^ 1]; + count = 1; + delta = 1 - (delta & 1) * 2; + + for (cp = &el->el_line.cursor[i]; count; ) { + cp += delta; + if (cp < el->el_line.buffer || cp >= el->el_line.lastchar) + return CC_ERROR; + if (*cp == o_ch) + count++; + else if (*cp == c_ch) + count--; + } + + el->el_line.cursor = cp; + + if (el->el_chared.c_vcmd.action != NOP) { + /* NB posix says char under cursor should NOT be deleted + for -ve delta - this is different to netbsd vi. */ + if (delta > 0) + el->el_line.cursor++; + cv_delfini(el); + return (CC_REFRESH); + } + return (CC_CURSOR); +} + +/* vi_undo_line(): + * Vi undo all changes to line + * [U] + */ +protected el_action_t +/*ARGSUSED*/ +vi_undo_line(EditLine *el, int c) +{ + + cv_undo(el); + return hist_get(el); +} + +/* vi_to_column(): + * Vi go to specified column + * [|] + * NB netbsd vi goes to screen column 'n', posix says nth character + */ +protected el_action_t +/*ARGSUSED*/ +vi_to_column(EditLine *el, int c) +{ + + el->el_line.cursor = el->el_line.buffer; + el->el_state.argument--; + return ed_next_char(el, 0); +} + +/* vi_yank_end(): + * Vi yank to end of line + * [Y] + */ +protected el_action_t +/*ARGSUSED*/ +vi_yank_end(EditLine *el, int c) +{ + + cv_yank(el, el->el_line.cursor, + el->el_line.lastchar - el->el_line.cursor); + return CC_REFRESH; +} + +/* vi_yank(): + * Vi yank + * [y] + */ +protected el_action_t +/*ARGSUSED*/ +vi_yank(EditLine *el, int c) +{ + + return cv_action(el, YANK); +} + +/* vi_comment_out(): + * Vi comment out current command + * [c] + */ +protected el_action_t +/*ARGSUSED*/ +vi_comment_out(EditLine *el, int c) +{ + + el->el_line.cursor = el->el_line.buffer; + c_insert(el, 1); + *el->el_line.cursor = '#'; + re_refresh(el); + return ed_newline(el, 0); +} + +/* vi_alias(): + * Vi include shell alias + * [@] + * NB: posix impiles that we should enter insert mode, however + * this is against historical precedent... + */ +protected el_action_t +/*ARGSUSED*/ +vi_alias(EditLine *el, int c) { - if (el->el_search.chacha == 0) +#ifdef __weak_extern + char alias_name[3]; + char *alias_text; + extern char *get_alias_text(const char *); + __weak_extern(get_alias_text); + + if (get_alias_text == 0) { + return CC_ERROR; + } + + alias_name[0] = '_'; + alias_name[2] = 0; + if (el_getc(el, &alias_name[1]) != 1) + return CC_ERROR; + + alias_text = get_alias_text(alias_name); + if (alias_text != NULL) + el_push(el, alias_text); + return CC_NORM; +#else return CC_ERROR; +#endif +} + +/* vi_to_history_line(): + * Vi go to specified history file line. + * [G] + */ +protected el_action_t +/*ARGSUSED*/ +vi_to_history_line(EditLine *el, int c) +{ + int sv_event_no = el->el_history.eventno; + el_action_t rval; + + + if (el->el_history.eventno == 0) { + (void) strncpy(el->el_history.buf, el->el_line.buffer, + EL_BUFSIZ); + el->el_history.last = el->el_history.buf + + (el->el_line.lastchar - el->el_line.buffer); + } + + /* Lack of a 'count' means oldest, not 1 */ + if (!el->el_state.doingarg) { + el->el_history.eventno = 0x7fffffff; + hist_get(el); + } else { + /* This is brain dead, all the rest of this code counts + * upwards going into the past. Here we need count in the + * other direction (to match the output of fc -l). + * I could change the world, but this seems to suffice. + */ + el->el_history.eventno = 1; + if (hist_get(el) == CC_ERROR) + return CC_ERROR; + el->el_history.eventno = 1 + el->el_history.ev.num + - el->el_state.argument; + if (el->el_history.eventno < 0) { + el->el_history.eventno = sv_event_no; + return CC_ERROR; + } + } + rval = hist_get(el); + if (rval == CC_ERROR) + el->el_history.eventno = sv_event_no; + return rval; +} + +/* vi_histedit(): + * Vi edit history line with vi + * [v] + */ +protected el_action_t +/*ARGSUSED*/ +vi_histedit(EditLine *el, int c) +{ + int fd; + pid_t pid; + int st; + char tempfile[] = "/tmp/histedit.XXXXXXXXXX"; + char *cp; + + if (el->el_state.doingarg) { + if (vi_to_history_line(el, 0) == CC_ERROR) + return CC_ERROR; + } + + fd = mkstemp(tempfile); + if (fd < 0) + return CC_ERROR; + cp = el->el_line.buffer; + write(fd, cp, el->el_line.lastchar - cp +0u); + write(fd, "\n", 1); + pid = fork(); + switch (pid) { + case -1: + close(fd); + unlink(tempfile); + return CC_ERROR; + case 0: + close(fd); + execlp("vi", "vi", tempfile, (char*)NULL); + exit(0); + /*NOTREACHED*/ + default: + while (waitpid(pid, &st, 0) != pid) + continue; + lseek(fd, 0ll, SEEK_SET); + st = read(fd, cp, el->el_line.limit - cp +0u); + if (st > 0 && cp[st - 1] == '\n') + st--; + el->el_line.cursor = cp; + el->el_line.lastchar = cp + st; + break; + } + + close(fd); + unlink(tempfile); + /* return CC_REFRESH; */ + return ed_newline(el, 0); +} + +/* vi_history_word(): + * Vi append word from previous input line + * [_] + * Who knows where this one came from! + * '_' in vi means 'entire current line', so 'cc' is a synonym for 'c_' + */ +protected el_action_t +/*ARGSUSED*/ +vi_history_word(EditLine *el, int c) +{ + const char *wp = HIST_FIRST(el); + const char *wep, *wsp; + int len; + char *cp; + const char *lim; + + if (wp == NULL) + return CC_ERROR; + + wep = wsp = 0; + do { + while (isspace((unsigned char)*wp)) + wp++; + if (*wp == 0) + break; + wsp = wp; + while (*wp && !isspace((unsigned char)*wp)) + wp++; + wep = wp; + } while ((!el->el_state.doingarg || --el->el_state.argument > 0) && *wp != 0); + + if (wsp == 0 || (el->el_state.doingarg && el->el_state.argument != 0)) + return CC_ERROR; + + cv_undo(el); + len = wep - wsp; + if (el->el_line.cursor < el->el_line.lastchar) + el->el_line.cursor++; + c_insert(el, len + 1); + cp = el->el_line.cursor; + lim = el->el_line.limit; + if (cp < lim) + *cp++ = ' '; + while (wsp < wep && cp < lim) + *cp++ = *wsp++; + el->el_line.cursor = cp; + + el->el_map.current = el->el_map.key; + return CC_REFRESH; +} + +/* vi_redo(): + * Vi redo last non-motion command + * [.] + */ +protected el_action_t +/*ARGSUSED*/ +vi_redo(EditLine *el, int c) +{ + c_redo_t *r = &el->el_chared.c_redo; + + if (!el->el_state.doingarg && r->count) { + el->el_state.doingarg = 1; + el->el_state.argument = r->count; + } + + el->el_chared.c_vcmd.pos = el->el_line.cursor; + el->el_chared.c_vcmd.action = r->action; + if (r->pos != r->buf) { + if (r->pos + 1 > r->lim) + /* sanity */ + r->pos = r->lim - 1; + r->pos[0] = 0; + el_push(el, r->buf); + } - return el->el_search.chadir == CHAR_BACK ? - cv_csearch_fwd(el, el->el_search.chacha, el->el_state.argument, 0) : - cv_csearch_back(el, el->el_search.chacha, el->el_state.argument, 0); + el->el_state.thiscmd = r->cmd; + el->el_state.thisch = r->ch; + return (*el->el_map.func[r->cmd])(el, r->ch); } -- cgit v1.2.3