From 76d00450e675825131c7cd211e274537cd42a542 Mon Sep 17 00:00:00 2001 From: Stefan Farfeleder Date: Sun, 7 Aug 2005 20:55:59 +0000 Subject: Sync libedit with recent NetBSD developments. Including improvements to the vi-mode, removal of clause 3, cleanups and the export of the tokenization functions. Not included: config.h, filecomplete.{c,h} --- lib/libedit/Makefile | 8 +- lib/libedit/TEST/test.c | 82 +++-- lib/libedit/chared.c | 343 ++++++++++++-------- lib/libedit/chared.h | 54 ++-- lib/libedit/common.c | 217 ++++++------- lib/libedit/editline.3 | 190 ++++++++++- lib/libedit/editrc.5 | 36 ++- lib/libedit/el.c | 127 ++++++-- lib/libedit/el.h | 35 +- lib/libedit/emacs.c | 104 +++--- lib/libedit/hist.c | 59 ++-- lib/libedit/hist.h | 12 +- lib/libedit/history.c | 258 +++++++++++---- lib/libedit/key.c | 50 +-- lib/libedit/key.h | 23 +- lib/libedit/makelist | 10 +- lib/libedit/map.c | 310 +++++++++--------- lib/libedit/map.h | 10 +- lib/libedit/parse.c | 36 ++- lib/libedit/parse.h | 10 +- lib/libedit/prompt.c | 14 +- lib/libedit/prompt.h | 8 +- lib/libedit/read.c | 215 +++++++++---- lib/libedit/read.h | 58 ++++ lib/libedit/refresh.c | 54 ++-- lib/libedit/refresh.h | 8 +- lib/libedit/search.c | 194 ++++++------ lib/libedit/search.h | 14 +- lib/libedit/sig.c | 14 +- lib/libedit/sig.h | 11 +- lib/libedit/sys.h | 19 +- lib/libedit/term.c | 68 ++-- lib/libedit/term.h | 29 +- lib/libedit/tokenizer.c | 128 +++++--- lib/libedit/tokenizer.h | 54 ---- lib/libedit/tty.c | 155 ++++++++- lib/libedit/tty.h | 16 +- lib/libedit/vi.c | 823 +++++++++++++++++++++++++++++------------------- 38 files changed, 2374 insertions(+), 1482 deletions(-) create mode 100644 lib/libedit/read.h delete mode 100644 lib/libedit/tokenizer.h (limited to 'lib') diff --git a/lib/libedit/Makefile b/lib/libedit/Makefile index dcd79eae2f5a..5ec70efc7a85 100644 --- a/lib/libedit/Makefile +++ b/lib/libedit/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.19 2000/08/15 12:01:40 mrg Exp $ +# $NetBSD: Makefile,v 1.34 2005/05/28 12:02:53 lukem Exp $ # @(#)Makefile 8.1 (Berkeley) 6/4/93 # $FreeBSD$ @@ -20,7 +20,9 @@ MLINKS= editline.3 el_deletestr.3 editline.3 el_end.3 editline.3 el_init.3 \ editline.3 history_init.3 editline.3 el_insertstr.3 \ editline.3 el_line.3 editline.3 el_parse.3 editline.3 el_push.3 \ editline.3 el_reset.3 editline.3 el_resize.3 editline.3 el_set.3 \ - editline.3 el_source.3 + editline.3 el_source.3 \ + editline.3 tok_init.3 editline.3 tok_end.3 editline.3 tok_reset.3 \ + editline.3 tok_line.3 editline.3 tok_str.3 # For speed and debugging #SRCS= ${OSRCS} tokenizer.c history.c @@ -31,7 +33,7 @@ CLEANFILES+= common.h editline.c emacs.h fcns.c fcns.h help.c help.h vi.h CFLAGS+= -I. -I${.CURDIR} CFLAGS+= #-DDEBUG_TTY -DDEBUG_KEY -DDEBUG_READ -DDEBUG -DDEBUG_REFRESH -CFLAGS+= #-DDEBUG_PASTE +CFLAGS+= #-DDEBUG_PASTE -DDEBUG_EDIT AHDR= vi.h emacs.h common.h ASRC= ${.CURDIR}/vi.c ${.CURDIR}/emacs.c ${.CURDIR}/common.c diff --git a/lib/libedit/TEST/test.c b/lib/libedit/TEST/test.c index d7b4df52336f..facbdaa7e3df 100644 --- a/lib/libedit/TEST/test.c +++ b/lib/libedit/TEST/test.c @@ -13,11 +13,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -43,7 +39,7 @@ __COPYRIGHT("@(#) Copyright (c) 1992, 1993\n\ #if !defined(lint) && !defined(SCCSID) static char sccsid[] = "@(#)test.c 8.1 (Berkeley) 6/4/93"; #endif /* not lint && not SCCSID */ -__RCSID("$NetBSD: test.c,v 1.8 1999/09/21 00:07:03 lukem Exp $"); +__RCSID("$NetBSD: test.c,v 1.18 2005/06/01 11:37:52 lukem Exp $"); __FBSDID("$FreeBSD$"); /* @@ -60,12 +56,11 @@ __FBSDID("$FreeBSD$"); #include #include "histedit.h" -#include "tokenizer.h" static int continuation = 0; -static EditLine *el = NULL; +volatile sig_atomic_t gotsig = 0; -static u_char complete(EditLine *, int); +static unsigned char complete(EditLine *, int); int main(int, char **); static char *prompt(EditLine *); static void sig(int); @@ -73,8 +68,8 @@ static void sig(int); static char * prompt(EditLine *el) { - static char a[] = "Edit$"; - static char b[] = "Edit>"; + static char a[] = "Edit$ "; + static char b[] = "Edit> "; return (continuation ? b : a); } @@ -82,9 +77,7 @@ prompt(EditLine *el) static void sig(int i) { - - (void) fprintf(stderr, "Got signal %d.\n", i); - el_reset(el); + gotsig = i; } static unsigned char @@ -99,7 +92,8 @@ complete(EditLine *el, int ch) /* * Find the last word */ - for (ptr = lf->cursor - 1; !isspace(*ptr) && ptr > lf->buffer; ptr--) + for (ptr = lf->cursor - 1; + !isspace((unsigned char)*ptr) && ptr > lf->buffer; ptr--) continue; len = lf->cursor - ++ptr; @@ -122,10 +116,14 @@ complete(EditLine *el, int ch) int main(int argc, char *argv[]) { + EditLine *el = NULL; int num; const char *buf; Tokenizer *tok; - int lastevent = 0, ncontinuation; +#if 0 + int lastevent = 0; +#endif + int ncontinuation; History *hist; HistEvent ev; @@ -169,17 +167,41 @@ main(int argc, char *argv[]) el_source(el, NULL); while ((buf = el_gets(el, &num)) != NULL && num != 0) { - int ac; - char **av; + int ac, cc, co; #ifdef DEBUG - (void) fprintf(stderr, "got %d %s", num, buf); + int i; #endif + const char **av; + const LineInfo *li; + li = el_line(el); +#ifdef DEBUG + (void) fprintf(stderr, "==> got %d %s", num, buf); + (void) fprintf(stderr, " > li `%.*s_%.*s'\n", + (li->cursor - li->buffer), li->buffer, + (li->lastchar - 1 - li->cursor), + (li->cursor >= li->lastchar) ? "" : li->cursor); + +#endif + if (gotsig) { + (void) fprintf(stderr, "Got signal %d.\n", gotsig); + gotsig = 0; + el_reset(el); + } + if (!continuation && num == 1) continue; - if (tok_line(tok, buf, &ac, &av) > 0) - ncontinuation = 1; - + ac = cc = co = 0; + ncontinuation = tok_line(tok, li, &ac, &av, &cc, &co); + if (ncontinuation < 0) { + (void) fprintf(stderr, "Internal error\n"); + continuation = 0; + continue; + } +#ifdef DEBUG + (void) fprintf(stderr, " > nc %d ac %d cc %d co %d\n", + ncontinuation, ac, cc, co); +#endif #if 0 if (continuation) { /* @@ -187,7 +209,7 @@ main(int argc, char *argv[]) * moved around in history. */ if (history(hist, &ev, H_SET, lastevent) == -1) - err(1, "%d: %s\n", lastevent, ev.str); + err(1, "%d: %s", lastevent, ev.str); history(hist, &ev, H_ADD , buf); } else { history(hist, &ev, H_ENTER, buf); @@ -200,6 +222,18 @@ main(int argc, char *argv[]) continuation = ncontinuation; ncontinuation = 0; + if (continuation) + continue; +#ifdef DEBUG + for (i = 0; i < ac; i++) { + (void) fprintf(stderr, " > arg# %2d ", i); + if (i != cc) + (void) fprintf(stderr, "`%s'\n", av[i]); + else + (void) fprintf(stderr, "`%.*s_%s'\n", + co, av[i], av[i] + co); + } +#endif if (strcmp(av[0], "history") == 0) { int rv; @@ -235,7 +269,7 @@ main(int argc, char *argv[]) } else if (el_parse(el, ac, av) == -1) { switch (fork()) { case 0: - execvp(av[0], av); + execvp(av[0], __DECONST(char *const *, av)); perror(av[0]); _exit(1); /*NOTREACHED*/ diff --git a/lib/libedit/chared.c b/lib/libedit/chared.c index 8efb35d3be47..6bbfcf877460 100644 --- a/lib/libedit/chared.c +++ b/lib/libedit/chared.c @@ -13,11 +13,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -33,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $NetBSD: chared.c,v 1.13 2001/04/13 01:04:19 lukem Exp $ + * $NetBSD: chared.c,v 1.24 2005/08/01 23:00:15 christos Exp $ */ #if !defined(lint) && !defined(SCCSID) @@ -50,6 +46,8 @@ __FBSDID("$FreeBSD$"); #include #include "el.h" +private void ch__clearmacro(EditLine *); + /* value to leave unused in line buffer */ #define EL_LEAVE 2 @@ -57,17 +55,36 @@ __FBSDID("$FreeBSD$"); * Handle state for the vi undo command */ protected void -cv_undo(EditLine *el,int action, size_t size, char *ptr) +cv_undo(EditLine *el) { c_undo_t *vu = &el->el_chared.c_undo; - vu->action = action; - vu->ptr = ptr; - vu->isize = size; - (void) memcpy(vu->buf, vu->ptr, size); -#ifdef DEBUG_UNDO - (void) fprintf(el->el_errfile, "Undo buffer \"%s\" size = +%d -%d\n", - vu->ptr, vu->isize, vu->dsize); -#endif + c_redo_t *r = &el->el_chared.c_redo; + unsigned int size; + + /* Save entire line for undo */ + size = el->el_line.lastchar - el->el_line.buffer; + vu->len = size; + vu->cursor = el->el_line.cursor - el->el_line.buffer; + memcpy(vu->buf, el->el_line.buffer, size); + + /* save command info for redo */ + r->count = el->el_state.doingarg ? el->el_state.argument : 0; + r->action = el->el_chared.c_vcmd.action; + r->pos = r->buf; + r->cmd = el->el_state.thiscmd; + r->ch = el->el_state.thisch; +} + +/* cv_yank(): + * Save yank/delete data for paste + */ +protected void +cv_yank(EditLine *el, const char *ptr, int size) +{ + c_kill_t *k = &el->el_chared.c_kill; + + memcpy(k->buf, ptr, size +0u); + k->last = k->buf + size; } @@ -79,8 +96,10 @@ c_insert(EditLine *el, int num) { char *cp; - if (el->el_line.lastchar + num >= el->el_line.limit) - return; /* can't go past end of buffer */ + if (el->el_line.lastchar + num >= el->el_line.limit) { + if (!ch_enlargebufs(el, num +0u)) + return; /* can't go past end of buffer */ + } if (el->el_line.cursor < el->el_line.lastchar) { /* if I must move chars */ @@ -101,12 +120,14 @@ c_delafter(EditLine *el, int num) if (el->el_line.cursor + num > el->el_line.lastchar) num = el->el_line.lastchar - el->el_line.cursor; + if (el->el_map.current != el->el_map.emacs) { + cv_undo(el); + cv_yank(el, el->el_line.cursor, num); + } + if (num > 0) { char *cp; - if (el->el_map.current != el->el_map.emacs) - cv_undo(el, INSERT, (size_t)num, el->el_line.cursor); - for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++) *cp = cp[num]; @@ -115,6 +136,21 @@ c_delafter(EditLine *el, int num) } +/* c_delafter1(): + * Delete the character after the cursor, do not yank + */ +protected void +c_delafter1(EditLine *el) +{ + char *cp; + + for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++) + *cp = cp[1]; + + el->el_line.lastchar--; +} + + /* c_delbefore(): * Delete num characters before the cursor */ @@ -125,13 +161,14 @@ c_delbefore(EditLine *el, int num) if (el->el_line.cursor - num < el->el_line.buffer) num = el->el_line.cursor - el->el_line.buffer; + if (el->el_map.current != el->el_map.emacs) { + cv_undo(el); + cv_yank(el, el->el_line.cursor - num, num); + } + if (num > 0) { char *cp; - if (el->el_map.current != el->el_map.emacs) - cv_undo(el, INSERT, (size_t)num, - el->el_line.cursor - num); - for (cp = el->el_line.cursor - num; cp <= el->el_line.lastchar; cp++) @@ -142,38 +179,52 @@ c_delbefore(EditLine *el, int num) } +/* c_delbefore1(): + * Delete the character before the cursor, do not yank + */ +protected void +c_delbefore1(EditLine *el) +{ + char *cp; + + for (cp = el->el_line.cursor - 1; cp <= el->el_line.lastchar; cp++) + *cp = cp[1]; + + el->el_line.lastchar--; +} + + /* ce__isword(): * Return if p is part of a word according to emacs */ protected int ce__isword(int p) { - return (isalpha((unsigned char)p) || isdigit((unsigned char)p) || strchr("*?_-.[]~=", p) != NULL); + return (isalnum(p) || strchr("*?_-.[]~=", p) != NULL); } /* cv__isword(): - * Return type of word for p according to vi + * Return if p is part of a word according to vi */ protected int cv__isword(int p) { - if (isspace((unsigned char) p)) - return 0; - if ((unsigned char) p == '_' || isalnum((unsigned char) p)) - return 1; - return 2; + if (isalnum(p) || p == '_') + return 1; + if (isgraph(p)) + return 2; + return 0; } -/* c___isword(): - * Return if p is part of a space-delimited word (!isspace) +/* cv__isWord(): + * Return if p is part of a big word according to vi */ protected int -c___isword(p) - int p; +cv__isWord(int p) { - return !isspace((unsigned char) p); + return (!isspace(p)); } @@ -235,7 +286,7 @@ cv_next_word(EditLine *el, char *p, char *high, int n, int (*wtest)(int)) * vi historically deletes with cw only the word preserving the * trailing whitespace! This is not what 'w' does.. */ - if (el->el_chared.c_vcmd.action != (DELETE|INSERT)) + if (n || el->el_chared.c_vcmd.action != (DELETE|INSERT)) while ((p < high) && isspace((unsigned char) *p)) p++; } @@ -252,26 +303,19 @@ cv_next_word(EditLine *el, char *p, char *high, int n, int (*wtest)(int)) * Find the previous word vi style */ protected char * -cv_prev_word(EditLine *el, char *p, char *low, int n, int (*wtest)(int)) +cv_prev_word(char *p, char *low, int n, int (*wtest)(int)) { int test; + p--; while (n--) { - p--; - /* - * vi historically deletes with cb only the word preserving the - * leading whitespace! This is not what 'b' does.. - */ - if (el->el_chared.c_vcmd.action != (DELETE|INSERT)) - while ((p > low) && isspace((unsigned char) *p)) - p--; + while ((p > low) && isspace((unsigned char) *p)) + p--; test = (*wtest)((unsigned char) *p); while ((p >= low) && (*wtest)((unsigned char) *p) == test) p--; - p++; - while (isspace((unsigned char) *p)) - p++; } + p++; /* p now points where we want it */ if (p < low) @@ -322,47 +366,34 @@ protected void cv_delfini(EditLine *el) { int size; - int oaction; + int action = el->el_chared.c_vcmd.action; - if (el->el_chared.c_vcmd.action & INSERT) + if (action & INSERT) el->el_map.current = el->el_map.key; - oaction = el->el_chared.c_vcmd.action; - el->el_chared.c_vcmd.action = NOP; - if (el->el_chared.c_vcmd.pos == 0) + /* sanity */ return; - - if (el->el_line.cursor > el->el_chared.c_vcmd.pos) { - size = (int) (el->el_line.cursor - el->el_chared.c_vcmd.pos); - c_delbefore(el, size); - el->el_line.cursor = el->el_chared.c_vcmd.pos; - re_refresh_cursor(el); - } else if (el->el_line.cursor < el->el_chared.c_vcmd.pos) { - size = (int)(el->el_chared.c_vcmd.pos - el->el_line.cursor); - c_delafter(el, size); - } else { + size = el->el_line.cursor - el->el_chared.c_vcmd.pos; + if (size == 0) size = 1; - c_delafter(el, size); - } - switch (oaction) { - case DELETE|INSERT: - el->el_chared.c_undo.action = DELETE|INSERT; - break; - case DELETE: - el->el_chared.c_undo.action = INSERT; - break; - case NOP: - case INSERT: - default: - EL_ABORT((el->el_errfile, "Bad oaction %d\n", oaction)); - break; + el->el_line.cursor = el->el_chared.c_vcmd.pos; + if (action & YANK) { + if (size > 0) + cv_yank(el, el->el_line.cursor, size); + else + cv_yank(el, el->el_line.cursor + size, -size); + } else { + if (size > 0) { + c_delafter(el, size); + re_refresh_cursor(el); + } else { + c_delbefore(el, -size); + el->el_line.cursor += size; + } } - - - el->el_chared.c_undo.ptr = el->el_line.cursor; - el->el_chared.c_undo.dsize = size; + el->el_chared.c_vcmd.action = NOP; } @@ -392,21 +423,19 @@ ce__endword(char *p, char *high, int n) * Go to the end of this word according to vi */ protected char * -cv__endword(char *p, char *high, int n) +cv__endword(char *p, char *high, int n, int (*wtest)(int)) { + int test; + p++; while (n--) { while ((p < high) && isspace((unsigned char) *p)) p++; - if (isalnum((unsigned char) *p)) - while ((p < high) && isalnum((unsigned char) *p)) - p++; - else - while ((p < high) && !(isspace((unsigned char) *p) || - isalnum((unsigned char) *p))) - p++; + test = (*wtest)((unsigned char) *p); + while ((p < high) && (*wtest)((unsigned char) *p) == test) + p++; } p--; return (p); @@ -418,6 +447,8 @@ cv__endword(char *p, char *high, int n) protected int ch_init(EditLine *el) { + c_macro_t *ma = &el->el_chared.c_macro; + el->el_line.buffer = (char *) el_malloc(EL_BUFSIZ); if (el->el_line.buffer == NULL) return (-1); @@ -425,20 +456,23 @@ ch_init(EditLine *el) (void) memset(el->el_line.buffer, 0, EL_BUFSIZ); el->el_line.cursor = el->el_line.buffer; el->el_line.lastchar = el->el_line.buffer; - el->el_line.limit = &el->el_line.buffer[EL_BUFSIZ - 2]; + el->el_line.limit = &el->el_line.buffer[EL_BUFSIZ - EL_LEAVE]; el->el_chared.c_undo.buf = (char *) el_malloc(EL_BUFSIZ); if (el->el_chared.c_undo.buf == NULL) return (-1); (void) memset(el->el_chared.c_undo.buf, 0, EL_BUFSIZ); - el->el_chared.c_undo.action = NOP; - el->el_chared.c_undo.isize = 0; - el->el_chared.c_undo.dsize = 0; - el->el_chared.c_undo.ptr = el->el_line.buffer; + el->el_chared.c_undo.len = -1; + el->el_chared.c_undo.cursor = 0; + el->el_chared.c_redo.buf = (char *) el_malloc(EL_BUFSIZ); + if (el->el_chared.c_redo.buf == NULL) + return (-1); + el->el_chared.c_redo.pos = el->el_chared.c_redo.buf; + el->el_chared.c_redo.lim = el->el_chared.c_redo.buf + EL_BUFSIZ; + el->el_chared.c_redo.cmd = ED_UNASSIGNED; el->el_chared.c_vcmd.action = NOP; el->el_chared.c_vcmd.pos = el->el_line.buffer; - el->el_chared.c_vcmd.ins = el->el_line.buffer; el->el_chared.c_kill.buf = (char *) el_malloc(EL_BUFSIZ); if (el->el_chared.c_kill.buf == NULL) @@ -455,11 +489,10 @@ ch_init(EditLine *el) el->el_state.argument = 1; el->el_state.lastcmd = ED_UNASSIGNED; - el->el_chared.c_macro.nline = NULL; - el->el_chared.c_macro.level = -1; - el->el_chared.c_macro.macro = (char **) el_malloc(EL_MAXMACRO * - sizeof(char *)); - if (el->el_chared.c_macro.macro == NULL) + ma->level = -1; + ma->offset = 0; + ma->macro = (char **) el_malloc(EL_MAXMACRO * sizeof(char *)); + if (ma->macro == NULL) return (-1); return (0); } @@ -468,19 +501,16 @@ ch_init(EditLine *el) * Reset the character editor */ protected void -ch_reset(EditLine *el) +ch_reset(EditLine *el, int mclear) { el->el_line.cursor = el->el_line.buffer; el->el_line.lastchar = el->el_line.buffer; - el->el_chared.c_undo.action = NOP; - el->el_chared.c_undo.isize = 0; - el->el_chared.c_undo.dsize = 0; - el->el_chared.c_undo.ptr = el->el_line.buffer; + el->el_chared.c_undo.len = -1; + el->el_chared.c_undo.cursor = 0; el->el_chared.c_vcmd.action = NOP; el->el_chared.c_vcmd.pos = el->el_line.buffer; - el->el_chared.c_vcmd.ins = el->el_line.buffer; el->el_chared.c_kill.mark = el->el_line.buffer; @@ -492,9 +522,17 @@ ch_reset(EditLine *el) el->el_state.argument = 1; el->el_state.lastcmd = ED_UNASSIGNED; - el->el_chared.c_macro.level = -1; + if (mclear) + ch__clearmacro(el); +} - el->el_history.eventno = 0; +private void +ch__clearmacro(el) + EditLine *el; +{ + c_macro_t *ma = &el->el_chared.c_macro; + while (ma->level >= 0) + el_free((ptr_t)ma->macro[ma->level--]); } /* ch_enlargebufs(): @@ -535,7 +573,8 @@ ch_enlargebufs(el, addlen) el->el_line.buffer = newbuffer; el->el_line.cursor = newbuffer + (el->el_line.cursor - oldbuf); el->el_line.lastchar = newbuffer + (el->el_line.lastchar - oldbuf); - el->el_line.limit = &newbuffer[newsz - EL_LEAVE]; + /* don't set new size until all buffers are enlarged */ + el->el_line.limit = &newbuffer[sz - EL_LEAVE]; /* * Reallocate kill buffer. @@ -564,14 +603,22 @@ ch_enlargebufs(el, addlen) /* zero the newly added memory, leave old data in */ (void) memset(&newbuffer[sz], 0, newsz - sz); - - el->el_chared.c_undo.ptr = el->el_line.buffer + - (el->el_chared.c_undo.ptr - oldbuf); el->el_chared.c_undo.buf = newbuffer; + + newbuffer = el_realloc(el->el_chared.c_redo.buf, newsz); + if (!newbuffer) + return 0; + el->el_chared.c_redo.pos = newbuffer + + (el->el_chared.c_redo.pos - el->el_chared.c_redo.buf); + el->el_chared.c_redo.lim = newbuffer + + (el->el_chared.c_redo.lim - el->el_chared.c_redo.buf); + el->el_chared.c_redo.buf = newbuffer; if (!hist_enlargebuf(el, sz, newsz)) return 0; + /* Safe to set enlarged buffer size */ + el->el_line.limit = &el->el_line.buffer[newsz - EL_LEAVE]; return 1; } @@ -586,11 +633,16 @@ ch_end(EditLine *el) el->el_line.limit = NULL; el_free((ptr_t) el->el_chared.c_undo.buf); el->el_chared.c_undo.buf = NULL; + el_free((ptr_t) el->el_chared.c_redo.buf); + el->el_chared.c_redo.buf = NULL; + el->el_chared.c_redo.pos = NULL; + el->el_chared.c_redo.lim = NULL; + el->el_chared.c_redo.cmd = ED_UNASSIGNED; el_free((ptr_t) el->el_chared.c_kill.buf); el->el_chared.c_kill.buf = NULL; + ch_reset(el, 1); el_free((ptr_t) el->el_chared.c_macro.macro); el->el_chared.c_macro.macro = NULL; - ch_reset(el); } @@ -638,51 +690,64 @@ el_deletestr(EditLine *el, int n) * Get a string */ protected int -c_gets(EditLine *el, char *buf) +c_gets(EditLine *el, char *buf, const char *prompt) { char ch; - int len = 0; + int len; + char *cp = el->el_line.buffer; + + if (prompt) { + len = strlen(prompt); + memcpy(cp, prompt, len + 0u); + cp += len; + } + len = 0; + + for (;;) { + el->el_line.cursor = cp; + *cp = ' '; + el->el_line.lastchar = cp + 1; + re_refresh(el); + + if (el_getc(el, &ch) != 1) { + ed_end_of_file(el, 0); + len = -1; + break; + } - for (ch = 0; ch == 0;) { - if (el_getc(el, &ch) != 1) - return (ed_end_of_file(el, 0)); switch (ch) { + case '\010': /* Delete and backspace */ case '\177': - if (len > 1) { - *el->el_line.cursor-- = '\0'; - el->el_line.lastchar = el->el_line.cursor; - buf[len--] = '\0'; - } else { - el->el_line.buffer[0] = '\0'; - el->el_line.lastchar = el->el_line.buffer; - el->el_line.cursor = el->el_line.buffer; - return (CC_REFRESH); + if (len <= 0) { + len = -1; + break; } - re_refresh(el); - ch = 0; - break; + cp--; + continue; case '\033': /* ESC */ case '\r': /* Newline */ case '\n': + buf[len] = ch; break; default: - if (len >= EL_BUFSIZ) + if (len >= EL_BUFSIZ - 16) term_beep(el); else { buf[len++] = ch; - *el->el_line.cursor++ = ch; - el->el_line.lastchar = el->el_line.cursor; + *cp++ = ch; } - re_refresh(el); - ch = 0; - break; + continue; } + break; } - buf[len] = ch; - return (len); + + el->el_line.buffer[0] = '\0'; + el->el_line.lastchar = el->el_line.buffer; + el->el_line.cursor = el->el_line.buffer; + return len; } diff --git a/lib/libedit/chared.h b/lib/libedit/chared.h index 80606bb83192..9ea1416ee0da 100644 --- a/lib/libedit/chared.h +++ b/lib/libedit/chared.h @@ -13,11 +13,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -34,7 +30,7 @@ * SUCH DAMAGE. * * @(#)chared.h 8.1 (Berkeley) 6/4/93 - * $NetBSD: chared.h,v 1.5 2000/09/04 22:06:29 lukem Exp $ + * $NetBSD: chared.h,v 1.15 2005/08/01 23:00:15 christos Exp $ * $FreeBSD$ */ @@ -66,28 +62,36 @@ typedef struct c_macro_t { int level; + int offset; char **macro; - char *nline; } c_macro_t; /* - * Undo information for both vi and emacs + * Undo information for vi - no undo in emacs (yet) */ typedef struct c_undo_t { - int action; - size_t isize; - size_t dsize; - char *ptr; - char *buf; + int len; /* length of saved line */ + int cursor; /* position of saved cursor */ + char *buf; /* full saved text */ } c_undo_t; +/* redo for vi */ +typedef struct c_redo_t { + char *buf; /* redo insert key sequence */ + char *pos; + char *lim; + el_action_t cmd; /* command to redo */ + char ch; /* char that invoked it */ + int count; + int action; /* from cv_action() */ +} c_redo_t; + /* * Current action information for vi */ typedef struct c_vcmd_t { int action; char *pos; - char *ins; } c_vcmd_t; /* @@ -106,6 +110,7 @@ typedef struct c_kill_t { typedef struct el_chared_t { c_undo_t c_undo; c_kill_t c_kill; + c_redo_t c_redo; c_vcmd_t c_vcmd; c_macro_t c_macro; } el_chared_t; @@ -120,10 +125,10 @@ typedef struct el_chared_t { #define NOP 0x00 #define DELETE 0x01 #define INSERT 0x02 -#define CHANGE 0x04 +#define YANK 0x04 -#define CHAR_FWD 0 -#define CHAR_BACK 1 +#define CHAR_FWD (+1) +#define CHAR_BACK (-1) #define MODE_INSERT 0 #define MODE_REPLACE 1 @@ -137,23 +142,26 @@ typedef struct el_chared_t { protected int cv__isword(int); +protected int cv__isWord(int); protected void cv_delfini(EditLine *); -protected char *cv__endword(char *, char *, int); +protected char *cv__endword(char *, char *, int, int (*)(int)); protected int ce__isword(int); -protected int c___isword(int); -protected void cv_undo(EditLine *, int, size_t, char *); +protected void cv_undo(EditLine *); +protected void cv_yank(EditLine *, const char *, int); protected char *cv_next_word(EditLine*, char *, char *, int, int (*)(int)); -protected char *cv_prev_word(EditLine*, char *, char *, int, int (*)(int)); +protected char *cv_prev_word(char *, char *, int, int (*)(int)); protected char *c__next_word(char *, char *, int, int (*)(int)); protected char *c__prev_word(char *, char *, int, int (*)(int)); protected void c_insert(EditLine *, int); protected void c_delbefore(EditLine *, int); +protected void c_delbefore1(EditLine *); protected void c_delafter(EditLine *, int); -protected int c_gets(EditLine *, char *); +protected void c_delafter1(EditLine *); +protected int c_gets(EditLine *, char *, const char *); protected int c_hpos(EditLine *); protected int ch_init(EditLine *); -protected void ch_reset(EditLine *); +protected void ch_reset(EditLine *, int); protected int ch_enlargebufs(EditLine *, size_t); protected void ch_end(EditLine *); diff --git a/lib/libedit/common.c b/lib/libedit/common.c index 145f4b7d6de4..99d4660340e9 100644 --- a/lib/libedit/common.c +++ b/lib/libedit/common.c @@ -13,11 +13,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -33,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $NetBSD: common.c,v 1.9 2000/09/04 22:06:29 lukem Exp $ + * $NetBSD: common.c,v 1.17 2005/08/01 23:00:15 christos Exp $ */ #if !defined(lint) && !defined(SCCSID) @@ -54,7 +50,7 @@ __FBSDID("$FreeBSD$"); */ protected el_action_t /*ARGSUSED*/ -ed_end_of_file(EditLine *el, int c) +ed_end_of_file(EditLine *el, int c __unused) { re_goto_bottom(el); @@ -70,7 +66,7 @@ ed_end_of_file(EditLine *el, int c) protected el_action_t ed_insert(EditLine *el, int c) { - int i; + int count = el->el_state.argument; if (c == '\0') return (CC_ERROR); @@ -78,46 +74,28 @@ ed_insert(EditLine *el, int c) if (el->el_line.lastchar + el->el_state.argument >= el->el_line.limit) { /* end of buffer space, try to allocate more */ - if (!ch_enlargebufs(el, (size_t) el->el_state.argument)) + if (!ch_enlargebufs(el, (size_t) count)) return CC_ERROR; /* error allocating more */ } - if (el->el_state.argument == 1) { - if (el->el_state.inputmode != MODE_INSERT) { - el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] = - *el->el_line.cursor; - el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] = - '\0'; - c_delafter(el, 1); - } - c_insert(el, 1); + if (count == 1) { + if (el->el_state.inputmode == MODE_INSERT + || el->el_line.cursor >= el->el_line.lastchar) + c_insert(el, 1); *el->el_line.cursor++ = c; - el->el_state.doingarg = 0; /* just in case */ re_fastaddc(el); /* fast refresh for one char. */ } else { - if (el->el_state.inputmode != MODE_INSERT) { - for (i = 0; i < el->el_state.argument; i++) - el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] = - el->el_line.cursor[i]; - - el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] = - '\0'; - c_delafter(el, el->el_state.argument); - } - c_insert(el, el->el_state.argument); + if (el->el_state.inputmode != MODE_REPLACE_1) + c_insert(el, el->el_state.argument); - while (el->el_state.argument--) + while (count-- && el->el_line.cursor < el->el_line.lastchar) *el->el_line.cursor++ = c; re_refresh(el); } - if (el->el_state.inputmode == MODE_REPLACE_1 - || el->el_state.inputmode == MODE_REPLACE) - el->el_chared.c_undo.action=CHANGE; - if (el->el_state.inputmode == MODE_REPLACE_1) - return (vi_command_mode(el, 0)); + return vi_command_mode(el, 0); return (CC_NORM); } @@ -129,7 +107,7 @@ ed_insert(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -ed_delete_prev_word(EditLine *el, int c) +ed_delete_prev_word(EditLine *el, int c __unused) { char *cp, *p, *kp; @@ -157,7 +135,7 @@ ed_delete_prev_word(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -ed_delete_next_char(EditLine *el, int c) +ed_delete_next_char(EditLine *el, int c __unused) { #ifdef notdef /* XXX */ #define EL el->el_line @@ -208,7 +186,7 @@ ed_delete_next_char(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -ed_kill_line(EditLine *el, int c) +ed_kill_line(EditLine *el, int c __unused) { char *kp, *cp; @@ -229,7 +207,7 @@ ed_kill_line(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -ed_move_to_end(EditLine *el, int c) +ed_move_to_end(EditLine *el, int c __unused) { el->el_line.cursor = el->el_line.lastchar; @@ -237,7 +215,7 @@ ed_move_to_end(EditLine *el, int c) #ifdef VI_MOVE el->el_line.cursor--; #endif - if (el->el_chared.c_vcmd.action & DELETE) { + if (el->el_chared.c_vcmd.action != NOP) { cv_delfini(el); return (CC_REFRESH); } @@ -252,7 +230,7 @@ ed_move_to_end(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -ed_move_to_beg(EditLine *el, int c) +ed_move_to_beg(EditLine *el, int c __unused) { el->el_line.cursor = el->el_line.buffer; @@ -261,7 +239,7 @@ ed_move_to_beg(EditLine *el, int c) /* We want FIRST non space character */ while (isspace((unsigned char) *el->el_line.cursor)) el->el_line.cursor++; - if (el->el_chared.c_vcmd.action & DELETE) { + if (el->el_chared.c_vcmd.action != NOP) { cv_delfini(el); return (CC_REFRESH); } @@ -301,18 +279,22 @@ ed_transpose_chars(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -ed_next_char(EditLine *el, int c) +ed_next_char(EditLine *el, int c __unused) { + char *lim = el->el_line.lastchar; - if (el->el_line.cursor >= el->el_line.lastchar) + if (el->el_line.cursor >= lim || + (el->el_line.cursor == lim - 1 && + el->el_map.type == MAP_VI && + el->el_chared.c_vcmd.action == NOP)) return (CC_ERROR); el->el_line.cursor += el->el_state.argument; - if (el->el_line.cursor > el->el_line.lastchar) - el->el_line.cursor = el->el_line.lastchar; + if (el->el_line.cursor > lim) + el->el_line.cursor = lim; if (el->el_map.type == MAP_VI) - if (el->el_chared.c_vcmd.action & DELETE) { + if (el->el_chared.c_vcmd.action != NOP) { cv_delfini(el); return (CC_REFRESH); } @@ -326,7 +308,7 @@ ed_next_char(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -ed_prev_word(EditLine *el, int c) +ed_prev_word(EditLine *el, int c __unused) { if (el->el_line.cursor == el->el_line.buffer) @@ -338,7 +320,7 @@ ed_prev_word(EditLine *el, int c) ce__isword); if (el->el_map.type == MAP_VI) - if (el->el_chared.c_vcmd.action & DELETE) { + if (el->el_chared.c_vcmd.action != NOP) { cv_delfini(el); return (CC_REFRESH); } @@ -352,7 +334,7 @@ ed_prev_word(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -ed_prev_char(EditLine *el, int c) +ed_prev_char(EditLine *el, int c __unused) { if (el->el_line.cursor > el->el_line.buffer) { @@ -361,7 +343,7 @@ ed_prev_char(EditLine *el, int c) el->el_line.cursor = el->el_line.buffer; if (el->el_map.type == MAP_VI) - if (el->el_chared.c_vcmd.action & DELETE) { + if (el->el_chared.c_vcmd.action != NOP) { cv_delfini(el); return (CC_REFRESH); } @@ -413,25 +395,9 @@ ed_digit(EditLine *el, int c) (el->el_state.argument * 10) + (c - '0'); } return (CC_ARGHACK); - } else { - if (el->el_line.lastchar + 1 >= el->el_line.limit) { - if (!ch_enlargebufs(el, 1)) - return (CC_ERROR); - } - - if (el->el_state.inputmode != MODE_INSERT) { - el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] = - *el->el_line.cursor; - el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] = - '\0'; - c_delafter(el, 1); - } - c_insert(el, 1); - *el->el_line.cursor++ = c; - el->el_state.doingarg = 0; - re_fastaddc(el); } - return (CC_NORM); + + return ed_insert(el, c); } @@ -465,12 +431,10 @@ ed_argument_digit(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -ed_unassigned(EditLine *el, int c) +ed_unassigned(EditLine *el, int c __unused) { - term_beep(el); - term__flush(); - return (CC_NORM); + return (CC_ERROR); } @@ -484,7 +448,8 @@ ed_unassigned(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -ed_tty_sigint(EditLine *el, int c) +ed_tty_sigint(EditLine *el __unused, + int c __unused) { return (CC_NORM); @@ -497,7 +462,8 @@ ed_tty_sigint(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -ed_tty_dsusp(EditLine *el, int c) +ed_tty_dsusp(EditLine *el __unused, + int c __unused) { return (CC_NORM); @@ -510,7 +476,8 @@ ed_tty_dsusp(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -ed_tty_flush_output(EditLine *el, int c) +ed_tty_flush_output(EditLine *el __unused, + int c __unused) { return (CC_NORM); @@ -523,7 +490,8 @@ ed_tty_flush_output(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -ed_tty_sigquit(EditLine *el, int c) +ed_tty_sigquit(EditLine *el __unused, + int c __unused) { return (CC_NORM); @@ -536,7 +504,8 @@ ed_tty_sigquit(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -ed_tty_sigtstp(EditLine *el, int c) +ed_tty_sigtstp(EditLine *el __unused, + int c __unused) { return (CC_NORM); @@ -549,7 +518,8 @@ ed_tty_sigtstp(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -ed_tty_stop_output(EditLine *el, int c) +ed_tty_stop_output(EditLine *el __unused, + int c __unused) { return (CC_NORM); @@ -562,7 +532,8 @@ ed_tty_stop_output(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -ed_tty_start_output(EditLine *el, int c) +ed_tty_start_output(EditLine *el __unused, + int c __unused) { return (CC_NORM); @@ -575,14 +546,12 @@ ed_tty_start_output(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -ed_newline(EditLine *el, int c) +ed_newline(EditLine *el, int c __unused) { re_goto_bottom(el); *el->el_line.lastchar++ = '\n'; *el->el_line.lastchar = '\0'; - if (el->el_map.type == MAP_VI) - el->el_chared.c_vcmd.ins = el->el_line.buffer; return (CC_NEWLINE); } @@ -593,7 +562,7 @@ ed_newline(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -ed_delete_prev_char(EditLine *el, int c) +ed_delete_prev_char(EditLine *el, int c __unused) { if (el->el_line.cursor <= el->el_line.buffer) @@ -613,7 +582,7 @@ ed_delete_prev_char(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -ed_clear_screen(EditLine *el, int c) +ed_clear_screen(EditLine *el, int c __unused) { term_clear_screen(el); /* clear the whole real screen */ @@ -628,7 +597,8 @@ ed_clear_screen(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -ed_redisplay(EditLine *el, int c) +ed_redisplay(EditLine *el __unused, + int c __unused) { return (CC_REDISPLAY); @@ -641,10 +611,10 @@ ed_redisplay(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -ed_start_over(EditLine *el, int c) +ed_start_over(EditLine *el, int c __unused) { - ch_reset(el); + ch_reset(el, 0); return (CC_REFRESH); } @@ -655,7 +625,8 @@ ed_start_over(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -ed_sequence_lead_in(EditLine *el, int c) +ed_sequence_lead_in(EditLine *el __unused, + int c __unused) { return (CC_NORM); @@ -668,11 +639,12 @@ ed_sequence_lead_in(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -ed_prev_history(EditLine *el, int c) +ed_prev_history(EditLine *el, int c __unused) { char beep = 0; + int sv_event = el->el_history.eventno; - el->el_chared.c_undo.action = NOP; + el->el_chared.c_undo.len = -1; *el->el_line.lastchar = '\0'; /* just in case */ if (el->el_history.eventno == 0) { /* save the current buffer @@ -685,15 +657,17 @@ ed_prev_history(EditLine *el, int c) el->el_history.eventno += el->el_state.argument; if (hist_get(el) == CC_ERROR) { + if (el->el_map.type == MAP_VI) { + el->el_history.eventno = sv_event; + return CC_ERROR; + } beep = 1; /* el->el_history.eventno was fixed by first call */ (void) hist_get(el); } - re_refresh(el); if (beep) - return (CC_ERROR); - else - return (CC_NORM); /* was CC_UP_HIST */ + return CC_REFRESH_BEEP; + return CC_REFRESH; } @@ -703,19 +677,24 @@ ed_prev_history(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -ed_next_history(EditLine *el, int c) +ed_next_history(EditLine *el, int c __unused) { + el_action_t beep = CC_REFRESH, rval; - el->el_chared.c_undo.action = NOP; + el->el_chared.c_undo.len = -1; *el->el_line.lastchar = '\0'; /* just in case */ el->el_history.eventno -= el->el_state.argument; if (el->el_history.eventno < 0) { el->el_history.eventno = 0; - return (CC_ERROR);/* make it beep */ + beep = CC_REFRESH_BEEP; } - return (hist_get(el)); + rval = hist_get(el); + if (rval == CC_REFRESH) + return beep; + return rval; + } @@ -725,14 +704,14 @@ ed_next_history(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -ed_search_prev_history(EditLine *el, int c) +ed_search_prev_history(EditLine *el, int c __unused) { const char *hp; int h; bool_t found = 0; el->el_chared.c_vcmd.action = NOP; - el->el_chared.c_undo.action = NOP; + el->el_chared.c_undo.len = -1; *el->el_line.lastchar = '\0'; /* just in case */ if (el->el_history.eventno < 0) { #ifdef DEBUG_EDIT @@ -793,14 +772,14 @@ ed_search_prev_history(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -ed_search_next_history(EditLine *el, int c) +ed_search_next_history(EditLine *el, int c __unused) { const char *hp; int h; bool_t found = 0; el->el_chared.c_vcmd.action = NOP; - el->el_chared.c_undo.action = NOP; + el->el_chared.c_undo.len = -1; *el->el_line.lastchar = '\0'; /* just in case */ if (el->el_history.eventno == 0) @@ -847,7 +826,7 @@ ed_search_next_history(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -ed_prev_line(EditLine *el, int c) +ed_prev_line(EditLine *el, int c __unused) { char *ptr; int nchars = c_hpos(el); @@ -890,7 +869,7 @@ ed_prev_line(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -ed_next_line(EditLine *el, int c) +ed_next_line(EditLine *el, int c __unused) { char *ptr; int nchars = c_hpos(el); @@ -924,30 +903,18 @@ ed_next_line(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -ed_command(EditLine *el, int c) +ed_command(EditLine *el, int c __unused) { char tmpbuf[EL_BUFSIZ]; int tmplen; - el->el_line.buffer[0] = '\0'; - el->el_line.lastchar = el->el_line.buffer; - el->el_line.cursor = el->el_line.buffer; - - c_insert(el, 3); /* prompt + ": " */ - *el->el_line.cursor++ = '\n'; - *el->el_line.cursor++ = ':'; - *el->el_line.cursor++ = ' '; - re_refresh(el); - - tmplen = c_gets(el, tmpbuf); - tmpbuf[tmplen] = '\0'; + tmplen = c_gets(el, tmpbuf, "\n: "); + term__putc('\n'); - el->el_line.buffer[0] = '\0'; - el->el_line.lastchar = el->el_line.buffer; - el->el_line.cursor = el->el_line.buffer; + if (tmplen < 0 || (tmpbuf[tmplen] = 0, parse_line(el, tmpbuf)) == -1) + term_beep(el); - if (parse_line(el, tmpbuf) == -1) - return (CC_ERROR); - else - return (CC_REFRESH); + el->el_map.current = el->el_map.key; + re_clear_display(el); + return CC_REFRESH; } diff --git a/lib/libedit/editline.3 b/lib/libedit/editline.3 index 56c81f49a1cf..b733c797fb6b 100644 --- a/lib/libedit/editline.3 +++ b/lib/libedit/editline.3 @@ -1,6 +1,6 @@ -.\" $NetBSD: editline.3,v 1.20 2000/02/28 17:41:05 chopps Exp $ +.\" $NetBSD: editline.3,v 1.48 2005/07/14 15:02:37 wiz Exp $ .\" -.\" Copyright (c) 1997-1999 The NetBSD Foundation, Inc. +.\" Copyright (c) 1997-2003 The NetBSD Foundation, Inc. .\" All rights reserved. .\" .\" This file was contributed to The NetBSD Foundation by Luke Mewburn. @@ -35,7 +35,7 @@ .\" .\" $FreeBSD$ .\" -.Dd November 12, 1999 +.Dd July 14, 2005 .Os .Dt EDITLINE 3 .Sh NAME @@ -55,8 +55,13 @@ .Nm el_deletestr , .Nm history_init , .Nm history_end , -.Nm history -.Nd line editor and history functions +.Nm history , +.Nm tok_init , +.Nm tok_end , +.Nm tok_reset , +.Nm tok_line , +.Nm tok_str +.Nd line editor, history and tokenization functions .Sh LIBRARY .Lb libedit .Sh SYNOPSIS @@ -74,7 +79,7 @@ .Ft void .Fn el_push "EditLine *e" "const char *str" .Ft int -.Fn el_parse "EditLine *e" "int argc" "char *argv[]" +.Fn el_parse "EditLine *e" "int argc" "const char *argv[]" .Ft int .Fn el_set "EditLine *e" "int op" "..." .Ft int @@ -95,10 +100,20 @@ .Fn history_end "History *h" .Ft int .Fn history "History *h" "HistEvent *ev" "int op" "..." +.Ft Tokenizer * +.Fn tok_init "const char *IFS" +.Ft void +.Fn tok_end "Tokenizer *t" +.Ft void +.Fn tok_reset "Tokenizer *t" +.Ft int +.Fn tok_line "Tokenizer *t" "const LineInfo *li" "int *argc" "const char **argv[]" "int *cursorc" "int *cursoro" +.Ft int +.Fn tok_str "Tokenizer *t" "const char *str" "int *argc" "const char **argv[]" .Sh DESCRIPTION The .Nm -library provides generic line editing and history functions, +library provides generic line editing, history and tokenization functions, similar to those found in .Xr sh 1 . .Pp @@ -154,7 +169,7 @@ if no characters were read or if an error occurred. Read a character from the tty. .Fa ch is modified to contain the character read. -Returns the number of characters read if successful, -1 otherwise. +Returns the number of characters read if successful, \-1 otherwise. .It Fn el_push Pushes .Fa str @@ -176,7 +191,7 @@ to execute builtin .Nm commands. If the command is prefixed with -.Dq prog: +.Dq prog : then .Fn el_parse will only execute the command if @@ -186,7 +201,7 @@ matches the argument supplied to .Fn el_init . The return value is --1 if the command is unknown, +\-1 if the command is unknown, 0 if there was no error or .Dq prog did not match, or @@ -305,7 +320,7 @@ for more information. .It Dv EL_ADDFN , Xo .Fa "const char *name" , .Fa "const char *help" , -.Fa "unsigned char (*func)(EditLine *e, int ch) +.Fa "unsigned char (*func)(EditLine *e, int ch)" .Xc Add a user defined function, .Fn func , @@ -370,6 +385,24 @@ check this (using .Fn el_get ) to determine if editing should be enabled or not. +.It Dv EL_GETCFN , Fa "int (*f)(EditLine *, char *c)" +Define the character reading function as +.Fa f , +which is to return the number of characters read and store them in +.Fa c . +This function is called internally by +.Fn el_gets +and +.Fn el_getc . +The builtin function can be set or restored with the special function +name ``EL_BUILTIN_GETCFN''. +.It Dv EL_CLIENTDATA , Fa "void *data" +Register +.Fa data +to be associated with this EditLine structure. +It can be retrieved with the corresponding +.Fn el_get +call. .El .It Fn el_get Get @@ -378,6 +411,7 @@ parameters. .Fa op determines which parameter to retrieve into .Fa result . +Returns 0 if successful, \-1 otherwise. .Pp The following values for .Fa op @@ -401,6 +435,22 @@ has installed private signal handlers (see above). .It Dv EL_EDITMODE, Fa "int *" Return non-zero if editing is enabled. +.It Dv EL_GETCFN, Fa "int (**f)(EditLine *, char *)" +Return a pointer to the function that read characters, which is equal to +``EL_BUILTIN_GETCFN'' in the case of the default builtin function. +.It Dv EL_CLIENTDATA , Fa "void **data" +Retrieve +.Fa data +previously registered with the corresponding +.Fn el_set +call. +.It Dv EL_UNBUFFERED, Fa "int" +Sets or clears unbuffered mode. +In this mode, +.Fn el_gets +will return immediately after processing a single character. +.It Dv EL_PREP_TERM, Fa "int" +Sets or clears terminal editing mode. .El .It Fn el_source Initialise @@ -443,11 +493,21 @@ typedef struct lineinfo { const char *lastchar; /* address of last character */ } LineInfo; .Ed +.Pp +.Fa buffer +is not NUL terminated. +This function may be called after +.Fn el_gets +to obtain the +.Fa LineInfo +structure pertaining to line returned by that function, +and from within user defined functions added with +.Dv EL_ADDFN . .It Fn el_insertstr Insert .Fa str into the line at the cursor. -Returns -1 if +Returns \-1 if .Fa str is empty or will not fit, and 0 otherwise. .It Fn el_deletestr @@ -527,7 +587,11 @@ Set the cursor to point to the requested element. .It Dv H_ADD , Fa "const char *str" Append .Fa str -to the current element of the history, or create an element with +to the current element of the history, or perform the +.Dv H_ENTER +operation with argument +.Fa str +if there is no current element. .It Dv H_APPEND , Fa "const char *str" Append .Fa str @@ -537,6 +601,17 @@ Add .Fa str as a new element to the history, and, if necessary, removing the oldest entry to keep the list to the created size. +If +.Dv H_SETUNIQUE +was has been called with a non-zero arguments, the element +will not be entered into the history if its contents match +the ones of the current history element. +If the element is entered +.Fn history +returns 1, if it is ignored as a duplicate returns 0. +Finally +.Fn history +returns \-1 if an error occurred. .It Dv H_PREV_STR , Fa "const char *str" Return the closest previous event that starts with .Fa str . @@ -555,6 +630,20 @@ Load the history list stored in .It Dv H_SAVE , Fa "const char *file" Save the history list to .Fa file . +.It Dv H_SETUNIQUE , Fa "int unique" +Set if the adjacent identical event strings should not be entered into +the history. +.It Dv H_GETUNIQUE +Retrieve the current setting if if adjacent elements should be entered into +the history. +.It Dv H_DEL , Fa "int num" +Delete the event numbered +.Fa e . +This function is only provided for +.Xr readline 3 +compatibility. +The caller is responsible for free'ing the string in the returned +.Fa HistEvent . .El .Pp The @@ -566,6 +655,78 @@ Otherwise, \-1 is returned and .Fa ev is updated to contain more details about the error. .El +.Sh TOKENIZATION FUNCTIONS +The tokenization functions use a common data structure, +.Fa Tokenizer , +which is created by +.Fn tok_init +and freed by +.Fn tok_end . +.Pp +The following functions are available: +.Bl -tag -width 4n +.It Fn tok_init +Initialise the tokenizer, and return a data structure +to be used by all other tokenizer functions. +.Fa IFS +contains the Input Field Separators, which defaults to +.Aq space , +.Aq tab , +and +.Aq newline +if +.Dv NULL . +.It Fn tok_end +Clean up and finish with +.Fa t , +assumed to have been created with +.Fn tok_init . +.It Fn tok_reset +Reset the tokenizer state. +Use after a line has been successfully tokenized +by +.Fn tok_line +or +.Fn tok_str +and before a new line is to be tokenized. +.It Fn tok_line +Tokenize +.Fa li , +If successful, modify: +.Fa argv +to contain the words, +.Fa argc +to contain the number of words, +.Fa cursorc +(if not +.Dv NULL ) +to contain the index of the word containing the cursor, +and +.Fa cursoro +(if not +.Dv NULL ) +to contain the offset within +.Fa argv[cursorc] +of the cursor. +.Pp +Returns +0 if successful, +\-1 for an internal error, +1 for an unmatched single quote, +2 for an unmatched double quote, +and +3 for a backslash quoted +.Aq newline . +A positive exit code indicates that another line should be read +and tokenization attempted again. +. +.It Fn tok_str +A simpler form of +.Fn tok_line ; +.Fa str +is a NUL terminated string to tokenize. +.El +. .\"XXX.Sh EXAMPLES .\"XXX: provide some examples .Sh SEE ALSO @@ -603,9 +764,6 @@ wrote this manual and implemented and .Dv EL_RPROMPT . .Sh BUGS -The tokenization functions are not publically defined in -.In histedit.h . -.Pp At this time, it is the responsibility of the caller to check the result of the .Dv EL_EDITMODE diff --git a/lib/libedit/editrc.5 b/lib/libedit/editrc.5 index e1fba8bb1eba..35d30cc671a4 100644 --- a/lib/libedit/editrc.5 +++ b/lib/libedit/editrc.5 @@ -1,4 +1,4 @@ -.\" $NetBSD: editrc.5,v 1.10 2000/11/08 00:09:38 lukem Exp $ +.\" $NetBSD: editrc.5,v 1.19 2003/11/01 23:35:33 christos Exp $ .\" .\" Copyright (c) 1997-2000 The NetBSD Foundation, Inc. .\" All rights reserved. @@ -35,7 +35,7 @@ .\" .\" $FreeBSD$ .\" -.Dd November 8, 2000 +.Dd October 18, 2003 .Os .Dt EDITRC 5 .Sh NAME @@ -64,7 +64,7 @@ for more information. .Ar prog is the program name string that a program defines when it calls .Xr el_init 3 -to setup +to set up .Xr editline 3 , which is usually .Va argv[0] . @@ -230,8 +230,24 @@ causes messages to be verbose. Enable or disable the .Nm editline functionality in a program. -.It Ic history -List the history. +.It Ic history Ar list | Ar size Dv n | Ar unique Dv n +The +.Ar list +command lists all entries in the history. +The +.Ar size +command sets the history size to +.Dv n +entries. +The +.Ar unique +command controls if history should keep duplicate entries. +If +.Dv n +is non zero, only keep unique history entries. +If +.Dv n +is zero, then keep all entries (the default). .It Ic telltc List the values of all the terminal capabilities (see .Xr termcap 5 ) . @@ -251,6 +267,7 @@ No sanity checking is done. .Op Ar +mode .Op Ar -mode .Op Ar mode +.Op Ar char=c .Xc Control which tty modes that .Nm @@ -287,6 +304,15 @@ fixes on or off or removes control of .Ar mode in the chosen set. +.Pp +.Ic Setty +can also be used to set tty characters to particular values using +.Ar char=value . +If +.Ar value +is empty +then the character is set to +.Dv _POSIX_VDISABLE . .El .Sh EDITOR COMMANDS The following editor commands are available for use in key bindings: diff --git a/lib/libedit/el.c b/lib/libedit/el.c index 4491b30e45a8..e06628e58476 100644 --- a/lib/libedit/el.c +++ b/lib/libedit/el.c @@ -13,11 +13,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -33,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $NetBSD: el.c,v 1.20 2000/11/11 22:18:57 christos Exp $ + * $NetBSD: el.c,v 1.40 2005/08/01 23:00:15 christos Exp $ */ #if !defined(lint) && !defined(SCCSID) @@ -54,6 +50,8 @@ __FBSDID("$FreeBSD$"); #include #include "el.h" +#define HAVE_ISSETUGID + /* el_init(): * Initialize editline and set default parameters. */ @@ -62,9 +60,6 @@ el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr) { EditLine *el = (EditLine *) el_malloc(sizeof(EditLine)); -#ifdef DEBUG - char *tty; -#endif if (el == NULL) return (NULL); @@ -74,14 +69,21 @@ el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr) el->el_infd = fileno(fin); el->el_outfile = fout; el->el_errfile = ferr; - el->el_prog = strdup(prog); + if ((el->el_prog = el_strdup(prog)) == NULL) { + el_free(el); + return NULL; + } /* * Initialize all the modules. Order is important!!! */ el->el_flags = 0; - (void) term_init(el); + if (term_init(el) == -1) { + el_free(el->el_prog); + el_free(el); + return NULL; + } (void) key_init(el); (void) map_init(el); if (tty_init(el) == -1) @@ -91,7 +93,7 @@ el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr) (void) hist_init(el); (void) prompt_init(el); (void) sig_init(el); - el->data = NULL; + (void) read_init(el); return (el); } @@ -132,7 +134,7 @@ el_reset(EditLine *el) { tty_cookedmode(el); - ch_reset(el); /* XXX: Do we want that? */ + ch_reset(el, 0); /* XXX: Do we want that? */ } @@ -143,11 +145,12 @@ public int el_set(EditLine *el, int op, ...) { va_list va; - int rv; - va_start(va, op); + int rv = 0; if (el == NULL) return (-1); + va_start(va, op); + switch (op) { case EL_PROMPT: case EL_RPROMPT: @@ -167,7 +170,6 @@ el_set(EditLine *el, int op, ...) el->el_flags |= HANDLE_SIGNALS; else el->el_flags &= ~HANDLE_SIGNALS; - rv = 0; break; case EL_BIND: @@ -176,7 +178,7 @@ el_set(EditLine *el, int op, ...) case EL_ECHOTC: case EL_SETTY: { - char *argv[20]; + const char *argv[20]; int i; for (i = 1; i < 20; i++) @@ -244,8 +246,41 @@ el_set(EditLine *el, int op, ...) rv = 0; break; + case EL_GETCFN: + { + el_rfunc_t rc = va_arg(va, el_rfunc_t); + rv = el_read_setfn(el, rc); + break; + } + + case EL_CLIENTDATA: + el->el_data = va_arg(va, void *); + break; + + case EL_UNBUFFERED: + rv = va_arg(va, int); + if (rv && !(el->el_flags & UNBUFFERED)) { + el->el_flags |= UNBUFFERED; + read_prepare(el); + } else if (!rv && (el->el_flags & UNBUFFERED)) { + el->el_flags &= ~UNBUFFERED; + read_finish(el); + } + rv = 0; + break; + + case EL_PREP_TERM: + rv = va_arg(va, int); + if (rv) + (void) tty_rawmode(el); + else + (void) tty_cookedmode(el); + rv = 0; + break; + default: rv = -1; + break; } va_end(va); @@ -266,11 +301,11 @@ el_get(EditLine *el, int op, void *ret) switch (op) { case EL_PROMPT: case EL_RPROMPT: - rv = prompt_get(el, (el_pfunc_t *) & ret, op); + rv = prompt_get(el, (void *) &ret, op); break; case EL_EDITOR: - rv = map_get_editor(el, (const char **) &ret); + rv = map_get_editor(el, (void *) &ret); break; case EL_SIGNAL: @@ -283,21 +318,22 @@ el_get(EditLine *el, int op, void *ret) rv = 0; break; -#if 0 /* XXX */ case EL_TERMINAL: - rv = term_get(el, (const char *) &ret); + term_get(el, (const char **)ret); + rv = 0; break; +#if 0 /* XXX */ case EL_BIND: case EL_TELLTC: case EL_SETTC: case EL_ECHOTC: case EL_SETTY: { - char *argv[20]; + const char *argv[20]; int i; - for (i = 1; i < 20; i++) + for (i = 1; i < sizeof(argv) / sizeof(argv[0]); i++) if ((argv[i] = va_arg(va, char *)) == NULL) break; @@ -354,6 +390,21 @@ el_get(EditLine *el, int op, void *ret) break; #endif /* XXX */ + case EL_GETCFN: + *((el_rfunc_t *)ret) = el_read_getfn(el); + rv = 0; + break; + + case EL_CLIENTDATA: + *((void **)ret) = el->el_data; + rv = 0; + break; + + case EL_UNBUFFERED: + *((int *) ret) = (!(el->el_flags & UNBUFFERED)); + rv = 0; + break; + default: rv = -1; } @@ -369,7 +420,7 @@ el_data_set (el, data) EditLine *el; void *data; { - el->data = data; + el->el_data = data; return; } @@ -381,8 +432,8 @@ public void * el_data_get (el) EditLine *el; { - if (el->data) - return (el->data); + if (el->el_data) + return (el->el_data); return (NULL); } @@ -396,7 +447,6 @@ el_line(EditLine *el) return (const LineInfo *) (void *) &el->el_line; } -static const char elpath[] = "/.editrc"; /* el_source(): * Source a file @@ -406,10 +456,14 @@ el_source(EditLine *el, const char *fname) { FILE *fp; size_t len; - char *ptr, path[MAXPATHLEN]; + char *ptr; fp = NULL; if (fname == NULL) { +#ifdef HAVE_ISSETUGID + static const char elpath[] = "/.editrc"; + char path[MAXPATHLEN]; + if (issetugid()) return (-1); if ((ptr = getenv("HOME")) == NULL) @@ -419,6 +473,14 @@ el_source(EditLine *el, const char *fname) if (strlcat(path, elpath, sizeof(path)) >= sizeof(path)) return (-1); fname = path; +#else + /* + * If issetugid() is missing, always return an error, in order + * to keep from inadvertently opening up the user to a security + * hole. + */ + return (-1); +#endif } if (fp == NULL) fp = fopen(fname, "r"); @@ -477,7 +539,7 @@ el_beep(EditLine *el) */ protected int /*ARGSUSED*/ -el_editmode(EditLine *el, int argc, char **argv) +el_editmode(EditLine *el, int argc, const char **argv) { const char *how; @@ -485,10 +547,13 @@ el_editmode(EditLine *el, int argc, char **argv) return (-1); how = argv[1]; - if (strcmp(how, "on") == 0) + if (strcmp(how, "on") == 0) { el->el_flags &= ~EDIT_DISABLED; - else if (strcmp(how, "off") == 0) + tty_rawmode(el); + } else if (strcmp(how, "off") == 0) { + tty_cookedmode(el); el->el_flags |= EDIT_DISABLED; + } else { (void) fprintf(el->el_errfile, "edit: Bad value `%s'.\n", how); return (-1); diff --git a/lib/libedit/el.h b/lib/libedit/el.h index 655b3912b763..fb07e26ed0df 100644 --- a/lib/libedit/el.h +++ b/lib/libedit/el.h @@ -13,11 +13,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -34,7 +30,7 @@ * SUCH DAMAGE. * * @(#)el.h 8.1 (Berkeley) 6/4/93 - * $NetBSD: el.h,v 1.7 2000/11/11 22:18:57 christos Exp $ + * $NetBSD: el.h,v 1.16 2003/10/18 23:48:42 christos Exp $ * $FreeBSD$ */ @@ -55,9 +51,10 @@ #define EL_BUFSIZ 1024 /* Maximum line size */ -#define HANDLE_SIGNALS 1<<0 -#define NO_TTY 1<<1 -#define EDIT_DISABLED 1<<2 +#define HANDLE_SIGNALS 0x01 +#define NO_TTY 0x02 +#define EDIT_DISABLED 0x04 +#define UNBUFFERED 0x08 typedef int bool_t; /* True or not */ @@ -72,7 +69,7 @@ typedef struct el_line_t { char *buffer; /* Input line */ char *cursor; /* Cursor position */ char *lastchar; /* Last character */ - const char *limit; /* Max position */ + const char *limit; /* Max position */ } el_line_t; /* @@ -84,11 +81,14 @@ typedef struct el_state_t { int argument; /* Numeric argument */ int metanext; /* Is the next char a meta char */ el_action_t lastcmd; /* Previous command */ + el_action_t thiscmd; /* this command */ + char thisch; /* char that generated it */ } el_state_t; /* * Until we come up with something better... */ +#define el_strdup(a) strdup(a) #define el_malloc(a) malloc(a) #define el_realloc(a,b) realloc(a, b) #define el_free(a) free(a) @@ -106,6 +106,7 @@ typedef struct el_state_t { #include "parse.h" #include "sig.h" #include "help.h" +#include "read.h" struct editline { char *el_prog; /* the program name */ @@ -116,6 +117,7 @@ struct editline { coord_t el_cursor; /* Cursor location */ char **el_display; /* Real screen image = what is there */ char **el_vdisplay; /* Virtual screen image = what we see */ + void *el_data; /* Client data */ el_line_t el_line; /* The current line information */ el_state_t el_state; /* Current editor state */ el_term_t el_term; /* Terminal dependent stuff */ @@ -129,15 +131,18 @@ struct editline { el_history_t el_history; /* History stuff */ el_search_t el_search; /* Search stuff */ el_signal_t el_signal; /* Signal handling stuff */ - - void *data; /* user data */ + el_read_t el_read; /* Character reading stuff */ }; -protected int el_editmode(EditLine *, int, char **); +protected int el_editmode(EditLine *, int, const char **); #ifdef DEBUG -#define EL_ABORT(a) (void) (fprintf(el->el_errfile, "%s, %d: ", \ - __FILE__, __LINE__), fprintf a, abort()) +#define EL_ABORT(a) do { \ + fprintf(el->el_errfile, "%s, %d: ", \ + __FILE__, __LINE__); \ + fprintf a; \ + abort(); \ + } while( /*CONSTCOND*/0); #else #define EL_ABORT(a) abort() #endif diff --git a/lib/libedit/emacs.c b/lib/libedit/emacs.c index eff478dfdbbc..e66961bf4f73 100644 --- a/lib/libedit/emacs.c +++ b/lib/libedit/emacs.c @@ -13,11 +13,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -33,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $NetBSD: emacs.c,v 1.8 2000/09/04 22:06:29 lukem Exp $ + * $NetBSD: emacs.c,v 1.19 2004/10/28 21:14:52 dsl Exp $ */ #if !defined(lint) && !defined(SCCSID) @@ -54,7 +50,7 @@ __FBSDID("$FreeBSD$"); */ protected el_action_t /*ARGSUSED*/ -em_delete_or_list(EditLine *el, int c) +em_delete_or_list(EditLine *el, int c __unused) { if (el->el_line.cursor == el->el_line.lastchar) { @@ -73,7 +69,10 @@ em_delete_or_list(EditLine *el, int c) return (CC_ERROR); } } else { - c_delafter(el, el->el_state.argument); /* delete after dot */ + if (el->el_state.doingarg) + c_delafter(el, el->el_state.argument); + else + c_delafter1(el); if (el->el_line.cursor > el->el_line.lastchar) el->el_line.cursor = el->el_line.lastchar; /* bounds check */ @@ -88,7 +87,7 @@ em_delete_or_list(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -em_delete_next_word(EditLine *el, int c) +em_delete_next_word(EditLine *el, int c __unused) { char *cp, *p, *kp; @@ -117,14 +116,12 @@ em_delete_next_word(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -em_yank(EditLine *el, int c) +em_yank(EditLine *el, int c __unused) { char *kp, *cp; - if (el->el_chared.c_kill.last == el->el_chared.c_kill.buf) { - if (!ch_enlargebufs(el, 1)) - return (CC_ERROR); - } + if (el->el_chared.c_kill.last == el->el_chared.c_kill.buf) + return (CC_NORM); if (el->el_line.lastchar + (el->el_chared.c_kill.last - el->el_chared.c_kill.buf) >= @@ -154,7 +151,7 @@ em_yank(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -em_kill_line(EditLine *el, int c) +em_kill_line(EditLine *el, int c __unused) { char *kp, *cp; @@ -176,7 +173,7 @@ em_kill_line(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -em_kill_region(EditLine *el, int c) +em_kill_region(EditLine *el, int c __unused) { char *kp, *cp; @@ -209,11 +206,11 @@ em_kill_region(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -em_copy_region(EditLine *el, int c) +em_copy_region(EditLine *el, int c __unused) { char *kp, *cp; - if (el->el_chared.c_kill.mark) + if (!el->el_chared.c_kill.mark) return (CC_ERROR); if (el->el_chared.c_kill.mark > el->el_line.cursor) { @@ -233,12 +230,12 @@ em_copy_region(EditLine *el, int c) } -/* em_gosmacs_traspose(): +/* em_gosmacs_transpose(): * Exchange the two characters before the cursor * Gosling emacs transpose chars [^T] */ protected el_action_t -em_gosmacs_traspose(EditLine *el, int c) +em_gosmacs_transpose(EditLine *el, int c) { if (el->el_line.cursor > &el->el_line.buffer[1]) { @@ -258,7 +255,7 @@ em_gosmacs_traspose(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -em_next_word(EditLine *el, int c) +em_next_word(EditLine *el, int c __unused) { if (el->el_line.cursor == el->el_line.lastchar) return (CC_ERROR); @@ -269,7 +266,7 @@ em_next_word(EditLine *el, int c) ce__isword); if (el->el_map.type == MAP_VI) - if (el->el_chared.c_vcmd.action & DELETE) { + if (el->el_chared.c_vcmd.action != NOP) { cv_delfini(el); return (CC_REFRESH); } @@ -283,7 +280,7 @@ em_next_word(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -em_upper_case(EditLine *el, int c) +em_upper_case(EditLine *el, int c __unused) { char *cp, *ep; @@ -291,8 +288,8 @@ em_upper_case(EditLine *el, int c) el->el_state.argument, ce__isword); for (cp = el->el_line.cursor; cp < ep; cp++) - if (islower((unsigned char) *cp)) - *cp = toupper((unsigned char) *cp); + if (islower((unsigned char)*cp)) + *cp = toupper((unsigned char)*cp); el->el_line.cursor = ep; if (el->el_line.cursor > el->el_line.lastchar) @@ -307,7 +304,7 @@ em_upper_case(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -em_capitol_case(EditLine *el, int c) +em_capitol_case(EditLine *el, int c __unused) { char *cp, *ep; @@ -315,16 +312,16 @@ em_capitol_case(EditLine *el, int c) el->el_state.argument, ce__isword); for (cp = el->el_line.cursor; cp < ep; cp++) { - if (isalpha((unsigned char) *cp)) { - if (islower((unsigned char) *cp)) - *cp = toupper((unsigned char) *cp); + if (isalpha((unsigned char)*cp)) { + if (islower((unsigned char)*cp)) + *cp = toupper((unsigned char)*cp); cp++; break; } } for (; cp < ep; cp++) - if (isupper((unsigned char) *cp)) - *cp = tolower((unsigned char) *cp); + if (isupper((unsigned char)*cp)) + *cp = tolower((unsigned char)*cp); el->el_line.cursor = ep; if (el->el_line.cursor > el->el_line.lastchar) @@ -339,7 +336,7 @@ em_capitol_case(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -em_lower_case(EditLine *el, int c) +em_lower_case(EditLine *el, int c __unused) { char *cp, *ep; @@ -347,8 +344,8 @@ em_lower_case(EditLine *el, int c) el->el_state.argument, ce__isword); for (cp = el->el_line.cursor; cp < ep; cp++) - if (isupper((unsigned char) *cp)) - *cp = tolower((unsigned char) *cp); + if (isupper((unsigned char)*cp)) + *cp = tolower((unsigned char)*cp); el->el_line.cursor = ep; if (el->el_line.cursor > el->el_line.lastchar) @@ -363,7 +360,7 @@ em_lower_case(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -em_set_mark(EditLine *el, int c) +em_set_mark(EditLine *el, int c __unused) { el->el_chared.c_kill.mark = el->el_line.cursor; @@ -377,7 +374,7 @@ em_set_mark(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -em_exchange_mark(EditLine *el, int c) +em_exchange_mark(EditLine *el, int c __unused) { char *cp; @@ -394,7 +391,7 @@ em_exchange_mark(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -em_universal_argument(EditLine *el, int c) +em_universal_argument(EditLine *el, int c __unused) { /* multiply current argument by 4 */ if (el->el_state.argument > 1000000) @@ -411,7 +408,7 @@ em_universal_argument(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -em_meta_next(EditLine *el, int c) +em_meta_next(EditLine *el, int c __unused) { el->el_state.metanext = 1; @@ -424,7 +421,7 @@ em_meta_next(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -em_toggle_overwrite(EditLine *el, int c) +em_toggle_overwrite(EditLine *el, int c __unused) { el->el_state.inputmode = (el->el_state.inputmode == MODE_INSERT) ? @@ -438,7 +435,7 @@ em_toggle_overwrite(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -em_copy_prev_word(EditLine *el, int c) +em_copy_prev_word(EditLine *el, int c __unused) { char *cp, *oldc, *dp; @@ -465,7 +462,7 @@ em_copy_prev_word(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -em_inc_search_next(EditLine *el, int c) +em_inc_search_next(EditLine *el, int c __unused) { el->el_search.patlen = 0; @@ -478,9 +475,32 @@ em_inc_search_next(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -em_inc_search_prev(EditLine *el, int c) +em_inc_search_prev(EditLine *el, int c __unused) { el->el_search.patlen = 0; return (ce_inc_search(el, ED_SEARCH_PREV_HISTORY)); } + + +/* em_delete_prev_char(): + * Delete the character to the left of the cursor + * [^?] + */ +protected el_action_t +/*ARGSUSED*/ +em_delete_prev_char(EditLine *el, int c __unused) +{ + + if (el->el_line.cursor <= el->el_line.buffer) + return (CC_ERROR); + + if (el->el_state.doingarg) + c_delbefore(el, el->el_state.argument); + else + c_delbefore1(el); + el->el_line.cursor -= el->el_state.argument; + if (el->el_line.cursor < el->el_line.buffer) + el->el_line.cursor = el->el_line.buffer; + return (CC_REFRESH); +} diff --git a/lib/libedit/hist.c b/lib/libedit/hist.c index f4bbf5dee2e3..601e10272dce 100644 --- a/lib/libedit/hist.c +++ b/lib/libedit/hist.c @@ -13,11 +13,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -33,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $NetBSD: hist.c,v 1.8 2001/01/10 07:45:41 jdolecek Exp $ + * $NetBSD: hist.c,v 1.15 2003/11/01 23:36:39 christos Exp $ */ #if !defined(lint) && !defined(SCCSID) @@ -130,18 +126,16 @@ hist_get(EditLine *el) el->el_history.eventno = h; return (CC_ERROR); } - (void) strncpy(el->el_line.buffer, hp, + (void) strlcpy(el->el_line.buffer, hp, (size_t)(el->el_line.limit - el->el_line.buffer)); el->el_line.lastchar = el->el_line.buffer + strlen(el->el_line.buffer); - if (el->el_line.lastchar > el->el_line.buffer) { - if (el->el_line.lastchar[-1] == '\n') - el->el_line.lastchar--; - if (el->el_line.lastchar[-1] == ' ') - el->el_line.lastchar--; - if (el->el_line.lastchar < el->el_line.buffer) - el->el_line.lastchar = el->el_line.buffer; - } + if (el->el_line.lastchar > el->el_line.buffer + && el->el_line.lastchar[-1] == '\n') + el->el_line.lastchar--; + if (el->el_line.lastchar > el->el_line.buffer + && el->el_line.lastchar[-1] == ' ') + el->el_line.lastchar--; #ifdef KSHVI if (el->el_map.type == MAP_VI) el->el_line.cursor = el->el_line.buffer; @@ -153,21 +147,40 @@ hist_get(EditLine *el) } -/* hist_list() - * List history entries +/* hist_command() + * process a history command */ protected int -/*ARGSUSED*/ -hist_list(EditLine *el, int argc, char **argv) +hist_command(EditLine *el, int argc, const char **argv) { const char *str; + int num; + HistEvent ev; if (el->el_history.ref == NULL) return (-1); - for (str = HIST_LAST(el); str != NULL; str = HIST_PREV(el)) - (void) fprintf(el->el_outfile, "%d %s", - el->el_history.ev.num, str); - return (0); + + if (argc == 1 || strcmp(argv[1], "list") == 0) { + /* List history entries */ + + for (str = HIST_LAST(el); str != NULL; str = HIST_PREV(el)) + (void) fprintf(el->el_outfile, "%d %s", + el->el_history.ev.num, str); + return (0); + } + + if (argc != 3) + return (-1); + + num = (int)strtol(argv[2], NULL, 0); + + if (strcmp(argv[1], "size") == 0) + return history(el->el_history.ref, &ev, H_SETSIZE, num); + + if (strcmp(argv[1], "unique") == 0) + return history(el->el_history.ref, &ev, H_SETUNIQUE, num); + + return -1; } /* hist_enlargebuf() diff --git a/lib/libedit/hist.h b/lib/libedit/hist.h index 7fbaaa4a5c78..4f2824aff200 100644 --- a/lib/libedit/hist.h +++ b/lib/libedit/hist.h @@ -13,11 +13,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -34,7 +30,7 @@ * SUCH DAMAGE. * * @(#)hist.h 8.1 (Berkeley) 6/4/93 - * $NetBSD: hist.h,v 1.5 2000/09/04 22:06:30 lukem Exp $ + * $NetBSD: hist.h,v 1.10 2003/08/07 16:44:31 agc Exp $ * $FreeBSD$ */ @@ -66,7 +62,7 @@ typedef struct el_history_t { #define HIST_FIRST(el) HIST_FUN(el, H_FIRST, NULL) #define HIST_LAST(el) HIST_FUN(el, H_LAST, NULL) #define HIST_PREV(el) HIST_FUN(el, H_PREV, NULL) -#define HIST_EVENT(el, num) HIST_FUN(el, H_EVENT, num) +#define HIST_SET(el, num) HIST_FUN(el, H_SET, num) #define HIST_LOAD(el, fname) HIST_FUN(el, H_LOAD fname) #define HIST_SAVE(el, fname) HIST_FUN(el, H_SAVE fname) @@ -74,7 +70,7 @@ protected int hist_init(EditLine *); protected void hist_end(EditLine *); protected el_action_t hist_get(EditLine *); protected int hist_set(EditLine *, hist_fun_t, ptr_t); -protected int hist_list(EditLine *, int, char **); +protected int hist_command(EditLine *, int, const char **); protected int hist_enlargebuf(EditLine *, size_t, size_t); #endif /* _h_el_hist */ diff --git a/lib/libedit/history.c b/lib/libedit/history.c index f2e6aee6fdce..af4892a92a21 100644 --- a/lib/libedit/history.c +++ b/lib/libedit/history.c @@ -13,11 +13,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -33,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $NetBSD: history.c,v 1.16 2000/09/04 22:06:30 lukem Exp $ + * $NetBSD: history.c,v 1.31 2005/08/01 14:34:06 christos Exp $ */ #if !defined(lint) && !defined(SCCSID) @@ -71,10 +67,12 @@ struct history { history_gfun_t h_prev; /* Get the previous element */ history_gfun_t h_curr; /* Get the current element */ history_sfun_t h_set; /* Set the current element */ + history_sfun_t h_del; /* Set the given element */ history_vfun_t h_clear; /* Clear the history list */ history_efun_t h_enter; /* Add an element */ history_efun_t h_add; /* Append to an element */ }; + #define HNEXT(h, ev) (*(h)->h_next)((h)->h_ref, ev) #define HFIRST(h, ev) (*(h)->h_first)((h)->h_ref, ev) #define HPREV(h, ev) (*(h)->h_prev)((h)->h_ref, ev) @@ -84,14 +82,24 @@ struct history { #define HCLEAR(h, ev) (*(h)->h_clear)((h)->h_ref, ev) #define HENTER(h, ev, str) (*(h)->h_enter)((h)->h_ref, ev, str) #define HADD(h, ev, str) (*(h)->h_add)((h)->h_ref, ev, str) +#define HDEL(h, ev, n) (*(h)->h_del)((h)->h_ref, ev, n) +#define h_strdup(a) strdup(a) #define h_malloc(a) malloc(a) #define h_realloc(a, b) realloc((a), (b)) #define h_free(a) free(a) +typedef struct { + int num; + char *str; +} HistEventPrivate; + + private int history_setsize(History *, HistEvent *, int); private int history_getsize(History *, HistEvent *); +private int history_setunique(History *, HistEvent *, int); +private int history_getunique(History *, HistEvent *); private int history_set_fun(History *, History *); private int history_load(History *, const char *); private int history_save(History *, const char *); @@ -110,31 +118,41 @@ typedef struct hentry_t { HistEvent ev; /* What we return */ struct hentry_t *next; /* Next entry */ struct hentry_t *prev; /* Previous entry */ -} hentry_t; +} hentry_t; typedef struct history_t { - hentry_t list; /* Fake list header element */ - hentry_t *cursor; /* Current element in the list */ - int max; /* Maximum number of events */ - int cur; /* Current number of events */ + hentry_t list; /* Fake list header element */ + hentry_t *cursor; /* Current element in the list */ + int max; /* Maximum number of events */ + int cur; /* Current number of events */ int eventid; /* For generation of unique event id */ -} history_t; + int flags; /* History flags */ +#define H_UNIQUE 1 /* Store only unique elements */ +} history_t; -private int history_def_first(ptr_t, HistEvent *); -private int history_def_last(ptr_t, HistEvent *); private int history_def_next(ptr_t, HistEvent *); +private int history_def_first(ptr_t, HistEvent *); private int history_def_prev(ptr_t, HistEvent *); +private int history_def_last(ptr_t, HistEvent *); private int history_def_curr(ptr_t, HistEvent *); -private int history_def_set(ptr_t, HistEvent *, const int n); +private int history_def_set(ptr_t, HistEvent *, const int); +private void history_def_clear(ptr_t, HistEvent *); private int history_def_enter(ptr_t, HistEvent *, const char *); private int history_def_add(ptr_t, HistEvent *, const char *); -private void history_def_init(ptr_t *, HistEvent *, int); -private void history_def_clear(ptr_t, HistEvent *); +private int history_def_del(ptr_t, HistEvent *, const int); + +private int history_def_init(ptr_t *, HistEvent *, int); private int history_def_insert(history_t *, HistEvent *, const char *); private void history_def_delete(history_t *, HistEvent *, hentry_t *); -#define history_def_setsize(p, num)(void) (((history_t *) p)->max = (num)) -#define history_def_getsize(p) (((history_t *) p)->cur) +#define history_def_setsize(p, num)(void) (((history_t *)p)->max = (num)) +#define history_def_getsize(p) (((history_t *)p)->cur) +#define history_def_getunique(p) (((((history_t *)p)->flags) & H_UNIQUE) != 0) +#define history_def_setunique(p, uni) \ + if (uni) \ + (((history_t *)p)->flags) |= H_UNIQUE; \ + else \ + (((history_t *)p)->flags) &= ~H_UNIQUE #define he_strerror(code) he_errlist[code] #define he_seterrev(evp, code) {\ @@ -227,20 +245,19 @@ history_def_next(ptr_t p, HistEvent *ev) { history_t *h = (history_t *) p; - if (h->cursor != &h->list) - h->cursor = h->cursor->next; - else { + if (h->cursor == &h->list) { he_seterrev(ev, _HE_EMPTY_LIST); return (-1); } - if (h->cursor != &h->list) - *ev = h->cursor->ev; - else { + if (h->cursor->next == &h->list) { he_seterrev(ev, _HE_END_REACHED); return (-1); } + h->cursor = h->cursor->next; + *ev = h->cursor->ev; + return (0); } @@ -253,21 +270,20 @@ history_def_prev(ptr_t p, HistEvent *ev) { history_t *h = (history_t *) p; - if (h->cursor != &h->list) - h->cursor = h->cursor->prev; - else { + if (h->cursor == &h->list) { he_seterrev(ev, (h->cur > 0) ? _HE_END_REACHED : _HE_EMPTY_LIST); return (-1); } - if (h->cursor != &h->list) - *ev = h->cursor->ev; - else { + if (h->cursor->prev == &h->list) { he_seterrev(ev, _HE_START_REACHED); return (-1); } + h->cursor = h->cursor->prev; + *ev = h->cursor->ev; + return (0); } @@ -328,39 +344,59 @@ history_def_add(ptr_t p, HistEvent *ev, const char *str) history_t *h = (history_t *) p; size_t len; char *s; + HistEventPrivate *evp = (void *)&h->cursor->ev; if (h->cursor == &h->list) return (history_def_enter(p, ev, str)); - len = strlen(h->cursor->ev.str) + strlen(str) + 1; + len = strlen(evp->str) + strlen(str) + 1; s = (char *) h_malloc(len); - if (!s) { + if (s == NULL) { he_seterrev(ev, _HE_MALLOC_FAILED); return (-1); } (void) strlcpy(s, h->cursor->ev.str, len); (void) strlcat(s, str, len); - /* LINTED const cast */ - h_free((ptr_t) h->cursor->ev.str); - h->cursor->ev.str = s; + h_free((ptr_t)evp->str); + evp->str = s; *ev = h->cursor->ev; return (0); } +/* history_def_del(): + * Delete element hp of the h list + */ +/* ARGSUSED */ +private int +history_def_del(ptr_t p, HistEvent *ev __unused, + const int num) +{ + history_t *h = (history_t *) p; + if (history_def_set(h, ev, num) != 0) + return (-1); + ev->str = strdup(h->cursor->ev.str); + ev->num = h->cursor->ev.num; + history_def_delete(h, ev, h->cursor); + return (0); +} + + /* history_def_delete(): * Delete element hp of the h list */ /* ARGSUSED */ private void -history_def_delete(history_t *h, HistEvent *ev, hentry_t *hp) +history_def_delete(history_t *h, + HistEvent *ev __unused, hentry_t *hp) { - + HistEventPrivate *evp = (void *)&hp->ev; if (hp == &h->list) abort(); + if (h->cursor == hp) + h->cursor = hp->prev; hp->prev->next = hp->next; hp->next->prev = hp->prev; - /* LINTED const cast */ - h_free((ptr_t) hp->ev.str); + h_free((ptr_t) evp->str); h_free(hp); h->cur--; } @@ -374,11 +410,11 @@ history_def_insert(history_t *h, HistEvent *ev, const char *str) { h->cursor = (hentry_t *) h_malloc(sizeof(hentry_t)); - if (h->cursor) - h->cursor->ev.str = strdup(str); - if (!h->cursor || !h->cursor->ev.str) { - he_seterrev(ev, _HE_MALLOC_FAILED); - return (-1); + if (h->cursor == NULL) + goto oomem; + if ((h->cursor->ev.str = h_strdup(str)) == NULL) { + h_free((ptr_t)h->cursor); + goto oomem; } h->cursor->ev.num = ++h->eventid; h->cursor->next = h->list.next; @@ -389,6 +425,9 @@ history_def_insert(history_t *h, HistEvent *ev, const char *str) *ev = h->cursor->ev; return (0); +oomem: + he_seterrev(ev, _HE_MALLOC_FAILED); + return (-1); } @@ -400,6 +439,10 @@ history_def_enter(ptr_t p, HistEvent *ev, const char *str) { history_t *h = (history_t *) p; + if ((h->flags & H_UNIQUE) != 0 && h->list.next != &h->list && + strcmp(h->list.next->ev.str, str) == 0) + return (0); + if (history_def_insert(h, ev, str) == -1) return (-1); /* error, keep error message */ @@ -407,10 +450,10 @@ history_def_enter(ptr_t p, HistEvent *ev, const char *str) * Always keep at least one entry. * This way we don't have to check for the empty list. */ - while (h->cur - 1 > h->max) + while (h->cur > h->max && h->cur > 0) history_def_delete(h, ev, h->list.prev); - return (0); + return (1); } @@ -418,10 +461,12 @@ history_def_enter(ptr_t p, HistEvent *ev, const char *str) * Default history initialization function */ /* ARGSUSED */ -private void -history_def_init(ptr_t *p, HistEvent *ev, int n) +private int +history_def_init(ptr_t *p, HistEvent *ev __unused, int n) { history_t *h = (history_t *) h_malloc(sizeof(history_t)); + if (h == NULL) + return -1; if (n <= 0) n = 0; @@ -432,7 +477,9 @@ history_def_init(ptr_t *p, HistEvent *ev, int n) h->list.ev.str = NULL; h->list.ev.num = 0; h->cursor = &h->list; + h->flags = 0; *p = (ptr_t) h; + return 0; } @@ -461,10 +508,15 @@ history_def_clear(ptr_t p, HistEvent *ev) public History * history_init(void) { - History *h = (History *) h_malloc(sizeof(History)); HistEvent ev; + History *h = (History *) h_malloc(sizeof(History)); + if (h == NULL) + return NULL; - history_def_init(&h->h_ref, &ev, 0); + if (history_def_init(&h->h_ref, &ev, 0) == -1) { + h_free((ptr_t)h); + return NULL; + } h->h_ent = -1; h->h_next = history_def_next; h->h_first = history_def_first; @@ -475,6 +527,7 @@ history_init(void) h->h_clear = history_def_clear; h->h_enter = history_def_enter; h->h_add = history_def_add; + h->h_del = history_def_del; return (h); } @@ -490,6 +543,7 @@ history_end(History *h) if (h->h_next == history_def_next) history_def_clear(h->h_ref, &ev); + h_free(h); } @@ -520,18 +574,46 @@ history_setsize(History *h, HistEvent *ev, int num) private int history_getsize(History *h, HistEvent *ev) { - int retval = 0; - if (h->h_next != history_def_next) { he_seterrev(ev, _HE_NOT_ALLOWED); return (-1); } - retval = history_def_getsize(h->h_ref); - if (retval < -1) { + ev->num = history_def_getsize(h->h_ref); + if (ev->num < -1) { he_seterrev(ev, _HE_SIZE_NEGATIVE); return (-1); } - ev->num = retval; + return (0); +} + + +/* history_setunique(): + * Set if adjacent equal events should not be entered in history. + */ +private int +history_setunique(History *h, HistEvent *ev, int uni) +{ + + if (h->h_next != history_def_next) { + he_seterrev(ev, _HE_NOT_ALLOWED); + return (-1); + } + history_def_setunique(h->h_ref, uni); + return (0); +} + + +/* history_getunique(): + * Get if adjacent equal events should not be entered in history. + */ +private int +history_getunique(History *h, HistEvent *ev) +{ + if (h->h_next != history_def_next) { + he_seterrev(ev, _HE_NOT_ALLOWED); + return (-1); + } + ev->num = history_def_getunique(h->h_ref); return (0); } @@ -547,7 +629,7 @@ history_set_fun(History *h, History *nh) if (nh->h_first == NULL || nh->h_next == NULL || nh->h_last == NULL || nh->h_prev == NULL || nh->h_curr == NULL || nh->h_set == NULL || nh->h_enter == NULL || nh->h_add == NULL || nh->h_clear == NULL || - nh->h_ref == NULL) { + nh->h_del == NULL || nh->h_ref == NULL) { if (h->h_next != history_def_next) { history_def_init(&h->h_ref, &ev, 0); h->h_first = history_def_first; @@ -559,6 +641,7 @@ history_set_fun(History *h, History *nh) h->h_clear = history_def_clear; h->h_enter = history_def_enter; h->h_add = history_def_add; + h->h_del = history_def_del; } return (-1); } @@ -575,6 +658,7 @@ history_set_fun(History *h, History *nh) h->h_clear = nh->h_clear; h->h_enter = nh->h_enter; h->h_add = nh->h_add; + h->h_del = nh->h_del; return (0); } @@ -603,6 +687,8 @@ history_load(History *h, const char *fname) goto done; ptr = h_malloc(max_size = 1024); + if (ptr == NULL) + goto done; for (i = 0; (line = fgetln(fp, &sz)) != NULL; i++) { char c = line[sz]; @@ -612,15 +698,24 @@ history_load(History *h, const char *fname) line[sz] = '\0'; if (max_size < sz) { - max_size = (sz + 1023) & ~1023; - ptr = h_realloc(ptr, max_size); + char *nptr; + max_size = (sz + 1024) & ~1023; + nptr = h_realloc(ptr, max_size); + if (nptr == NULL) { + i = -1; + goto oomem; + } + ptr = nptr; } (void) strunvis(ptr, line); line[sz] = c; - HENTER(h, &ev, ptr); + if (HENTER(h, &ev, ptr) == -1) { + h_free((ptr_t)ptr); + return -1; + } } - h_free(ptr); - +oomem: + h_free((ptr_t)ptr); done: (void) fclose(fp); return (i); @@ -635,28 +730,40 @@ history_save(History *h, const char *fname) { FILE *fp; HistEvent ev; - int i = 0, retval; + int i = -1, retval; size_t len, max_size; char *ptr; if ((fp = fopen(fname, "w")) == NULL) return (-1); - (void) fchmod(fileno(fp), S_IRUSR|S_IWUSR); - (void) fputs(hist_cookie, fp); + if (fchmod(fileno(fp), S_IRUSR|S_IWUSR) == -1) + goto done; + if (fputs(hist_cookie, fp) == EOF) + goto done; ptr = h_malloc(max_size = 1024); - for (retval = HLAST(h, &ev); + if (ptr == NULL) + goto done; + for (i = 0, retval = HLAST(h, &ev); retval != -1; retval = HPREV(h, &ev), i++) { len = strlen(ev.str) * 4; if (len >= max_size) { - max_size = (len + 1023) & 1023; - ptr = h_realloc(ptr, max_size); + char *nptr; + max_size = (len + 1024) & ~1023; + nptr = h_realloc(ptr, max_size); + if (nptr == NULL) { + i = -1; + goto oomem; + } + ptr = nptr; } (void) strvis(ptr, ev.str, VIS_WHITE); (void) fprintf(fp, "%s\n", ptr); } - h_free(ptr); +oomem: + h_free((ptr_t)ptr); +done: (void) fclose(fp); return (i); } @@ -755,11 +862,23 @@ history(History *h, HistEvent *ev, int fun, ...) retval = history_setsize(h, ev, va_arg(va, int)); break; + case H_GETUNIQUE: + retval = history_getunique(h, ev); + break; + + case H_SETUNIQUE: + retval = history_setunique(h, ev, va_arg(va, int)); + break; + case H_ADD: str = va_arg(va, const char *); retval = HADD(h, ev, str); break; + case H_DEL: + retval = HDEL(h, ev, va_arg(va, const int)); + break; + case H_ENTER: str = va_arg(va, const char *); if ((retval = HENTER(h, ev, str)) != -1) @@ -844,6 +963,7 @@ history(History *h, HistEvent *ev, int fun, ...) hf.h_clear = va_arg(va, history_vfun_t); hf.h_enter = va_arg(va, history_efun_t); hf.h_add = va_arg(va, history_efun_t); + hf.h_del = va_arg(va, history_sfun_t); if ((retval = history_set_fun(h, &hf)) == -1) he_seterrev(ev, _HE_PARAM_MISSING); diff --git a/lib/libedit/key.c b/lib/libedit/key.c index 7643f3d75d5d..ada5648e8e61 100644 --- a/lib/libedit/key.c +++ b/lib/libedit/key.c @@ -13,11 +13,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -33,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $NetBSD: key.c,v 1.11 2001/01/23 15:55:30 jdolecek Exp $ + * $NetBSD: key.c,v 1.16 2005/07/06 21:13:02 christos Exp $ */ #if !defined(lint) && !defined(SCCSID) @@ -63,7 +59,6 @@ __FBSDID("$FreeBSD$"); * 1) It is not possible to have one key that is a * substr of another. */ -#include "sys.h" #include #include @@ -87,9 +82,11 @@ private int node_trav(EditLine *, key_node_t *, char *, private int node__try(EditLine *, key_node_t *, const char *, key_value_t *, int); private key_node_t *node__get(int); +private void node__free(key_node_t *); private void node__put(EditLine *, key_node_t *); -private int node__delete(EditLine *, key_node_t **, char *); -private int node_lookup(EditLine *, char *, key_node_t *, int); +private int node__delete(EditLine *, key_node_t **, const char *); +private int node_lookup(EditLine *, const char *, key_node_t *, + int); private int node_enum(EditLine *, key_node_t *, int); private int key__decode_char(char *, int, int); @@ -111,7 +108,6 @@ key_init(EditLine *el) return (0); } - /* key_end(): * Free the key maps */ @@ -121,8 +117,7 @@ key_end(EditLine *el) el_free((ptr_t) el->el_key.buf); el->el_key.buf = NULL; - /* XXX: provide a function to clear the keys */ - el->el_key.map = NULL; + node__free(el->el_key.map); } @@ -216,7 +211,7 @@ key_add(EditLine *el, const char *key, key_value_t *val, int ntype) * */ protected void -key_clear(EditLine *el, el_action_t *map, char *in) +key_clear(EditLine *el, el_action_t *map, const char *in) { if ((map[(unsigned char)*in] == ED_SEQUENCE_LEAD_IN) && @@ -233,7 +228,7 @@ key_clear(EditLine *el, el_action_t *map, char *in) * they exists. */ protected int -key_delete(EditLine *el, char *key) +key_delete(EditLine *el, const char *key) { if (key[0] == '\0') { @@ -254,7 +249,7 @@ key_delete(EditLine *el, char *key) * Print entire el->el_key.map if null */ protected void -key_print(EditLine *el, char *key) +key_print(EditLine *el, const char *key) { /* do nothing if el->el_key.map is empty and null key specified */ @@ -353,7 +348,8 @@ node__try(EditLine *el, key_node_t *ptr, const char *str, key_value_t *val, int break; case XK_STR: case XK_EXE: - ptr->val.str = strdup(val->str); + if ((ptr->val.str = el_strdup(val->str)) == NULL) + return -1; break; default: EL_ABORT((el->el_errfile, "Bad XK_ type %d\n", ntype)); @@ -373,7 +369,7 @@ node__try(EditLine *el, key_node_t *ptr, const char *str, key_value_t *val, int * Delete node that matches str */ private int -node__delete(EditLine *el, key_node_t **inptr, char *str) +node__delete(EditLine *el, key_node_t **inptr, const char *str) { key_node_t *ptr; key_node_t *prev_ptr = NULL; @@ -468,14 +464,22 @@ node__get(int ch) return (ptr); } - +private void +node__free(key_node_t *k) +{ + if (k == NULL) + return; + node__free(k->sibling); + node__free(k->next); + el_free((ptr_t) k); +} /* node_lookup(): * look for the str starting at node ptr. * Print if last node */ private int -node_lookup(EditLine *el, char *str, key_node_t *ptr, int cnt) +node_lookup(EditLine *el, const char *str, key_node_t *ptr, int cnt) { int ncnt; @@ -565,7 +569,7 @@ node_enum(EditLine *el, key_node_t *ptr, int cnt) * function specified by val */ protected void -key_kprint(EditLine *el, char *key, key_value_t *val, int ntype) +key_kprint(EditLine *el, const char *key, key_value_t *val, int ntype) { el_bindings_t *fp; char unparsbuf[EL_BUFSIZ]; @@ -638,13 +642,15 @@ key__decode_char(char *buf, int cnt, int ch) return (cnt); } + /* key__decode_str(): * Make a printable version of the ey */ protected char * -key__decode_str(char *str, char *buf, char *sep) +key__decode_str(const char *str, char *buf, const char *sep) { - char *b, *p; + char *b; + const char *p; b = buf; if (sep[0] != '\0') diff --git a/lib/libedit/key.h b/lib/libedit/key.h index c6d71881e840..c318788587c4 100644 --- a/lib/libedit/key.h +++ b/lib/libedit/key.h @@ -13,11 +13,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -34,7 +30,7 @@ * SUCH DAMAGE. * * @(#)key.h 8.1 (Berkeley) 6/4/93 - * $NetBSD: key.h,v 1.4 2000/09/04 22:06:30 lukem Exp $ + * $NetBSD: key.h,v 1.8 2003/08/07 16:44:32 agc Exp $ * $FreeBSD$ */ @@ -62,6 +58,10 @@ typedef struct el_key_t { #define XK_NOD 2 #define XK_EXE 3 +#undef key_end +#undef key_clear +#undef key_print + protected int key_init(EditLine *); protected void key_end(EditLine *); protected key_value_t *key_map_cmd(EditLine *, int); @@ -69,10 +69,11 @@ protected key_value_t *key_map_str(EditLine *, char *); protected void key_reset(EditLine *); protected int key_get(EditLine *, char *, key_value_t *); protected void key_add(EditLine *, const char *, key_value_t *, int); -protected void key_clear(EditLine *, el_action_t *, char *); -protected int key_delete(EditLine *, char *); -protected void key_print(EditLine *, char *); -protected void key_kprint(EditLine *, char *, key_value_t *, int); -protected char *key__decode_str(char *, char *, char *); +protected void key_clear(EditLine *, el_action_t *, const char *); +protected int key_delete(EditLine *, const char *); +protected void key_print(EditLine *, const char *); +protected void key_kprint(EditLine *, const char *, key_value_t *, + int); +protected char *key__decode_str(const char *, char *, const char *); #endif /* _h_el_key */ diff --git a/lib/libedit/makelist b/lib/libedit/makelist index 3201a1436c20..75faa417e83c 100644 --- a/lib/libedit/makelist +++ b/lib/libedit/makelist @@ -1,5 +1,5 @@ #!/bin/sh - -# $NetBSD: makelist,v 1.6 2000/09/04 23:45:18 lukem Exp $ +# $NetBSD: makelist,v 1.9 2005/05/16 13:14:43 lukem Exp $ # $FreeBSD$ # # Copyright (c) 1992, 1993 @@ -16,11 +16,7 @@ # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. -# 3. All advertising materials mentioning features or use of this software -# must display the following acknowledgement: -# This product includes software developed by the University of -# California, Berkeley and its contributors. -# 4. Neither the name of the University nor the names of its contributors +# 3. Neither the name of the University nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # @@ -40,7 +36,7 @@ # makelist.sh: Automatically generate header files... -AWK=/usr/bin/awk +AWK=awk USAGE="usage: $0 -h|-e|-fc|-fh|-bc|-bh|-m " if [ "x$1" = "x" ] diff --git a/lib/libedit/map.c b/lib/libedit/map.c index eae4da2a9298..4f225e84545f 100644 --- a/lib/libedit/map.c +++ b/lib/libedit/map.c @@ -13,11 +13,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -33,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $NetBSD: map.c,v 1.13 2001/01/04 15:56:32 christos Exp $ + * $NetBSD: map.c,v 1.20 2004/08/13 12:10:39 mycroft Exp $ */ #if !defined(lint) && !defined(SCCSID) @@ -51,7 +47,7 @@ __FBSDID("$FreeBSD$"); #define N_KEYS 256 -private void map_print_key(EditLine *, el_action_t *, char *); +private void map_print_key(EditLine *, el_action_t *, const char *); private void map_print_some_keys(EditLine *, el_action_t *, int, int); private void map_print_all_keys(EditLine *); private void map_init_nls(EditLine *); @@ -69,7 +65,7 @@ private const el_action_t el_map_emacs[] = { /* 5 */ ED_MOVE_TO_END, /* ^E */ /* 6 */ ED_NEXT_CHAR, /* ^F */ /* 7 */ ED_UNASSIGNED, /* ^G */ - /* 8 */ ED_DELETE_PREV_CHAR, /* ^H */ + /* 8 */ EM_DELETE_PREV_CHAR, /* ^H */ /* 9 */ ED_UNASSIGNED, /* ^I */ /* 10 */ ED_NEWLINE, /* ^J */ /* 11 */ ED_KILL_LINE, /* ^K */ @@ -188,7 +184,7 @@ private const el_action_t el_map_emacs[] = { /* 124 */ ED_INSERT, /* | */ /* 125 */ ED_INSERT, /* } */ /* 126 */ ED_INSERT, /* ~ */ - /* 127 */ ED_DELETE_PREV_CHAR, /* ^? */ + /* 127 */ EM_DELETE_PREV_CHAR, /* ^? */ /* 128 */ ED_UNASSIGNED, /* M-^@ */ /* 129 */ ED_UNASSIGNED, /* M-^A */ /* 130 */ ED_UNASSIGNED, /* M-^B */ @@ -377,7 +373,7 @@ private const el_action_t el_map_vi_insert[] = { /* 5 */ ED_MOVE_TO_END, /* ^E */ /* 6 */ ED_NEXT_CHAR, /* ^F */ /* 7 */ ED_UNASSIGNED, /* ^G */ - /* 8 */ ED_DELETE_PREV_CHAR, /* ^H */ /* BackSpace key */ + /* 8 */ VI_DELETE_PREV_CHAR, /* ^H */ /* BackSpace key */ /* 9 */ ED_UNASSIGNED, /* ^I */ /* Tab Key */ /* 10 */ ED_NEWLINE, /* ^J */ /* 11 */ ED_KILL_LINE, /* ^K */ @@ -497,135 +493,135 @@ private const el_action_t el_map_vi_insert[] = { /* 124 */ ED_INSERT, /* | */ /* 125 */ ED_INSERT, /* } */ /* 126 */ ED_INSERT, /* ~ */ - /* 127 */ ED_DELETE_PREV_CHAR, /* ^? */ - /* 128 */ ED_UNASSIGNED, /* M-^@ */ - /* 129 */ ED_UNASSIGNED, /* M-^A */ - /* 130 */ ED_UNASSIGNED, /* M-^B */ - /* 131 */ ED_UNASSIGNED, /* M-^C */ - /* 132 */ ED_UNASSIGNED, /* M-^D */ - /* 133 */ ED_UNASSIGNED, /* M-^E */ - /* 134 */ ED_UNASSIGNED, /* M-^F */ - /* 135 */ ED_UNASSIGNED, /* M-^G */ - /* 136 */ ED_UNASSIGNED, /* M-^H */ - /* 137 */ ED_UNASSIGNED, /* M-^I */ - /* 138 */ ED_UNASSIGNED, /* M-^J */ - /* 139 */ ED_UNASSIGNED, /* M-^K */ - /* 140 */ ED_UNASSIGNED, /* M-^L */ - /* 141 */ ED_UNASSIGNED, /* M-^M */ - /* 142 */ ED_UNASSIGNED, /* M-^N */ - /* 143 */ ED_UNASSIGNED, /* M-^O */ - /* 144 */ ED_UNASSIGNED, /* M-^P */ - /* 145 */ ED_UNASSIGNED, /* M-^Q */ - /* 146 */ ED_UNASSIGNED, /* M-^R */ - /* 147 */ ED_UNASSIGNED, /* M-^S */ - /* 148 */ ED_UNASSIGNED, /* M-^T */ - /* 149 */ ED_UNASSIGNED, /* M-^U */ - /* 150 */ ED_UNASSIGNED, /* M-^V */ - /* 151 */ ED_UNASSIGNED, /* M-^W */ - /* 152 */ ED_UNASSIGNED, /* M-^X */ - /* 153 */ ED_UNASSIGNED, /* M-^Y */ - /* 154 */ ED_UNASSIGNED, /* M-^Z */ - /* 155 */ ED_UNASSIGNED, /* M-^[ */ - /* 156 */ ED_UNASSIGNED, /* M-^\ */ - /* 157 */ ED_UNASSIGNED, /* M-^] */ - /* 158 */ ED_UNASSIGNED, /* M-^^ */ - /* 159 */ ED_UNASSIGNED, /* M-^_ */ - /* 160 */ ED_UNASSIGNED, /* M-SPACE */ - /* 161 */ ED_UNASSIGNED, /* M-! */ - /* 162 */ ED_UNASSIGNED, /* M-" */ - /* 163 */ ED_UNASSIGNED, /* M-# */ - /* 164 */ ED_UNASSIGNED, /* M-$ */ - /* 165 */ ED_UNASSIGNED, /* M-% */ - /* 166 */ ED_UNASSIGNED, /* M-& */ - /* 167 */ ED_UNASSIGNED, /* M-' */ - /* 168 */ ED_UNASSIGNED, /* M-( */ - /* 169 */ ED_UNASSIGNED, /* M-) */ - /* 170 */ ED_UNASSIGNED, /* M-* */ - /* 171 */ ED_UNASSIGNED, /* M-+ */ - /* 172 */ ED_UNASSIGNED, /* M-, */ - /* 173 */ ED_UNASSIGNED, /* M-- */ - /* 174 */ ED_UNASSIGNED, /* M-. */ - /* 175 */ ED_UNASSIGNED, /* M-/ */ - /* 176 */ ED_UNASSIGNED, /* M-0 */ - /* 177 */ ED_UNASSIGNED, /* M-1 */ - /* 178 */ ED_UNASSIGNED, /* M-2 */ - /* 179 */ ED_UNASSIGNED, /* M-3 */ - /* 180 */ ED_UNASSIGNED, /* M-4 */ - /* 181 */ ED_UNASSIGNED, /* M-5 */ - /* 182 */ ED_UNASSIGNED, /* M-6 */ - /* 183 */ ED_UNASSIGNED, /* M-7 */ - /* 184 */ ED_UNASSIGNED, /* M-8 */ - /* 185 */ ED_UNASSIGNED, /* M-9 */ - /* 186 */ ED_UNASSIGNED, /* M-: */ - /* 187 */ ED_UNASSIGNED, /* M-; */ - /* 188 */ ED_UNASSIGNED, /* M-< */ - /* 189 */ ED_UNASSIGNED, /* M-= */ - /* 190 */ ED_UNASSIGNED, /* M-> */ - /* 191 */ ED_UNASSIGNED, /* M-? */ - /* 192 */ ED_UNASSIGNED, /* M-@ */ - /* 193 */ ED_UNASSIGNED, /* M-A */ - /* 194 */ ED_UNASSIGNED, /* M-B */ - /* 195 */ ED_UNASSIGNED, /* M-C */ - /* 196 */ ED_UNASSIGNED, /* M-D */ - /* 197 */ ED_UNASSIGNED, /* M-E */ - /* 198 */ ED_UNASSIGNED, /* M-F */ - /* 199 */ ED_UNASSIGNED, /* M-G */ - /* 200 */ ED_UNASSIGNED, /* M-H */ - /* 201 */ ED_UNASSIGNED, /* M-I */ - /* 202 */ ED_UNASSIGNED, /* M-J */ - /* 203 */ ED_UNASSIGNED, /* M-K */ - /* 204 */ ED_UNASSIGNED, /* M-L */ - /* 205 */ ED_UNASSIGNED, /* M-M */ - /* 206 */ ED_UNASSIGNED, /* M-N */ - /* 207 */ ED_UNASSIGNED, /* M-O */ - /* 208 */ ED_UNASSIGNED, /* M-P */ - /* 209 */ ED_UNASSIGNED, /* M-Q */ - /* 210 */ ED_UNASSIGNED, /* M-R */ - /* 211 */ ED_UNASSIGNED, /* M-S */ - /* 212 */ ED_UNASSIGNED, /* M-T */ - /* 213 */ ED_UNASSIGNED, /* M-U */ - /* 214 */ ED_UNASSIGNED, /* M-V */ - /* 215 */ ED_UNASSIGNED, /* M-W */ - /* 216 */ ED_UNASSIGNED, /* M-X */ - /* 217 */ ED_UNASSIGNED, /* M-Y */ - /* 218 */ ED_UNASSIGNED, /* M-Z */ - /* 219 */ ED_UNASSIGNED, /* M-[ */ - /* 220 */ ED_UNASSIGNED, /* M-\ */ - /* 221 */ ED_UNASSIGNED, /* M-] */ - /* 222 */ ED_UNASSIGNED, /* M-^ */ - /* 223 */ ED_UNASSIGNED, /* M-_ */ - /* 224 */ ED_UNASSIGNED, /* M-` */ - /* 225 */ ED_UNASSIGNED, /* M-a */ - /* 226 */ ED_UNASSIGNED, /* M-b */ - /* 227 */ ED_UNASSIGNED, /* M-c */ - /* 228 */ ED_UNASSIGNED, /* M-d */ - /* 229 */ ED_UNASSIGNED, /* M-e */ - /* 230 */ ED_UNASSIGNED, /* M-f */ - /* 231 */ ED_UNASSIGNED, /* M-g */ - /* 232 */ ED_UNASSIGNED, /* M-h */ - /* 233 */ ED_UNASSIGNED, /* M-i */ - /* 234 */ ED_UNASSIGNED, /* M-j */ - /* 235 */ ED_UNASSIGNED, /* M-k */ - /* 236 */ ED_UNASSIGNED, /* M-l */ - /* 237 */ ED_UNASSIGNED, /* M-m */ - /* 238 */ ED_UNASSIGNED, /* M-n */ - /* 239 */ ED_UNASSIGNED, /* M-o */ - /* 240 */ ED_UNASSIGNED, /* M-p */ - /* 241 */ ED_UNASSIGNED, /* M-q */ - /* 242 */ ED_UNASSIGNED, /* M-r */ - /* 243 */ ED_UNASSIGNED, /* M-s */ - /* 244 */ ED_UNASSIGNED, /* M-t */ - /* 245 */ ED_UNASSIGNED, /* M-u */ - /* 246 */ ED_UNASSIGNED, /* M-v */ - /* 247 */ ED_UNASSIGNED, /* M-w */ - /* 248 */ ED_UNASSIGNED, /* M-x */ - /* 249 */ ED_UNASSIGNED, /* M-y */ - /* 250 */ ED_UNASSIGNED, /* M-z */ - /* 251 */ ED_UNASSIGNED, /* M-{ */ - /* 252 */ ED_UNASSIGNED, /* M-| */ - /* 253 */ ED_UNASSIGNED, /* M-} */ - /* 254 */ ED_UNASSIGNED, /* M-~ */ - /* 255 */ ED_UNASSIGNED /* M-^? */ + /* 127 */ VI_DELETE_PREV_CHAR, /* ^? */ + /* 128 */ ED_INSERT, /* M-^@ */ + /* 129 */ ED_INSERT, /* M-^A */ + /* 130 */ ED_INSERT, /* M-^B */ + /* 131 */ ED_INSERT, /* M-^C */ + /* 132 */ ED_INSERT, /* M-^D */ + /* 133 */ ED_INSERT, /* M-^E */ + /* 134 */ ED_INSERT, /* M-^F */ + /* 135 */ ED_INSERT, /* M-^G */ + /* 136 */ ED_INSERT, /* M-^H */ + /* 137 */ ED_INSERT, /* M-^I */ + /* 138 */ ED_INSERT, /* M-^J */ + /* 139 */ ED_INSERT, /* M-^K */ + /* 140 */ ED_INSERT, /* M-^L */ + /* 141 */ ED_INSERT, /* M-^M */ + /* 142 */ ED_INSERT, /* M-^N */ + /* 143 */ ED_INSERT, /* M-^O */ + /* 144 */ ED_INSERT, /* M-^P */ + /* 145 */ ED_INSERT, /* M-^Q */ + /* 146 */ ED_INSERT, /* M-^R */ + /* 147 */ ED_INSERT, /* M-^S */ + /* 148 */ ED_INSERT, /* M-^T */ + /* 149 */ ED_INSERT, /* M-^U */ + /* 150 */ ED_INSERT, /* M-^V */ + /* 151 */ ED_INSERT, /* M-^W */ + /* 152 */ ED_INSERT, /* M-^X */ + /* 153 */ ED_INSERT, /* M-^Y */ + /* 154 */ ED_INSERT, /* M-^Z */ + /* 155 */ ED_INSERT, /* M-^[ */ + /* 156 */ ED_INSERT, /* M-^\ */ + /* 157 */ ED_INSERT, /* M-^] */ + /* 158 */ ED_INSERT, /* M-^^ */ + /* 159 */ ED_INSERT, /* M-^_ */ + /* 160 */ ED_INSERT, /* M-SPACE */ + /* 161 */ ED_INSERT, /* M-! */ + /* 162 */ ED_INSERT, /* M-" */ + /* 163 */ ED_INSERT, /* M-# */ + /* 164 */ ED_INSERT, /* M-$ */ + /* 165 */ ED_INSERT, /* M-% */ + /* 166 */ ED_INSERT, /* M-& */ + /* 167 */ ED_INSERT, /* M-' */ + /* 168 */ ED_INSERT, /* M-( */ + /* 169 */ ED_INSERT, /* M-) */ + /* 170 */ ED_INSERT, /* M-* */ + /* 171 */ ED_INSERT, /* M-+ */ + /* 172 */ ED_INSERT, /* M-, */ + /* 173 */ ED_INSERT, /* M-- */ + /* 174 */ ED_INSERT, /* M-. */ + /* 175 */ ED_INSERT, /* M-/ */ + /* 176 */ ED_INSERT, /* M-0 */ + /* 177 */ ED_INSERT, /* M-1 */ + /* 178 */ ED_INSERT, /* M-2 */ + /* 179 */ ED_INSERT, /* M-3 */ + /* 180 */ ED_INSERT, /* M-4 */ + /* 181 */ ED_INSERT, /* M-5 */ + /* 182 */ ED_INSERT, /* M-6 */ + /* 183 */ ED_INSERT, /* M-7 */ + /* 184 */ ED_INSERT, /* M-8 */ + /* 185 */ ED_INSERT, /* M-9 */ + /* 186 */ ED_INSERT, /* M-: */ + /* 187 */ ED_INSERT, /* M-; */ + /* 188 */ ED_INSERT, /* M-< */ + /* 189 */ ED_INSERT, /* M-= */ + /* 190 */ ED_INSERT, /* M-> */ + /* 191 */ ED_INSERT, /* M-? */ + /* 192 */ ED_INSERT, /* M-@ */ + /* 193 */ ED_INSERT, /* M-A */ + /* 194 */ ED_INSERT, /* M-B */ + /* 195 */ ED_INSERT, /* M-C */ + /* 196 */ ED_INSERT, /* M-D */ + /* 197 */ ED_INSERT, /* M-E */ + /* 198 */ ED_INSERT, /* M-F */ + /* 199 */ ED_INSERT, /* M-G */ + /* 200 */ ED_INSERT, /* M-H */ + /* 201 */ ED_INSERT, /* M-I */ + /* 202 */ ED_INSERT, /* M-J */ + /* 203 */ ED_INSERT, /* M-K */ + /* 204 */ ED_INSERT, /* M-L */ + /* 205 */ ED_INSERT, /* M-M */ + /* 206 */ ED_INSERT, /* M-N */ + /* 207 */ ED_INSERT, /* M-O */ + /* 208 */ ED_INSERT, /* M-P */ + /* 209 */ ED_INSERT, /* M-Q */ + /* 210 */ ED_INSERT, /* M-R */ + /* 211 */ ED_INSERT, /* M-S */ + /* 212 */ ED_INSERT, /* M-T */ + /* 213 */ ED_INSERT, /* M-U */ + /* 214 */ ED_INSERT, /* M-V */ + /* 215 */ ED_INSERT, /* M-W */ + /* 216 */ ED_INSERT, /* M-X */ + /* 217 */ ED_INSERT, /* M-Y */ + /* 218 */ ED_INSERT, /* M-Z */ + /* 219 */ ED_INSERT, /* M-[ */ + /* 220 */ ED_INSERT, /* M-\ */ + /* 221 */ ED_INSERT, /* M-] */ + /* 222 */ ED_INSERT, /* M-^ */ + /* 223 */ ED_INSERT, /* M-_ */ + /* 224 */ ED_INSERT, /* M-` */ + /* 225 */ ED_INSERT, /* M-a */ + /* 226 */ ED_INSERT, /* M-b */ + /* 227 */ ED_INSERT, /* M-c */ + /* 228 */ ED_INSERT, /* M-d */ + /* 229 */ ED_INSERT, /* M-e */ + /* 230 */ ED_INSERT, /* M-f */ + /* 231 */ ED_INSERT, /* M-g */ + /* 232 */ ED_INSERT, /* M-h */ + /* 233 */ ED_INSERT, /* M-i */ + /* 234 */ ED_INSERT, /* M-j */ + /* 235 */ ED_INSERT, /* M-k */ + /* 236 */ ED_INSERT, /* M-l */ + /* 237 */ ED_INSERT, /* M-m */ + /* 238 */ ED_INSERT, /* M-n */ + /* 239 */ ED_INSERT, /* M-o */ + /* 240 */ ED_INSERT, /* M-p */ + /* 241 */ ED_INSERT, /* M-q */ + /* 242 */ ED_INSERT, /* M-r */ + /* 243 */ ED_INSERT, /* M-s */ + /* 244 */ ED_INSERT, /* M-t */ + /* 245 */ ED_INSERT, /* M-u */ + /* 246 */ ED_INSERT, /* M-v */ + /* 247 */ ED_INSERT, /* M-w */ + /* 248 */ ED_INSERT, /* M-x */ + /* 249 */ ED_INSERT, /* M-y */ + /* 250 */ ED_INSERT, /* M-z */ + /* 251 */ ED_INSERT, /* M-{ */ + /* 252 */ ED_INSERT, /* M-| */ + /* 253 */ ED_INSERT, /* M-} */ + /* 254 */ ED_INSERT, /* M-~ */ + /* 255 */ ED_INSERT /* M-^? */ }; private const el_action_t el_map_vi_command[] = { @@ -637,7 +633,7 @@ private const el_action_t el_map_vi_command[] = { /* 5 */ ED_MOVE_TO_END, /* ^E */ /* 6 */ ED_UNASSIGNED, /* ^F */ /* 7 */ ED_UNASSIGNED, /* ^G */ - /* 8 */ ED_PREV_CHAR, /* ^H */ + /* 8 */ ED_DELETE_PREV_CHAR, /* ^H */ /* 9 */ ED_UNASSIGNED, /* ^I */ /* 10 */ ED_NEWLINE, /* ^J */ /* 11 */ ED_KILL_LINE, /* ^K */ @@ -664,9 +660,9 @@ private const el_action_t el_map_vi_command[] = { /* 32 */ ED_NEXT_CHAR, /* SPACE */ /* 33 */ ED_UNASSIGNED, /* ! */ /* 34 */ ED_UNASSIGNED, /* " */ - /* 35 */ ED_UNASSIGNED, /* # */ + /* 35 */ VI_COMMENT_OUT, /* # */ /* 36 */ ED_MOVE_TO_END, /* $ */ - /* 37 */ ED_UNASSIGNED, /* % */ + /* 37 */ VI_MATCH, /* % */ /* 38 */ ED_UNASSIGNED, /* & */ /* 39 */ ED_UNASSIGNED, /* ' */ /* 40 */ ED_UNASSIGNED, /* ( */ @@ -675,7 +671,7 @@ private const el_action_t el_map_vi_command[] = { /* 43 */ ED_NEXT_HISTORY, /* + */ /* 44 */ VI_REPEAT_PREV_CHAR, /* , */ /* 45 */ ED_PREV_HISTORY, /* - */ - /* 46 */ ED_UNASSIGNED, /* . */ + /* 46 */ VI_REDO, /* . */ /* 47 */ VI_SEARCH_PREV, /* / */ /* 48 */ VI_ZERO, /* 0 */ /* 49 */ ED_ARGUMENT_DIGIT, /* 1 */ @@ -693,14 +689,14 @@ private const el_action_t el_map_vi_command[] = { /* 61 */ ED_UNASSIGNED, /* = */ /* 62 */ ED_UNASSIGNED, /* > */ /* 63 */ VI_SEARCH_NEXT, /* ? */ - /* 64 */ ED_UNASSIGNED, /* @ */ + /* 64 */ VI_ALIAS, /* @ */ /* 65 */ VI_ADD_AT_EOL, /* A */ - /* 66 */ VI_PREV_SPACE_WORD, /* B */ + /* 66 */ VI_PREV_BIG_WORD, /* B */ /* 67 */ VI_CHANGE_TO_EOL, /* C */ /* 68 */ ED_KILL_LINE, /* D */ - /* 69 */ VI_TO_END_WORD, /* E */ + /* 69 */ VI_END_BIG_WORD, /* E */ /* 70 */ VI_PREV_CHAR, /* F */ - /* 71 */ ED_UNASSIGNED, /* G */ + /* 71 */ VI_TO_HISTORY_LINE, /* G */ /* 72 */ ED_UNASSIGNED, /* H */ /* 73 */ VI_INSERT_AT_BOL, /* I */ /* 74 */ ED_SEARCH_NEXT_HISTORY, /* J */ @@ -716,15 +712,15 @@ private const el_action_t el_map_vi_command[] = { /* 84 */ VI_TO_PREV_CHAR, /* T */ /* 85 */ VI_UNDO_LINE, /* U */ /* 86 */ ED_UNASSIGNED, /* V */ - /* 87 */ VI_NEXT_SPACE_WORD, /* W */ + /* 87 */ VI_NEXT_BIG_WORD, /* W */ /* 88 */ ED_DELETE_PREV_CHAR, /* X */ - /* 89 */ ED_UNASSIGNED, /* Y */ + /* 89 */ VI_YANK_END, /* Y */ /* 90 */ ED_UNASSIGNED, /* Z */ /* 91 */ ED_SEQUENCE_LEAD_IN, /* [ */ /* 92 */ ED_UNASSIGNED, /* \ */ /* 93 */ ED_UNASSIGNED, /* ] */ /* 94 */ ED_MOVE_TO_BEG, /* ^ */ - /* 95 */ ED_UNASSIGNED, /* _ */ + /* 95 */ VI_HISTORY_WORD, /* _ */ /* 96 */ ED_UNASSIGNED, /* ` */ /* 97 */ VI_ADD, /* a */ /* 98 */ VI_PREV_WORD, /* b */ @@ -747,13 +743,13 @@ private const el_action_t el_map_vi_command[] = { /* 115 */ VI_SUBSTITUTE_CHAR, /* s */ /* 116 */ VI_TO_NEXT_CHAR, /* t */ /* 117 */ VI_UNDO, /* u */ - /* 118 */ ED_UNASSIGNED, /* v */ + /* 118 */ VI_HISTEDIT, /* v */ /* 119 */ VI_NEXT_WORD, /* w */ /* 120 */ ED_DELETE_NEXT_CHAR, /* x */ - /* 121 */ ED_UNASSIGNED, /* y */ + /* 121 */ VI_YANK, /* y */ /* 122 */ ED_UNASSIGNED, /* z */ /* 123 */ ED_UNASSIGNED, /* { */ - /* 124 */ ED_UNASSIGNED, /* | */ + /* 124 */ VI_TO_COLUMN, /* | */ /* 125 */ ED_UNASSIGNED, /* } */ /* 126 */ VI_CHANGE_CASE, /* ~ */ /* 127 */ ED_DELETE_PREV_CHAR, /* ^? */ @@ -1124,7 +1120,7 @@ map_get_editor(EditLine *el, const char **editor) * Print the function description for 1 key */ private void -map_print_key(EditLine *el, el_action_t *map, char *in) +map_print_key(EditLine *el, el_action_t *map, const char *in) { char outbuf[EL_BUFSIZ]; el_bindings_t *bp; @@ -1237,14 +1233,14 @@ map_print_all_keys(EditLine *el) * Add/remove/change bindings */ protected int -map_bind(EditLine *el, int argc, char **argv) +map_bind(EditLine *el, int argc, const char **argv) { el_action_t *map; int ntype, rem; - char *p; + const char *p; char inbuf[EL_BUFSIZ]; char outbuf[EL_BUFSIZ]; - char *in = NULL; + const char *in = NULL; char *out = NULL; el_bindings_t *bp; int cmd; diff --git a/lib/libedit/map.h b/lib/libedit/map.h index 5ca7f52b29af..a76d8727b92a 100644 --- a/lib/libedit/map.h +++ b/lib/libedit/map.h @@ -13,11 +13,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -34,7 +30,7 @@ * SUCH DAMAGE. * * @(#)map.h 8.1 (Berkeley) 6/4/93 - * $NetBSD: map.h,v 1.5 2000/09/04 22:06:31 lukem Exp $ + * $NetBSD: map.h,v 1.8 2003/08/07 16:44:32 agc Exp $ * $FreeBSD$ */ @@ -67,7 +63,7 @@ typedef struct el_map_t { #define MAP_EMACS 0 #define MAP_VI 1 -protected int map_bind(EditLine *, int, char **); +protected int map_bind(EditLine *, int, const char **); protected int map_init(EditLine *); protected void map_end(EditLine *); protected void map_init_vi(EditLine *); diff --git a/lib/libedit/parse.c b/lib/libedit/parse.c index f83dc94c6e38..0ffe51d8ec45 100644 --- a/lib/libedit/parse.c +++ b/lib/libedit/parse.c @@ -13,11 +13,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -33,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $NetBSD: parse.c,v 1.13 2000/09/04 22:06:31 lukem Exp $ + * $NetBSD: parse.c,v 1.22 2005/05/29 04:58:15 lukem Exp $ */ #if !defined(lint) && !defined(SCCSID) @@ -57,17 +53,16 @@ __FBSDID("$FreeBSD$"); */ #include "sys.h" #include "el.h" -#include "tokenizer.h" #include private const struct { - char *name; - int (*func)(EditLine *, int, char **); + const char *name; + int (*func)(EditLine *, int, const char **); } cmds[] = { { "bind", map_bind }, { "echotc", term_echotc }, { "edit", el_editmode }, - { "history", hist_list }, + { "history", hist_command }, { "telltc", term_telltc }, { "settc", term_settc }, { "setty", tty_stty }, @@ -81,12 +76,12 @@ private const struct { protected int parse_line(EditLine *el, const char *line) { - char **argv; + const char **argv; int argc; Tokenizer *tok; tok = tok_init(NULL); - tok_line(tok, line, &argc, &argv); + tok_str(tok, line, &argc, &argv); argc = el_parse(el, argc, argv); tok_end(tok); return (argc); @@ -97,9 +92,9 @@ parse_line(EditLine *el, const char *line) * Command dispatcher */ public int -el_parse(EditLine *el, int argc, char *argv[]) +el_parse(EditLine *el, int argc, const char *argv[]) { - char *ptr; + const char *ptr; int i; if (argc < 1) @@ -139,7 +134,7 @@ el_parse(EditLine *el, int argc, char *argv[]) * the appropriate character or -1 if the escape is not valid */ protected int -parse__escape(const char **const ptr) +parse__escape(const char **ptr) { const char *p; int c; @@ -204,7 +199,7 @@ parse__escape(const char **const ptr) c = *p; break; } - } else if (*p == '^' && isascii(p[1]) && (p[1] == '?' || isalpha(p[1]))) { + } else if (*p == '^') { p++; c = (*p == '?') ? '\177' : (*p & 0237); } else @@ -212,6 +207,7 @@ parse__escape(const char **const ptr) *ptr = ++p; return ((unsigned char)c); } + /* parse__string(): * Parse the escapes from in and put the raw string out */ @@ -234,6 +230,14 @@ parse__string(char *out, const char *in) *out++ = n; break; + case 'M': + if (in[1] == '-' && in[2] != '\0') { + *out++ = '\033'; + in += 2; + break; + } + /*FALLTHROUGH*/ + default: *out++ = *in++; break; diff --git a/lib/libedit/parse.h b/lib/libedit/parse.h index 356750d7ad60..cca4abf1999c 100644 --- a/lib/libedit/parse.h +++ b/lib/libedit/parse.h @@ -13,11 +13,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -34,7 +30,7 @@ * SUCH DAMAGE. * * @(#)parse.h 8.1 (Berkeley) 6/4/93 - * $NetBSD: parse.h,v 1.3 1999/07/02 15:21:26 simonb Exp $ + * $NetBSD: parse.h,v 1.6 2005/05/29 04:58:15 lukem Exp $ * $FreeBSD$ */ @@ -45,7 +41,7 @@ #define _h_el_parse protected int parse_line(EditLine *, const char *); -protected int parse__escape(const char ** const); +protected int parse__escape(const char **); protected char *parse__string(char *, const char *); protected int parse_cmd(EditLine *, const char *); diff --git a/lib/libedit/prompt.c b/lib/libedit/prompt.c index 10ba70b2baca..3d72da73e947 100644 --- a/lib/libedit/prompt.c +++ b/lib/libedit/prompt.c @@ -13,11 +13,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -33,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $NetBSD: prompt.c,v 1.7 2000/09/04 22:06:31 lukem Exp $ + * $NetBSD: prompt.c,v 1.11 2003/08/07 16:44:32 agc Exp $ */ #if !defined(lint) && !defined(SCCSID) @@ -57,7 +53,7 @@ private char *prompt_default_r(EditLine *); */ private char * /*ARGSUSED*/ -prompt_default(EditLine *el) +prompt_default(EditLine *el __unused) { static char a[3] = {'?', ' ', '\0'}; @@ -70,7 +66,7 @@ prompt_default(EditLine *el) */ private char * /*ARGSUSED*/ -prompt_default_r(EditLine *el) +prompt_default_r(EditLine *el __unused) { static char a[1] = {'\0'}; @@ -125,7 +121,7 @@ prompt_init(EditLine *el) */ protected void /*ARGSUSED*/ -prompt_end(EditLine *el) +prompt_end(EditLine *el __unused) { } diff --git a/lib/libedit/prompt.h b/lib/libedit/prompt.h index 509c9207cf29..6523add855cd 100644 --- a/lib/libedit/prompt.h +++ b/lib/libedit/prompt.h @@ -13,11 +13,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -34,7 +30,7 @@ * SUCH DAMAGE. * * @(#)prompt.h 8.1 (Berkeley) 6/4/93 - * $NetBSD: prompt.h,v 1.4 1999/11/12 01:05:07 lukem Exp $ + * $NetBSD: prompt.h,v 1.6 2003/08/07 16:44:32 agc Exp $ * $FreeBSD$ */ diff --git a/lib/libedit/read.c b/lib/libedit/read.c index 6b9d71688aa7..4d0b39460cfe 100644 --- a/lib/libedit/read.c +++ b/lib/libedit/read.c @@ -13,11 +13,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -33,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $NetBSD: read.c,v 1.18 2000/11/11 22:18:58 christos Exp $ + * $NetBSD: read.c,v 1.39 2005/08/02 12:11:14 christos Exp $ */ #if !defined(lint) && !defined(SCCSID) @@ -57,8 +53,48 @@ __FBSDID("$FreeBSD$"); private int read__fixio(int, int); private int read_preread(EditLine *); -private int read_getcmd(EditLine *, el_action_t *, char *); private int read_char(EditLine *, char *); +private int read_getcmd(EditLine *, el_action_t *, char *); + +/* read_init(): + * Initialize the read stuff + */ +protected int +read_init(EditLine *el) +{ + /* builtin read_char */ + el->el_read.read_char = read_char; + return 0; +} + + +/* el_read_setfn(): + * Set the read char function to the one provided. + * If it is set to EL_BUILTIN_GETCFN, then reset to the builtin one. + */ +protected int +el_read_setfn(EditLine *el, el_rfunc_t rc) +{ + el->el_read.read_char = (rc == EL_BUILTIN_GETCFN) ? read_char : rc; + return 0; +} + + +/* el_read_getfn(): + * return the current read char function, or EL_BUILTIN_GETCFN + * if it is the default one + */ +protected el_rfunc_t +el_read_getfn(EditLine *el) +{ + return (el->el_read.read_char == read_char) ? + EL_BUILTIN_GETCFN : el->el_read.read_char; +} + + +#ifndef MIN +#define MIN(A,B) ((A) < (B) ? (A) : (B)) +#endif #ifdef DEBUG_EDIT private void @@ -84,7 +120,7 @@ read_debug(EditLine *el) */ /* ARGSUSED */ private int -read__fixio(int fd, int e) +read__fixio(int fd __unused, int e) { switch (e) { @@ -149,10 +185,6 @@ read_preread(EditLine *el) { int chrs = 0; - if (el->el_chared.c_macro.nline) { - el_free((ptr_t) el->el_chared.c_macro.nline); - el->el_chared.c_macro.nline = NULL; - } if (el->el_tty.t_mode == ED_IO) return (0); @@ -165,8 +197,7 @@ read_preread(EditLine *el) (size_t) MIN(chrs, EL_BUFSIZ - 1)); if (chrs > 0) { buf[chrs] = '\0'; - el->el_chared.c_macro.nline = strdup(buf); - el_push(el, el->el_chared.c_macro.nline); + el_push(el, buf); } } #endif /* FIONREAD */ @@ -179,18 +210,18 @@ read_preread(EditLine *el) * Push a macro */ public void -el_push(EditLine *el, const char *str) +el_push(EditLine *el, char *str) { c_macro_t *ma = &el->el_chared.c_macro; if (str != NULL && ma->level + 1 < EL_MAXMACRO) { ma->level++; - /* LINTED const cast */ - ma->macro[ma->level] = (char *) str; - } else { - term_beep(el); - term__flush(); + if ((ma->macro[ma->level] = el_strdup(str)) != NULL) + return; + ma->level--; } + term_beep(el); + term__flush(); } @@ -200,10 +231,10 @@ el_push(EditLine *el, const char *str) private int read_getcmd(EditLine *el, el_action_t *cmdnum, char *ch) { - el_action_t cmd = ED_UNASSIGNED; + el_action_t cmd; int num; - while (cmd == ED_UNASSIGNED || cmd == ED_SEQUENCE_LEAD_IN) { + do { if ((num = el_getc(el, ch)) != 1) /* if EOF or error */ return (num); @@ -242,7 +273,7 @@ read_getcmd(EditLine *el, el_action_t *cmdnum, char *ch) } if (el->el_map.alt == NULL) el->el_map.current = el->el_map.key; - } + } while (cmd == ED_SEQUENCE_LEAD_IN); *cmdnum = cmd; return (OKCMD); } @@ -287,14 +318,16 @@ el_getc(EditLine *el, char *cp) if (ma->level < 0) break; - if (*ma->macro[ma->level] == 0) { - ma->level--; + if (ma->macro[ma->level][ma->offset] == '\0') { + el_free(ma->macro[ma->level--]); + ma->offset = 0; continue; } - *cp = *ma->macro[ma->level]++ & 0377; - if (*ma->macro[ma->level] == 0) { /* Needed for QuoteMode - * On */ - ma->level--; + *cp = ma->macro[ma->level][ma->offset++] & 0377; + if (ma->macro[ma->level][ma->offset] == '\0') { + /* Needed for QuoteMode On */ + el_free(ma->macro[ma->level--]); + ma->offset = 0; } return (1); } @@ -308,13 +341,42 @@ el_getc(EditLine *el, char *cp) #ifdef DEBUG_READ (void) fprintf(el->el_errfile, "Reading a character\n"); #endif /* DEBUG_READ */ - num_read = read_char(el, cp); + num_read = (*el->el_read.read_char)(el, cp); #ifdef DEBUG_READ (void) fprintf(el->el_errfile, "Got it %c\n", *cp); #endif /* DEBUG_READ */ return (num_read); } +protected void +read_prepare(EditLine *el) +{ + if (el->el_flags & HANDLE_SIGNALS) + sig_set(el); + if (el->el_flags & NO_TTY) + return; + if ((el->el_flags & (UNBUFFERED|EDIT_DISABLED)) == UNBUFFERED) + tty_rawmode(el); + + /* This is relatively cheap, and things go terribly wrong if + we have the wrong size. */ + el_resize(el); + re_clear_display(el); /* reset the display stuff */ + ch_reset(el, 0); + re_refresh(el); /* print the prompt */ + + if (el->el_flags & UNBUFFERED) + term__flush(); +} + +protected void +read_finish(EditLine *el) +{ + if ((el->el_flags & UNBUFFERED) == 0) + (void) tty_cookedmode(el); + if (el->el_flags & HANDLE_SIGNALS) + sig_clr(el); +} public const char * el_gets(EditLine *el, int *nread) @@ -323,18 +385,16 @@ el_gets(EditLine *el, int *nread) el_action_t cmdnum = 0; int num; /* how many chars we have read at NL */ char ch; + int crlf = 0; #ifdef FIONREAD c_macro_t *ma = &el->el_chared.c_macro; #endif /* FIONREAD */ - if (el->el_flags & HANDLE_SIGNALS) - sig_set(el); - if (el->el_flags & NO_TTY) { char *cp = el->el_line.buffer; size_t idx; - while (read_char(el, cp) == 1) { + while ((*el->el_read.read_char)(el, cp) == 1) { /* make sure there is space for next character */ if (cp + 1 >= el->el_line.limit) { idx = (cp - el->el_line.buffer); @@ -343,6 +403,8 @@ el_gets(EditLine *el, int *nread) cp = &el->el_line.buffer[idx]; } cp++; + if (el->el_flags & UNBUFFERED) + break; if (cp[-1] == '\r' || cp[-1] == '\n') break; } @@ -353,8 +415,7 @@ el_gets(EditLine *el, int *nread) *nread = el->el_line.cursor - el->el_line.buffer; return (el->el_line.buffer); } - re_clear_display(el); /* reset the display stuff */ - ch_reset(el); + #ifdef FIONREAD if (el->el_tty.t_mode == EX_IO && ma->level < 0) { @@ -371,15 +432,20 @@ el_gets(EditLine *el, int *nread) } #endif /* FIONREAD */ - re_refresh(el); /* print the prompt */ + if ((el->el_flags & UNBUFFERED) == 0) + read_prepare(el); if (el->el_flags & EDIT_DISABLED) { - char *cp = el->el_line.buffer; + char *cp; size_t idx; + if ((el->el_flags & UNBUFFERED) == 0) + cp = el->el_line.buffer; + else + cp = el->el_line.lastchar; term__flush(); - while (read_char(el, cp) == 1) { + while ((*el->el_read.read_char)(el, cp) == 1) { /* make sure there is space next character */ if (cp + 1 >= el->el_line.limit) { idx = (cp - el->el_line.buffer); @@ -387,8 +453,13 @@ el_gets(EditLine *el, int *nread) break; cp = &el->el_line.buffer[idx]; } + if (*cp == 4) /* ought to be stty eof */ + break; cp++; - if (cp[-1] == '\r' || cp[-1] == '\n') + crlf = cp[-1] == '\r' || cp[-1] == '\n'; + if (el->el_flags & UNBUFFERED) + break; + if (crlf) break; } @@ -398,6 +469,7 @@ el_gets(EditLine *el, int *nread) *nread = el->el_line.cursor - el->el_line.buffer; return (el->el_line.buffer); } + for (num = OKCMD; num == OKCMD;) { /* while still editing this * line */ #ifdef DEBUG_EDIT @@ -411,7 +483,7 @@ el_gets(EditLine *el, int *nread) #endif /* DEBUG_READ */ break; } - if ((int) cmdnum >= el->el_map.nfunc) { /* BUG CHECK command */ + if ((unsigned int)cmdnum >= el->el_map.nfunc) { /* BUG CHECK command */ #ifdef DEBUG_EDIT (void) fprintf(el->el_errfile, "ERROR: illegal command from key 0%o\r\n", ch); @@ -433,7 +505,24 @@ el_gets(EditLine *el, int *nread) "Error command = %d\n", cmdnum); } #endif /* DEBUG_READ */ + /* vi redo needs these way down the levels... */ + el->el_state.thiscmd = cmdnum; + el->el_state.thisch = ch; + if (el->el_map.type == MAP_VI && + el->el_map.current == el->el_map.key && + el->el_chared.c_redo.pos < el->el_chared.c_redo.lim) { + if (cmdnum == VI_DELETE_PREV_CHAR && + el->el_chared.c_redo.pos != el->el_chared.c_redo.buf + && isprint((unsigned char)el->el_chared.c_redo.pos[-1])) + el->el_chared.c_redo.pos--; + else + *el->el_chared.c_redo.pos++ = ch; + } retval = (*el->el_map.func[cmdnum]) (el, ch); +#ifdef DEBUG_READ + (void) fprintf(el->el_errfile, + "Returned state %d\n", retval ); +#endif /* DEBUG_READ */ /* save the last command here */ el->el_state.lastcmd = cmdnum; @@ -441,8 +530,6 @@ el_gets(EditLine *el, int *nread) /* use any return value */ switch (retval) { case CC_CURSOR: - el->el_state.argument = 1; - el->el_state.doingarg = 0; re_refresh_cursor(el); break; @@ -452,29 +539,29 @@ el_gets(EditLine *el, int *nread) /* FALLTHROUGH */ case CC_REFRESH: - el->el_state.argument = 1; - el->el_state.doingarg = 0; re_refresh(el); break; case CC_REFRESH_BEEP: - el->el_state.argument = 1; - el->el_state.doingarg = 0; re_refresh(el); term_beep(el); break; case CC_NORM: /* normal char */ - el->el_state.argument = 1; - el->el_state.doingarg = 0; break; case CC_ARGHACK: /* Suggested by Rich Salz */ /* */ - break; /* keep going... */ + continue; /* keep going... */ case CC_EOF: /* end of file typed */ - num = 0; + if ((el->el_flags & UNBUFFERED) == 0) + num = 0; + else if (num == -1) { + *el->el_line.lastchar++ = CONTROL('d'); + el->el_line.cursor = el->el_line.lastchar; + num = 1; + } break; case CC_NEWLINE: /* normal end of line */ @@ -488,10 +575,8 @@ el_gets(EditLine *el, int *nread) #endif /* DEBUG_READ */ /* put (real) cursor in a known place */ re_clear_display(el); /* reset the display stuff */ - ch_reset(el); /* reset the input pointers */ + ch_reset(el, 1); /* reset the input pointers */ re_refresh(el); /* print the prompt again */ - el->el_state.argument = 1; - el->el_state.doingarg = 0; break; case CC_ERROR: @@ -500,20 +585,26 @@ el_gets(EditLine *el, int *nread) (void) fprintf(el->el_errfile, "*** editor ERROR ***\r\n\n"); #endif /* DEBUG_READ */ - el->el_state.argument = 1; - el->el_state.doingarg = 0; term_beep(el); term__flush(); break; } + el->el_state.argument = 1; + el->el_state.doingarg = 0; + el->el_chared.c_vcmd.action = NOP; + if (el->el_flags & UNBUFFERED) + break; } term__flush(); /* flush any buffered output */ - /* make sure the tty is set up correctly */ - (void) tty_cookedmode(el); - if (el->el_flags & HANDLE_SIGNALS) - sig_clr(el); - if (nread) - *nread = num; + /* make sure the tty is set up correctly */ + if ((el->el_flags & UNBUFFERED) == 0) { + read_finish(el); + if (nread) + *nread = num; + } else { + if (nread) + *nread = el->el_line.lastchar - el->el_line.buffer; + } return (num ? el->el_line.buffer : NULL); } diff --git a/lib/libedit/read.h b/lib/libedit/read.h new file mode 100644 index 000000000000..e4a87991f7d9 --- /dev/null +++ b/lib/libedit/read.h @@ -0,0 +1,58 @@ +/*- + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Anthony Mallet. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $NetBSD: read.h,v 1.4 2004/02/27 14:52:18 christos Exp $ + * $FreeBSD$ + */ + +/* + * el.read.h: Character reading functions + */ +#ifndef _h_el_read +#define _h_el_read + +typedef int (*el_rfunc_t)(EditLine *, char *); + +typedef struct el_read_t { + el_rfunc_t read_char; /* Function to read a character */ +} el_read_t; + +protected int read_init(EditLine *); +protected void read_prepare(EditLine *); +protected void read_finish(EditLine *); +protected int el_read_setfn(EditLine *, el_rfunc_t); +protected el_rfunc_t el_read_getfn(EditLine *); + +#endif /* _h_el_read */ diff --git a/lib/libedit/refresh.c b/lib/libedit/refresh.c index 08f1336e203a..72556545507e 100644 --- a/lib/libedit/refresh.c +++ b/lib/libedit/refresh.c @@ -13,11 +13,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -33,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $NetBSD: refresh.c,v 1.16 2001/01/10 07:45:42 jdolecek Exp $ + * $NetBSD: refresh.c,v 1.26 2003/08/07 16:44:33 agc Exp $ */ #if !defined(lint) && !defined(SCCSID) @@ -47,6 +43,7 @@ __FBSDID("$FreeBSD$"); */ #include "sys.h" #include +#include #include #include @@ -58,24 +55,24 @@ private void re_insert (EditLine *, char *, int, int, char *, int); private void re_delete(EditLine *, char *, int, int, int); private void re_fastputc(EditLine *, int); private void re__strncopy(char *, char *, size_t); -private void re__copy_and_pad(char *, char *, size_t); +private void re__copy_and_pad(char *, const char *, size_t); #ifdef DEBUG_REFRESH -private void re_printstr(EditLine *, char *, char *, char *); +private void re_printstr(EditLine *, const char *, char *, char *); #define __F el->el_errfile #define ELRE_ASSERT(a, b, c) do \ - if (a) { \ + if (/*CONSTCOND*/ a) { \ (void) fprintf b; \ c; \ } \ - while (0) + while (/*CONSTCOND*/0) #define ELRE_DEBUG(a, b) ELRE_ASSERT(a,b,;) /* re_printstr(): * Print a string on the debugging pty */ private void -re_printstr(EditLine *el, char *str, char *f, char *t) +re_printstr(EditLine *el, const char *str, char *f, char *t) { ELRE_DEBUG(1, (__F, "%s:\"", str)); @@ -96,8 +93,6 @@ private void re_addc(EditLine *el, int c) { - c = (unsigned char)c; - if (isprint(c)) { re_putc(el, c, 1); return; @@ -208,6 +203,14 @@ re_refresh(EditLine *el) el->el_refresh.r_cursor.h = 0; el->el_refresh.r_cursor.v = 0; + if (el->el_line.cursor >= el->el_line.lastchar) { + if (el->el_map.current == el->el_map.alt + && el->el_line.lastchar != el->el_line.buffer) + el->el_line.cursor = el->el_line.lastchar - 1; + else + el->el_line.cursor = el->el_line.lastchar; + } + cur.h = -1; /* set flag in case I'm not set */ cur.v = 0; @@ -317,7 +320,6 @@ re_goto_bottom(EditLine *el) { term_move_to_line(el, el->el_refresh.r_oldcv); - term__putc('\r'); term__putc('\n'); re_clear_display(el); term__flush(); @@ -330,7 +332,8 @@ re_goto_bottom(EditLine *el) */ private void /*ARGSUSED*/ -re_insert(EditLine *el, char *d, int dat, int dlen, char *s, int num) +re_insert(EditLine *el __unused, + char *d, int dat, int dlen, char *s, int num) { char *a, *b; @@ -373,7 +376,8 @@ re_insert(EditLine *el, char *d, int dat, int dlen, char *s, int num) */ private void /*ARGSUSED*/ -re_delete(EditLine *el, char *d, int dat, int dlen, int num) +re_delete(EditLine *el __unused, + char *d, int dat, int dlen, int num) { char *a, *b; @@ -906,9 +910,9 @@ re_update_line(EditLine *el, char *old, char *new, int i) * Copy string and pad with spaces */ private void -re__copy_and_pad(char *dst, char *src, size_t width) +re__copy_and_pad(char *dst, const char *src, size_t width) { - int i; + size_t i; for (i = 0; i < width; i++) { if (*src == '\0') @@ -932,6 +936,14 @@ re_refresh_cursor(EditLine *el) char *cp, c; int h, v, th; + if (el->el_line.cursor >= el->el_line.lastchar) { + if (el->el_map.current == el->el_map.alt + && el->el_line.lastchar != el->el_line.buffer) + el->el_line.cursor = el->el_line.lastchar - 1; + else + el->el_line.cursor = el->el_line.lastchar; + } + /* first we must find where the cursor is... */ h = el->el_prompt.p_pos.h; v = el->el_prompt.p_pos.v; @@ -939,7 +951,7 @@ re_refresh_cursor(EditLine *el) /* do input buffer to el->el_line.cursor */ for (cp = el->el_line.buffer; cp < el->el_line.cursor; cp++) { - c = (unsigned char)*cp; + c = *cp; h++; /* all chars at least this long */ if (c == '\n') {/* handle newline in data part too */ @@ -1054,8 +1066,8 @@ re_fastaddc(EditLine *el) re_fastputc(el, c); } else { re_fastputc(el, '\\'); - re_fastputc(el, (int) ((((unsigned int) c >> 6) & 7) + '0')); - re_fastputc(el, (int) ((((unsigned int) c >> 3) & 7) + '0')); + re_fastputc(el, (int)(((((unsigned int)c) >> 6) & 3) + '0')); + re_fastputc(el, (int)(((((unsigned int)c) >> 3) & 7) + '0')); re_fastputc(el, (c & 7) + '0'); } term__flush(); diff --git a/lib/libedit/refresh.h b/lib/libedit/refresh.h index 516f3ad2825c..e44ef9c5f274 100644 --- a/lib/libedit/refresh.h +++ b/lib/libedit/refresh.h @@ -13,11 +13,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -34,7 +30,7 @@ * SUCH DAMAGE. * * @(#)refresh.h 8.1 (Berkeley) 6/4/93 - * $NetBSD: refresh.h,v 1.3 2000/09/04 22:06:32 lukem Exp $ + * $NetBSD: refresh.h,v 1.5 2003/08/07 16:44:33 agc Exp $ * $FreeBSD$ */ diff --git a/lib/libedit/search.c b/lib/libedit/search.c index 96a0206bd285..991bad246141 100644 --- a/lib/libedit/search.c +++ b/lib/libedit/search.c @@ -13,11 +13,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -33,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $NetBSD: search.c,v 1.10 2001/01/04 15:56:32 christos Exp $ + * $NetBSD: search.c,v 1.20 2004/11/04 01:16:03 christos Exp $ */ #if !defined(lint) && !defined(SCCSID) @@ -74,7 +70,8 @@ search_init(EditLine *el) el->el_search.patlen = 0; el->el_search.patdir = -1; el->el_search.chacha = '\0'; - el->el_search.chadir = -1; + el->el_search.chadir = CHAR_FWD; + el->el_search.chatflg = 0; return (0); } @@ -223,8 +220,11 @@ ce_inc_search(EditLine *el, int dir) if (el->el_search.patlen == 0) { /* first round */ pchar = ':'; #ifdef ANCHOR +#define LEN 2 el->el_search.patbuf[el->el_search.patlen++] = '.'; el->el_search.patbuf[el->el_search.patlen++] = '*'; +#else +#define LEN 0 #endif } done = redo = 0; @@ -233,7 +233,7 @@ ce_inc_search(EditLine *el, int dir) *cp; *el->el_line.lastchar++ = *cp++) continue; *el->el_line.lastchar++ = pchar; - for (cp = &el->el_search.patbuf[1]; + for (cp = &el->el_search.patbuf[LEN]; cp < &el->el_search.patbuf[el->el_search.patlen]; *el->el_line.lastchar++ = *cp++) continue; @@ -246,7 +246,7 @@ ce_inc_search(EditLine *el, int dir) switch (el->el_map.current[(unsigned char) ch]) { case ED_INSERT: case ED_DIGIT: - if (el->el_search.patlen > EL_BUFSIZ - 3) + if (el->el_search.patlen >= EL_BUFSIZ - LEN) term_beep(el); else { el->el_search.patbuf[el->el_search.patlen++] = @@ -267,8 +267,9 @@ ce_inc_search(EditLine *el, int dir) redo++; break; + case EM_DELETE_PREV_CHAR: case ED_DELETE_PREV_CHAR: - if (el->el_search.patlen > 1) + if (el->el_search.patlen > LEN) done++; else term_beep(el); @@ -283,17 +284,18 @@ ce_inc_search(EditLine *el, int dir) case 0027: /* ^W: Append word */ /* No can do if globbing characters in pattern */ - for (cp = &el->el_search.patbuf[1];; cp++) - if (cp >= &el->el_search.patbuf[el->el_search.patlen]) { + for (cp = &el->el_search.patbuf[LEN];; cp++) + if (cp >= &el->el_search.patbuf[ + el->el_search.patlen]) { el->el_line.cursor += - el->el_search.patlen - 1; + el->el_search.patlen - LEN - 1; cp = c__next_word(el->el_line.cursor, el->el_line.lastchar, 1, ce__isword); while (el->el_line.cursor < cp && *el->el_line.cursor != '\n') { - if (el->el_search.patlen > - EL_BUFSIZ - 3) { + if (el->el_search.patlen >= + EL_BUFSIZ - LEN) { term_beep(el); break; } @@ -335,13 +337,13 @@ ce_inc_search(EditLine *el, int dir) /* Can't search if unmatched '[' */ for (cp = &el->el_search.patbuf[el->el_search.patlen-1], ch = ']'; - cp > el->el_search.patbuf; + cp >= &el->el_search.patbuf[LEN]; cp--) if (*cp == '[' || *cp == ']') { ch = *cp; break; } - if (el->el_search.patlen > 1 && ch != '[') { + if (el->el_search.patlen > LEN && ch != '[') { if (redo && newdir == dir) { if (pchar == '?') { /* wrap around */ el->el_history.eventno = @@ -371,9 +373,8 @@ ce_inc_search(EditLine *el, int dir) '\0'; if (el->el_line.cursor < el->el_line.buffer || el->el_line.cursor > el->el_line.lastchar || - (ret = ce_search_line(el, - &el->el_search.patbuf[1], - newdir)) == CC_ERROR) { + (ret = ce_search_line(el, newdir)) + == CC_ERROR) { /* avoid c_setpat */ el->el_state.lastcmd = (el_action_t) newdir; @@ -386,11 +387,11 @@ ce_inc_search(EditLine *el, int dir) el->el_line.lastchar : el->el_line.buffer; (void) ce_search_line(el, - &el->el_search.patbuf[1], newdir); } } - el->el_search.patbuf[--el->el_search.patlen] = + el->el_search.patlen -= LEN; + el->el_search.patbuf[el->el_search.patlen] = '\0'; if (ret == CC_ERROR) { term_beep(el); @@ -446,29 +447,20 @@ cv_search(EditLine *el, int dir) char tmpbuf[EL_BUFSIZ]; int tmplen; - tmplen = 0; #ifdef ANCHOR - tmpbuf[tmplen++] = '.'; - tmpbuf[tmplen++] = '*'; + tmpbuf[0] = '.'; + tmpbuf[1] = '*'; #endif + tmplen = LEN; - el->el_line.buffer[0] = '\0'; - el->el_line.lastchar = el->el_line.buffer; - el->el_line.cursor = el->el_line.buffer; el->el_search.patdir = dir; - c_insert(el, 2); /* prompt + '\n' */ - *el->el_line.cursor++ = '\n'; - *el->el_line.cursor++ = dir == ED_SEARCH_PREV_HISTORY ? '/' : '?'; - re_refresh(el); - -#ifdef ANCHOR -#define LEN 2 -#else -#define LEN 0 -#endif + tmplen = c_gets(el, &tmpbuf[LEN], + dir == ED_SEARCH_PREV_HISTORY ? "\n/" : "\n?" ); + if (tmplen == -1) + return CC_REFRESH; - tmplen = c_gets(el, &tmpbuf[LEN]) + LEN; + tmplen += LEN; ch = tmpbuf[tmplen]; tmpbuf[tmplen] = '\0'; @@ -477,9 +469,6 @@ cv_search(EditLine *el, int dir) * Use the old pattern, but wild-card it. */ if (el->el_search.patlen == 0) { - el->el_line.buffer[0] = '\0'; - el->el_line.lastchar = el->el_line.buffer; - el->el_line.cursor = el->el_line.buffer; re_refresh(el); return (CC_ERROR); } @@ -510,19 +499,15 @@ cv_search(EditLine *el, int dir) el->el_state.lastcmd = (el_action_t) dir; /* avoid c_setpat */ el->el_line.cursor = el->el_line.lastchar = el->el_line.buffer; if ((dir == ED_SEARCH_PREV_HISTORY ? ed_search_prev_history(el, 0) : - ed_search_next_history(el, 0)) == CC_ERROR) { + ed_search_next_history(el, 0)) == CC_ERROR) { re_refresh(el); return (CC_ERROR); - } else { - if (ch == 0033) { - re_refresh(el); - *el->el_line.lastchar++ = '\n'; - *el->el_line.lastchar = '\0'; - re_goto_bottom(el); - return (CC_NEWLINE); - } else - return (CC_REFRESH); } + if (ch == 0033) { + re_refresh(el); + return ed_newline(el, 0); + } + return (CC_REFRESH); } @@ -530,24 +515,39 @@ cv_search(EditLine *el, int dir) * Look for a pattern inside a line */ protected el_action_t -ce_search_line(EditLine *el, char *pattern, int dir) +ce_search_line(EditLine *el, int dir) { - char *cp; + char *cp = el->el_line.cursor; + char *pattern = el->el_search.patbuf; + char oc, *ocp; +#ifdef ANCHOR + ocp = &pattern[1]; + oc = *ocp; + *ocp = '^'; +#else + ocp = pattern; + oc = *ocp; +#endif if (dir == ED_SEARCH_PREV_HISTORY) { - for (cp = el->el_line.cursor; cp >= el->el_line.buffer; cp--) - if (el_match(cp, pattern)) { + for (; cp >= el->el_line.buffer; cp--) { + if (el_match(cp, ocp)) { + *ocp = oc; el->el_line.cursor = cp; return (CC_NORM); } + } + *ocp = oc; return (CC_ERROR); } else { - for (cp = el->el_line.cursor; *cp != '\0' && - cp < el->el_line.limit; cp++) - if (el_match(cp, pattern)) { + for (; *cp != '\0' && cp < el->el_line.limit; cp++) { + if (el_match(cp, ocp)) { + *ocp = oc; el->el_line.cursor = cp; return (CC_NORM); } + } + *ocp = oc; return (CC_ERROR); } } @@ -579,69 +579,53 @@ cv_repeat_srch(EditLine *el, int c) } -/* cv_csearch_back(): - * Vi character search reverse +/* cv_csearch(): + * Vi character search */ protected el_action_t -cv_csearch_back(EditLine *el, int ch, int count, int tflag) +cv_csearch(EditLine *el, int direction, int ch, int count, int tflag) { char *cp; - cp = el->el_line.cursor; - while (count--) { - if (*cp == ch) - cp--; - while (cp > el->el_line.buffer && *cp != ch) - cp--; - } + if (ch == 0) + return CC_ERROR; - if (cp < el->el_line.buffer || (cp == el->el_line.buffer && *cp != ch)) - return (CC_ERROR); - - if (*cp == ch && tflag) - cp++; - - el->el_line.cursor = cp; - - if (el->el_chared.c_vcmd.action & DELETE) { - el->el_line.cursor++; - cv_delfini(el); - return (CC_REFRESH); + if (ch == -1) { + char c; + if (el_getc(el, &c) != 1) + return ed_end_of_file(el, 0); + ch = c; } - re_refresh_cursor(el); - return (CC_NORM); -} - -/* cv_csearch_fwd(): - * Vi character search forward - */ -protected el_action_t -cv_csearch_fwd(EditLine *el, int ch, int count, int tflag) -{ - char *cp; + /* Save for ';' and ',' commands */ + el->el_search.chacha = ch; + el->el_search.chadir = direction; + el->el_search.chatflg = tflag; cp = el->el_line.cursor; while (count--) { if (*cp == ch) - cp++; - while (cp < el->el_line.lastchar && *cp != ch) - cp++; + cp += direction; + for (;;cp += direction) { + if (cp >= el->el_line.lastchar) + return CC_ERROR; + if (cp < el->el_line.buffer) + return CC_ERROR; + if (*cp == ch) + break; + } } - if (cp >= el->el_line.lastchar) - return (CC_ERROR); - - if (*cp == ch && tflag) - cp--; + if (tflag) + cp -= direction; el->el_line.cursor = cp; - if (el->el_chared.c_vcmd.action & DELETE) { - el->el_line.cursor++; + if (el->el_chared.c_vcmd.action != NOP) { + if (direction > 0) + el->el_line.cursor++; cv_delfini(el); - return (CC_REFRESH); + return CC_REFRESH; } - re_refresh_cursor(el); - return (CC_NORM); + return CC_CURSOR; } diff --git a/lib/libedit/search.h b/lib/libedit/search.h index 8f9594a0d0be..725af7cadacd 100644 --- a/lib/libedit/search.h +++ b/lib/libedit/search.h @@ -13,11 +13,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -34,7 +30,7 @@ * SUCH DAMAGE. * * @(#)search.h 8.1 (Berkeley) 6/4/93 - * $NetBSD: search.h,v 1.4 1999/07/02 15:21:27 simonb Exp $ + * $NetBSD: search.h,v 1.8 2003/10/18 23:27:36 christos Exp $ * $FreeBSD$ */ @@ -52,6 +48,7 @@ typedef struct el_search_t { int patdir; /* Direction of the last search */ int chadir; /* Character search direction */ char chacha; /* Character we are looking for */ + char chatflg; /* 0 if f, 1 if t */ } el_search_t; @@ -62,9 +59,8 @@ protected int c_hmatch(EditLine *, const char *); protected void c_setpat(EditLine *); protected el_action_t ce_inc_search(EditLine *, int); protected el_action_t cv_search(EditLine *, int); -protected el_action_t ce_search_line(EditLine *, char *, int); +protected el_action_t ce_search_line(EditLine *, int); protected el_action_t cv_repeat_srch(EditLine *, int); -protected el_action_t cv_csearch_back(EditLine *, int, int, int); -protected el_action_t cv_csearch_fwd(EditLine *, int, int, int); +protected el_action_t cv_csearch(EditLine *, int, int, int, int); #endif /* _h_el_search */ diff --git a/lib/libedit/sig.c b/lib/libedit/sig.c index 55bebb03b59c..a895aeabb158 100644 --- a/lib/libedit/sig.c +++ b/lib/libedit/sig.c @@ -13,11 +13,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -33,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $NetBSD: sig.c,v 1.7 2001/01/04 15:55:03 christos Exp $ + * $NetBSD: sig.c,v 1.11 2003/08/07 16:44:33 agc Exp $ */ #if !defined(lint) && !defined(SCCSID) @@ -119,9 +115,9 @@ sig_init(EditLine *el) #undef _DO (void) sigprocmask(SIG_BLOCK, &nset, &oset); -#define SIGSIZE (sizeof(sighdl) / sizeof(sighdl[0]) * sizeof(sig_t)) +#define SIGSIZE (sizeof(sighdl) / sizeof(sighdl[0]) * sizeof(el_signalhandler_t)) - el->el_signal = (sig_t *) el_malloc(SIGSIZE); + el->el_signal = (el_signalhandler_t *) el_malloc(SIGSIZE); if (el->el_signal == NULL) return (-1); for (i = 0; sighdl[i] != -1; i++) @@ -161,7 +157,7 @@ sig_set(EditLine *el) (void) sigprocmask(SIG_BLOCK, &nset, &oset); for (i = 0; sighdl[i] != -1; i++) { - sig_t s; + el_signalhandler_t s; /* This could happen if we get interrupted */ if ((s = signal(sighdl[i], sig_handler)) != sig_handler) el->el_signal[i] = s; diff --git a/lib/libedit/sig.h b/lib/libedit/sig.h index 80910658c856..b1ce14b09096 100644 --- a/lib/libedit/sig.h +++ b/lib/libedit/sig.h @@ -13,11 +13,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -34,7 +30,7 @@ * SUCH DAMAGE. * * @(#)sig.h 8.1 (Berkeley) 6/4/93 - * $NetBSD: sig.h,v 1.2 1997/01/11 06:48:11 lukem Exp $ + * $NetBSD: sig.h,v 1.5 2003/08/07 16:44:33 agc Exp $ * $FreeBSD$ */ @@ -62,7 +58,8 @@ _DO(SIGCONT) \ _DO(SIGWINCH) -typedef sig_t *el_signal_t; +typedef void (*el_signalhandler_t)(int); +typedef el_signalhandler_t *el_signal_t; protected void sig_end(EditLine*); protected int sig_init(EditLine*); diff --git a/lib/libedit/sys.h b/lib/libedit/sys.h index 894f59e8ec66..323aebe4dafa 100644 --- a/lib/libedit/sys.h +++ b/lib/libedit/sys.h @@ -13,11 +13,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -34,7 +30,7 @@ * SUCH DAMAGE. * * @(#)sys.h 8.1 (Berkeley) 6/4/93 - * $NetBSD: sys.h,v 1.3 1997/01/11 06:48:12 lukem Exp $ + * $NetBSD: sys.h,v 1.9 2004/01/17 17:57:40 christos Exp $ * $FreeBSD$ */ @@ -74,20 +70,24 @@ typedef void *ioctl_t; #define REGEX /* Use POSIX.2 regular expression functions */ #undef REGEXP /* Use UNIX V8 regular expression functions */ -#ifdef SUNOS +#ifdef notdef # undef REGEX # undef REGEXP # include -typedef void (*sig_t)(int); # ifdef __GNUC__ /* * Broken hdrs. */ +extern int tgetent(const char *bp, char *name); +extern int tgetflag(const char *id); +extern int tgetnum(const char *id); +extern char *tgetstr(const char *id, char **area); +extern char *tgoto(const char *cap, int col, int row); +extern int tputs(const char *str, int affcnt, int (*putc)(int)); extern char *getenv(const char *); extern int fprintf(FILE *, const char *, ...); extern int sigsetmask(int); extern int sigblock(int); -extern int ioctl(int, int, void *); extern int fputc(int, FILE *); extern int fgetc(FILE *); extern int fflush(FILE *); @@ -96,7 +96,6 @@ extern int toupper(int); extern int errno, sys_nerr; extern char *sys_errlist[]; extern void perror(const char *); -extern int read(int, const char*, int); # include # define strerror(e) sys_errlist[e] # endif diff --git a/lib/libedit/term.c b/lib/libedit/term.c index 03cd4c444536..b9263034c97b 100644 --- a/lib/libedit/term.c +++ b/lib/libedit/term.c @@ -13,11 +13,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -33,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $NetBSD: term.c,v 1.31 2001/01/10 22:42:56 jdolecek Exp $ + * $NetBSD: term.c,v 1.40 2004/05/22 23:21:28 christos Exp $ */ #if !defined(lint) && !defined(SCCSID) @@ -47,13 +43,15 @@ __FBSDID("$FreeBSD$"); * We have to declare a static variable here, since the * termcap putchar routine does not take an argument! */ -#include "sys.h" #include #include #include #include #include #include +#include +#include +#include #include #include @@ -258,7 +256,7 @@ private void term_setflags(EditLine *); private int term_rebuffer_display(EditLine *); private void term_free_display(EditLine *); private int term_alloc_display(EditLine *); -private void term_alloc(EditLine *, const struct termcapstr *, char *); +private void term_alloc(EditLine *, const struct termcapstr *, const char *); private void term_init_arrow(EditLine *); private void term_reset_arrow(EditLine *); @@ -339,10 +337,10 @@ term_init(EditLine *el) (void) memset(el->el_term.t_val, 0, T_val * sizeof(int)); term_outfile = el->el_outfile; term_init_arrow(el); - if (term_set(el, NULL) == -1) - return (-1); + (void) term_set(el, NULL); return (0); } + /* term_end(): * Clean up the terminal stuff */ @@ -359,6 +357,8 @@ term_end(EditLine *el) el->el_term.t_str = NULL; el_free((ptr_t) el->el_term.t_val); el->el_term.t_val = NULL; + el_free((ptr_t) el->el_term.t_fkey); + el->el_term.t_fkey = NULL; term_free_display(el); } @@ -367,7 +367,7 @@ term_end(EditLine *el) * Maintain a string pool for termcap strings */ private void -term_alloc(EditLine *el, const struct termcapstr *t, char *cap) +term_alloc(EditLine *el, const struct termcapstr *t, const char *cap) { char termbuf[TC_BUFSIZE]; int tlen, clen; @@ -635,7 +635,8 @@ mc_again: * from col 0 */ if (EL_CAN_TAB ? - (-del > (((unsigned int) where >> 3) + + ((unsigned int)-del > + (((unsigned int) where >> 3) + (where & 07))) : (-del > where)) { term__putc('\r'); /* do a CR */ @@ -655,7 +656,7 @@ mc_again: * Overstrike num characters */ protected void -term_overwrite(EditLine *el, char *cp, int n) +term_overwrite(EditLine *el, const char *cp, int n) { if (n <= 0) return; /* catch bugs */ @@ -863,12 +864,18 @@ term_clear_to_bottom(EditLine *el) } #endif +protected void +term_get(EditLine *el, const char **term) +{ + *term = el->el_term.t_name; +} + /* term_set(): * Read in the terminal capabilities from the requested terminal */ protected int -term_set(EditLine *el, char *term) +term_set(EditLine *el, const char *term) { int i; char buf[TC_BUFSIZE]; @@ -924,8 +931,11 @@ term_set(EditLine *el, char *term) /* Get the size */ Val(T_co) = tgetnum("co"); Val(T_li) = tgetnum("li"); - for (t = tstr; t->name != NULL; t++) - term_alloc(el, t, tgetstr(t->name, &area)); + for (t = tstr; t->name != NULL; t++) { + /* XXX: some systems tgetstr needs non const */ + term_alloc(el, t, tgetstr(strchr(t->name, *t->name), + &area)); + } } if (Val(T_co) < 2) @@ -944,6 +954,7 @@ term_set(EditLine *el, char *term) return (-1); (void) sigprocmask(SIG_SETMASK, &oset, NULL); term_bind_arrow(el); + el->el_term.t_name = term; return (i <= 0 ? -1 : 0); } @@ -1105,7 +1116,7 @@ term_reset_arrow(EditLine *el) * Set an arrow key binding */ protected int -term_set_arrow(EditLine *el, char *name, key_value_t *fun, int type) +term_set_arrow(EditLine *el, const char *name, key_value_t *fun, int type) { fkey_t *arrow = el->el_term.t_fkey; int i; @@ -1124,7 +1135,7 @@ term_set_arrow(EditLine *el, char *name, key_value_t *fun, int type) * Clear an arrow key binding */ protected int -term_clear_arrow(EditLine *el, char *name) +term_clear_arrow(EditLine *el, const char *name) { fkey_t *arrow = el->el_term.t_fkey; int i; @@ -1142,7 +1153,7 @@ term_clear_arrow(EditLine *el, char *name) * Print the arrow key bindings */ protected void -term_print_arrow(EditLine *el, char *name) +term_print_arrow(EditLine *el, const char *name) { int i; fkey_t *arrow = el->el_term.t_fkey; @@ -1239,7 +1250,8 @@ term__flush(void) */ protected int /*ARGSUSED*/ -term_telltc(EditLine *el, int argc, char **argv) +term_telltc(EditLine *el, int argc __unused, + const char **argv __unused) { const struct termcapstr *t; char **ts; @@ -1274,11 +1286,12 @@ term_telltc(EditLine *el, int argc, char **argv) */ protected int /*ARGSUSED*/ -term_settc(EditLine *el, int argc, char **argv) +term_settc(EditLine *el, int argc __unused, + const char **argv) { const struct termcapstr *ts; const struct termcapval *tv; - char *what, *how; + const char *what, *how; if (argv == NULL || argv[1] == NULL || argv[2] == NULL) return (-1); @@ -1350,7 +1363,8 @@ term_settc(EditLine *el, int argc, char **argv) */ protected int /*ARGSUSED*/ -term_echotc(EditLine *el, int argc, char **argv) +term_echotc(EditLine *el, int argc __unused, + const char **argv) { char *cap, *scap, *ep; int arg_need, arg_cols, arg_rows; @@ -1409,7 +1423,7 @@ term_echotc(EditLine *el, int argc, char **argv) } (void) fprintf(el->el_outfile, fmtd, 0); #else - (void) fprintf(el->el_outfile, fmtd, el->el_tty.t_speed); + (void) fprintf(el->el_outfile, fmtd, (int)el->el_tty.t_speed); #endif return (0); } else if (strcmp(*argv, "rows") == 0 || strcmp(*argv, "lines") == 0) { @@ -1428,8 +1442,10 @@ term_echotc(EditLine *el, int argc, char **argv) scap = el->el_term.t_str[t - tstr]; break; } - if (t->name == NULL) - scap = tgetstr(*argv, &area); + if (t->name == NULL) { + /* XXX: some systems tgetstr needs non const */ + scap = tgetstr(strchr(*argv, **argv), &area); + } if (!scap || scap[0] == '\0') { if (!silent) (void) fprintf(el->el_errfile, diff --git a/lib/libedit/term.h b/lib/libedit/term.h index 9dff45727344..d97b46d35789 100644 --- a/lib/libedit/term.h +++ b/lib/libedit/term.h @@ -13,11 +13,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -34,7 +30,7 @@ * SUCH DAMAGE. * * @(#)term.h 8.1 (Berkeley) 6/4/93 - * $NetBSD: term.h,v 1.11 2000/11/11 22:18:58 christos Exp $ + * $NetBSD: term.h,v 1.16 2005/03/15 00:10:40 christos Exp $ * $FreeBSD$ */ @@ -47,13 +43,14 @@ #include "histedit.h" typedef struct { /* Symbolic function key bindings */ - char *name; /* name of the key */ + const char *name; /* name of the key */ int key; /* Index in termcap table */ key_value_t fun; /* Function bound to it */ int type; /* Type of function */ } fkey_t; typedef struct { + const char *t_name; /* the terminal name */ coord_t t_size; /* # lines and cols */ int t_flags; #define TERM_CAN_INSERT 0x001 /* Has insert cap */ @@ -87,7 +84,7 @@ typedef struct { protected void term_move_to_line(EditLine *, int); protected void term_move_to_char(EditLine *, int); protected void term_clear_EOL(EditLine *, int); -protected void term_overwrite(EditLine *, char *, int); +protected void term_overwrite(EditLine *, const char *, int); protected void term_insertwrite(EditLine *, char *, int); protected void term_deletechars(EditLine *, int); protected void term_clear_screen(EditLine *); @@ -96,14 +93,15 @@ protected int term_change_size(EditLine *, int, int); protected int term_get_size(EditLine *, int *, int *); protected int term_init(EditLine *); protected void term_bind_arrow(EditLine *); -protected void term_print_arrow(EditLine *, char *); -protected int term_clear_arrow(EditLine *, char *); -protected int term_set_arrow(EditLine *, char *, key_value_t *, int); +protected void term_print_arrow(EditLine *, const char *); +protected int term_clear_arrow(EditLine *, const char *); +protected int term_set_arrow(EditLine *, const char *, key_value_t *, int); protected void term_end(EditLine *); -protected int term_set(EditLine *, char *); -protected int term_settc(EditLine *, int, char **); -protected int term_telltc(EditLine *, int, char **); -protected int term_echotc(EditLine *, int, char **); +protected void term_get(EditLine *, const char **); +protected int term_set(EditLine *, const char *); +protected int term_settc(EditLine *, int, const char **); +protected int term_telltc(EditLine *, int, const char **); +protected int term_echotc(EditLine *, int, const char **); protected int term__putc(int); protected void term__flush(void); @@ -117,6 +115,7 @@ protected void term__flush(void); #define EL_CAN_CEOL (EL_FLAGS & TERM_CAN_CEOL) #define EL_CAN_TAB (EL_FLAGS & TERM_CAN_TAB) #define EL_CAN_ME (EL_FLAGS & TERM_CAN_ME) +#define EL_CAN_UP (EL_FLAGS & TERM_CAN_UP) #define EL_HAS_META (EL_FLAGS & TERM_HAS_META) #define EL_HAS_AUTO_MARGINS (EL_FLAGS & TERM_HAS_AUTO_MARGINS) #define EL_HAS_MAGIC_MARGINS (EL_FLAGS & TERM_HAS_MAGIC_MARGINS) diff --git a/lib/libedit/tokenizer.c b/lib/libedit/tokenizer.c index 463a980bcad6..8e3100de586b 100644 --- a/lib/libedit/tokenizer.c +++ b/lib/libedit/tokenizer.c @@ -13,11 +13,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -33,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $NetBSD: tokenizer.c,v 1.6 2000/09/04 22:06:33 lukem Exp $ + * $NetBSD: tokenizer.c,v 1.14 2003/12/05 13:37:48 lukem Exp $ */ #if !defined(lint) && !defined(SCCSID) @@ -48,7 +44,7 @@ __FBSDID("$FreeBSD$"); #include "sys.h" #include #include -#include "tokenizer.h" +#include "histedit.h" typedef enum { Q_none, Q_single, Q_double, Q_one, Q_doubleone @@ -62,6 +58,7 @@ typedef enum { #define WINCR 20 #define AINCR 10 +#define tok_strdup(a) strdup(a) #define tok_malloc(a) malloc(a) #define tok_free(a) free(a) #define tok_realloc(a, b) realloc(a, b) @@ -107,16 +104,29 @@ tok_init(const char *ifs) { Tokenizer *tok = (Tokenizer *) tok_malloc(sizeof(Tokenizer)); - tok->ifs = strdup(ifs ? ifs : IFS); + if (tok == NULL) + return NULL; + tok->ifs = tok_strdup(ifs ? ifs : IFS); + if (tok->ifs == NULL) { + tok_free((ptr_t)tok); + return NULL; + } tok->argc = 0; tok->amax = AINCR; tok->argv = (char **) tok_malloc(sizeof(char *) * tok->amax); - if (tok->argv == NULL) - return (NULL); + if (tok->argv == NULL) { + tok_free((ptr_t)tok->ifs); + tok_free((ptr_t)tok); + return NULL; + } tok->argv[0] = NULL; tok->wspace = (char *) tok_malloc(WINCR); - if (tok->wspace == NULL) - return (NULL); + if (tok->wspace == NULL) { + tok_free((ptr_t)tok->argv); + tok_free((ptr_t)tok->ifs); + tok_free((ptr_t)tok); + return NULL; + } tok->wmax = tok->wspace + WINCR; tok->wstart = tok->wspace; tok->wptr = tok->wspace; @@ -158,21 +168,39 @@ tok_end(Tokenizer *tok) /* tok_line(): - * Bourne shell like tokenizing - * Return: - * -1: Internal error - * 3: Quoted return - * 2: Unmatched double quote - * 1: Unmatched single quote - * 0: Ok + * Bourne shell (sh(1)) like tokenizing + * Arguments: + * tok current tokenizer state (setup with tok_init()) + * line line to parse + * Returns: + * -1 Internal error + * 3 Quoted return + * 2 Unmatched double quote + * 1 Unmatched single quote + * 0 Ok + * Modifies (if return value is 0): + * argc number of arguments + * argv argument array + * cursorc if !NULL, argv element containing cursor + * cursorv if !NULL, offset in argv[cursorc] of cursor */ public int -tok_line(Tokenizer *tok, const char *line, int *argc, char ***argv) +tok_line(Tokenizer *tok, const LineInfo *line, + int *argc, const char ***argv, int *cursorc, int *cursoro) { const char *ptr; - - for (;;) { - switch (*(ptr = line++)) { + int cc, co; + + cc = co = -1; + ptr = line->buffer; + for (ptr = line->buffer; ;ptr++) { + if (ptr >= line->lastchar) + ptr = ""; + if (ptr == line->cursor) { + cc = tok->argc; + co = tok->wptr - tok->wstart; + } + switch (*ptr) { case '\'': tok->flags |= TOK_KEEP; tok->flags &= ~TOK_EAT; @@ -271,10 +299,7 @@ tok_line(Tokenizer *tok, const char *line, int *argc, char ***argv) tok->flags &= ~TOK_EAT; switch (tok->quote) { case Q_none: - tok_finish(tok); - *argv = tok->argv; - *argc = tok->argc; - return (0); + goto tok_line_outok; case Q_single: case Q_double: @@ -304,10 +329,7 @@ tok_line(Tokenizer *tok, const char *line, int *argc, char ***argv) tok->flags &= ~TOK_EAT; return (3); } - tok_finish(tok); - *argv = tok->argv; - *argc = tok->argc; - return (0); + goto tok_line_outok; case Q_single: return (1); @@ -367,20 +389,20 @@ tok_line(Tokenizer *tok, const char *line, int *argc, char ***argv) if (tok->wptr >= tok->wmax - 4) { size_t size = tok->wmax - tok->wspace + WINCR; char *s = (char *) tok_realloc(tok->wspace, size); - /* SUPPRESS 22 */ - int offs = s - tok->wspace; if (s == NULL) return (-1); - if (offs != 0) { + if (s != tok->wspace) { int i; - for (i = 0; i < tok->argc; i++) - tok->argv[i] = tok->argv[i] + offs; - tok->wptr = tok->wptr + offs; - tok->wstart = tok->wstart + offs; - tok->wmax = s + size; + for (i = 0; i < tok->argc; i++) { + tok->argv[i] = + (tok->argv[i] - tok->wspace) + s; + } + tok->wptr = (tok->wptr - tok->wspace) + s; + tok->wstart = (tok->wstart - tok->wspace) + s; tok->wspace = s; } + tok->wmax = s + size; } if (tok->argc >= tok->amax - 4) { char **p; @@ -392,4 +414,32 @@ tok_line(Tokenizer *tok, const char *line, int *argc, char ***argv) tok->argv = p; } } + tok_line_outok: + if (cc == -1 && co == -1) { + cc = tok->argc; + co = tok->wptr - tok->wstart; + } + if (cursorc != NULL) + *cursorc = cc; + if (cursoro != NULL) + *cursoro = co; + tok_finish(tok); + *argv = (const char **)tok->argv; + *argc = tok->argc; + return (0); +} + +/* tok_str(): + * Simpler version of tok_line, taking a NUL terminated line + * and splitting into words, ignoring cursor state. + */ +public int +tok_str(Tokenizer *tok, const char *line, int *argc, const char ***argv) +{ + LineInfo li; + + memset(&li, 0, sizeof(li)); + li.buffer = line; + li.cursor = li.lastchar = strchr(line, '\0'); + return (tok_line(tok, &li, argc, argv, NULL, NULL)); } diff --git a/lib/libedit/tokenizer.h b/lib/libedit/tokenizer.h deleted file mode 100644 index b49c9dbc0f8c..000000000000 --- a/lib/libedit/tokenizer.h +++ /dev/null @@ -1,54 +0,0 @@ -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Christos Zoulas of Cornell University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)tokenizer.h 8.1 (Berkeley) 6/4/93 - * $NetBSD: tokenizer.h,v 1.3 1999/07/02 15:21:27 simonb Exp $ - * $FreeBSD$ - */ - -/* - * tokenizer.h: Header file for tokenizer routines - */ -#ifndef _h_tokenizer -#define _h_tokenizer - -typedef struct tokenizer Tokenizer; - -Tokenizer *tok_init(const char *); -void tok_reset(Tokenizer *); -void tok_end(Tokenizer *); -int tok_line(Tokenizer *, const char *, int *, char ***); - -#endif /* _h_tokenizer */ diff --git a/lib/libedit/tty.c b/lib/libedit/tty.c index b4c9f4f4e10e..e2b99327ea96 100644 --- a/lib/libedit/tty.c +++ b/lib/libedit/tty.c @@ -13,11 +13,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -33,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $NetBSD: tty.c,v 1.14 2001/01/09 17:31:04 jdolecek Exp $ + * $NetBSD: tty.c,v 1.23 2005/06/01 11:37:52 lukem Exp $ */ #if !defined(lint) && !defined(SCCSID) @@ -45,20 +41,21 @@ __FBSDID("$FreeBSD$"); /* * tty.c: tty interface stuff */ +#include #include "sys.h" #include "tty.h" #include "el.h" typedef struct ttymodes_t { const char *m_name; - u_int m_value; + unsigned int m_value; int m_type; } ttymodes_t; typedef struct ttymap_t { int nch, och; /* Internal and termio rep of chars */ el_action_t bind[3]; /* emacs, vi, and vi-cmd */ -} ttymap_t; +} ttymap_t; private const ttyperm_t ttyperm = { @@ -122,11 +119,11 @@ private const ttychar_t ttychar = { private const ttymap_t tty_map[] = { #ifdef VERASE {C_ERASE, VERASE, - {ED_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}}, + {EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}}, #endif /* VERASE */ #ifdef VERASE2 {C_ERASE2, VERASE2, - {ED_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}}, + {EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}}, #endif /* VERASE2 */ #ifdef VKILL {C_KILL, VKILL, @@ -453,6 +450,7 @@ private const ttymodes_t ttymodes[] = { #define tty__geteightbit(td) (((td)->c_cflag & CSIZE) == CS8) #define tty__cooked_mode(td) ((td)->c_lflag & ICANON) +private int tty__getcharindex(int); private void tty__getchar(struct termios *, unsigned char *); private void tty__setchar(struct termios *, unsigned char *); private speed_t tty__getspeed(struct termios *); @@ -544,7 +542,7 @@ tty_init(EditLine *el) */ protected void /*ARGSUSED*/ -tty_end(EditLine *el) +tty_end(EditLine *el __unused) { /* XXX: Maybe reset to an initial state? */ @@ -564,6 +562,113 @@ tty__getspeed(struct termios *td) return (spd); } +/* tty__getspeed(): + * Return the index of the asked char in the c_cc array + */ +private int +tty__getcharindex(int i) +{ + switch (i) { +#ifdef VINTR + case C_INTR: + return VINTR; +#endif /* VINTR */ +#ifdef VQUIT + case C_QUIT: + return VQUIT; +#endif /* VQUIT */ +#ifdef VERASE + case C_ERASE: + return VERASE; +#endif /* VERASE */ +#ifdef VKILL + case C_KILL: + return VKILL; +#endif /* VKILL */ +#ifdef VEOF + case C_EOF: + return VEOF; +#endif /* VEOF */ +#ifdef VEOL + case C_EOL: + return VEOL; +#endif /* VEOL */ +#ifdef VEOL2 + case C_EOL2: + return VEOL2; +#endif /* VEOL2 */ +#ifdef VSWTCH + case C_SWTCH: + return VSWTCH; +#endif /* VSWTCH */ +#ifdef VDSWTCH + case C_DSWTCH: + return VDSWTCH; +#endif /* VDSWTCH */ +#ifdef VERASE2 + case C_ERASE2: + return VERASE2; +#endif /* VERASE2 */ +#ifdef VSTART + case C_START: + return VSTART; +#endif /* VSTART */ +#ifdef VSTOP + case C_STOP: + return VSTOP; +#endif /* VSTOP */ +#ifdef VWERASE + case C_WERASE: + return VWERASE; +#endif /* VWERASE */ +#ifdef VSUSP + case C_SUSP: + return VSUSP; +#endif /* VSUSP */ +#ifdef VDSUSP + case C_DSUSP: + return VDSUSP; +#endif /* VDSUSP */ +#ifdef VREPRINT + case C_REPRINT: + return VREPRINT; +#endif /* VREPRINT */ +#ifdef VDISCARD + case C_DISCARD: + return VDISCARD; +#endif /* VDISCARD */ +#ifdef VLNEXT + case C_LNEXT: + return VLNEXT; +#endif /* VLNEXT */ +#ifdef VSTATUS + case C_STATUS: + return VSTATUS; +#endif /* VSTATUS */ +#ifdef VPAGE + case C_PAGE: + return VPAGE; +#endif /* VPAGE */ +#ifdef VPGOFF + case C_PGOFF: + return VPGOFF; +#endif /* VPGOFF */ +#ifdef VKILL2 + case C_KILL2: + return VKILL2; +#endif /* KILL2 */ +#ifdef VMIN + case C_MIN: + return VMIN; +#endif /* VMIN */ +#ifdef VTIME + case C_TIME: + return VTIME; +#endif /* VTIME */ + default: + return -1; + } +} /* tty__getchar(): * Get the tty characters @@ -990,13 +1095,14 @@ tty_noquotemode(EditLine *el) */ protected int /*ARGSUSED*/ -tty_stty(EditLine *el, int argc, char **argv) +tty_stty(EditLine *el, int argc __unused, const char **argv) { const ttymodes_t *m; - char x, *d; + char x; int aflag = 0; - char *s; - char *name; + const char *s, *d; + const char *name; + struct termios *tios = &el->el_tty.t_ex; int z = EX_IO; if (argv == NULL) @@ -1011,14 +1117,17 @@ tty_stty(EditLine *el, int argc, char **argv) break; case 'd': argv++; + tios = &el->el_tty.t_ed; z = ED_IO; break; case 'x': argv++; + tios = &el->el_tty.t_ex; z = EX_IO; break; case 'q': argv++; + tios = &el->el_tty.t_ts; z = QU_IO; break; default: @@ -1068,6 +1177,7 @@ tty_stty(EditLine *el, int argc, char **argv) return (0); } while (argv && (s = *argv++)) { + const char *p; switch (*s) { case '+': case '-': @@ -1078,8 +1188,11 @@ tty_stty(EditLine *el, int argc, char **argv) break; } d = s; + p = strchr(s, '='); for (m = ttymodes; m->m_name; m++) - if (strcmp(m->m_name, d) == 0) + if ((p ? strncmp(m->m_name, d, (size_t)(p - d)) : + strcmp(m->m_name, d)) == 0 && + (p == NULL || m->m_type == MD_CHAR)) break; if (!m->m_name) { @@ -1087,6 +1200,16 @@ tty_stty(EditLine *el, int argc, char **argv) "%s: Invalid argument `%s'.\n", name, d); return (-1); } + if (p) { + int c = ffs((int)m->m_value); + int v = *++p ? parse__escape((const char **) &p) : + el->el_tty.t_vdisable; + assert(c-- != 0); + c = tty__getcharindex(c); + assert(c != -1); + tios->c_cc[c] = v; + continue; + } switch (x) { case '+': el->el_tty.t_t[z][m->m_type].t_setmask |= m->m_value; diff --git a/lib/libedit/tty.h b/lib/libedit/tty.h index 7e9cd8b038ae..3a4e94accf33 100644 --- a/lib/libedit/tty.h +++ b/lib/libedit/tty.h @@ -13,11 +13,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -34,7 +30,7 @@ * SUCH DAMAGE. * * @(#)tty.h 8.1 (Berkeley) 6/4/93 - * $NetBSD: tty.h,v 1.7 1999/09/26 14:37:47 lukem Exp $ + * $NetBSD: tty.h,v 1.11 2005/06/01 11:37:52 lukem Exp $ * $FreeBSD$ */ @@ -453,16 +449,16 @@ #define MD_NN 5 typedef struct { - char *t_name; - u_int t_setmask; - u_int t_clrmask; + const char *t_name; + unsigned int t_setmask; + unsigned int t_clrmask; } ttyperm_t[NN_IO][MD_NN]; typedef unsigned char ttychar_t[NN_IO][C_NCC]; protected int tty_init(EditLine *); protected void tty_end(EditLine *); -protected int tty_stty(EditLine *, int, char**); +protected int tty_stty(EditLine *, int, const char **); protected int tty_rawmode(EditLine *); protected int tty_cookedmode(EditLine *); protected int tty_quotemode(EditLine *); diff --git a/lib/libedit/vi.c b/lib/libedit/vi.c index 72de5c9b0ce7..ae65bbcb29ba 100644 --- a/lib/libedit/vi.c +++ b/lib/libedit/vi.c @@ -13,11 +13,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -33,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $NetBSD: vi.c,v 1.7 1999/07/02 15:21:28 simonb Exp $ + * $NetBSD: vi.c,v 1.21 2005/04/25 01:06:03 matt Exp $ */ #if !defined(lint) && !defined(SCCSID) @@ -45,6 +41,7 @@ __FBSDID("$FreeBSD$"); /* * vi.c: Vi mode commands. */ +#include #include "sys.h" #include "el.h" @@ -57,22 +54,18 @@ private el_action_t cv_paste(EditLine *, int); private el_action_t cv_action(EditLine *el, int c) { - char *cp, *kp; - if (el->el_chared.c_vcmd.action & DELETE) { + 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_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++; - } - - 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) @@ -83,25 +76,8 @@ cv_action(EditLine *el, int c) 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 } - /* cv_paste(): * Paste previous deletion before or after the cursor */ @@ -109,23 +85,25 @@ private el_action_t cv_paste(EditLine *el, int c) { char *ptr; - c_undo_t *un = &el->el_chared.c_undo; + 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); + + 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, (int) un->isize); - if (el->el_line.cursor + un->isize > el->el_line.lastchar) + c_insert(el, len); + if (el->el_line.cursor + len > el->el_line.lastchar) return (CC_ERROR); - (void) memcpy(ptr, un->buf, un->isize); + (void) memcpy(ptr, k->buf, len +0u); return (CC_REFRESH); } @@ -136,7 +114,7 @@ cv_paste(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -vi_paste_next(EditLine *el, int c) +vi_paste_next(EditLine *el, int c __unused) { return (cv_paste(el, 0)); @@ -149,31 +127,31 @@ vi_paste_next(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -vi_paste_prev(EditLine *el, int c) +vi_paste_prev(EditLine *el, int c __unused) { 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(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.cursor = cv_prev_word(el->el_line.cursor, el->el_line.buffer, el->el_state.argument, - c___isword); + cv__isWord); - if (el->el_chared.c_vcmd.action & DELETE) { + if (el->el_chared.c_vcmd.action != NOP) { cv_delfini(el); return (CC_REFRESH); } @@ -187,18 +165,18 @@ vi_prev_space_word(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -vi_prev_word(EditLine *el, int c) +vi_prev_word(EditLine *el, int c __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.cursor = cv_prev_word(el->el_line.cursor, el->el_line.buffer, el->el_state.argument, cv__isword); - if (el->el_chared.c_vcmd.action & DELETE) { + if (el->el_chared.c_vcmd.action != NOP) { cv_delfini(el); return (CC_REFRESH); } @@ -206,25 +184,23 @@ vi_prev_word(EditLine *el, int c) } -/* 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(EditLine *el, int c) +vi_next_big_word(EditLine *el, int c) { - if (el->el_line.cursor == el->el_line.lastchar) + if (el->el_line.cursor >= el->el_line.lastchar - 1) return (CC_ERROR); el->el_line.cursor = cv_next_word(el, el->el_line.cursor, - el->el_line.lastchar, - el->el_state.argument, - c___isword); + el->el_line.lastchar, el->el_state.argument, cv__isWord); if (el->el_map.type == MAP_VI) - if (el->el_chared.c_vcmd.action & DELETE) { + if (el->el_chared.c_vcmd.action != NOP) { cv_delfini(el); return (CC_REFRESH); } @@ -238,19 +214,17 @@ vi_next_space_word(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -vi_next_word(EditLine *el, int c) +vi_next_word(EditLine *el, int c __unused) { - if (el->el_line.cursor == el->el_line.lastchar) + if (el->el_line.cursor >= el->el_line.lastchar - 1) 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); + el->el_line.lastchar, el->el_state.argument, cv__isword); if (el->el_map.type == MAP_VI) - if (el->el_chared.c_vcmd.action & DELETE) { + if (el->el_chared.c_vcmd.action != NOP) { cv_delfini(el); return (CC_REFRESH); } @@ -265,19 +239,27 @@ vi_next_word(EditLine *el, int c) protected el_action_t vi_change_case(EditLine *el, int c) { + int i; - if (el->el_line.cursor < el->el_line.lastchar) { - c = (unsigned char)*el->el_line.cursor; + 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); + *el->el_line.cursor = tolower(c); else if (islower(c)) - *el->el_line.cursor++ = toupper(c); - else - el->el_line.cursor++; + *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); + return CC_NORM; } @@ -287,7 +269,7 @@ vi_change_case(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -vi_change_meta(EditLine *el, int c) +vi_change_meta(EditLine *el, int c __unused) { /* @@ -304,15 +286,11 @@ vi_change_meta(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -vi_insert_at_bol(EditLine *el, int c) +vi_insert_at_bol(EditLine *el, int c __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; - + cv_undo(el); el->el_map.current = el->el_map.key; return (CC_CURSOR); } @@ -324,15 +302,15 @@ vi_insert_at_bol(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -vi_replace_char(EditLine *el, int c) +vi_replace_char(EditLine *el, int c __unused) { + 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; - 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; + cv_undo(el); return (CC_ARGHACK); } @@ -343,16 +321,13 @@ vi_replace_char(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -vi_replace_mode(EditLine *el, int c) +vi_replace_mode(EditLine *el, int c __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_ARGHACK); + cv_undo(el); + return (CC_NORM); } @@ -362,7 +337,7 @@ vi_replace_mode(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -vi_substitute_char(EditLine *el, int c) +vi_substitute_char(EditLine *el, int c __unused) { c_delafter(el, el->el_state.argument); @@ -377,9 +352,12 @@ vi_substitute_char(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -vi_substitute_line(EditLine *el, int c) +vi_substitute_line(EditLine *el, int c __unused) { + 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); @@ -392,9 +370,12 @@ vi_substitute_line(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -vi_change_to_eol(EditLine *el, int c) +vi_change_to_eol(EditLine *el, int c __unused) { + 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); @@ -407,15 +388,11 @@ vi_change_to_eol(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -vi_insert(EditLine *el, int c) +vi_insert(EditLine *el, int c __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; - + cv_undo(el); return (CC_NORM); } @@ -426,9 +403,9 @@ vi_insert(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -vi_add(EditLine *el, int c) +vi_add(EditLine *el, int c __unused) { - el_action_t ret; + int ret; el->el_map.current = el->el_map.key; if (el->el_line.cursor < el->el_line.lastchar) { @@ -439,9 +416,7 @@ vi_add(EditLine *el, int c) } 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); } @@ -453,16 +428,12 @@ vi_add(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -vi_add_at_eol(EditLine *el, int c) +vi_add_at_eol(EditLine *el, int c __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; + cv_undo(el); return (CC_CURSOR); } @@ -473,29 +444,29 @@ vi_add_at_eol(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -vi_delete_meta(EditLine *el, int c) +vi_delete_meta(EditLine *el, int c __unused) { return (cv_action(el, DELETE)); } -/* vi_end_word(): +/* vi_end_big_word(): * Vi move to the end of the current space delimited word * [E] */ protected el_action_t /*ARGSUSED*/ -vi_end_word(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); + el->el_line.lastchar, el->el_state.argument, cv__isWord); - if (el->el_chared.c_vcmd.action & DELETE) { + if (el->el_chared.c_vcmd.action != NOP) { el->el_line.cursor++; cv_delfini(el); return (CC_REFRESH); @@ -504,22 +475,22 @@ vi_end_word(EditLine *el, int c) } -/* 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(EditLine *el, int c) +vi_end_word(EditLine *el, int c __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); + el->el_line.lastchar, el->el_state.argument, cv__isword); - if (el->el_chared.c_vcmd.action & DELETE) { + if (el->el_chared.c_vcmd.action != NOP) { el->el_line.cursor++; cv_delfini(el); return (CC_REFRESH); @@ -534,144 +505,40 @@ vi_to_end_word(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -vi_undo(EditLine *el, int c) +vi_undo(EditLine *el, int c __unused) { - char *cp, *kp; - char temp; - int i, size; - 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; + c_undo_t un = el->el_chared.c_undo; - 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, (int) un->isize); - (void) 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); } -/* vi_undo_line(): - * Vi undo all changes - * [U] - */ -protected el_action_t -/*ARGSUSED*/ -vi_undo_line(EditLine *el, int c) -{ - - return hist_get(el); -} - - /* vi_command_mode(): * Vi enter command mode (use alternative key bindings) * [] */ protected el_action_t /*ARGSUSED*/ -vi_command_mode(EditLine *el, int c) +vi_command_mode(EditLine *el, int c __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; el->el_state.inputmode = MODE_INSERT; el->el_map.current = el->el_map.alt; @@ -691,42 +558,32 @@ protected el_action_t 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 { - 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_state.doingarg) + return ed_argument_digit(el, c); + + el->el_line.cursor = el->el_line.buffer; + 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] + * [^H] in insert mode only */ protected el_action_t /*ARGSUSED*/ -vi_delete_prev_char(EditLine *el, int c) +vi_delete_prev_char(EditLine *el, int c __unused) { - if (el->el_chared.c_vcmd.ins == 0) + if (el->el_line.cursor <= el->el_line.buffer) return (CC_ERROR); - if (el->el_chared.c_vcmd.ins > - el->el_line.cursor - el->el_state.argument) - return (CC_ERROR); - - c_delbefore(el, el->el_state.argument); - el->el_line.cursor -= el->el_state.argument; - + c_delbefore1(el); + el->el_line.cursor--; return (CC_REFRESH); } @@ -737,23 +594,35 @@ vi_delete_prev_char(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -vi_list_or_eof(EditLine *el, int c) +vi_list_or_eof(EditLine *el, int c __unused) { -#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 an EOF */ - term__flush(); - return (CC_EOF); -#ifdef notyet + 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 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 + } } @@ -763,7 +632,7 @@ vi_list_or_eof(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -vi_kill_line_prev(EditLine *el, int c) +vi_kill_line_prev(EditLine *el, int c __unused) { char *kp, *cp; @@ -784,7 +653,7 @@ vi_kill_line_prev(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -vi_search_prev(EditLine *el, int c) +vi_search_prev(EditLine *el, int c __unused) { return (cv_search(el, ED_SEARCH_PREV_HISTORY)); @@ -797,7 +666,7 @@ vi_search_prev(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -vi_search_next(EditLine *el, int c) +vi_search_next(EditLine *el, int c __unused) { return (cv_search(el, ED_SEARCH_NEXT_HISTORY)); @@ -810,7 +679,7 @@ vi_search_next(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -vi_repeat_search_next(EditLine *el, int c) +vi_repeat_search_next(EditLine *el, int c __unused) { if (el->el_search.patlen == 0) @@ -826,7 +695,7 @@ vi_repeat_search_next(EditLine *el, int c) */ /*ARGSUSED*/ protected el_action_t -vi_repeat_search_prev(EditLine *el, int c) +vi_repeat_search_prev(EditLine *el, int c __unused) { if (el->el_search.patlen == 0) @@ -844,18 +713,9 @@ vi_repeat_search_prev(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -vi_next_char(EditLine *el, int c) +vi_next_char(EditLine *el, int c __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); } @@ -865,17 +725,9 @@ vi_next_char(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -vi_prev_char(EditLine *el, int c) +vi_prev_char(EditLine *el, int c __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); } @@ -885,15 +737,9 @@ vi_prev_char(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -vi_to_next_char(EditLine *el, int c) +vi_to_next_char(EditLine *el, int c __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); } @@ -903,14 +749,9 @@ vi_to_next_char(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -vi_to_prev_char(EditLine *el, int c) +vi_to_prev_char(EditLine *el, int c __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); } @@ -920,17 +761,11 @@ vi_to_prev_char(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -vi_repeat_next_char(EditLine *el, int c) +vi_repeat_next_char(EditLine *el, int c __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); } @@ -940,13 +775,345 @@ vi_repeat_next_char(EditLine *el, int c) */ protected el_action_t /*ARGSUSED*/ -vi_repeat_prev_char(EditLine *el, int c) +vi_repeat_prev_char(EditLine *el, int c __unused) { + el_action_t r; + int dir = el->el_search.chadir; - if (el->el_search.chacha == 0) - return (CC_ERROR); + 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) +{ +#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, 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