diff options
author | Otto Moerbeek <otto@cvs.openbsd.org> | 2003-10-31 08:42:25 +0000 |
---|---|---|
committer | Otto Moerbeek <otto@cvs.openbsd.org> | 2003-10-31 08:42:25 +0000 |
commit | 6ff1c1765c2b4495f0292fe730d9bb9a5daef063 (patch) | |
tree | f9b79c5d3b01533c847610f8410f66661df68535 | |
parent | 4c1c60ce562b0cf6d8cb6e2e49e2b53193359874 (diff) |
Update to NetBSD libedit (from Oct 1, 2003), adding some string
cleaning and history bug fixes. The code includes GNU libreadline
functionality, but the corresponding header files are not installed,
since some libreadline functions are missing. There are some minor API
changes, notably:
old: EditLine *el_init(const char *, FILE *, FILE *);
new: EditLine *el_init(const char *, FILE *, FILE *, FILE *);
old: HistEvent *history(History *h, int op, ...);
new: int history(History *h, HistEvent *ev, int op, ...); plus some
changes in operation names. See editline(3) for details.
Tested by djm@, mouring@, jmc@.
ok deraadt@
45 files changed, 12701 insertions, 8933 deletions
diff --git a/lib/libedit/Makefile b/lib/libedit/Makefile index 79cf0a73d74..2931a939652 100644 --- a/lib/libedit/Makefile +++ b/lib/libedit/Makefile @@ -1,68 +1,95 @@ -# $OpenBSD: Makefile,v 1.7 1998/07/24 00:10:48 millert Exp $ -# from: @(#)Makefile 8.1 (Berkeley) 6/4/93 +# $OpenBSD: Makefile,v 1.8 2003/10/31 08:42:23 otto Exp $ +# $NetBSD: Makefile,v 1.28 2003/08/01 17:03:58 lukem Exp $ +# @(#)Makefile 8.1 (Berkeley) 6/4/93 LIB= edit +USE_SHLIBDIR= yes -OSRCS= chared.c common.c el.c emacs.c fcns.c hist.c key.c map.c parse.c \ - prompt.c read.c refresh.c search.c sig.c term.c tty.c vi.c help.c +OSRCS= chared.c common.c el.c emacs.c fcns.c help.c hist.c key.c map.c \ + parse.c prompt.c read.c refresh.c search.c sig.c term.c tty.c vi.c MAN= editline.3 editrc.5 MLINKS= editline.3 el_init.3 editline.3 el_end.3 editline.3 el_reset.3 \ editline.3 el_gets.3 editline.3 el_getc.3 editline.3 el_push.3 \ - editline.3 el_parse.3 editline.3 el_set.3 editline.3 el_source.3 \ - editline.3 el_resize.3 editline.3 el_line.3 \ + editline.3 el_parse.3 editline.3 el_set.3 editline.3 el_get.3 \ + editline.3 el_source.3 editline.3 el_resize.3 editline.3 el_line.3 \ editline.3 el_insertstr.3 editline.3 el_deletestr.3 \ editline.3 history_init.3 editline.3 history_end.3 editline.3 history.3 # For speed and debugging -#SRCS= ${OSRCS} tokenizer.c history.c +#SRCS= ${OSRCS} tokenizer.c history.c readline.c # For protection -SRCS= editline.c tokenizer.c history.c +SRCS= editline.c tokenizer.c history.c readline.c -CLEANFILES+=common.h emacs.h fcns.h help.h vi.h help.c fcns.c editline.c -CFLAGS+=-I. -I${.CURDIR} -CFLAGS+=#-DDEBUG_TTY -DDEBUG_KEY -DDEBUG_READ -DDEBUG -DDEBUG_REFRESH -CFLAGS+=#-DDEBUG_PASTE +LIBEDITDIR?=${.CURDIR} + +INCS= histedit.h +INCSDIR=/usr/include + +CLEANFILES+=editline.c +CLEANFILES+=common.h.tmp editline.c.tmp emacs.h.tmp fcns.c.tmp fcns.h.tmp +CLEANFILES+=help.c.tmp help.h.tmp vi.h.tmp +CFLAGS+=-Wall +CPPFLAGS+=-I. -I${LIBEDITDIR} +CPPFLAGS+=-I. -I${.CURDIR} +CPPFLAGS+=#-DDEBUG_TTY -DDEBUG_KEY -DDEBUG_READ -DDEBUG -DDEBUG_REFRESH +CPPFLAGS+=#-DDEBUG_PASTE -DDEBUG_EDIT AHDR=vi.h emacs.h common.h -ASRC=${.CURDIR}/vi.c ${.CURDIR}/emacs.c ${.CURDIR}/common.c +ASRC=${LIBEDITDIR}/vi.c ${LIBEDITDIR}/emacs.c ${LIBEDITDIR}/common.c + +DPSRCS+= ${AHDR} fcns.h help.h fcns.c help.c +CLEANFILES+= ${AHDR} fcns.h help.h fcns.c help.c + +#SUBDIR+= readline +HOST_SH= sh vi.h: vi.c makelist - sh ${.CURDIR}/makelist -h ${.CURDIR}/vi.c > ${.TARGET} + ${HOST_SH} ${LIBEDITDIR}/makelist -h ${LIBEDITDIR}/vi.c \ + > ${.TARGET}.tmp && \ + mv ${.TARGET}.tmp ${.TARGET} emacs.h: emacs.c makelist - sh ${.CURDIR}/makelist -h ${.CURDIR}/emacs.c > ${.TARGET} + ${HOST_SH} ${LIBEDITDIR}/makelist -h ${LIBEDITDIR}/emacs.c \ + > ${.TARGET}.tmp && \ + mv ${.TARGET}.tmp ${.TARGET} common.h: common.c makelist - sh ${.CURDIR}/makelist -h ${.CURDIR}/common.c > ${.TARGET} + ${HOST_SH} ${LIBEDITDIR}/makelist -h ${LIBEDITDIR}/common.c \ + > ${.TARGET}.tmp && \ + mv ${.TARGET}.tmp ${.TARGET} fcns.h: ${AHDR} makelist - sh ${.CURDIR}/makelist -fh ${AHDR} > ${.TARGET} + ${HOST_SH} ${LIBEDITDIR}/makelist -fh ${AHDR} > ${.TARGET}.tmp && \ + mv ${.TARGET}.tmp ${.TARGET} -fcns.c: ${AHDR} fcns.h makelist - sh ${.CURDIR}/makelist -fc ${AHDR} > ${.TARGET} +fcns.c: ${AHDR} fcns.h help.h makelist + ${HOST_SH} ${LIBEDITDIR}/makelist -fc ${AHDR} > ${.TARGET}.tmp && \ + mv ${.TARGET}.tmp ${.TARGET} help.c: ${ASRC} makelist - sh ${.CURDIR}/makelist -bc ${ASRC} > ${.TARGET} + ${HOST_SH} ${LIBEDITDIR}/makelist -bc ${ASRC} > ${.TARGET}.tmp && \ + mv ${.TARGET}.tmp ${.TARGET} help.h: ${ASRC} makelist - sh ${.CURDIR}/makelist -bh ${ASRC} > ${.TARGET} + ${HOST_SH} ${LIBEDITDIR}/makelist -bh ${ASRC} > ${.TARGET}.tmp && \ + mv ${.TARGET}.tmp ${.TARGET} editline.c: ${OSRCS} - sh ${.CURDIR}/makelist -e ${.ALLSRC:T} > ${.TARGET} - -.depend: vi.h emacs.h common.h fcns.h help.h help.c -all: vi.h emacs.h common.h fcns.h help.h help.c - + ${HOST_SH} ${LIBEDITDIR}/makelist -e ${.ALLSRC:T} > ${.TARGET}.tmp && \ + mv ${.TARGET}.tmp ${.TARGET} +test.o: ${LIBEDITDIR}/TEST/test.c + test: libedit.a test.o - ${CC} ${CFLAGS} ${.ALLSRC} -o ${.TARGET} libedit.a ${LDADD} -lcurses + ${CC} ${LDFLAGS} ${.ALLSRC} -o ${.TARGET} libedit.a ${LDADD} -ltermcap includes: -cd ${.CURDIR}; cmp -s histedit.h ${DESTDIR}/usr/include/histedit.h > \ - /dev/null 2>&1 || \ - ${INSTALL} ${INSTALL_COPY} -o ${BINOWN} -g ${BINGRP} -m 444 histedit.h \ - ${DESTDIR}/usr/include + /dev/null 2>&1 || \ + ${INSTALL} ${INSTALL_COPY} -o ${BINOWN} -g ${BINGRP} -m 444 histedit.h \ + ${DESTDIR}/usr/include .include <bsd.lib.mk> +.include <bsd.subdir.mk> diff --git a/lib/libedit/TEST/test.c b/lib/libedit/TEST/test.c index 42ec0f7904c..78adcf6a374 100644 --- a/lib/libedit/TEST/test.c +++ b/lib/libedit/TEST/test.c @@ -1,4 +1,5 @@ -/* $OpenBSD: test.c,v 1.5 2003/06/02 20:18:40 millert Exp $ */ +/* $OpenBSD: test.c,v 1.6 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: test.c,v 1.13 2003/08/07 16:44:35 agc Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -32,24 +33,23 @@ * SUCH DAMAGE. */ +#include "config.h" #ifndef lint -static char copyright[] = -"@(#) Copyright (c) 1992, 1993\n\ - The Regents of the University of California. All rights reserved.\n"; +//__COPYRIGHT("@(#) Copyright (c) 1992, 1993\n\ +// The Regents of the University of California. All rights reserved.\n"); #endif /* not lint */ #if !defined(lint) && !defined(SCCSID) #if 0 static char sccsid[] = "@(#)test.c 8.1 (Berkeley) 6/4/93"; #else -static const char rcsid[] = "$OpenBSD: test.c,v 1.5 2003/06/02 20:18:40 millert Exp $"; +static const char *rcsid = "$OpenBSD: test.c,v 1.6 2003/10/31 08:42:24 otto Exp $"; #endif #endif /* not lint && not SCCSID */ /* * test.c: A little test program */ -#include "sys.h" #include <stdio.h> #include <string.h> #include <signal.h> @@ -65,182 +65,201 @@ static const char rcsid[] = "$OpenBSD: test.c,v 1.5 2003/06/02 20:18:40 millert static int continuation = 0; static EditLine *el = NULL; +static u_char complete(EditLine *, int); + int main(int, char **); +static char *prompt(EditLine *); +static void sig(int); + static char * -/*ARGSUSED*/ -prompt(el) - EditLine *el; +prompt(EditLine *el) { - static char a[] = "Edit$"; - static char b[] = "Edit>"; - return continuation ? b : a; + static char a[] = "Edit$"; + static char b[] = "Edit>"; + + return (continuation ? b : a); } static void -sig(i) - int i; +sig(int i) { - (void) fprintf(stderr, "Got signal %d.\n", i); - el_reset(el); + + (void) fprintf(stderr, "Got signal %d.\n", i); + el_reset(el); } static unsigned char -/*ARGSUSED*/ -complete(el, ch) - EditLine *el; - int ch; +complete(EditLine *el, int ch) { - DIR *dd = opendir("."); - struct dirent *dp; - const char* ptr; - const LineInfo *lf = el_line(el); - int len; - - /* - * Find the last word - */ - for (ptr = lf->cursor - 1; !isspace(*ptr) && ptr > lf->buffer; ptr--) - continue; - len = lf->cursor - ++ptr; - - for (dp = readdir(dd); dp != NULL; dp = readdir(dd)) { - if (len > strlen(dp->d_name)) - continue; - if (strncmp(dp->d_name, ptr, len) == 0) { - closedir(dd); - if (el_insertstr(el, &dp->d_name[len]) == -1) - return CC_ERROR; - else - return CC_REFRESH; + DIR *dd = opendir("."); + struct dirent *dp; + const char* ptr; + const LineInfo *lf = el_line(el); + int len; + + /* + * Find the last word + */ + for (ptr = lf->cursor - 1; !isspace(*ptr) && ptr > lf->buffer; ptr--) + continue; + len = lf->cursor - ++ptr; + + for (dp = readdir(dd); dp != NULL; dp = readdir(dd)) { + if (len > strlen(dp->d_name)) + continue; + if (strncmp(dp->d_name, ptr, len) == 0) { + closedir(dd); + if (el_insertstr(el, &dp->d_name[len]) == -1) + return (CC_ERROR); + else + return (CC_REFRESH); + } } - } - closedir(dd); - return CC_ERROR; + closedir(dd); + return (CC_ERROR); } int -/*ARGSUSED*/ -main(argc, argv) - int argc; - char *argv[]; +main(int argc, char *argv[]) { - int num; - const char *buf; - Tokenizer *tok; - History *hist; + int num; + const char *buf; + Tokenizer *tok; +#if 0 + int lastevent = 0; +#endif + int ncontinuation; + History *hist; + HistEvent ev; - (void) signal(SIGINT, sig); - (void) signal(SIGQUIT, sig); - (void) signal(SIGHUP, sig); - (void) signal(SIGTERM, sig); + (void) signal(SIGINT, sig); + (void) signal(SIGQUIT, sig); + (void) signal(SIGHUP, sig); + (void) signal(SIGTERM, sig); - hist = history_init(); /* Init the builtin history */ - history(hist, H_EVENT, 100); /* Remember 100 events */ + hist = history_init(); /* Init the builtin history */ + /* Remember 100 events */ + history(hist, &ev, H_SETSIZE, 100); - tok = tok_init(NULL); /* Initialize the tokenizer */ + tok = tok_init(NULL); /* Initialize the tokenizer */ - el = el_init(*argv, stdin, stdout); /* Initialize editline */ + /* Initialize editline */ + el = el_init(*argv, stdin, stdout, stderr); - el_set(el, EL_EDITOR, "vi"); /* Default editor is vi */ - el_set(el, EL_SIGNAL, 1); /* Handle signals gracefully */ - el_set(el, EL_PROMPT, prompt); /* Set the prompt function */ + el_set(el, EL_EDITOR, "vi"); /* Default editor is vi */ + el_set(el, EL_SIGNAL, 1); /* Handle signals gracefully */ + el_set(el, EL_PROMPT, prompt); /* Set the prompt function */ - /* Tell editline to use this history interface */ - el_set(el, EL_HIST, history, hist); + /* Tell editline to use this history interface */ + el_set(el, EL_HIST, history, hist); - /* Add a user-defined function */ - el_set(el, EL_ADDFN, "ed-complete", "Complete argument", complete); + /* Add a user-defined function */ + el_set(el, EL_ADDFN, "ed-complete", "Complete argument", complete); - el_set(el, EL_BIND, "^I", "ed-complete", NULL);/* Bind tab to it */ + /* Bind tab to it */ + el_set(el, EL_BIND, "^I", "ed-complete", NULL); - /* - * Bind j, k in vi command mode to previous and next line, instead - * of previous and next history. - */ - el_set(el, EL_BIND, "-a", "k", "ed-prev-line", NULL); - el_set(el, EL_BIND, "-a", "j", "ed-next-line", NULL); + /* + * Bind j, k in vi command mode to previous and next line, instead + * of previous and next history. + */ + el_set(el, EL_BIND, "-a", "k", "ed-prev-line", NULL); + el_set(el, EL_BIND, "-a", "j", "ed-next-line", NULL); - /* - * Source the user's defaults file. - */ - el_source(el, NULL); + /* + * Source the user's defaults file. + */ + el_source(el, NULL); - while ((buf = el_gets(el, &num)) != NULL && num != 0) { - int ac; - char **av; + while ((buf = el_gets(el, &num)) != NULL && num != 0) { + int ac; + const char **av; #ifdef DEBUG - (void) fprintf(stderr, "got %d %s", num, buf); + (void) fprintf(stderr, "got %d %s", num, buf); #endif - if (!continuation && num == 1) - continue; + if (!continuation && num == 1) + continue; - if (tok_line(tok, buf, &ac, &av) > 0) { - history(hist, continuation ? H_ADD : H_ENTER, buf); - continuation = 1; - continue; - } + ncontinuation = tok_line(tok, buf, &ac, &av) > 0; +#if 0 + if (continuation) { + /* + * Append to the right event in case the user + * moved around in history. + */ + if (history(hist, &ev, H_SET, lastevent) == -1) + err(1, "%d: %s", lastevent, ev.str); + history(hist, &ev, H_ADD , buf); + } else { + history(hist, &ev, H_ENTER, buf); + lastevent = ev.num; + } +#else + /* Simpler */ + history(hist, &ev, continuation ? H_APPEND : H_ENTER, buf); +#endif - history(hist, continuation ? H_ADD : H_ENTER, buf); - - continuation = 0; - - if (strcmp(av[0], "history") == 0) { - const struct HistEvent *he; - - switch (ac) { - case 1: - for (he = history(hist, H_LAST); he; - he = history(hist, H_PREV)) - (void) fprintf(stdout, "%4d %s", he->num, he->str); - break; - - case 2: - if (strcmp(av[1], "clear") == 0) - history(hist, H_CLEAR); - else - goto badhist; - break; - - case 3: - if (strcmp(av[1], "load") == 0) - history(hist, H_LOAD, av[2]); - else if (strcmp(av[1], "save") == 0) - history(hist, H_SAVE, av[2]); - break; - - badhist: - default: - (void) fprintf(stderr, "Bad history arguments\n"); - break; - } + continuation = ncontinuation; + ncontinuation = 0; + + if (strcmp(av[0], "history") == 0) { + int rv; + + switch (ac) { + case 1: + for (rv = history(hist, &ev, H_LAST); rv != -1; + rv = history(hist, &ev, H_PREV)) + (void) fprintf(stdout, "%4d %s", + ev.num, ev.str); + break; + + case 2: + if (strcmp(av[1], "clear") == 0) + history(hist, &ev, H_CLEAR); + else + goto badhist; + break; + + case 3: + if (strcmp(av[1], "load") == 0) + history(hist, &ev, H_LOAD, av[2]); + else if (strcmp(av[1], "save") == 0) + history(hist, &ev, H_SAVE, av[2]); + break; + + badhist: + default: + (void) fprintf(stderr, + "Bad history arguments\n"); + break; + } + } else if (el_parse(el, ac, av) == -1) { + switch (fork()) { + case 0: + execvp(av[0], (char *const *)av); + perror(av[0]); + _exit(1); + /*NOTREACHED*/ + break; + + case -1: + perror("fork"); + break; + + default: + if (wait(&num) == -1) + perror("wait"); + (void) fprintf(stderr, "Exit %x\n", num); + break; + } + } + + tok_reset(tok); } - else if (el_parse(el, ac, av) == -1) { - switch (fork()) { - case 0: - execvp(av[0], av); - perror(av[0]); - _exit(1); - /*NOTREACHED*/ - break; - - case -1: - perror("fork"); - break; - - default: - if (wait(&num) == -1) - perror("wait"); - (void) fprintf(stderr, "Exit %x\n", num); - break; - } - } - - tok_reset(tok); - } - el_end(el); - tok_end(tok); - history_end(hist); + el_end(el); + tok_end(tok); + history_end(hist); - return 0; + return (0); } diff --git a/lib/libedit/chared.c b/lib/libedit/chared.c index df1207f34b7..0275dfe6c81 100644 --- a/lib/libedit/chared.c +++ b/lib/libedit/chared.c @@ -1,5 +1,5 @@ -/* $OpenBSD: chared.c,v 1.6 2003/06/02 20:18:40 millert Exp $ */ -/* $NetBSD: chared.c,v 1.2 1997/01/11 06:47:48 lukem Exp $ */ +/* $OpenBSD: chared.c,v 1.7 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: chared.c,v 1.19 2003/08/07 16:44:30 agc Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -33,88 +33,106 @@ * SUCH DAMAGE. */ +#include "config.h" #if !defined(lint) && !defined(SCCSID) #if 0 static char sccsid[] = "@(#)chared.c 8.1 (Berkeley) 6/4/93"; #else -static const char rcsid[] = "$OpenBSD: chared.c,v 1.6 2003/06/02 20:18:40 millert Exp $"; +static const char rcsid[] = "$OpenBSD: chared.c,v 1.7 2003/10/31 08:42:24 otto Exp $"; #endif #endif /* not lint && not SCCSID */ -/* +/* * chared.c: Character editor utilities */ -#include "sys.h" - #include <stdlib.h> #include "el.h" +/* value to leave unused in line buffer */ +#define EL_LEAVE 2 + /* cv_undo(): * Handle state for the vi undo command */ protected void -cv_undo(el, action, size, ptr) - EditLine *el; - int action, 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_undo_t *vu = &el->el_chared.c_undo; + c_redo_t *r = &el->el_chared.c_redo; + uint 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; } -/* c_insert(): +/* c_insert(): * Insert num characters */ protected void -c_insert(el, num) - EditLine *el; - int num; +c_insert(EditLine *el, int num) { - char *cp; + 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 */ - for (cp = el->el_line.lastchar; cp >= el->el_line.cursor; cp--) - cp[num] = *cp; - } - el->el_line.lastchar += num; -} /* end c_insert */ + if (el->el_line.cursor < el->el_line.lastchar) { + /* if I must move chars */ + for (cp = el->el_line.lastchar; cp >= el->el_line.cursor; cp--) + cp[num] = *cp; + } + el->el_line.lastchar += num; +} /* c_delafter(): * Delete num characters after the cursor */ protected void -c_delafter(el, num) - EditLine *el; - int num; +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_line.cursor + num > el->el_line.lastchar) + num = el->el_line.lastchar - el->el_line.cursor; - if (num > 0) { - char *cp; + if (el->el_map.current != el->el_map.emacs) { + cv_undo(el); + cv_yank(el, el->el_line.cursor, num); + } - if (el->el_map.current != el->el_map.emacs) - cv_undo(el, INSERT, num, el->el_line.cursor); + if (num > 0) { + char *cp; - for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++) - *cp = cp[num]; + for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++) + *cp = cp[num]; - el->el_line.lastchar -= num; - } + el->el_line.lastchar -= num; + } } @@ -122,25 +140,27 @@ c_delafter(el, num) * Delete num characters before the cursor */ protected void -c_delbefore(el, num) - EditLine *el; - int num; +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_line.cursor - num < el->el_line.buffer) + num = el->el_line.cursor - el->el_line.buffer; - if (num > 0) { - char *cp; + if (el->el_map.current != el->el_map.emacs) { + cv_undo(el); + cv_yank(el, el->el_line.cursor - num, num); + } - if (el->el_map.current != el->el_map.emacs) - cv_undo(el, INSERT, num, el->el_line.cursor - num); + if (num > 0) { + char *cp; - for (cp = el->el_line.cursor - num; cp <= el->el_line.lastchar; cp++) - *cp = cp[num]; + for (cp = el->el_line.cursor - num; + cp <= el->el_line.lastchar; + cp++) + *cp = cp[num]; - el->el_line.lastchar -= num; - } + el->el_line.lastchar -= num; + } } @@ -148,10 +168,9 @@ c_delbefore(el, num) * Return if p is part of a word according to emacs */ protected int -ce__isword(p) - int p; +ce__isword(int p) { - return isalpha(p) || isdigit(p) || strchr("*?_-.[]~=", p) != NULL; + return (isalnum(p) || strchr("*?_-.[]~=", p) != NULL); } @@ -159,10 +178,23 @@ ce__isword(p) * Return if p is part of a word according to vi */ protected int -cv__isword(p) - int p; +cv__isword(int p) +{ + if (isalnum(p) || p == '_') + return 1; + if (isgraph(p)) + return 2; + return 0; +} + + +/* cv__isWord(): + * Return if p is part of a big word according to vi + */ +protected int +cv__isWord(int p) { - return !isspace(p); + return (!isspace(p)); } @@ -170,26 +202,23 @@ cv__isword(p) * Find the previous word */ protected char * -c__prev_word(p, low, n, wtest) - register char *p, *low; - register int n; - int (*wtest)(int); +c__prev_word(char *p, char *low, int n, int (*wtest)(int)) { - p--; - - while (n--) { - while ((p >= low) && !(*wtest)((unsigned char) *p)) - p--; - while ((p >= low) && (*wtest)((unsigned char) *p)) - p--; - } - - /* cp now points to one character before the word */ - p++; - if (p < low) - p = low; - /* cp now points where we want it */ - return p; + p--; + + while (n--) { + while ((p >= low) && !(*wtest)((unsigned char) *p)) + p--; + while ((p >= low) && (*wtest)((unsigned char) *p)) + p--; + } + + /* cp now points to one character before the word */ + p++; + if (p < low) + p = low; + /* cp now points where we want it */ + return (p); } @@ -197,53 +226,46 @@ c__prev_word(p, low, n, wtest) * Find the next word */ protected char * -c__next_word(p, high, n, wtest) - register char *p, *high; - register int n; - int (*wtest)(int); +c__next_word(char *p, char *high, int n, int (*wtest)(int)) { - while (n--) { - while ((p < high) && !(*wtest)((unsigned char) *p)) - p++; - while ((p < high) && (*wtest)((unsigned char) *p)) - p++; - } - if (p > high) - p = high; - /* p now points where we want it */ - return p; + while (n--) { + while ((p < high) && !(*wtest)((unsigned char) *p)) + p++; + while ((p < high) && (*wtest)((unsigned char) *p)) + p++; + } + if (p > high) + p = high; + /* p now points where we want it */ + return (p); } /* cv_next_word(): * Find the next word vi style */ protected char * -cv_next_word(el, p, high, n, wtest) - EditLine *el; - register char *p, *high; - register int n; - int (*wtest)(int); +cv_next_word(EditLine *el, char *p, char *high, int n, int (*wtest)(int)) { - int test; + int test; + + while (n--) { + test = (*wtest)((unsigned char) *p); + while ((p < high) && (*wtest)((unsigned char) *p) == test) + p++; + /* + * vi historically deletes with cw only the word preserving the + * trailing whitespace! This is not what 'w' does.. + */ + if (n || el->el_chared.c_vcmd.action != (DELETE|INSERT)) + while ((p < high) && isspace((unsigned char) *p)) + p++; + } - while (n--) { - test = (*wtest)((unsigned char) *p); - while ((p < high) && (*wtest)((unsigned char) *p) == test) - p++; - /* - * 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)) - while ((p < high) && isspace((unsigned char) *p)) - p++; - } - - /* p now points where we want it */ - if (p > high) - return high; - else - return p; + /* p now points where we want it */ + if (p > high) + return (high); + else + return (p); } @@ -251,36 +273,25 @@ cv_next_word(el, p, high, n, wtest) * Find the previous word vi style */ protected char * -cv_prev_word(el, p, low, n, wtest) - EditLine *el; - register char *p, *low; - register int n; - int (*wtest)(int); +cv_prev_word(char *p, char *low, int n, int (*wtest)(int)) { - int test; + int test; - 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--; - test = (*wtest)((unsigned char) *p); - while ((p >= low) && (*wtest)((unsigned char) *p) == test) - p--; + while (n--) { + 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 now points where we want it */ - if (p < low) - return low; - else - return p; + + /* p now points where we want it */ + if (p < low) + return (low); + else + return (p); } @@ -291,30 +302,30 @@ cv_prev_word(el, p, low, n, wtest) * Return p pointing to last char used. */ protected char * -c__number(p, num, dval) - char *p; /* character position */ - int *num; /* Return value */ - int dval; /* dval is the number to subtract from like $-3 */ +c__number( + char *p, /* character position */ + int *num, /* Return value */ + int dval) /* dval is the number to subtract from like $-3 */ { - register int i; - register int sign = 1; - - if (*++p == '^') { - *num = 1; - return p; - } - if (*p == '$') { - if (*++p != '-') { - *num = 0x7fffffff; /* Handle $ */ - return --p; + int i; + int sign = 1; + + if (*++p == '^') { + *num = 1; + return (p); + } + if (*p == '$') { + if (*++p != '-') { + *num = 0x7fffffff; /* Handle $ */ + return (--p); + } + sign = -1; /* Handle $- */ + ++p; } - sign = -1; /* Handle $- */ - ++p; - } - for (i = 0; isdigit((unsigned char) *p); i = 10 * i + *p++ - '0') - continue; - *num = (sign < 0 ? dval - i : i); - return --p; + for (i = 0; isdigit((unsigned char) *p); i = 10 * i + *p++ - '0') + continue; + *num = (sign < 0 ? dval - i : i); + return (--p); } #endif @@ -322,53 +333,37 @@ c__number(p, num, dval) * Finish vi delete action */ protected void -cv_delfini(el) - EditLine *el; +cv_delfini(EditLine *el) { - register int size; - int oaction; - - if (el->el_chared.c_vcmd.action & INSERT) - el->el_map.current = el->el_map.key; + int size; + int action = el->el_chared.c_vcmd.action; - oaction = el->el_chared.c_vcmd.action; - el->el_chared.c_vcmd.action = NOP; + if (action & INSERT) + el->el_map.current = el->el_map.key; - if (el->el_chared.c_vcmd.pos == 0) - return; + 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); + size = el->el_line.cursor - el->el_chared.c_vcmd.pos; + if (size == 0) + size = 1; 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 = 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: - abort(); - break; - } - - - el->el_chared.c_undo.ptr = el->el_line.cursor; - el->el_chared.c_undo.dsize = size; + 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_vcmd.action = NOP; } @@ -377,21 +372,19 @@ cv_delfini(el) * Go to the end of this word according to emacs */ protected char * -ce__endword(p, high, n) - char *p, *high; - int n; +ce__endword(char *p, char *high, int n) { - p++; + p++; - while (n--) { - while ((p < high) && isspace((unsigned char) *p)) - p++; - while ((p < high) && !isspace((unsigned char) *p)) - p++; - } + while (n--) { + while ((p < high) && isspace((unsigned char) *p)) + p++; + while ((p < high) && !isspace((unsigned char) *p)) + p++; + } - p--; - return p; + p--; + return (p); } #endif @@ -400,124 +393,217 @@ ce__endword(p, high, n) * Go to the end of this word according to vi */ protected char * -cv__endword(p, high, n) - char *p, *high; - int n; +cv__endword(char *p, char *high, int n, int (*wtest)(int)) { - p++; + int test; + + p++; - while (n--) { - while ((p < high) && isspace((unsigned char) *p)) - 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++; - } - p--; - return p; + test = (*wtest)((unsigned char) *p); + while ((p < high) && (*wtest)((unsigned char) *p) == test) + p++; + } + p--; + return (p); } /* ch_init(): * Initialize the character editor */ protected int -ch_init(el) - EditLine *el; +ch_init(EditLine *el) { - el->el_line.buffer = (char *) el_malloc(EL_BUFSIZ); - (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_chared.c_undo.buf = (char *) el_malloc(EL_BUFSIZ); - (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_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); - (void)memset(el->el_chared.c_kill.buf, 0, EL_BUFSIZ); - el->el_chared.c_kill.mark = el->el_line.buffer; - el->el_chared.c_kill.last = el->el_chared.c_kill.buf; - - el->el_map.current = el->el_map.key; - - el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */ - el->el_state.doingarg = 0; - el->el_state.metanext = 0; - 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 *)); - return 0; + el->el_line.buffer = (char *) el_malloc(EL_BUFSIZ); + if (el->el_line.buffer == NULL) + return (-1); + + (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 - 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.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_kill.buf = (char *) el_malloc(EL_BUFSIZ); + if (el->el_chared.c_kill.buf == NULL) + return (-1); + (void) memset(el->el_chared.c_kill.buf, 0, EL_BUFSIZ); + el->el_chared.c_kill.mark = el->el_line.buffer; + el->el_chared.c_kill.last = el->el_chared.c_kill.buf; + + el->el_map.current = el->el_map.key; + + el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */ + el->el_state.doingarg = 0; + el->el_state.metanext = 0; + 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) + return (-1); + return (0); } /* ch_reset(): * Reset the character editor */ protected void -ch_reset(el) - EditLine *el; +ch_reset(EditLine *el) { - el->el_line.cursor = el->el_line.buffer; - el->el_line.lastchar = el->el_line.buffer; + 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_vcmd.action = NOP; + el->el_chared.c_vcmd.pos = el->el_line.buffer; - el->el_chared.c_kill.mark = el->el_line.buffer; + el->el_chared.c_kill.mark = el->el_line.buffer; - el->el_map.current = el->el_map.key; + el->el_map.current = el->el_map.key; - el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */ - el->el_state.doingarg = 0; - el->el_state.metanext = 0; - el->el_state.argument = 1; - el->el_state.lastcmd = ED_UNASSIGNED; + el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */ + el->el_state.doingarg = 0; + el->el_state.metanext = 0; + el->el_state.argument = 1; + el->el_state.lastcmd = ED_UNASSIGNED; - el->el_chared.c_macro.level = -1; + el->el_chared.c_macro.level = -1; - el->el_history.eventno = 0; + el->el_history.eventno = 0; } +/* ch_enlargebufs(): + * Enlarge line buffer to be able to hold twice as much characters. + * Returns 1 if successful, 0 if not. + */ +protected int +ch_enlargebufs(el, addlen) + EditLine *el; + size_t addlen; +{ + size_t sz, newsz; + char *newbuffer, *oldbuf, *oldkbuf; + + sz = el->el_line.limit - el->el_line.buffer + EL_LEAVE; + newsz = sz * 2; + /* + * If newly required length is longer than current buffer, we need + * to make the buffer big enough to hold both old and new stuff. + */ + if (addlen > sz) { + while(newsz - sz < addlen) + newsz *= 2; + } + + /* + * Reallocate line buffer. + */ + newbuffer = el_realloc(el->el_line.buffer, newsz); + if (!newbuffer) + return 0; + + /* zero the newly added memory, leave old data in */ + (void) memset(&newbuffer[sz], 0, newsz - sz); + + oldbuf = el->el_line.buffer; + + 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); + /* don't set new size until all buffers are enlarged */ + el->el_line.limit = &newbuffer[sz - EL_LEAVE]; + + /* + * Reallocate kill buffer. + */ + newbuffer = el_realloc(el->el_chared.c_kill.buf, newsz); + if (!newbuffer) + return 0; + + /* zero the newly added memory, leave old data in */ + (void) memset(&newbuffer[sz], 0, newsz - sz); + + oldkbuf = el->el_chared.c_kill.buf; + + el->el_chared.c_kill.buf = newbuffer; + el->el_chared.c_kill.last = newbuffer + + (el->el_chared.c_kill.last - oldkbuf); + el->el_chared.c_kill.mark = el->el_line.buffer + + (el->el_chared.c_kill.mark - oldbuf); + + /* + * Reallocate undo buffer. + */ + newbuffer = el_realloc(el->el_chared.c_undo.buf, newsz); + if (!newbuffer) + return 0; + + /* zero the newly added memory, leave old data in */ + (void) memset(&newbuffer[sz], 0, newsz - sz); + 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 = &newbuffer[newsz - EL_LEAVE]; + return 1; +} /* ch_end(): * Free the data structures used by the editor */ protected void -ch_end(el) - EditLine *el; +ch_end(EditLine *el) { - el_free((ptr_t) el->el_line.buffer); - el->el_line.buffer = NULL; - 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_kill.buf); - el->el_chared.c_kill.buf = NULL; - el_free((ptr_t) el->el_chared.c_macro.macro); - el->el_chared.c_macro.macro = NULL; - ch_reset(el); + el_free((ptr_t) el->el_line.buffer); + el->el_line.buffer = NULL; + 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; + el_free((ptr_t) el->el_chared.c_macro.macro); + el->el_chared.c_macro.macro = NULL; + ch_reset(el); } @@ -525,21 +611,21 @@ ch_end(el) * Insert string at cursorI */ public int -el_insertstr(el, s) - EditLine *el; - char *s; +el_insertstr(EditLine *el, const char *s) { - int len; + size_t len; - if ((len = strlen(s)) == 0) - return -1; - if (el->el_line.lastchar + len >= el->el_line.limit) - return -1; + if ((len = strlen(s)) == 0) + return (-1); + if (el->el_line.lastchar + len >= el->el_line.limit) { + if (!ch_enlargebufs(el, len)) + return (-1); + } - c_insert(el, len); - while (*s) - *el->el_line.cursor++ = *s++; - return 0; + c_insert(el, (int)len); + while (*s) + *el->el_line.cursor++ = *s++; + return (0); } @@ -547,74 +633,82 @@ el_insertstr(el, s) * Delete num characters before the cursor */ public void -el_deletestr(el, n) - EditLine *el; - int n; +el_deletestr(EditLine *el, int n) { - if (n <= 0) - return; + if (n <= 0) + return; - if (el->el_line.cursor < &el->el_line.buffer[n]) - return; + if (el->el_line.cursor < &el->el_line.buffer[n]) + return; - c_delbefore(el, n); /* delete before dot */ - el->el_line.cursor -= n; - if (el->el_line.cursor < el->el_line.buffer) - el->el_line.cursor = el->el_line.buffer; + c_delbefore(el, n); /* delete before dot */ + el->el_line.cursor -= n; + if (el->el_line.cursor < el->el_line.buffer) + el->el_line.cursor = el->el_line.buffer; } /* c_gets(): * Get a string */ protected int -c_gets(el, buf) - EditLine *el; - char *buf; +c_gets(EditLine *el, char *buf, const char *prompt) { - char ch; - int len = 0; - - for (ch = 0; ch == 0;) { - if (el_getc(el, &ch) != 1) - return ed_end_of_file(el, 0); - switch (ch) { - case 0010: /* Delete and backspace */ - case 0177: - 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; - } - re_refresh(el); - ch = 0; - break; - - case 0033: /* ESC */ - case '\r': /* Newline */ - case '\n': - break; - - default: - if (len >= EL_BUFSIZ) - term_beep(el); - else { - buf[len++] = ch; - *el->el_line.cursor++ = ch; - el->el_line.lastchar = el->el_line.cursor; - } - re_refresh(el); - ch = 0; - break; + char ch; + 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; + } + + switch (ch) { + + case 0010: /* Delete and backspace */ + case 0177: + if (len <= 0) { + len = -1; + break; + } + cp--; + continue; + + case 0033: /* ESC */ + case '\r': /* Newline */ + case '\n': + buf[len] = ch; + break; + + default: + if (len >= EL_BUFSIZ - 16) + term_beep(el); + else { + buf[len++] = ch; + *cp++ = ch; + } + 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; } @@ -622,21 +716,20 @@ c_gets(el, buf) * Return the current horizontal position of the cursor */ protected int -c_hpos(el) - EditLine *el; +c_hpos(EditLine *el) { - char *ptr; + char *ptr; - /* - * Find how many characters till the beginning of this line. - */ - if (el->el_line.cursor == el->el_line.buffer) - return 0; - else { - for (ptr = el->el_line.cursor - 1; - ptr >= el->el_line.buffer && *ptr != '\n'; - ptr--) - continue; - return el->el_line.cursor - ptr - 1; - } + /* + * Find how many characters till the beginning of this line. + */ + if (el->el_line.cursor == el->el_line.buffer) + return (0); + else { + for (ptr = el->el_line.cursor - 1; + ptr >= el->el_line.buffer && *ptr != '\n'; + ptr--) + continue; + return (el->el_line.cursor - ptr - 1); + } } diff --git a/lib/libedit/chared.h b/lib/libedit/chared.h index 4a506f9dd35..8192eace5ee 100644 --- a/lib/libedit/chared.h +++ b/lib/libedit/chared.h @@ -1,5 +1,5 @@ -/* $OpenBSD: chared.h,v 1.6 2003/06/02 20:18:40 millert Exp $ */ -/* $NetBSD: chared.h,v 1.2 1997/01/11 06:47:49 lukem Exp $ */ +/* $OpenBSD: chared.h,v 1.7 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: chared.h,v 1.12 2003/08/07 16:44:30 agc Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -39,61 +39,69 @@ * el.chared.h: Character editor interface */ #ifndef _h_el_chared -#define _h_el_chared +#define _h_el_chared #include <ctype.h> #include <string.h> #include "histedit.h" -#define EL_MAXMACRO 10 +#define EL_MAXMACRO 10 /* * This is a issue of basic "vi" look-and-feel. Defining VI_MOVE works * like real vi: i.e. the transition from command<->insert modes moves * the cursor. * - * On the other hand we really don't want to move the cursor, because + * On the other hand we really don't want to move the cursor, because * all the editing commands don't include the character under the cursor. * Probably the best fix is to make all the editing commands aware of * this fact. */ -#define VI_MOVE +#define VI_MOVE typedef struct c_macro_t { - int level; - char **macro; - char *nline; + int level; + 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; - int isize; - int 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; + int action; + char *pos; } c_vcmd_t; /* * Kill buffer for emacs */ typedef struct c_kill_t { - char *buf; - char *last; - char *mark; + char *buf; + char *last; + char *mark; } c_kill_t; /* @@ -101,30 +109,31 @@ typedef struct c_kill_t { * commands from both editors! */ typedef struct el_chared_t { - c_undo_t c_undo; - c_kill_t c_kill; - c_vcmd_t c_vcmd; - c_macro_t c_macro; + 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; -#define STReof "^D\b\b" -#define STRQQ "\"\"" +#define STReof "^D\b\b" +#define STRQQ "\"\"" -#define isglob(a) (strchr("*[]?", (a)) != NULL) -#define isword(a) (isprint(a)) +#define isglob(a) (strchr("*[]?", (a)) != NULL) +#define isword(a) (isprint(a)) -#define NOP 0x00 -#define DELETE 0x01 -#define INSERT 0x02 -#define CHANGE 0x04 +#define NOP 0x00 +#define DELETE 0x01 +#define INSERT 0x02 +#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 -#define MODE_REPLACE_1 2 +#define MODE_INSERT 0 +#define MODE_REPLACE 1 +#define MODE_REPLACE_1 2 #include "common.h" #include "vi.h" @@ -133,23 +142,26 @@ typedef struct el_chared_t { #include "fcns.h" -protected int cv__isword(int); -protected void cv_delfini(EditLine *); -protected char *cv__endword(char *, char *, int); -protected int ce__isword(int); -protected void cv_undo(EditLine *, int, int, char *); -protected char *cv_next_word(EditLine*, char *, char *, int, int (*)(int)); -protected char *cv_prev_word(EditLine*, 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_delafter(EditLine *, int); -protected int c_gets(EditLine *, char *); -protected int c_hpos(EditLine *); - -protected int ch_init(EditLine *); -protected void ch_reset(EditLine *); -protected void ch_end(EditLine *); +protected int cv__isword(int); +protected int cv__isWord(int); +protected void cv_delfini(EditLine *); +protected char *cv__endword(char *, char *, int, int (*)(int)); +protected int ce__isword(int); +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(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_delafter(EditLine *, int); +protected int c_gets(EditLine *, char *, const char *); +protected int c_hpos(EditLine *); + +protected int ch_init(EditLine *); +protected void ch_reset(EditLine *); +protected int ch_enlargebufs(EditLine *, size_t); +protected void ch_end(EditLine *); #endif /* _h_el_chared */ diff --git a/lib/libedit/common.c b/lib/libedit/common.c index 07318aa4c9f..35176dd75ee 100644 --- a/lib/libedit/common.c +++ b/lib/libedit/common.c @@ -1,5 +1,5 @@ -/* $OpenBSD: common.c,v 1.5 2003/06/02 20:18:40 millert Exp $ */ -/* $NetBSD: common.c,v 1.3 1997/01/14 04:17:22 lukem Exp $ */ +/* $OpenBSD: common.c,v 1.6 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: common.c,v 1.16 2003/08/07 16:44:30 agc Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -33,456 +33,411 @@ * SUCH DAMAGE. */ +#include "config.h" #if !defined(lint) && !defined(SCCSID) #if 0 static char sccsid[] = "@(#)common.c 8.1 (Berkeley) 6/4/93"; #else -static const char rcsid[] = "$OpenBSD: common.c,v 1.5 2003/06/02 20:18:40 millert Exp $"; +static const char rcsid[] = "$OpenBSD: common.c,v 1.6 2003/10/31 08:42:24 otto Exp $"; #endif #endif /* not lint && not SCCSID */ /* * common.c: Common Editor functions */ -#include "sys.h" #include "el.h" -/* ed_end_of_file(): +/* ed_end_of_file(): * Indicate end of file * [^D] */ protected el_action_t /*ARGSUSED*/ -ed_end_of_file(el, c) - EditLine *el; - int c; +ed_end_of_file(EditLine *el, int c __attribute__((__unused__))) { - re_goto_bottom(el); - *el->el_line.lastchar = '\0'; - return CC_EOF; + + re_goto_bottom(el); + *el->el_line.lastchar = '\0'; + return (CC_EOF); } -/* ed_insert(): +/* ed_insert(): * Add character to the line * Insert a character [bound to all insert keys] */ protected el_action_t -ed_insert(el, c) - EditLine *el; - int c; +ed_insert(EditLine *el, int c) { - int i; - - if (c == '\0') - return CC_ERROR; - - if (el->el_line.lastchar + el->el_state.argument >= - el->el_line.limit) - return CC_ERROR; /* end of buffer space */ + int count = el->el_state.argument; - 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); - } + if (c == '\0') + return (CC_ERROR); - 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]; + 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) count)) + return CC_ERROR; /* error allocating more */ + } - el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] = '\0'; - c_delafter(el, el->el_state.argument); - } + if (count == 1) { + if (el->el_state.inputmode == MODE_INSERT + || el->el_line.cursor >= el->el_line.lastchar) + c_insert(el, 1); - c_insert(el, el->el_state.argument); + *el->el_line.cursor++ = c; + re_fastaddc(el); /* fast refresh for one char. */ + } else { + if (el->el_state.inputmode != MODE_REPLACE_1) + c_insert(el, el->el_state.argument); - while (el->el_state.argument--) - *el->el_line.cursor++ = c; - re_refresh(el); - } + 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) - (void)vi_command_mode(el, 0); + if (el->el_state.inputmode == MODE_REPLACE_1) + return vi_command_mode(el, 0); - return CC_NORM; + return (CC_NORM); } -/* ed_delete_prev_word(): +/* ed_delete_prev_word(): * Delete from beginning of current word to cursor * [M-^?] [^W] */ protected el_action_t /*ARGSUSED*/ -ed_delete_prev_word(el, c) - EditLine *el; - int c; +ed_delete_prev_word(EditLine *el, int c __attribute__((__unused__))) { - char *cp, *p, *kp; + char *cp, *p, *kp; - if (el->el_line.cursor == el->el_line.buffer) - return CC_ERROR; + if (el->el_line.cursor == el->el_line.buffer) + return (CC_ERROR); - cp = c__prev_word(el->el_line.cursor, el->el_line.buffer, - el->el_state.argument, ce__isword); + cp = c__prev_word(el->el_line.cursor, el->el_line.buffer, + el->el_state.argument, ce__isword); - for (p = cp, kp = el->el_chared.c_kill.buf; p < el->el_line.cursor; p++) - *kp++ = *p; - el->el_chared.c_kill.last = kp; + for (p = cp, kp = el->el_chared.c_kill.buf; p < el->el_line.cursor; p++) + *kp++ = *p; + el->el_chared.c_kill.last = kp; - c_delbefore(el, el->el_line.cursor - cp); /* delete before dot */ - el->el_line.cursor = cp; - if (el->el_line.cursor < el->el_line.buffer) - el->el_line.cursor = el->el_line.buffer; /* bounds check */ - return CC_REFRESH; + c_delbefore(el, el->el_line.cursor - cp); /* delete before dot */ + el->el_line.cursor = cp; + if (el->el_line.cursor < el->el_line.buffer) + el->el_line.cursor = el->el_line.buffer; /* bounds check */ + return (CC_REFRESH); } -/* ed_delete_next_char(): +/* ed_delete_next_char(): * Delete character under cursor * [^D] [x] */ protected el_action_t /*ARGSUSED*/ -ed_delete_next_char(el, c) - EditLine *el; - int c; -{ -#ifdef notdef /* XXX */ -#define EL el->el_line -fprintf(stderr, "\nD(b: %x(%s) c: %x(%s) last: %x(%s) limit: %x(%s)\n", - EL.buffer, EL.buffer, EL.cursor, EL.cursor, EL.lastchar, EL.lastchar, EL.limit, EL.limit); +ed_delete_next_char(EditLine *el, int c __attribute__((__unused__))) +{ +#ifdef notdef /* XXX */ +#define EL el->el_line + (void) fprintf(el->el_errlfile, + "\nD(b: %x(%s) c: %x(%s) last: %x(%s) limit: %x(%s)\n", + EL.buffer, EL.buffer, EL.cursor, EL.cursor, EL.lastchar, + EL.lastchar, EL.limit, EL.limit); #endif - if (el->el_line.cursor == el->el_line.lastchar) {/* if I'm at the end */ - if (el->el_map.type == MAP_VI) { - if (el->el_line.cursor == el->el_line.buffer) { - /* if I'm also at the beginning */ + if (el->el_line.cursor == el->el_line.lastchar) { + /* if I'm at the end */ + if (el->el_map.type == MAP_VI) { + if (el->el_line.cursor == el->el_line.buffer) { + /* if I'm also at the beginning */ #ifdef KSHVI - return CC_ERROR; + return (CC_ERROR); #else - term_overwrite(el, STReof, 4);/* then do a EOF */ - term__flush(); - return CC_EOF; + term_overwrite(el, STReof, 4); + /* then do a EOF */ + term__flush(); + return (CC_EOF); #endif - } - else { + } else { #ifdef KSHVI - el->el_line.cursor--; + el->el_line.cursor--; #else - return CC_ERROR; + return (CC_ERROR); #endif - } - } - else { - if (el->el_line.cursor != el->el_line.buffer) - el->el_line.cursor--; - else - return CC_ERROR; + } + } else { + if (el->el_line.cursor != el->el_line.buffer) + el->el_line.cursor--; + else + return (CC_ERROR); + } } - } - c_delafter(el, el->el_state.argument); /* delete after dot */ - if (el->el_line.cursor >= el->el_line.lastchar && el->el_line.cursor > el->el_line.buffer) - el->el_line.cursor = el->el_line.lastchar - 1; /* bounds check */ - return CC_REFRESH; + c_delafter(el, el->el_state.argument); /* delete after dot */ + if (el->el_line.cursor >= el->el_line.lastchar && + el->el_line.cursor > el->el_line.buffer) + /* bounds check */ + el->el_line.cursor = el->el_line.lastchar - 1; + return (CC_REFRESH); } -/* ed_kill_line(): +/* ed_kill_line(): * Cut to the end of line * [^K] [^K] */ protected el_action_t /*ARGSUSED*/ -ed_kill_line(el, c) - EditLine *el; - int c; +ed_kill_line(EditLine *el, int c __attribute__((__unused__))) { - char *kp, *cp; + char *kp, *cp; - cp = el->el_line.cursor; - kp = el->el_chared.c_kill.buf; - while (cp < el->el_line.lastchar) - *kp++ = *cp++; /* copy it */ - el->el_chared.c_kill.last = kp; - el->el_line.lastchar = el->el_line.cursor; /* zap! -- delete to end */ - return CC_REFRESH; + cp = el->el_line.cursor; + kp = el->el_chared.c_kill.buf; + while (cp < el->el_line.lastchar) + *kp++ = *cp++; /* copy it */ + el->el_chared.c_kill.last = kp; + /* zap! -- delete to end */ + el->el_line.lastchar = el->el_line.cursor; + return (CC_REFRESH); } -/* ed_move_to_end(): +/* ed_move_to_end(): * Move cursor to the end of line * [^E] [^E] */ protected el_action_t /*ARGSUSED*/ -ed_move_to_end(el, c) - EditLine *el; - int c; +ed_move_to_end(EditLine *el, int c __attribute__((__unused__))) { - el->el_line.cursor = el->el_line.lastchar; - if (el->el_map.type == MAP_VI) { + + el->el_line.cursor = el->el_line.lastchar; + if (el->el_map.type == MAP_VI) { #ifdef VI_MOVE - el->el_line.cursor--; + el->el_line.cursor--; #endif - if (el->el_chared.c_vcmd.action & DELETE) { - cv_delfini(el); - return CC_REFRESH; + if (el->el_chared.c_vcmd.action != NOP) { + cv_delfini(el); + return (CC_REFRESH); + } } - } - return CC_CURSOR; + return (CC_CURSOR); } -/* ed_move_to_beg(): +/* ed_move_to_beg(): * Move cursor to the beginning of line * [^A] [^A] */ protected el_action_t /*ARGSUSED*/ -ed_move_to_beg(el, c) - EditLine *el; - int c; -{ - el->el_line.cursor = el->el_line.buffer; - - if (el->el_map.type == MAP_VI) { - /* We want FIRST non space character */ - while (isspace(*el->el_line.cursor)) - el->el_line.cursor++; - if (el->el_chared.c_vcmd.action & DELETE) { - cv_delfini(el); - return CC_REFRESH; - } - } +ed_move_to_beg(EditLine *el, int c __attribute__((__unused__))) +{ - return CC_CURSOR; + el->el_line.cursor = el->el_line.buffer; + + if (el->el_map.type == MAP_VI) { + /* 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 != NOP) { + cv_delfini(el); + return (CC_REFRESH); + } + } + return (CC_CURSOR); } -/* ed_transpose_chars(): +/* ed_transpose_chars(): * Exchange the character to the left of the cursor with the one under it * [^T] [^T] */ protected el_action_t -ed_transpose_chars(el, c) - EditLine *el; - int c; -{ - if (el->el_line.cursor < el->el_line.lastchar) { - if (el->el_line.lastchar <= &el->el_line.buffer[1]) - return CC_ERROR; - else - el->el_line.cursor++; - } - if (el->el_line.cursor > &el->el_line.buffer[1]) { - /* must have at least two chars entered */ - c = el->el_line.cursor[-2]; - el->el_line.cursor[-2] = el->el_line.cursor[-1]; - el->el_line.cursor[-1] = c; - return CC_REFRESH; - } - else - return CC_ERROR; +ed_transpose_chars(EditLine *el, int c) +{ + + if (el->el_line.cursor < el->el_line.lastchar) { + if (el->el_line.lastchar <= &el->el_line.buffer[1]) + return (CC_ERROR); + else + el->el_line.cursor++; + } + if (el->el_line.cursor > &el->el_line.buffer[1]) { + /* must have at least two chars entered */ + c = el->el_line.cursor[-2]; + el->el_line.cursor[-2] = el->el_line.cursor[-1]; + el->el_line.cursor[-1] = c; + return (CC_REFRESH); + } else + return (CC_ERROR); } -/* ed_next_char(): +/* ed_next_char(): * Move to the right one character * [^F] [^F] */ protected el_action_t /*ARGSUSED*/ -ed_next_char(el, c) - EditLine *el; - int c; +ed_next_char(EditLine *el, int c __attribute__((__unused__))) { - if (el->el_line.cursor >= el->el_line.lastchar) - return CC_ERROR; + char *lim = el->el_line.lastchar; - 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 - 1 && + el->el_map.type == MAP_VI && + el->el_chared.c_vcmd.action == NOP)) + return (CC_ERROR); - if (el->el_map.type == MAP_VI) - if (el->el_chared.c_vcmd.action & DELETE) { - cv_delfini(el); - return CC_REFRESH; - } + el->el_line.cursor += el->el_state.argument; + if (el->el_line.cursor > lim) + el->el_line.cursor = lim; - return CC_CURSOR; + if (el->el_map.type == MAP_VI) + if (el->el_chared.c_vcmd.action != NOP) { + cv_delfini(el); + return (CC_REFRESH); + } + return (CC_CURSOR); } -/* ed_prev_word(): +/* ed_prev_word(): * Move to the beginning of the current word * [M-b] [b] */ protected el_action_t /*ARGSUSED*/ -ed_prev_word(el, c) - EditLine *el; - int c; +ed_prev_word(EditLine *el, int c __attribute__((__unused__))) { - if (el->el_line.cursor == el->el_line.buffer) - return CC_ERROR; - el->el_line.cursor = c__prev_word(el->el_line.cursor, el->el_line.buffer, - el->el_state.argument, - ce__isword); + if (el->el_line.cursor == el->el_line.buffer) + return (CC_ERROR); - if (el->el_map.type == MAP_VI) - if (el->el_chared.c_vcmd.action & DELETE) { - cv_delfini(el); - return CC_REFRESH; - } + el->el_line.cursor = c__prev_word(el->el_line.cursor, + el->el_line.buffer, + el->el_state.argument, + ce__isword); - return CC_CURSOR; + if (el->el_map.type == MAP_VI) + if (el->el_chared.c_vcmd.action != NOP) { + cv_delfini(el); + return (CC_REFRESH); + } + return (CC_CURSOR); } -/* ed_prev_char(): +/* ed_prev_char(): * Move to the left one character * [^B] [^B] */ protected el_action_t /*ARGSUSED*/ -ed_prev_char(el, c) - EditLine *el; - int c; +ed_prev_char(EditLine *el, int c __attribute__((__unused__))) { - if (el->el_line.cursor > el->el_line.buffer) { - 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; - if (el->el_map.type == MAP_VI) - if (el->el_chared.c_vcmd.action & DELETE) { - cv_delfini(el); - return CC_REFRESH; - } + if (el->el_line.cursor > el->el_line.buffer) { + 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_CURSOR; - } - else - return CC_ERROR; + if (el->el_map.type == MAP_VI) + if (el->el_chared.c_vcmd.action != NOP) { + cv_delfini(el); + return (CC_REFRESH); + } + return (CC_CURSOR); + } else + return (CC_ERROR); } -/* ed_quoted_insert(): +/* ed_quoted_insert(): * Add the next character typed verbatim * [^V] [^V] */ protected el_action_t -ed_quoted_insert(el, c) - EditLine *el; - int c; +ed_quoted_insert(EditLine *el, int c) { - int num; - char tc; + int num; + char tc; - tty_quotemode(el); - num = el_getc(el, &tc); - c = (unsigned char) tc; - tty_noquotemode(el); - if (num == 1) - return ed_insert(el, c); - else - return ed_end_of_file(el, 0); + tty_quotemode(el); + num = el_getc(el, &tc); + c = (unsigned char) tc; + tty_noquotemode(el); + if (num == 1) + return (ed_insert(el, c)); + else + return (ed_end_of_file(el, 0)); } -/* ed_digit(): +/* ed_digit(): * Adds to argument or enters a digit */ protected el_action_t -ed_digit(el, c) - EditLine *el; - int c; +ed_digit(EditLine *el, int c) { - if (!isdigit(c)) - return CC_ERROR; - if (el->el_state.doingarg) { - /* if doing an arg, add this in... */ - if (el->el_state.lastcmd == EM_UNIVERSAL_ARGUMENT) - el->el_state.argument = c - '0'; - else { - if (el->el_state.argument > 1000000) - return CC_ERROR; - el->el_state.argument = - (el->el_state.argument * 10) + (c - '0'); + if (!isdigit(c)) + return (CC_ERROR); + + if (el->el_state.doingarg) { + /* if doing an arg, add this in... */ + if (el->el_state.lastcmd == EM_UNIVERSAL_ARGUMENT) + el->el_state.argument = c - '0'; + else { + if (el->el_state.argument > 1000000) + return (CC_ERROR); + el->el_state.argument = + (el->el_state.argument * 10) + (c - '0'); + } + return (CC_ARGHACK); } - return CC_ARGHACK; - } - else { - if (el->el_line.lastchar + 1 >= el->el_line.limit) - 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; -} - - -/* ed_argument_digit(): + + return ed_insert(el, c); +} + + +/* ed_argument_digit(): * Digit that starts argument * For ESC-n */ protected el_action_t -ed_argument_digit(el, c) - EditLine *el; - register int c; +ed_argument_digit(EditLine *el, int c) { - if (!isdigit(c)) - return CC_ERROR; - 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'); - } - else { /* else starting an argument */ - el->el_state.argument = c - '0'; - el->el_state.doingarg = 1; - } - return CC_ARGHACK; + if (!isdigit(c)) + return (CC_ERROR); + + 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'); + } else { /* else starting an argument */ + el->el_state.argument = c - '0'; + el->el_state.doingarg = 1; + } + return (CC_ARGHACK); } -/* ed_unassigned(): +/* ed_unassigned(): * Indicates unbound character * Bound to keys that are not assigned */ protected el_action_t /*ARGSUSED*/ -ed_unassigned(el, c) - EditLine *el; - int c; +ed_unassigned(EditLine *el, int c __attribute__((__unused__))) { - term_beep(el); - term__flush(); - return CC_NORM; + + return (CC_ERROR); } @@ -490,392 +445,381 @@ ed_unassigned(el, c) ** TTY key handling. **/ -/* ed_tty_sigint(): +/* ed_tty_sigint(): * Tty interrupt character * [^C] */ protected el_action_t /*ARGSUSED*/ -ed_tty_sigint(el, c) - EditLine *el; - int c; -{ - return CC_NORM; +ed_tty_sigint(EditLine *el __attribute__((__unused__)), + int c __attribute__((__unused__))) +{ + + return (CC_NORM); } -/* ed_tty_dsusp(): +/* ed_tty_dsusp(): * Tty delayed suspend character * [^Y] */ protected el_action_t /*ARGSUSED*/ -ed_tty_dsusp(el, c) - EditLine *el; - int c; +ed_tty_dsusp(EditLine *el __attribute__((__unused__)), + int c __attribute__((__unused__))) { - return CC_NORM; + + return (CC_NORM); } -/* ed_tty_flush_output(): +/* ed_tty_flush_output(): * Tty flush output characters * [^O] */ protected el_action_t /*ARGSUSED*/ -ed_tty_flush_output(el, c) - EditLine *el; - int c; +ed_tty_flush_output(EditLine *el __attribute__((__unused__)), + int c __attribute__((__unused__))) { - return CC_NORM; + + return (CC_NORM); } -/* ed_tty_sigquit(): +/* ed_tty_sigquit(): * Tty quit character * [^\] */ protected el_action_t /*ARGSUSED*/ -ed_tty_sigquit(el, c) - EditLine *el; - int c; +ed_tty_sigquit(EditLine *el __attribute__((__unused__)), + int c __attribute__((__unused__))) { - return CC_NORM; + + return (CC_NORM); } -/* ed_tty_sigtstp(): +/* ed_tty_sigtstp(): * Tty suspend character * [^Z] */ protected el_action_t /*ARGSUSED*/ -ed_tty_sigtstp(el, c) - EditLine *el; - int c; +ed_tty_sigtstp(EditLine *el __attribute__((__unused__)), + int c __attribute__((__unused__))) { - return CC_NORM; + + return (CC_NORM); } -/* ed_tty_stop_output(): +/* ed_tty_stop_output(): * Tty disallow output characters * [^S] */ protected el_action_t /*ARGSUSED*/ -ed_tty_stop_output(el, c) - EditLine *el; - int c; +ed_tty_stop_output(EditLine *el __attribute__((__unused__)), + int c __attribute__((__unused__))) { - return CC_NORM; + + return (CC_NORM); } -/* ed_tty_start_output(): +/* ed_tty_start_output(): * Tty allow output characters * [^Q] */ protected el_action_t /*ARGSUSED*/ -ed_tty_start_output(el, c) - EditLine *el; - int c; +ed_tty_start_output(EditLine *el __attribute__((__unused__)), + int c __attribute__((__unused__))) { - return CC_NORM; + + return (CC_NORM); } -/* ed_newline(): +/* ed_newline(): * Execute command * [^J] */ protected el_action_t /*ARGSUSED*/ -ed_newline(el, c) - EditLine *el; - int c; +ed_newline(EditLine *el, int c __attribute__((__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; + + re_goto_bottom(el); + *el->el_line.lastchar++ = '\n'; + *el->el_line.lastchar = '\0'; + return (CC_NEWLINE); } -/* ed_delete_prev_char(): +/* ed_delete_prev_char(): * Delete the character to the left of the cursor * [^?] */ protected el_action_t /*ARGSUSED*/ -ed_delete_prev_char(el, c) - EditLine *el; - int c; +ed_delete_prev_char(EditLine *el, int c __attribute__((__unused__))) { - if (el->el_line.cursor <= el->el_line.buffer) - return CC_ERROR; - c_delbefore(el, el->el_state.argument); - 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; + if (el->el_line.cursor <= el->el_line.buffer) + return (CC_ERROR); + + c_delbefore(el, el->el_state.argument); + 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); } -/* ed_clear_screen(): +/* ed_clear_screen(): * Clear screen leaving current line at the top * [^L] */ protected el_action_t /*ARGSUSED*/ -ed_clear_screen(el, c) - EditLine *el; - int c; +ed_clear_screen(EditLine *el, int c __attribute__((__unused__))) { - term_clear_screen(el); /* clear the whole real screen */ - re_clear_display(el); /* reset everything */ - return CC_REFRESH; + + term_clear_screen(el); /* clear the whole real screen */ + re_clear_display(el); /* reset everything */ + return (CC_REFRESH); } -/* ed_redisplay(): +/* ed_redisplay(): * Redisplay everything * ^R */ protected el_action_t /*ARGSUSED*/ -ed_redisplay(el, c) - EditLine *el; - int c; +ed_redisplay(EditLine *el __attribute__((__unused__)), + int c __attribute__((__unused__))) { - return CC_REDISPLAY; + + return (CC_REDISPLAY); } -/* ed_start_over(): +/* ed_start_over(): * Erase current line and start from scratch * [^G] */ protected el_action_t /*ARGSUSED*/ -ed_start_over(el, c) - EditLine *el; - int c; +ed_start_over(EditLine *el, int c __attribute__((__unused__))) { - ch_reset(el); - return CC_REFRESH; + + ch_reset(el); + return (CC_REFRESH); } -/* ed_sequence_lead_in(): +/* ed_sequence_lead_in(): * First character in a bound sequence * Placeholder for external keys */ protected el_action_t /*ARGSUSED*/ -ed_sequence_lead_in(el, c) - EditLine *el; - int c; +ed_sequence_lead_in(EditLine *el __attribute__((__unused__)), + int c __attribute__((__unused__))) { - return CC_NORM; + + return (CC_NORM); } -/* ed_prev_history(): +/* ed_prev_history(): * Move to the previous history line * [^P] [k] */ protected el_action_t /*ARGSUSED*/ -ed_prev_history(el, c) - EditLine *el; - int c; +ed_prev_history(EditLine *el, int c __attribute__((__unused__))) { - char beep = 0; - - el->el_chared.c_undo.action = NOP; - *el->el_line.lastchar = '\0'; /* just in case */ - - if (el->el_history.eventno == 0) { /* save the current buffer away */ - (void)strncpy(el->el_history.buf, el->el_line.buffer, EL_BUFSIZ - 1); - el->el_history.buf[EL_BUFSIZ - 1] = '\0'; - el->el_history.last = el->el_history.buf + - (el->el_line.lastchar - el->el_line.buffer); - } - - el->el_history.eventno += el->el_state.argument; + char beep = 0; + int sv_event = el->el_history.eventno; - if (hist_get(el) == CC_ERROR) { - beep = 1; - /* el->el_history.eventno was fixed by first call */ - (void)hist_get(el); - } + el->el_chared.c_undo.len = -1; + *el->el_line.lastchar = '\0'; /* just in case */ - re_refresh(el); - if (beep) - return CC_ERROR; - else - return CC_NORM; /* was CC_UP_HIST */ + if (el->el_history.eventno == 0) { /* save the current buffer + * away */ + (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); + } + 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); + } + if (beep) + return CC_REFRESH_BEEP; + return CC_REFRESH; } -/* ed_next_history(): +/* ed_next_history(): * Move to the next history line * [^N] [j] */ protected el_action_t /*ARGSUSED*/ -ed_next_history(el, c) - EditLine *el; - int c; +ed_next_history(EditLine *el, int c __attribute__((__unused__))) { - el->el_chared.c_undo.action = NOP; - *el->el_line.lastchar = '\0'; /* just in case */ + el_action_t beep = CC_REFRESH, rval; - el->el_history.eventno -= el->el_state.argument; + el->el_chared.c_undo.len = -1; + *el->el_line.lastchar = '\0'; /* just in case */ - if (el->el_history.eventno < 0) { - el->el_history.eventno = 0; - return CC_ERROR; /* make it beep */ - } + el->el_history.eventno -= el->el_state.argument; + + if (el->el_history.eventno < 0) { + el->el_history.eventno = 0; + beep = CC_REFRESH_BEEP; + } + rval = hist_get(el); + if (rval == CC_REFRESH) + return beep; + return rval; - return hist_get(el); } -/* ed_search_prev_history(): +/* ed_search_prev_history(): * Search previous in history for a line matching the current * next search history [M-P] [K] */ protected el_action_t /*ARGSUSED*/ -ed_search_prev_history(el, c) - EditLine *el; - int c; -{ - 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_line.lastchar = '\0'; /* just in case */ - if (el->el_history.eventno < 0) { +ed_search_prev_history(EditLine *el, int c __attribute__((__unused__))) +{ + const char *hp; + int h; + bool_t found = 0; + + el->el_chared.c_vcmd.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 - (void)fprintf(el->el_errfile, "e_prev_search_hist(): eventno < 0;\n"); + (void) fprintf(el->el_errfile, + "e_prev_search_hist(): eventno < 0;\n"); #endif - el->el_history.eventno = 0; - return CC_ERROR; - } - - if (el->el_history.eventno == 0) { - (void)strncpy(el->el_history.buf, el->el_line.buffer, EL_BUFSIZ - 1); - el->el_history.buf[EL_BUFSIZ - 1] = '\0'; - el->el_history.last = el->el_history.buf + - (el->el_line.lastchar - el->el_line.buffer); - } - - - if (el->el_history.ref == NULL) - return CC_ERROR; + el->el_history.eventno = 0; + return (CC_ERROR); + } + 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); + } + if (el->el_history.ref == NULL) + return (CC_ERROR); - hp = HIST_FIRST(el); - if (hp == NULL) - return CC_ERROR; + hp = HIST_FIRST(el); + if (hp == NULL) + return (CC_ERROR); - c_setpat(el); /* Set search pattern !! */ + c_setpat(el); /* Set search pattern !! */ - for (h = 1; h <= el->el_history.eventno; h++) - hp = HIST_NEXT(el); + for (h = 1; h <= el->el_history.eventno; h++) + hp = HIST_NEXT(el); - while (hp != NULL) { + while (hp != NULL) { #ifdef SDEBUG - (void)fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp); + (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp); #endif - if ((strncmp(hp, el->el_line.buffer, - el->el_line.lastchar - el->el_line.buffer) || - hp[el->el_line.lastchar-el->el_line.buffer]) && - c_hmatch(el, hp)) { - found++; - break; + if ((strncmp(hp, el->el_line.buffer, (size_t) + (el->el_line.lastchar - el->el_line.buffer)) || + hp[el->el_line.lastchar - el->el_line.buffer]) && + c_hmatch(el, hp)) { + found++; + break; + } + h++; + hp = HIST_NEXT(el); } - h++; - hp = HIST_NEXT(el); - } - if (!found) { + if (!found) { #ifdef SDEBUG - (void)fprintf(el->el_errfile, "not found\n"); + (void) fprintf(el->el_errfile, "not found\n"); #endif - return CC_ERROR; - } - - el->el_history.eventno = h; + return (CC_ERROR); + } + el->el_history.eventno = h; - return hist_get(el); + return (hist_get(el)); } -/* ed_search_next_history(): +/* ed_search_next_history(): * Search next in history for a line matching the current * [M-N] [J] */ protected el_action_t /*ARGSUSED*/ -ed_search_next_history(el, c) - EditLine *el; - int c; +ed_search_next_history(EditLine *el, int c __attribute__((__unused__))) { - const char *hp; - int h; - bool_t found = 0; + 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_line.lastchar = '\0'; /* just in case */ + el->el_chared.c_vcmd.action = NOP; + el->el_chared.c_undo.len = -1; + *el->el_line.lastchar = '\0'; /* just in case */ - if (el->el_history.eventno == 0) - return CC_ERROR; + if (el->el_history.eventno == 0) + return (CC_ERROR); - if (el->el_history.ref == NULL) - return CC_ERROR; + if (el->el_history.ref == NULL) + return (CC_ERROR); - hp = HIST_FIRST(el); - if (hp == NULL) - return CC_ERROR; + hp = HIST_FIRST(el); + if (hp == NULL) + return (CC_ERROR); - c_setpat(el); /* Set search pattern !! */ + c_setpat(el); /* Set search pattern !! */ - for (h = 1; h < el->el_history.eventno && hp; h++) { + for (h = 1; h < el->el_history.eventno && hp; h++) { #ifdef SDEBUG - (void)fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp); + (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp); #endif - if ((strncmp(hp, el->el_line.buffer, - el->el_line.lastchar - el->el_line.buffer) || - hp[el->el_line.lastchar-el->el_line.buffer]) && - c_hmatch(el, hp)) - found = h; - hp = HIST_NEXT(el); - } - - if (!found) { /* is it the current history number? */ - if (!c_hmatch(el, el->el_history.buf)) { + if ((strncmp(hp, el->el_line.buffer, (size_t) + (el->el_line.lastchar - el->el_line.buffer)) || + hp[el->el_line.lastchar - el->el_line.buffer]) && + c_hmatch(el, hp)) + found = h; + hp = HIST_NEXT(el); + } + + if (!found) { /* is it the current history number? */ + if (!c_hmatch(el, el->el_history.buf)) { #ifdef SDEBUG - (void)fprintf(el->el_errfile, "not found\n"); + (void) fprintf(el->el_errfile, "not found\n"); #endif - return CC_ERROR; + return (CC_ERROR); + } } - } + el->el_history.eventno = found; - el->el_history.eventno = found; - - return hist_get(el); + return (hist_get(el)); } @@ -885,42 +829,40 @@ ed_search_next_history(el, c) */ protected el_action_t /*ARGSUSED*/ -ed_prev_line(el, c) - EditLine *el; - int c; -{ - char *ptr; - int nchars = c_hpos(el); - - /* - * Move to the line requested - */ - if (*(ptr = el->el_line.cursor) == '\n') - ptr--; - - for (; ptr >= el->el_line.buffer; ptr--) - if (*ptr == '\n' && --el->el_state.argument <= 0) - break; - - if (el->el_state.argument > 0) - return CC_ERROR; - - /* - * Move to the beginning of the line - */ - for (ptr--; ptr >= el->el_line.buffer && *ptr != '\n'; ptr--) - continue; - - /* - * Move to the character requested - */ - for (ptr++; - nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n'; - ptr++) - continue; - - el->el_line.cursor = ptr; - return CC_CURSOR; +ed_prev_line(EditLine *el, int c __attribute__((__unused__))) +{ + char *ptr; + int nchars = c_hpos(el); + + /* + * Move to the line requested + */ + if (*(ptr = el->el_line.cursor) == '\n') + ptr--; + + for (; ptr >= el->el_line.buffer; ptr--) + if (*ptr == '\n' && --el->el_state.argument <= 0) + break; + + if (el->el_state.argument > 0) + return (CC_ERROR); + + /* + * Move to the beginning of the line + */ + for (ptr--; ptr >= el->el_line.buffer && *ptr != '\n'; ptr--) + continue; + + /* + * Move to the character requested + */ + for (ptr++; + nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n'; + ptr++) + continue; + + el->el_line.cursor = ptr; + return (CC_CURSOR); } @@ -930,68 +872,52 @@ ed_prev_line(el, c) */ protected el_action_t /*ARGSUSED*/ -ed_next_line(el, c) - EditLine *el; - int c; +ed_next_line(EditLine *el, int c __attribute__((__unused__))) { - char *ptr; - int nchars = c_hpos(el); + char *ptr; + int nchars = c_hpos(el); + + /* + * Move to the line requested + */ + for (ptr = el->el_line.cursor; ptr < el->el_line.lastchar; ptr++) + if (*ptr == '\n' && --el->el_state.argument <= 0) + break; - /* - * Move to the line requested - */ - for (ptr = el->el_line.cursor; ptr < el->el_line.lastchar; ptr++) - if (*ptr == '\n' && --el->el_state.argument <= 0) - break; + if (el->el_state.argument > 0) + return (CC_ERROR); - if (el->el_state.argument > 0) - return CC_ERROR; + /* + * Move to the character requested + */ + for (ptr++; + nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n'; + ptr++) + continue; - /* - * Move to the character requested - */ - for (ptr++; - nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n'; - ptr++) - continue; - - el->el_line.cursor = ptr; - return CC_CURSOR; + el->el_line.cursor = ptr; + return (CC_CURSOR); } -/* ed_command(): +/* ed_command(): * Editline extended command * [M-X] [:] */ protected el_action_t /*ARGSUSED*/ -ed_command(el, c) - EditLine *el; - int c; +ed_command(EditLine *el, int c __attribute__((__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); + char tmpbuf[EL_BUFSIZ]; + int tmplen; - 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 + el->el_map.current = el->el_map.key; + re_clear_display(el); return CC_REFRESH; } diff --git a/lib/libedit/config.h b/lib/libedit/config.h new file mode 100644 index 00000000000..a3986766294 --- /dev/null +++ b/lib/libedit/config.h @@ -0,0 +1,19 @@ +/* $OpenBSD: config.h,v 1.1 2003/10/31 08:42:24 otto Exp $ */ +/* config.h. Generated automatically by configure. */ +/* #undef SUNOS */ + +#define HAVE_SYS_CDEFS_H 1 +#define HAVE_TERMCAP_H 1 +/* #undef HAVE_CURSES_H */ +/* #undef HAVE_NCURSES_H */ +/* #undef HAVE_TERM_H */ +#define HAVE_VIS_H 1 +#define HAVE_ISSETUGID 1 + +#define HAVE_STRLCAT 1 +#define HAVE_STRLCPY 1 +#define HAVE_FGETLN 1 +#define HAVE_STRVIS 1 +#define HAVE_STRUNVIS 1 + +#include "sys.h" diff --git a/lib/libedit/editline.3 b/lib/libedit/editline.3 index 3e9c988a781..1276ed29cbc 100644 --- a/lib/libedit/editline.3 +++ b/lib/libedit/editline.3 @@ -1,7 +1,6 @@ -.\" $OpenBSD: editline.3,v 1.12 2003/08/08 07:46:30 jmc Exp $ -.\" $NetBSD: editline.3,v 1.4 1997/01/14 04:17:23 lukem Exp $ +.\" $NetBSD: editline.3,v 1.38 2003/09/26 21:09:13 wiz Exp $ .\" -.\" Copyright (c) 1997 The NetBSD Foundation, Inc. +.\" Copyright (c) 1997-1999 The NetBSD Foundation, Inc. .\" All rights reserved. .\" .\" This file was contributed to The NetBSD Foundation by Luke Mewburn. @@ -25,8 +24,8 @@ .\" 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 REGENTS OR CONTRIBUTORS BE -.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" 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 @@ -34,9 +33,9 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd January 11, 1997 -.Dt EDITLINE 3 +.Dd September 26, 2003 .Os +.Dt EDITLINE 3 .Sh NAME .Nm editline , .Nm el_init , @@ -56,10 +55,12 @@ .Nm history_end , .Nm history .Nd line editor and history functions +.Sh LIBRARY +.Lb libedit .Sh SYNOPSIS -.Fd #include <histedit.h> +.In histedit.h .Ft EditLine * -.Fn el_init "const char *prog" "FILE *fin" "FILE *fout" +.Fn el_init "const char *prog" "FILE *fin" "FILE *fout" "FILE *ferr" .Ft void .Fn el_end "EditLine *e" .Ft void @@ -71,25 +72,27 @@ .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 +.Fn el_get "EditLine *e" "int op" "void *result" +.Ft int .Fn el_source "EditLine *e" "const char *file" .Ft void .Fn el_resize "EditLine *e" .Ft const LineInfo * .Fn el_line "EditLine *e" .Ft int -.Fn el_insertstr "EditLine *e" "char *str" +.Fn el_insertstr "EditLine *e" "const char *str" .Ft void .Fn el_deletestr "EditLine *e" "int count" .Ft History * .Fn history_init .Ft void .Fn history_end "History *h" -.Ft HistEvent * -.Fn history "History *h" "int op" "..." +.Ft int +.Fn history "History *h" "HistEvent *ev" "int op" "..." .Sh DESCRIPTION The .Nm @@ -100,13 +103,13 @@ similar to those found in These functions are available in the .Nm libedit library (which needs the -.Nm libcurses +.Nm libtermcap library). Programs should be linked with -.Fl ledit lcurses . +.Fl ledit ltermcap . .Sh LINE EDITING FUNCTIONS The line editing functions use a common data structure, -.Fa editline , +.Fa EditLine , which is created by .Fn el_init and freed by @@ -121,10 +124,11 @@ to be used by all other line editing functions. is the name of the invoking program, used when reading the .Xr editrc 5 file to determine which settings to use. -.Fa fin -and +.Fa fin , .Fa fout -are the input and output streams (respectively) to use. +and +.Fa ferr +are the input, output, and error streams (respectively) to use. In this documentation, references to .Dq the tty are actually to this input/output stream combination. @@ -166,11 +170,11 @@ Parses the array (which is .Fa argc elements in size) -to execute built-in +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 @@ -188,19 +192,6 @@ didn't match, or Refer to .Xr editrc 5 for more information. -.Pp -.Em NOTE : -.Va argv[0] -may be modified by -.Fn el_parse . -The colon between -.Dq prog -and the command, -.Ar command , -will be replaced with a NUL -.Po -.Dq \e0 -.Pc . .It Fn el_set Set .Nm @@ -217,6 +208,10 @@ are supported, along with the required argument list: Define prompt printing function as .Fa f , which is to return a string that contains the prompt. +.It Dv EL_RPROMPT , Fa "char *(*f)(EditLine *)" +Define right side prompt printing function as +.Fa f , +which is to return a string that contains the prompt. .It Dv EL_TERMINAL , Fa "const char *type" Define terminal type of the tty to be .Fa type , @@ -257,7 +252,7 @@ Otherwise, the current signal handlers will be used. .Xc Perform the .Ic bind -built-in command. +builtin command. Refer to .Xr editrc 5 for more information. @@ -268,7 +263,7 @@ for more information. .Xc Perform the .Ic echotc -built-in command. +builtin command. Refer to .Xr editrc 5 for more information. @@ -279,7 +274,7 @@ for more information. .Xc Perform the .Ic settc -built-in command. +builtin command. Refer to .Xr editrc 5 for more information. @@ -290,7 +285,7 @@ for more information. .Xc Perform the .Ic setty -built-in command. +builtin command. Refer to .Xr editrc 5 for more information. @@ -301,7 +296,7 @@ for more information. .Xc Perform the .Ic telltc -built-in command. +builtin command. Refer to .Xr editrc 5 for more information. @@ -337,6 +332,8 @@ EOF was entered. Expecting further command input as arguments, do nothing visually. .It Dv CC_REFRESH Refresh display. +.It Dv CC_REFRESH_BEEP +Refresh display, and beep. .It Dv CC_CURSOR Cursor moved, so update and perform .Dv CC_REFRESH . @@ -358,6 +355,83 @@ Defines which history function to use, which is usually .Fa ptr should be the value returned by .Fn history_init . +.It Dv EL_EDITMODE , Fa "int flag" +If +.Fa flag +is non-zero, +editing is enabled (the default). +Note that this is only an indication, and does not +affect the operation of +.Nm . +At this time, it is the caller's responsibility to +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 +.Nm +parameters. +.Fa op +determines which parameter to retrieve into +.Fa result . +Returns 0 if successful, \-1 otherwise. +.Pp +The following values for +.Fa op +are supported, along with actual type of +.Fa result : +.Bl -tag -width 4n +.It Dv EL_PROMPT , Fa "char *(*f)(EditLine *)" +Return a pointer to the function that displays the prompt. +.It Dv EL_RPROMPT , Fa "char *(*f)(EditLine *)" +Return a pointer to the function that displays the rightside prompt. +.It Dv EL_EDITOR , Fa "const char *" +Return the name of the editor, which will be one of +.Dq emacs +or +.Dq vi . +.It Dv EL_SIGNAL , Fa "int *" +Return non-zero if +.Nm +has installed private signal handlers (see +.Fn el_get +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. .El .It Fn el_source Initialise @@ -391,7 +465,7 @@ Otherwise, it's the responsibility of the application to call on the appropriate occasions. .It Fn el_line Return the editing information for the current line in a -.Fa lineinfo +.Fa LineInfo structure, which is defined as follows: .Bd -literal typedef struct lineinfo { @@ -414,7 +488,7 @@ characters before the cursor. .El .Sh HISTORY LIST FUNCTIONS The history functions use a common data structure, -.Fa history , +.Fa History , which is created by .Fn history_init and freed by @@ -435,14 +509,18 @@ Perform operation .Fa op on the history list, with optional arguments as needed by the operation. +.Fa ev +is changed accordingly to operation. The following values for .Fa op are supported, along with the required argument list: .Bl -tag -width 4n -.It Dv H_EVENT , Fa "int size" +.It Dv H_SETSIZE , Fa "int size" Set size of history to .Fa size elements. +.It Dv H_GETSIZE +Get number of events currently in history. .It Dv H_END Cleans up and finishes with .Fa h , @@ -457,6 +535,7 @@ Clear the history. .Fa "history_gfun_t last" , .Fa "history_gfun_t prev" , .Fa "history_gfun_t curr" , +.Fa "history_sfun_t set" , .Fa "history_vfun_t clear" , .Fa "history_efun_t enter" , .Fa "history_efun_t add" @@ -474,17 +553,32 @@ Return the previous element in the history. Return the next element in the history. .It Dv H_CURR Return the current element in the history. +.It Dv H_SET +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 -.Dv H_ENTER -if there isn't one. +.It Dv H_APPEND , Fa "const char *str" +Append +.Fa str +to the last new element of the history. .It Dv H_ENTER , Fa "const char *str" 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 . @@ -503,7 +597,21 @@ 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. .El +.Pp +.Fn history +returns >= 0 if the operation succeeds +.Fa op +succeeds. +Otherwise, \-1 is returned and +.Fa ev +is updated to contain more details about the error. .El .\"XXX.Sh EXAMPLES .\"XXX: provide some examples @@ -517,17 +625,46 @@ The .Nm library first appeared in .Bx 4.4 . +.Dv CC_REDISPLAY +appeared in +.Nx 1.3 . +.Dv CC_REFRESH_BEEP , +.Dv EL_EDITMODE +and the readline emulation appeared in +.Nx 1.4 . +.Dv EL_RPROMPT +appeared in +.Nx 1.5 . .Sh AUTHORS The .Nm -library was written by Christos Zoulas, -and this manual was written by Luke Mewburn. +library was written by Christos Zoulas. +Luke Mewburn wrote this manual and implemented +.Dv CC_REDISPLAY , +.Dv CC_REFRESH_BEEP , +.Dv EL_EDITMODE , +and +.Dv EL_RPROMPT . +Jaromir Dolecek implemented the readline emulation. .Sh BUGS -This documentation is probably incomplete. -.Pp -.Fn el_parse -should not modify the supplied -.Va argv[0] . -.Pp -The tokenization functions are not publically defined in +The tokenization functions are not publicly defined in .Aq Pa histedit.h . +.Pp +At this time, it is the responsibility of the caller to +check the result of the +.Dv EL_EDITMODE +operation of +.Fn el_get +(after an +.Fn el_source +or +.Fn el_parse ) +to determine if +.Nm +should be used for further input. +I.e., +.Dv EL_EDITMODE +is purely an indication of the result of the most recent +.Xr editrc 5 +.Ic edit +command. diff --git a/lib/libedit/editrc.5 b/lib/libedit/editrc.5 index 671bc771e6f..3298bfeafe7 100644 --- a/lib/libedit/editrc.5 +++ b/lib/libedit/editrc.5 @@ -1,7 +1,7 @@ -.\" $OpenBSD: editrc.5,v 1.15 2003/10/22 07:49:03 jmc Exp $ -.\" $NetBSD: editrc.5,v 1.4 1997/04/24 20:20:31 christos Exp $ +.\" $OpenBSD: editrc.5,v 1.16 2003/10/31 08:42:24 otto Exp $ +.\" $NetBSD: editrc.5,v 1.16 2003/06/27 18:57:09 wiz Exp $ .\" -.\" Copyright (c) 1997 The NetBSD Foundation, Inc. +.\" Copyright (c) 1997-2000 The NetBSD Foundation, Inc. .\" All rights reserved. .\" .\" This file was contributed to The NetBSD Foundation by Luke Mewburn. @@ -25,8 +25,8 @@ .\" 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 REGENTS OR CONTRIBUTORS BE -.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" 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 @@ -34,14 +34,14 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd January 11, 1997 -.Dt EDITRC 5 +.Dd November 8, 2000 .Os +.Dt EDITRC 5 .Sh NAME .Nm editrc .Nd configuration file for editline library .Sh SYNOPSIS -.Nm editrc +.Nm .Sh DESCRIPTION The .Nm @@ -49,17 +49,15 @@ file defines various settings to be used by the .Xr editline 3 library. .Pp -The format of each line is either: -.Dl prog:command [arg [...]] -or -.Dl command [arg [...]] +The format of each line is: +.Dl [prog:]command [arg [...]] .Pp .Ar command is one of the .Xr editline 3 -built-in commands. +builtin commands. Refer to -.Sx BUILT-IN COMMANDS +.Sx BUILTIN COMMANDS for more information. .Pp .Ar prog @@ -80,16 +78,22 @@ style regular expression, in which case .Ar command will be executed for any program that matches the regular expression. -.Sh BUILT-IN COMMANDS +.Pp +If +.Ar prog +is absent, +.Ar command +is executed for all programs. +.Sh BUILTIN COMMANDS The .Nm editline -library has some built-in commands, which affect the way +library has some builtin commands, which affect the way that the line editing and history functions operate. -These are based on similarly named built-in commands present in the -.Xr tcsh +These are based on similar named builtins present in the +.Xr tcsh 1 shell. .Pp -The following built-in commands are available: +The following builtin commands are available: .Bl -tag -width 4n .It Ic bind Xo .Op Fl a @@ -119,7 +123,7 @@ Options include: Bind all keys to the standard GNU Emacs-like bindings. .It Fl v Bind all keys to the standard -.Xr vi 1 -like +.Xr vi 1 Ns -like bindings. .It Fl a List or change key bindings in the @@ -148,6 +152,11 @@ are themselves reinterpreted, and this continues for ten levels of interpretation. .El .Pp +.Ar command +may be one of the commands documented in +.Sx "EDITOR COMMANDS" +below, or another key. +.Pp .Ar key and .Ar command @@ -156,7 +165,7 @@ can contain control characters of the form .Sq No ^ Ar character .Sm on .Po -e.g., +e.g. .Sq ^A .Pc , and the following backslashed escape sequences: @@ -218,6 +227,10 @@ returns an empty string for non-existent capabilities, rather than causing an error. .Fl v causes messages to be verbose. +.It Ic edit Op Li on | Li off +Enable or disable the +.Nm editline +functionality in a program. .It Ic history List the history. .It Ic telltc @@ -280,6 +293,192 @@ on or off or removes control of .Ar mode in the chosen set. .El +.Sh EDITOR COMMANDS +The following editor commands are available for use in key bindings: +.\" Section automatically generated with makelist +.Bl -tag -width 4n +.It Ic vi-paste-next +Vi paste previous deletion to the right of the cursor. +.It Ic vi-paste-prev +Vi paste previous deletion to the left of the cursor. +.It Ic vi-prev-space-word +Vi move to the previous space delimited word. +.It Ic vi-prev-word +Vi move to the previous word. +.It Ic vi-next-space-word +Vi move to the next space delimited word. +.It Ic vi-next-word +Vi move to the next word. +.It Ic vi-change-case +Vi change case of character under the cursor and advance one character. +.It Ic vi-change-meta +Vi change prefix command. +.It Ic vi-insert-at-bol +Vi enter insert mode at the beginning of line. +.It Ic vi-replace-char +Vi replace character under the cursor with the next character typed. +.It Ic vi-replace-mode +Vi enter replace mode. +.It Ic vi-substitute-char +Vi replace character under the cursor and enter insert mode. +.It Ic vi-substitute-line +Vi substitute entire line. +.It Ic vi-change-to-eol +Vi change to end of line. +.It Ic vi-insert +Vi enter insert mode. +.It Ic vi-add +Vi enter insert mode after the cursor. +.It Ic vi-add-at-eol +Vi enter insert mode at end of line. +.It Ic vi-delete-meta +Vi delete prefix command. +.It Ic vi-end-word +Vi move to the end of the current space delimited word. +.It Ic vi-to-end-word +Vi move to the end of the current word. +.It Ic vi-undo +Vi undo last change. +.It Ic vi-command-mode +Vi enter command mode (use alternative key bindings). +.It Ic vi-zero +Vi move to the beginning of line. +.It Ic vi-delete-prev-char +Vi move to previous character (backspace). +.It Ic vi-list-or-eof +Vi list choices for completion or indicate end of file if empty line. +.It Ic vi-kill-line-prev +Vi cut from beginning of line to cursor. +.It Ic vi-search-prev +Vi search history previous. +.It Ic vi-search-next +Vi search history next. +.It Ic vi-repeat-search-next +Vi repeat current search in the same search direction. +.It Ic vi-repeat-search-prev +Vi repeat current search in the opposite search direction. +.It Ic vi-next-char +Vi move to the character specified next. +.It Ic vi-prev-char +Vi move to the character specified previous. +.It Ic vi-to-next-char +Vi move up to the character specified next. +.It Ic vi-to-prev-char +Vi move up to the character specified previous. +.It Ic vi-repeat-next-char +Vi repeat current character search in the same search direction. +.It Ic vi-repeat-prev-char +Vi repeat current character search in the opposite search direction. +.It Ic em-delete-or-list +Delete character under cursor or list completions if at end of line. +.It Ic em-delete-next-word +Cut from cursor to end of current word. +.It Ic em-yank +Paste cut buffer at cursor position. +.It Ic em-kill-line +Cut the entire line and save in cut buffer. +.It Ic em-kill-region +Cut area between mark and cursor and save in cut buffer. +.It Ic em-copy-region +Copy area between mark and cursor to cut buffer. +.It Ic em-gosmacs-transpose +Exchange the two characters before the cursor. +.It Ic em-next-word +Move next to end of current word. +.It Ic em-upper-case +Uppercase the characters from cursor to end of current word. +.It Ic em-capitol-case +Capitalize the characters from cursor to end of current word. +.It Ic em-lower-case +Lowercase the characters from cursor to end of current word. +.It Ic em-set-mark +Set the mark at cursor. +.It Ic em-exchange-mark +Exchange the cursor and mark. +.It Ic em-universal-argument +Universal argument (argument times 4). +.It Ic em-meta-next +Add 8th bit to next character typed. +.It Ic em-toggle-overwrite +Switch from insert to overwrite mode or vice versa. +.It Ic em-copy-prev-word +Copy current word to cursor. +.It Ic em-inc-search-next +Emacs incremental next search. +.It Ic em-inc-search-prev +Emacs incremental reverse search. +.It Ic ed-end-of-file +Indicate end of file. +.It Ic ed-insert +Add character to the line. +.It Ic ed-delete-prev-word +Delete from beginning of current word to cursor. +.It Ic ed-delete-next-char +Delete character under cursor. +.It Ic ed-kill-line +Cut to the end of line. +.It Ic ed-move-to-end +Move cursor to the end of line. +.It Ic ed-move-to-beg +Move cursor to the beginning of line. +.It Ic ed-transpose-chars +Exchange the character to the left of the cursor with the one under it. +.It Ic ed-next-char +Move to the right one character. +.It Ic ed-prev-word +Move to the beginning of the current word. +.It Ic ed-prev-char +Move to the left one character. +.It Ic ed-quoted-insert +Add the next character typed verbatim. +.It Ic ed-digit +Adds to argument or enters a digit. +.It Ic ed-argument-digit +Digit that starts argument. +.It Ic ed-unassigned +Indicates unbound character. +.It Ic ed-tty-sigint +Tty interrupt character. +.It Ic ed-tty-dsusp +Tty delayed suspend character. +.It Ic ed-tty-flush-output +Tty flush output characters. +.It Ic ed-tty-sigquit +Tty quit character. +.It Ic ed-tty-sigtstp +Tty suspend character. +.It Ic ed-tty-stop-output +Tty disallow output characters. +.It Ic ed-tty-start-output +Tty allow output characters. +.It Ic ed-newline +Execute command. +.It Ic ed-delete-prev-char +Delete the character to the left of the cursor. +.It Ic ed-clear-screen +Clear screen leaving current line at the top. +.It Ic ed-redisplay +Redisplay everything. +.It Ic ed-start-over +Erase current line and start from scratch. +.It Ic ed-sequence-lead-in +First character in a bound sequence. +.It Ic ed-prev-history +Move to the previous history line. +.It Ic ed-next-history +Move to the next history line. +.It Ic ed-search-prev-history +Search previous in history for a line matching the current. +.It Ic ed-search-next-history +Search next in history for a line matching the current. +.It Ic ed-prev-line +Move up one line. +.It Ic ed-next-line +Move down one line. +.It Ic ed-command +Editline extended command. +.El +.\" End of section automatically generated with makelist .Sh SEE ALSO .Xr editline 3 , .Xr regex 3 , @@ -290,4 +489,4 @@ The library was written by Christos Zoulas, and this manual was written by Luke Mewburn, with some sections inspired by -.Xr tcsh . +.Xr tcsh 1 . diff --git a/lib/libedit/el.c b/lib/libedit/el.c index a6f48afa854..d798dad8491 100644 --- a/lib/libedit/el.c +++ b/lib/libedit/el.c @@ -1,5 +1,5 @@ -/* $OpenBSD: el.c,v 1.11 2003/06/02 20:18:40 millert Exp $ */ -/* $NetBSD: el.c,v 1.6 1997/04/24 18:54:16 christos Exp $ */ +/* $OpenBSD: el.c,v 1.12 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: el.c,v 1.34 2003/09/26 17:44:51 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -33,117 +33,105 @@ * SUCH DAMAGE. */ +#include "config.h" #if !defined(lint) && !defined(SCCSID) #if 0 static char sccsid[] = "@(#)el.c 8.2 (Berkeley) 1/3/94"; #else -static const char rcsid[] = "$OpenBSD: el.c,v 1.11 2003/06/02 20:18:40 millert Exp $"; +static const char rcsid[] = "$OpenBSD: el.c,v 1.12 2003/10/31 08:42:24 otto Exp $"; #endif #endif /* not lint && not SCCSID */ /* * el.c: EditLine interface functions */ -#include "sys.h" - #include <sys/types.h> #include <sys/param.h> #include <string.h> #include <stdlib.h> #include <stdarg.h> -#include <unistd.h> #include "el.h" /* el_init(): * Initialize editline and set default parameters. */ public EditLine * -el_init(prog, fin, fout) - const char *prog; - FILE *fin, *fout; +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; + EditLine *el = (EditLine *) el_malloc(sizeof(EditLine)); + + if (el == NULL) + return (NULL); - memset(el, 0, sizeof(EditLine)); + memset(el, 0, sizeof(EditLine)); - el->el_infd = fileno(fin); - el->el_outfile = fout; - el->el_prog = strdup(prog); + el->el_infd = fileno(fin); + el->el_outfile = fout; + el->el_errfile = ferr; + el->el_prog = strdup(prog); -#ifdef DEBUG - if (issetugid() == 0 && (tty = getenv("DEBUGTTY")) != NULL) { - el->el_errfile = fopen(tty, "w"); - if (el->el_errfile == NULL) { - extern errno; - (void)fprintf(stderr, "Cannot open %s (%s).\n", - tty, strerror(errno)); + /* + * Initialize all the modules. Order is important!!! + */ + el->el_flags = 0; + + if (term_init(el) == -1) { + free(el->el_prog); + el_free(el); return NULL; } - } - else -#endif - el->el_errfile = stderr; - - /* - * Initialize all the modules. Order is important!!! - */ - (void)term_init(el); - (void)tty_init(el); - (void)key_init(el); - (void)map_init(el); - (void)ch_init(el); - (void)search_init(el); - (void)hist_init(el); - (void)prompt_init(el); - (void)sig_init(el); - el->el_flags = 0; - - return el; -} /* end el_init */ + (void) key_init(el); + (void) map_init(el); + if (tty_init(el) == -1) + el->el_flags |= NO_TTY; + (void) ch_init(el); + (void) search_init(el); + (void) hist_init(el); + (void) prompt_init(el); + (void) sig_init(el); + (void) read_init(el); + + return (el); +} /* el_end(): * Clean up. */ public void -el_end(el) - EditLine *el; +el_end(EditLine *el) { - if (el == NULL) - return; - el_reset(el); + if (el == NULL) + return; - term_end(el); - tty_end(el); - key_end(el); - map_end(el); - ch_end(el); - search_end(el); - hist_end(el); - prompt_end(el); - sig_end(el); + el_reset(el); - el_free((ptr_t) el->el_prog); - el_free((ptr_t) el); -} /* end el_end */ + term_end(el); + key_end(el); + map_end(el); + tty_end(el); + ch_end(el); + search_end(el); + hist_end(el); + prompt_end(el); + sig_end(el); + + el_free((ptr_t) el->el_prog); + el_free((ptr_t) el); +} /* el_reset(): * Reset the tty and the parser */ public void -el_reset(el) - EditLine *el; +el_reset(EditLine *el) { - tty_cookedmode(el); - ch_reset(el); /* XXX: Do we want that? */ + + tty_cookedmode(el); + ch_reset(el); /* XXX: Do we want that? */ } @@ -153,151 +141,328 @@ el_reset(el) public int el_set(EditLine *el, int op, ...) { - va_list va; - int rv; - - va_start(va, op); - - switch (op) { - case EL_PROMPT: - rv = prompt_set(el, va_arg(va, el_pfunc_t)); - break; - - case EL_TERMINAL: - rv = term_set(el, va_arg(va, char *)); - break; - - case EL_EDITOR: - rv = map_set_editor(el, va_arg(va, char *)); - break; - - case EL_SIGNAL: - if (va_arg(va, int)) - el->el_flags |= HANDLE_SIGNALS; - else - el->el_flags &= ~HANDLE_SIGNALS; - rv = 0; - break; - - case EL_BIND: - case EL_TELLTC: - case EL_SETTC: - case EL_ECHOTC: - case EL_SETTY: + va_list va; + int rv = 0; + + if (el == NULL) + return (-1); + va_start(va, op); + + switch (op) { + case EL_PROMPT: + case EL_RPROMPT: + rv = prompt_set(el, va_arg(va, el_pfunc_t), op); + break; + + case EL_TERMINAL: + rv = term_set(el, va_arg(va, char *)); + break; + + case EL_EDITOR: + rv = map_set_editor(el, va_arg(va, char *)); + break; + + case EL_SIGNAL: + if (va_arg(va, int)) + el->el_flags |= HANDLE_SIGNALS; + else + el->el_flags &= ~HANDLE_SIGNALS; + break; + + case EL_BIND: + case EL_TELLTC: + case EL_SETTC: + case EL_ECHOTC: + case EL_SETTY: { - char *argv[20]; - int i; - for (i = 1; i < 20; i++) - if ((argv[i] = va_arg(va, char *)) == NULL) - break; - - switch (op) { - case EL_BIND: - argv[0] = "bind"; - rv = map_bind(el, i, argv); + const char *argv[20]; + int i; + + for (i = 1; i < 20; i++) + if ((argv[i] = va_arg(va, char *)) == NULL) + break; + + switch (op) { + case EL_BIND: + argv[0] = "bind"; + rv = map_bind(el, i, argv); + break; + + case EL_TELLTC: + argv[0] = "telltc"; + rv = term_telltc(el, i, argv); + break; + + case EL_SETTC: + argv[0] = "settc"; + rv = term_settc(el, i, argv); + break; + + case EL_ECHOTC: + argv[0] = "echotc"; + rv = term_echotc(el, i, argv); + break; + + case EL_SETTY: + argv[0] = "setty"; + rv = tty_stty(el, i, argv); + break; + + default: + rv = -1; + EL_ABORT((el->el_errfile, "Bad op %d\n", op)); + break; + } break; + } - case EL_TELLTC: - argv[0] = "telltc"; - rv = term_telltc(el, i, argv); + case EL_ADDFN: + { + char *name = va_arg(va, char *); + char *help = va_arg(va, char *); + el_func_t func = va_arg(va, el_func_t); + + rv = map_addfunc(el, name, help, func); + break; + } + + case EL_HIST: + { + hist_fun_t func = va_arg(va, hist_fun_t); + ptr_t ptr = va_arg(va, char *); + + rv = hist_set(el, func, ptr); break; + } - case EL_SETTC: - argv[0] = "settc"; - rv = term_settc(el, i, argv); + case EL_EDITMODE: + if (va_arg(va, int)) + el->el_flags &= ~EDIT_DISABLED; + else + el->el_flags |= EDIT_DISABLED; + 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_ECHOTC: - argv[0] = "echotc"; - rv = term_echotc(el, i, argv); + case EL_CLIENTDATA: + el->el_data = va_arg(va, void *); break; - case EL_SETTY: - argv[0] = "setty"; - rv = tty_stty(el, i, argv); + 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; - default: + default: rv = -1; - abort(); break; - } } - break; - - case EL_ADDFN: + + va_end(va); + return (rv); +} + + +/* el_get(): + * retrieve the editline parameters + */ +public int +el_get(EditLine *el, int op, void *ret) +{ + int rv; + + if (el == NULL || ret == NULL) + return (-1); + switch (op) { + case EL_PROMPT: + case EL_RPROMPT: + rv = prompt_get(el, (void *) &ret, op); + break; + + case EL_EDITOR: + rv = map_get_editor(el, (void *) &ret); + break; + + case EL_SIGNAL: + *((int *) ret) = (el->el_flags & HANDLE_SIGNALS); + rv = 0; + break; + + case EL_EDITMODE: + *((int *) ret) = (!(el->el_flags & EDIT_DISABLED)); + rv = 0; + break; + + case EL_TERMINAL: + 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 *name = va_arg(va, char *); - char *help = va_arg(va, char *); - el_func_t func = va_arg(va, el_func_t); - rv = map_addfunc(el, name, help, func); + const char *argv[20]; + int i; + + for (i = 1; i < sizeof(argv) / sizeof(argv[0]); i++) + if ((argv[i] = va_arg(va, char *)) == NULL) + break; + + switch (op) { + case EL_BIND: + argv[0] = "bind"; + rv = map_bind(el, i, argv); + break; + + case EL_TELLTC: + argv[0] = "telltc"; + rv = term_telltc(el, i, argv); + break; + + case EL_SETTC: + argv[0] = "settc"; + rv = term_settc(el, i, argv); + break; + + case EL_ECHOTC: + argv[0] = "echotc"; + rv = term_echotc(el, i, argv); + break; + + case EL_SETTY: + argv[0] = "setty"; + rv = tty_stty(el, i, argv); + break; + + default: + rv = -1; + EL_ABORT((el->errfile, "Bad op %d\n", op)); + break; + } + break; } - break; - case EL_HIST: + case EL_ADDFN: { - hist_fun_t func = va_arg(va, hist_fun_t); - ptr_t ptr = va_arg(va, char *); - rv = hist_set(el, func, ptr); + char *name = va_arg(va, char *); + char *help = va_arg(va, char *); + el_func_t func = va_arg(va, el_func_t); + + rv = map_addfunc(el, name, help, func); + break; } - break; - default: - rv = -1; - } + case EL_HIST: + { + hist_fun_t func = va_arg(va, hist_fun_t); + ptr_t ptr = va_arg(va, char *); + rv = hist_set(el, func, ptr); + } + 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; + } - va_end(va); - return rv; -} /* end el_set */ + return (rv); +} /* el_line(): * Return editing info */ public const LineInfo * -el_line(el) - EditLine *el; +el_line(EditLine *el) { - return (const LineInfo *) &el->el_line; + + return (const LineInfo *) (void *) &el->el_line; } -static const char elpath[] = "/.editrc"; /* el_source(): * Source a file */ public int -el_source(el, fname) - EditLine *el; - const char *fname; +el_source(EditLine *el, const char *fname) { - FILE *fp; - size_t len; - char *ptr, path[MAXPATHLEN]; - - if (fname == NULL) { - ptr = getenv("HOME"); - if (issetugid() != 0 || ptr == NULL || *ptr == '\0') - return -1; - (void) snprintf(path, sizeof(path), "%s%s", ptr, elpath); - fname = path; - } - - if ((fp = fopen(fname, "r")) == NULL) - return -1; - - while ((ptr = fgetln(fp, &len)) != NULL) { - if (ptr[len - 1] == '\n') - --len; - ptr[len] = '\0'; - if (parse_line(el, ptr) == -1) { - (void)fclose(fp); - return -1; + FILE *fp; + size_t len; + 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) + return (-1); + if (strlcpy(path, ptr, sizeof(path)) >= sizeof(path)) + return (-1); + 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"); + if (fp == NULL) + return (-1); + + while ((ptr = fgetln(fp, &len)) != NULL) { + if (len > 0 && ptr[len - 1] == '\n') + --len; + ptr[len] = '\0'; + if (parse_line(el, ptr) == -1) { + (void) fclose(fp); + return (-1); + } } - } - (void)fclose(fp); - return 0; + (void) fclose(fp); + return (0); } @@ -305,18 +470,54 @@ el_source(el, fname) * Called from program when terminal is resized */ public void -el_resize(el) - EditLine *el; +el_resize(EditLine *el) +{ + int lins, cols; + sigset_t oset, nset; + + (void) sigemptyset(&nset); + (void) sigaddset(&nset, SIGWINCH); + (void) sigprocmask(SIG_BLOCK, &nset, &oset); + + /* get the correct window size */ + if (term_get_size(el, &lins, &cols)) + term_change_size(el, lins, cols); + + (void) sigprocmask(SIG_SETMASK, &oset, NULL); +} + + +/* el_beep(): + * Called from the program to beep + */ +public void +el_beep(EditLine *el) { - int lins, cols; - sigset_t oset, nset; - (void)sigemptyset(&nset); - (void)sigaddset(&nset, SIGWINCH); - (void)sigprocmask(SIG_BLOCK, &nset, &oset); - /* get the correct window size */ - if (term_get_size(el, &lins, &cols)) - term_change_size(el, lins, cols); + term_beep(el); +} + - (void)sigprocmask(SIG_SETMASK, &oset, NULL); +/* el_editmode() + * Set the state of EDIT_DISABLED from the `edit' command. + */ +protected int +/*ARGSUSED*/ +el_editmode(EditLine *el, int argc, const char **argv) +{ + const char *how; + + if (argv == NULL || argc != 2 || argv[1] == NULL) + return (-1); + + how = argv[1]; + if (strcmp(how, "on") == 0) + el->el_flags &= ~EDIT_DISABLED; + else if (strcmp(how, "off") == 0) + el->el_flags |= EDIT_DISABLED; + else { + (void) fprintf(el->el_errfile, "edit: Bad value `%s'.\n", how); + return (-1); + } + return (0); } diff --git a/lib/libedit/el.h b/lib/libedit/el.h index e91d1ac527f..b926292bf40 100644 --- a/lib/libedit/el.h +++ b/lib/libedit/el.h @@ -1,5 +1,5 @@ -/* $OpenBSD: el.h,v 1.4 2003/06/02 20:18:40 millert Exp $ */ -/* $NetBSD: el.h,v 1.2 1997/01/11 06:47:53 lukem Exp $ */ +/* $OpenBSD: el.h,v 1.5 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: el.h,v 1.15 2003/09/26 17:44:51 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -39,53 +39,59 @@ * el.h: Internal structures. */ #ifndef _h_el -#define _h_el +#define _h_el /* * Local defaults */ -#define KSHVI -#define VIDEFAULT -#define ANCHOR +#define KSHVI +#define VIDEFAULT +#define ANCHOR #include <stdio.h> #include <sys/types.h> -#define EL_BUFSIZ 1024 /* Maximum line size */ +#define EL_BUFSIZ 1024 /* Maximum line size */ -#define HANDLE_SIGNALS 1 +#define HANDLE_SIGNALS 0x01 +#define NO_TTY 0x02 +#define EDIT_DISABLED 0x04 +#define UNBUFFERED 0x08 typedef int bool_t; /* True or not */ typedef unsigned char el_action_t; /* Index to command array */ typedef struct coord_t { /* Position on the screen */ - int h, v; + int h; + int v; } coord_t; typedef struct el_line_t { - char *buffer, /* Input line */ - *cursor, /* Cursor position */ - *lastchar, /* Last character */ - *limit; /* Max position */ + char *buffer; /* Input line */ + char *cursor; /* Cursor position */ + char *lastchar; /* Last character */ + const char *limit; /* Max position */ } el_line_t; /* * Editor state */ typedef struct el_state_t { - int inputmode; /* What mode are we in? */ - int doingarg; /* Are we getting an argument? */ - int argument; /* Numeric argument */ - int metanext; /* Is the next char a meta char */ - el_action_t lastcmd; /* Previous command */ + int inputmode; /* What mode are we in? */ + int doingarg; /* Are we getting an argument? */ + 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_malloc(a) malloc(a) -#define el_realloc(a,b) realloc(a, b) -#define el_free(a) free(a) +#define el_malloc(a) malloc(a) +#define el_realloc(a,b) realloc(a, b) +#define el_free(a) free(a) #include "tty.h" #include "prompt.h" @@ -100,29 +106,44 @@ 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 */ - FILE *el_outfile; /* Stdio stuff */ - FILE *el_errfile; /* Stdio stuff */ - int el_infd; /* Input file descriptor */ - int el_flags; /* Various flags. */ - coord_t el_cursor; /* Cursor location */ - char **el_display, /* Real screen image = what is there */ - **el_vdisplay; /* Virtual screen image = what we see */ - - 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 */ - el_tty_t el_tty; /* Tty dependent stuff */ - el_refresh_t el_refresh; /* Refresh stuff */ - el_prompt_t el_prompt; /* Prompt stuff */ - el_chared_t el_chared; /* Characted editor stuff */ - el_map_t el_map; /* Key mapping stuff */ - el_key_t el_key; /* Key binding stuff */ - el_history_t el_history; /* History stuff */ - el_search_t el_search; /* Search stuff */ - el_signal_t el_signal; /* Signal handling stuff */ + char *el_prog; /* the program name */ + FILE *el_outfile; /* Stdio stuff */ + FILE *el_errfile; /* Stdio stuff */ + int el_infd; /* Input file descriptor */ + int el_flags; /* Various flags. */ + 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 */ + el_tty_t el_tty; /* Tty dependent stuff */ + el_refresh_t el_refresh; /* Refresh stuff */ + el_prompt_t el_prompt; /* Prompt stuff */ + el_prompt_t el_rprompt; /* Prompt stuff */ + el_chared_t el_chared; /* Characted editor stuff */ + el_map_t el_map; /* Key mapping stuff */ + el_key_t el_key; /* Key binding stuff */ + el_history_t el_history; /* History stuff */ + el_search_t el_search; /* Search stuff */ + el_signal_t el_signal; /* Signal handling stuff */ + el_read_t el_read; /* Character reading stuff */ }; +protected int el_editmode(EditLine *, int, const char **); + +#ifdef DEBUG +#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 #endif /* _h_el */ diff --git a/lib/libedit/emacs.c b/lib/libedit/emacs.c index b4d92cf5aa1..59b01ac31fc 100644 --- a/lib/libedit/emacs.c +++ b/lib/libedit/emacs.c @@ -1,5 +1,5 @@ -/* $OpenBSD: emacs.c,v 1.5 2003/06/02 20:18:40 millert Exp $ */ -/* $NetBSD: emacs.c,v 1.3 1997/01/11 06:47:54 lukem Exp $ */ +/* $OpenBSD: emacs.c,v 1.6 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: emacs.c,v 1.15 2003/08/07 16:44:31 agc Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -33,18 +33,18 @@ * SUCH DAMAGE. */ +#include "config.h" #if !defined(lint) && !defined(SCCSID) #if 0 static char sccsid[] = "@(#)emacs.c 8.1 (Berkeley) 6/4/93"; #else -static const char rcsid[] = "$OpenBSD: emacs.c,v 1.5 2003/06/02 20:18:40 millert Exp $"; +static const char rcsid[] = "$OpenBSD: emacs.c,v 1.6 2003/10/31 08:42:24 otto Exp $"; #endif #endif /* not lint && not SCCSID */ -/* +/* * emacs.c: Emacs functions */ -#include "sys.h" #include "el.h" /* em_delete_or_list(): @@ -53,28 +53,31 @@ static const char rcsid[] = "$OpenBSD: emacs.c,v 1.5 2003/06/02 20:18:40 millert */ protected el_action_t /*ARGSUSED*/ -em_delete_or_list(el, c) - EditLine *el; - int c; +em_delete_or_list(EditLine *el, int c __attribute__((__unused__))) { - if (el->el_line.cursor == el->el_line.lastchar) { /* if I'm at the end */ - if (el->el_line.cursor == el->el_line.buffer) { /* and the beginning */ - 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; + + if (el->el_line.cursor == el->el_line.lastchar) { + /* if I'm at the end */ + if (el->el_line.cursor == el->el_line.buffer) { + /* and the beginning */ + 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 { + c_delafter(el, el->el_state.argument); /* delete after dot */ + if (el->el_line.cursor > el->el_line.lastchar) + el->el_line.cursor = el->el_line.lastchar; + /* bounds check */ + return (CC_REFRESH); } - } - else { - c_delafter(el, el->el_state.argument); /* delete after dot */ - if (el->el_line.cursor > el->el_line.lastchar) - el->el_line.cursor = el->el_line.lastchar; /* bounds check */ - return CC_REFRESH; - } } @@ -84,27 +87,26 @@ em_delete_or_list(el, c) */ protected el_action_t /*ARGSUSED*/ -em_delete_next_word(el, c) - EditLine *el; - int c; +em_delete_next_word(EditLine *el, int c __attribute__((__unused__))) { - char *cp, *p, *kp; + char *cp, *p, *kp; - if (el->el_line.cursor == el->el_line.lastchar) - return CC_ERROR; + if (el->el_line.cursor == el->el_line.lastchar) + return (CC_ERROR); - cp = c__next_word(el->el_line.cursor, el->el_line.lastchar, - el->el_state.argument, ce__isword); + cp = c__next_word(el->el_line.cursor, el->el_line.lastchar, + el->el_state.argument, ce__isword); - for (p = el->el_line.cursor, kp = el->el_chared.c_kill.buf; p < cp; p++) - /* save the text */ - *kp++ = *p; - el->el_chared.c_kill.last = kp; + for (p = el->el_line.cursor, kp = el->el_chared.c_kill.buf; p < cp; p++) + /* save the text */ + *kp++ = *p; + el->el_chared.c_kill.last = kp; - c_delafter(el, cp - el->el_line.cursor); /* delete after dot */ - if (el->el_line.cursor > el->el_line.lastchar) - el->el_line.cursor = el->el_line.lastchar; /* bounds check */ - return CC_REFRESH; + c_delafter(el, cp - el->el_line.cursor); /* delete after dot */ + if (el->el_line.cursor > el->el_line.lastchar) + el->el_line.cursor = el->el_line.lastchar; + /* bounds check */ + return (CC_REFRESH); } @@ -114,34 +116,34 @@ em_delete_next_word(el, c) */ protected el_action_t /*ARGSUSED*/ -em_yank(el, c) - EditLine *el; - int c; +em_yank(EditLine *el, int c __attribute__((__unused__))) { - char *kp, *cp; + char *kp, *cp; - if (el->el_chared.c_kill.last == el->el_chared.c_kill.buf) - return CC_ERROR; + if (el->el_chared.c_kill.last == el->el_chared.c_kill.buf) { + if (!ch_enlargebufs(el, 1)) + return (CC_ERROR); + } - if (el->el_line.lastchar + - (el->el_chared.c_kill.last - el->el_chared.c_kill.buf) >= - el->el_line.limit) - return CC_ERROR; + if (el->el_line.lastchar + + (el->el_chared.c_kill.last - el->el_chared.c_kill.buf) >= + el->el_line.limit) + return (CC_ERROR); - el->el_chared.c_kill.mark = el->el_line.cursor; - cp = el->el_line.cursor; + el->el_chared.c_kill.mark = el->el_line.cursor; + cp = el->el_line.cursor; - /* open the space, */ - c_insert(el, el->el_chared.c_kill.last - el->el_chared.c_kill.buf); - /* copy the chars */ - for (kp = el->el_chared.c_kill.buf; kp < el->el_chared.c_kill.last; kp++) - *cp++ = *kp; + /* open the space, */ + c_insert(el, el->el_chared.c_kill.last - el->el_chared.c_kill.buf); + /* copy the chars */ + for (kp = el->el_chared.c_kill.buf; kp < el->el_chared.c_kill.last; kp++) + *cp++ = *kp; - /* if an arg, cursor at beginning else cursor at end */ - if (el->el_state.argument == 1) - el->el_line.cursor = cp; + /* if an arg, cursor at beginning else cursor at end */ + if (el->el_state.argument == 1) + el->el_line.cursor = cp; - return CC_REFRESH; + return (CC_REFRESH); } @@ -151,20 +153,19 @@ em_yank(el, c) */ protected el_action_t /*ARGSUSED*/ -em_kill_line(el, c) - EditLine *el; - int c; +em_kill_line(EditLine *el, int c __attribute__((__unused__))) { - char *kp, *cp; - - cp = el->el_line.buffer; - kp = el->el_chared.c_kill.buf; - while (cp < el->el_line.lastchar) - *kp++ = *cp++; /* copy it */ - el->el_chared.c_kill.last = kp; - el->el_line.lastchar = el->el_line.buffer; /* zap! -- delete all of it */ - el->el_line.cursor = el->el_line.buffer; - return CC_REFRESH; + char *kp, *cp; + + cp = el->el_line.buffer; + kp = el->el_chared.c_kill.buf; + while (cp < el->el_line.lastchar) + *kp++ = *cp++; /* copy it */ + el->el_chared.c_kill.last = kp; + /* zap! -- delete all of it */ + el->el_line.lastchar = el->el_line.buffer; + el->el_line.cursor = el->el_line.buffer; + return (CC_REFRESH); } @@ -174,33 +175,30 @@ em_kill_line(el, c) */ protected el_action_t /*ARGSUSED*/ -em_kill_region(el, c) - EditLine *el; - int c; +em_kill_region(EditLine *el, int c __attribute__((__unused__))) { - char *kp, *cp; - - if (!el->el_chared.c_kill.mark) - return CC_ERROR; - - if (el->el_chared.c_kill.mark > el->el_line.cursor) { - cp = el->el_line.cursor; - kp = el->el_chared.c_kill.buf; - while (cp < el->el_chared.c_kill.mark) - *kp++ = *cp++; /* copy it */ - el->el_chared.c_kill.last = kp; - c_delafter(el, cp - el->el_line.cursor); - } - else { /* mark is before cursor */ - cp = el->el_chared.c_kill.mark; - kp = el->el_chared.c_kill.buf; - while (cp < el->el_line.cursor) - *kp++ = *cp++; /* copy it */ - el->el_chared.c_kill.last = kp; - c_delbefore(el, cp - el->el_chared.c_kill.mark); - el->el_line.cursor = el->el_chared.c_kill.mark; - } - return CC_REFRESH; + char *kp, *cp; + + if (!el->el_chared.c_kill.mark) + return (CC_ERROR); + + if (el->el_chared.c_kill.mark > el->el_line.cursor) { + cp = el->el_line.cursor; + kp = el->el_chared.c_kill.buf; + while (cp < el->el_chared.c_kill.mark) + *kp++ = *cp++; /* copy it */ + el->el_chared.c_kill.last = kp; + c_delafter(el, cp - el->el_line.cursor); + } else { /* mark is before cursor */ + cp = el->el_chared.c_kill.mark; + kp = el->el_chared.c_kill.buf; + while (cp < el->el_line.cursor) + *kp++ = *cp++; /* copy it */ + el->el_chared.c_kill.last = kp; + c_delbefore(el, cp - el->el_chared.c_kill.mark); + el->el_line.cursor = el->el_chared.c_kill.mark; + } + return (CC_REFRESH); } @@ -210,52 +208,46 @@ em_kill_region(el, c) */ protected el_action_t /*ARGSUSED*/ -em_copy_region(el, c) - EditLine *el; - int c; +em_copy_region(EditLine *el, int c __attribute__((__unused__))) { - char *kp, *cp; - - if (el->el_chared.c_kill.mark) - return CC_ERROR; - - if (el->el_chared.c_kill.mark > el->el_line.cursor) { - cp = el->el_line.cursor; - kp = el->el_chared.c_kill.buf; - while (cp < el->el_chared.c_kill.mark) - *kp++ = *cp++; /* copy it */ - el->el_chared.c_kill.last = kp; - } - else { - cp = el->el_chared.c_kill.mark; - kp = el->el_chared.c_kill.buf; - while (cp < el->el_line.cursor) - *kp++ = *cp++; /* copy it */ - el->el_chared.c_kill.last = kp; - } - return CC_NORM; + char *kp, *cp; + + if (!el->el_chared.c_kill.mark) + return (CC_ERROR); + + if (el->el_chared.c_kill.mark > el->el_line.cursor) { + cp = el->el_line.cursor; + kp = el->el_chared.c_kill.buf; + while (cp < el->el_chared.c_kill.mark) + *kp++ = *cp++; /* copy it */ + el->el_chared.c_kill.last = kp; + } else { + cp = el->el_chared.c_kill.mark; + kp = el->el_chared.c_kill.buf; + while (cp < el->el_line.cursor) + *kp++ = *cp++; /* copy it */ + el->el_chared.c_kill.last = kp; + } + return (CC_NORM); } -/* 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(el, c) - EditLine *el; - int c; +em_gosmacs_transpose(EditLine *el, int c) { - if (el->el_line.cursor > &el->el_line.buffer[1]) { - /* must have at least two chars entered */ - c = el->el_line.cursor[-2]; - el->el_line.cursor[-2] = el->el_line.cursor[-1]; - el->el_line.cursor[-1] = c; - return CC_REFRESH; - } - else - return CC_ERROR; + if (el->el_line.cursor > &el->el_line.buffer[1]) { + /* must have at least two chars entered */ + c = el->el_line.cursor[-2]; + el->el_line.cursor[-2] = el->el_line.cursor[-1]; + el->el_line.cursor[-1] = c; + return (CC_REFRESH); + } else + return (CC_ERROR); } @@ -265,49 +257,46 @@ em_gosmacs_traspose(el, c) */ protected el_action_t /*ARGSUSED*/ -em_next_word(el, c) - EditLine *el; - int c; +em_next_word(EditLine *el, int c __attribute__((__unused__))) { - if (el->el_line.cursor == el->el_line.lastchar) - return CC_ERROR; - - el->el_line.cursor = c__next_word(el->el_line.cursor, el->el_line.lastchar, - el->el_state.argument, - ce__isword); - - if (el->el_map.type == MAP_VI) - if (el->el_chared.c_vcmd.action & DELETE) { - cv_delfini(el); - return CC_REFRESH; - } - - return CC_CURSOR; + if (el->el_line.cursor == el->el_line.lastchar) + return (CC_ERROR); + + el->el_line.cursor = c__next_word(el->el_line.cursor, + el->el_line.lastchar, + el->el_state.argument, + ce__isword); + + if (el->el_map.type == MAP_VI) + if (el->el_chared.c_vcmd.action != NOP) { + cv_delfini(el); + return (CC_REFRESH); + } + return (CC_CURSOR); } + /* em_upper_case(): * Uppercase the characters from cursor to end of current word * [M-u] */ protected el_action_t /*ARGSUSED*/ -em_upper_case(el, c) - EditLine *el; - int c; +em_upper_case(EditLine *el, int c __attribute__((__unused__))) { - char *cp, *ep; + char *cp, *ep; - ep = c__next_word(el->el_line.cursor, el->el_line.lastchar, - el->el_state.argument, ce__isword); + ep = c__next_word(el->el_line.cursor, el->el_line.lastchar, + el->el_state.argument, ce__isword); - for (cp = el->el_line.cursor; cp < ep; cp++) - if (islower(*cp)) - *cp = toupper(*cp); + for (cp = el->el_line.cursor; cp < ep; cp++) + if (islower((unsigned char) *cp)) + *cp = toupper(*cp); - el->el_line.cursor = ep; - if (el->el_line.cursor > el->el_line.lastchar) - el->el_line.cursor = el->el_line.lastchar; - return CC_REFRESH; + el->el_line.cursor = ep; + if (el->el_line.cursor > el->el_line.lastchar) + el->el_line.cursor = el->el_line.lastchar; + return (CC_REFRESH); } @@ -317,56 +306,53 @@ em_upper_case(el, c) */ protected el_action_t /*ARGSUSED*/ -em_capitol_case(el, c) - EditLine *el; - int c; +em_capitol_case(EditLine *el, int c __attribute__((__unused__))) { - char *cp, *ep; - - ep = c__next_word(el->el_line.cursor, el->el_line.lastchar, - el->el_state.argument, ce__isword); - - for (cp = el->el_line.cursor; cp < ep; cp++) { - if (isalpha(*cp)) { - if (islower(*cp)) - *cp = toupper(*cp); - cp++; - break; + char *cp, *ep; + + ep = c__next_word(el->el_line.cursor, el->el_line.lastchar, + 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(*cp); + cp++; + break; + } } - } - for (; cp < ep; cp++) - if (isupper(*cp)) - *cp = tolower(*cp); - - el->el_line.cursor = ep; - if (el->el_line.cursor > el->el_line.lastchar) - el->el_line.cursor = el->el_line.lastchar; - return CC_REFRESH; + for (; cp < ep; cp++) + if (isupper((unsigned char) *cp)) + *cp = tolower(*cp); + + el->el_line.cursor = ep; + if (el->el_line.cursor > el->el_line.lastchar) + el->el_line.cursor = el->el_line.lastchar; + return (CC_REFRESH); } + /* em_lower_case(): * Lowercase the characters from cursor to end of current word * [M-l] */ protected el_action_t /*ARGSUSED*/ -em_lower_case(el, c) - EditLine *el; - int c; +em_lower_case(EditLine *el, int c __attribute__((__unused__))) { - char *cp, *ep; + char *cp, *ep; - ep = c__next_word(el->el_line.cursor, el->el_line.lastchar, - el->el_state.argument, ce__isword); + ep = c__next_word(el->el_line.cursor, el->el_line.lastchar, + el->el_state.argument, ce__isword); - for (cp = el->el_line.cursor; cp < ep; cp++) - if (isupper(*cp)) - *cp = tolower(*cp); + for (cp = el->el_line.cursor; cp < ep; cp++) + if (isupper((unsigned char) *cp)) + *cp = tolower(*cp); - el->el_line.cursor = ep; - if (el->el_line.cursor > el->el_line.lastchar) - el->el_line.cursor = el->el_line.lastchar; - return CC_REFRESH; + el->el_line.cursor = ep; + if (el->el_line.cursor > el->el_line.lastchar) + el->el_line.cursor = el->el_line.lastchar; + return (CC_REFRESH); } @@ -376,62 +362,59 @@ em_lower_case(el, c) */ protected el_action_t /*ARGSUSED*/ -em_set_mark(el, c) - EditLine *el; - int c; +em_set_mark(EditLine *el, int c __attribute__((__unused__))) { - el->el_chared.c_kill.mark = el->el_line.cursor; - return CC_NORM; + + el->el_chared.c_kill.mark = el->el_line.cursor; + return (CC_NORM); } /* em_exchange_mark(): - * Exchange the cursor and mark + * Exchange the cursor and mark * [^X^X] */ protected el_action_t /*ARGSUSED*/ -em_exchange_mark(el, c) - EditLine *el; - int c; +em_exchange_mark(EditLine *el, int c __attribute__((__unused__))) { - register char *cp; + char *cp; - cp = el->el_line.cursor; - el->el_line.cursor = el->el_chared.c_kill.mark; - el->el_chared.c_kill.mark = cp; - return CC_CURSOR; + cp = el->el_line.cursor; + el->el_line.cursor = el->el_chared.c_kill.mark; + el->el_chared.c_kill.mark = cp; + return (CC_CURSOR); } + /* em_universal_argument(): * Universal argument (argument times 4) * [^U] */ protected el_action_t /*ARGSUSED*/ -em_universal_argument(el, c) - EditLine *el; - int c; +em_universal_argument(EditLine *el, int c __attribute__((__unused__))) { /* multiply current argument by 4 */ - if (el->el_state.argument > 1000000) - return CC_ERROR; - el->el_state.doingarg = 1; - el->el_state.argument *= 4; - return CC_ARGHACK; + + if (el->el_state.argument > 1000000) + return (CC_ERROR); + el->el_state.doingarg = 1; + el->el_state.argument *= 4; + return (CC_ARGHACK); } + /* em_meta_next(): * Add 8th bit to next character typed * [<ESC>] */ protected el_action_t /*ARGSUSED*/ -em_meta_next(el, c) - EditLine *el; - int c; +em_meta_next(EditLine *el, int c __attribute__((__unused__))) { - el->el_state.metanext = 1; - return CC_ARGHACK; + + el->el_state.metanext = 1; + return (CC_ARGHACK); } @@ -440,13 +423,12 @@ em_meta_next(el, c) */ protected el_action_t /*ARGSUSED*/ -em_toggle_overwrite(el, c) - EditLine *el; - int c; +em_toggle_overwrite(EditLine *el, int c __attribute__((__unused__))) { - el->el_state.inputmode = - (el->el_state.inputmode == MODE_INSERT) ? MODE_REPLACE : MODE_INSERT; - return CC_NORM; + + el->el_state.inputmode = (el->el_state.inputmode == MODE_INSERT) ? + MODE_REPLACE : MODE_INSERT; + return (CC_NORM); } @@ -455,27 +437,25 @@ em_toggle_overwrite(el, c) */ protected el_action_t /*ARGSUSED*/ -em_copy_prev_word(el, c) - EditLine *el; - int c; +em_copy_prev_word(EditLine *el, int c __attribute__((__unused__))) { - char *cp, *oldc, *dp; + char *cp, *oldc, *dp; - if (el->el_line.cursor == el->el_line.buffer) - return CC_ERROR; + if (el->el_line.cursor == el->el_line.buffer) + return (CC_ERROR); - oldc = el->el_line.cursor; - /* does a bounds check */ - cp = c__prev_word(el->el_line.cursor, el->el_line.buffer, - el->el_state.argument, ce__isword); + oldc = el->el_line.cursor; + /* does a bounds check */ + cp = c__prev_word(el->el_line.cursor, el->el_line.buffer, + el->el_state.argument, ce__isword); - c_insert(el, oldc - cp); - for (dp = oldc; cp < oldc && dp < el->el_line.lastchar; cp++) - *dp++ = *cp; + c_insert(el, oldc - cp); + for (dp = oldc; cp < oldc && dp < el->el_line.lastchar; cp++) + *dp++ = *cp; - el->el_line.cursor = dp; /* put cursor at end */ + el->el_line.cursor = dp;/* put cursor at end */ - return CC_REFRESH; + return (CC_REFRESH); } @@ -484,12 +464,11 @@ em_copy_prev_word(el, c) */ protected el_action_t /*ARGSUSED*/ -em_inc_search_next(el, c) - EditLine *el; - int c; +em_inc_search_next(EditLine *el, int c __attribute__((__unused__))) { - el->el_search.patlen = 0; - return ce_inc_search(el, ED_SEARCH_NEXT_HISTORY); + + el->el_search.patlen = 0; + return (ce_inc_search(el, ED_SEARCH_NEXT_HISTORY)); } @@ -498,10 +477,9 @@ em_inc_search_next(el, c) */ protected el_action_t /*ARGSUSED*/ -em_inc_search_prev(el, c) - EditLine *el; - int c; +em_inc_search_prev(EditLine *el, int c __attribute__((__unused__))) { - el->el_search.patlen = 0; - return ce_inc_search(el, ED_SEARCH_PREV_HISTORY); + + el->el_search.patlen = 0; + return (ce_inc_search(el, ED_SEARCH_PREV_HISTORY)); } diff --git a/lib/libedit/hist.c b/lib/libedit/hist.c index ae3314bad13..5d99e27c573 100644 --- a/lib/libedit/hist.c +++ b/lib/libedit/hist.c @@ -1,5 +1,5 @@ -/* $OpenBSD: hist.c,v 1.5 2003/06/02 20:18:40 millert Exp $ */ -/* $NetBSD: hist.c,v 1.2 1997/01/11 06:47:55 lukem Exp $ */ +/* $OpenBSD: hist.c,v 1.6 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: hist.c,v 1.14 2003/08/07 16:44:31 agc Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -33,18 +33,18 @@ * SUCH DAMAGE. */ +#include "config.h" #if !defined(lint) && !defined(SCCSID) #if 0 static char sccsid[] = "@(#)hist.c 8.1 (Berkeley) 6/4/93"; #else -static const char rcsid[] = "$OpenBSD: hist.c,v 1.5 2003/06/02 20:18:40 millert Exp $"; +static const char rcsid[] = "$OpenBSD: hist.c,v 1.6 2003/10/31 08:42:24 otto Exp $"; #endif #endif /* not lint && not SCCSID */ /* * hist.c: History access functions */ -#include "sys.h" #include <stdlib.h> #include "el.h" @@ -52,14 +52,17 @@ static const char rcsid[] = "$OpenBSD: hist.c,v 1.5 2003/06/02 20:18:40 millert * Initialization function. */ protected int -hist_init(el) - EditLine *el; +hist_init(EditLine *el) { - el->el_history.fun = NULL; - el->el_history.ref = NULL; - el->el_history.buf = (char *) el_malloc(EL_BUFSIZ); - el->el_history.last = el->el_history.buf; - return 0; + + el->el_history.fun = NULL; + el->el_history.ref = NULL; + el->el_history.buf = (char *) el_malloc(EL_BUFSIZ); + el->el_history.sz = EL_BUFSIZ; + if (el->el_history.buf == NULL) + return (-1); + el->el_history.last = el->el_history.buf; + return (0); } @@ -67,11 +70,11 @@ hist_init(el) * clean up history; */ protected void -hist_end(el) - EditLine *el; +hist_end(EditLine *el) { - el_free((ptr_t) el->el_history.buf); - el->el_history.buf = NULL; + + el_free((ptr_t) el->el_history.buf); + el->el_history.buf = NULL; } @@ -79,15 +82,12 @@ hist_end(el) * Set new history interface */ protected int -hist_set(el, fun, ptr) - EditLine *el; - hist_fun_t fun; - ptr_t ptr; - +hist_set(EditLine *el, hist_fun_t fun, ptr_t ptr) { - el->el_history.ref = ptr; - el->el_history.fun = fun; - return 0; + + el->el_history.ref = ptr; + el->el_history.fun = fun; + return (0); } @@ -96,80 +96,116 @@ hist_set(el, fun, ptr) * eventno tells us the event to get. */ protected el_action_t -hist_get(el) - EditLine *el; +hist_get(EditLine *el) { - const char *hp; - int h; + const char *hp; + int h; - if (el->el_history.eventno == 0) { /* if really the current line */ - (void)strncpy(el->el_line.buffer, el->el_history.buf, EL_BUFSIZ - 1); - el->el_line.buffer[EL_BUFSIZ - 1] = '\0'; - el->el_line.lastchar = el->el_line.buffer + - (el->el_history.last - el->el_history.buf); + if (el->el_history.eventno == 0) { /* if really the current line */ + (void) strncpy(el->el_line.buffer, el->el_history.buf, + el->el_history.sz); + el->el_line.lastchar = el->el_line.buffer + + (el->el_history.last - el->el_history.buf); #ifdef KSHVI - if (el->el_map.type == MAP_VI) - el->el_line.cursor = el->el_line.buffer; - else + if (el->el_map.type == MAP_VI) + el->el_line.cursor = el->el_line.buffer; + else #endif /* KSHVI */ - el->el_line.cursor = el->el_line.lastchar; + el->el_line.cursor = el->el_line.lastchar; - return CC_REFRESH; - } + return (CC_REFRESH); + } + if (el->el_history.ref == NULL) + return (CC_ERROR); + + hp = HIST_FIRST(el); + + if (hp == NULL) + return (CC_ERROR); + + for (h = 1; h < el->el_history.eventno; h++) + if ((hp = HIST_NEXT(el)) == NULL) { + el->el_history.eventno = h; + return (CC_ERROR); + } + (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 + && 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; + else +#endif /* KSHVI */ + el->el_line.cursor = el->el_line.lastchar; - if (el->el_history.ref == NULL) - return CC_ERROR; + return (CC_REFRESH); +} - hp = HIST_FIRST(el); - if (hp == NULL) - return CC_ERROR; +/* hist_command() + * process a history command + */ +protected int +hist_command(EditLine *el, int argc, const char **argv) +{ + const char *str; + int num; + HistEvent ev; - for (h = 1; h < el->el_history.eventno; h++) - if ((hp = HIST_NEXT(el)) == NULL) { - el->el_history.eventno = h; - return CC_ERROR; + if (el->el_history.ref == NULL) + return (-1); + + 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); } - (void)strncpy(el->el_line.buffer, hp, EL_BUFSIZ - 1); - el->el_line.buffer[EL_BUFSIZ - 1] = '\0'; - el->el_line.lastchar = el->el_line.buffer + strlen(el->el_line.buffer); + if (argc != 3) + return (-1); - 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; - } + num = (int)strtol(argv[2], NULL, 0); -#ifdef KSHVI - if (el->el_map.type == MAP_VI) - el->el_line.cursor = el->el_line.buffer; - else -#endif /* KSHVI */ - el->el_line.cursor = el->el_line.lastchar; + 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 CC_REFRESH; + return -1; } -/* hist_list() - * List history entries +/* hist_enlargebuf() + * Enlarge history buffer to specified value. Called from el_enlargebufs(). + * Return 0 for failure, 1 for success. */ protected int /*ARGSUSED*/ -hist_list(el, argc, argv) - EditLine *el; - int argc; - char **argv; +hist_enlargebuf(EditLine *el, size_t oldsz, size_t newsz) { - const char *str; + char *newbuf; - 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; + newbuf = realloc(el->el_history.buf, newsz); + if (!newbuf) + return 0; + + (void) memset(&newbuf[oldsz], '\0', newsz - oldsz); + + el->el_history.last = newbuf + + (el->el_history.last - el->el_history.buf); + el->el_history.buf = newbuf; + el->el_history.sz = newsz; + + return 1; } diff --git a/lib/libedit/hist.h b/lib/libedit/hist.h index 8ff9a529636..60c49a9ca59 100644 --- a/lib/libedit/hist.h +++ b/lib/libedit/hist.h @@ -1,5 +1,5 @@ -/* $OpenBSD: hist.h,v 1.6 2003/06/02 20:18:40 millert Exp $ */ -/* $NetBSD: hist.h,v 1.3 1997/01/11 06:47:56 lukem Exp $ */ +/* $OpenBSD: hist.h,v 1.7 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: hist.h,v 1.10 2003/08/07 16:44:31 agc Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -39,38 +39,39 @@ * el.hist.c: History functions */ #ifndef _h_el_hist -#define _h_el_hist +#define _h_el_hist #include "histedit.h" -typedef const HistEvent * (*hist_fun_t)(ptr_t, int, ...); +typedef int (*hist_fun_t)(ptr_t, HistEvent *, int, ...); typedef struct el_history_t { - char *buf; /* The history buffer */ - char *last; /* The last character */ - int eventno; /* Event we are looking for */ - ptr_t ref; /* Argument for history fcns */ - hist_fun_t fun; /* Event access */ - const HistEvent *ev; /* Event cookie */ + char *buf; /* The history buffer */ + size_t sz; /* Size of history buffer */ + char *last; /* The last character */ + int eventno; /* Event we are looking for */ + ptr_t ref; /* Argument for history fcns */ + hist_fun_t fun; /* Event access */ + HistEvent ev; /* Event cookie */ } el_history_t; -#define HIST_FUN(el, fn, arg) \ - ((((el)->el_history.ev = \ - (*(el)->el_history.fun)((el)->el_history.ref, fn, arg)) == NULL) ? \ - NULL : (el)->el_history.ev->str) +#define HIST_FUN(el, fn, arg) \ + ((((*(el)->el_history.fun) ((el)->el_history.ref, &(el)->el_history.ev, \ + fn, arg)) == -1) ? NULL : (el)->el_history.ev.str) #define HIST_NEXT(el) HIST_FUN(el, H_NEXT, NULL) #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) -protected int hist_init(EditLine *); -protected void hist_end(EditLine *); +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/histedit.h b/lib/libedit/histedit.h index 87750d2987f..6b2fdee861c 100644 --- a/lib/libedit/histedit.h +++ b/lib/libedit/histedit.h @@ -1,5 +1,5 @@ -/* $OpenBSD: histedit.h,v 1.7 2003/06/02 20:18:40 millert Exp $ */ -/* $NetBSD: histedit.h,v 1.5 1997/04/11 17:52:45 christos Exp $ */ +/* $OpenBSD: histedit.h,v 1.8 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: histedit.h,v 1.23 2003/09/26 17:44:51 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -38,8 +38,11 @@ /* * histedit.h: Line editor and history interface. */ -#ifndef _h_editline -#define _h_editline +#ifndef _HISTEDIT_H_ +#define _HISTEDIT_H_ + +#define LIBEDIT_MAJOR 2 +#define LIBEDIT_MINOR 8 #include <sys/types.h> #include <stdio.h> @@ -53,9 +56,9 @@ typedef struct editline EditLine; * For user-defined function interface */ typedef struct lineinfo { - const char *buffer; - const char *cursor; - const char *lastchar; + const char *buffer; + const char *cursor; + const char *lastchar; } LineInfo; @@ -66,17 +69,18 @@ typedef struct lineinfo { #define CC_NORM 0 #define CC_NEWLINE 1 #define CC_EOF 2 -#define CC_ARGHACK 3 -#define CC_REFRESH 4 +#define CC_ARGHACK 3 +#define CC_REFRESH 4 #define CC_CURSOR 5 #define CC_ERROR 6 -#define CC_FATAL 7 -#define CC_REDISPLAY 8 +#define CC_FATAL 7 +#define CC_REDISPLAY 8 +#define CC_REFRESH_BEEP 9 /* * Initialization, cleanup, and resetting */ -EditLine *el_init(const char *, FILE *, FILE *); +EditLine *el_init(const char *, FILE *, FILE *, FILE *); void el_reset(EditLine *); void el_end(EditLine *); @@ -86,26 +90,32 @@ void el_end(EditLine *); */ const char *el_gets(EditLine *, int *); int el_getc(EditLine *, char *); -void el_push(EditLine *, const char *); +void el_push(EditLine *, char *); + +/* + * Beep! + */ +void el_beep(EditLine *); /* * High level function internals control * Parses argc, argv array and executes builtin editline commands */ -int el_parse(EditLine *, int, char **); +int el_parse(EditLine *, int, const char **); /* - * Low level editline access function + * Low level editline access functions */ -int el_set(EditLine *, int, ...); +int el_set(EditLine *, int, ...); +int el_get(EditLine *, int, void *); /* * el_set/el_get parameters */ -#define EL_PROMPT 0 /* , el_pfunc_t); */ -#define EL_TERMINAL 1 /* , const char *); */ -#define EL_EDITOR 2 /* , const char *); */ -#define EL_SIGNAL 3 /* , int); */ +#define EL_PROMPT 0 /* , el_pfunc_t); */ +#define EL_TERMINAL 1 /* , const char *); */ +#define EL_EDITOR 2 /* , const char *); */ +#define EL_SIGNAL 3 /* , int); */ #define EL_BIND 4 /* , const char *, ..., NULL); */ #define EL_TELLTC 5 /* , const char *, ..., NULL); */ #define EL_SETTC 6 /* , const char *, ..., NULL); */ @@ -113,7 +123,14 @@ int el_set(EditLine *, int, ...); #define EL_SETTY 8 /* , const char *, ..., NULL); */ #define EL_ADDFN 9 /* , const char *, const char * */ /* , el_func_t); */ -#define EL_HIST 10 /* , hist_fun_t, const char *); */ +#define EL_HIST 10 /* , hist_fun_t, const char *); */ +#define EL_EDITMODE 11 /* , int); */ +#define EL_RPROMPT 12 /* , el_pfunc_t); */ +#define EL_GETCFN 13 /* , el_rfunc_t); */ +#define EL_CLIENTDATA 14 /* , void *); */ +#define EL_UNBUFFERED 15 /* , int); */ + +#define EL_BUILTIN_GETCFN (NULL) /* * Source named file or $PWD/.editrc or $HOME/.editrc @@ -131,9 +148,9 @@ void el_resize(EditLine *); /* * User-defined function interface. */ -const LineInfo *el_line(EditLine *); -int el_insertstr(EditLine *, char *); -void el_deletestr(EditLine *, int); +const LineInfo *el_line(EditLine *); +int el_insertstr(EditLine *, const char *); +void el_deletestr(EditLine *, int); /* * ==== History ==== @@ -142,34 +159,39 @@ void el_deletestr(EditLine *, int); typedef struct history History; typedef struct HistEvent { - int num; - const char *str; + int num; + const char *str; } HistEvent; /* * History access functions. */ -History * history_init(void); -void history_end(History *); - -const HistEvent * history(History *, int, ...); - -#define H_FUNC 0 /* , UTSL */ -#define H_EVENT 1 /* , const int); */ -#define H_FIRST 2 /* , void); */ -#define H_LAST 3 /* , void); */ -#define H_PREV 4 /* , void); */ -#define H_NEXT 5 /* , void); */ -#define H_CURR 6 /* , void); */ -#define H_ADD 7 /* , const char*); */ -#define H_ENTER 8 /* , const char*); */ -#define H_END 9 /* , void); */ -#define H_NEXT_STR 10 /* , const char*); */ -#define H_PREV_STR 11 /* , const char*); */ -#define H_NEXT_EVENT 12 /* , const int); */ -#define H_PREV_EVENT 13 /* , const int); */ -#define H_LOAD 14 /* , const char *); */ -#define H_SAVE 15 /* , const char *); */ -#define H_CLEAR 16 /* , void); */ - -#endif /* _h_editline */ +History * history_init(void); +void history_end(History *); + +int history(History *, HistEvent *, int, ...); + +#define H_FUNC 0 /* , UTSL */ +#define H_SETSIZE 1 /* , const int); */ +#define H_GETSIZE 2 /* , void); */ +#define H_FIRST 3 /* , void); */ +#define H_LAST 4 /* , void); */ +#define H_PREV 5 /* , void); */ +#define H_NEXT 6 /* , void); */ +#define H_CURR 8 /* , const int); */ +#define H_SET 7 /* , int); */ +#define H_ADD 9 /* , const char *); */ +#define H_ENTER 10 /* , const char *); */ +#define H_APPEND 11 /* , const char *); */ +#define H_END 12 /* , void); */ +#define H_NEXT_STR 13 /* , const char *); */ +#define H_PREV_STR 14 /* , const char *); */ +#define H_NEXT_EVENT 15 /* , const int); */ +#define H_PREV_EVENT 16 /* , const int); */ +#define H_LOAD 17 /* , const char *); */ +#define H_SAVE 18 /* , const char *); */ +#define H_CLEAR 19 /* , void); */ +#define H_SETUNIQUE 20 /* , int); */ +#define H_GETUNIQUE 21 /* , void); */ + +#endif /* _HISTEDIT_H_ */ diff --git a/lib/libedit/history.c b/lib/libedit/history.c index 6a3fcade6ec..c9d440b8736 100644 --- a/lib/libedit/history.c +++ b/lib/libedit/history.c @@ -1,5 +1,5 @@ -/* $OpenBSD: history.c,v 1.10 2003/06/02 20:18:40 millert Exp $ */ -/* $NetBSD: history.c,v 1.5 1997/04/11 17:52:46 christos Exp $ */ +/* $OpenBSD: history.c,v 1.11 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: history.c,v 1.24 2003/08/07 16:44:31 agc Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -33,64 +33,83 @@ * SUCH DAMAGE. */ +#include "config.h" #if !defined(lint) && !defined(SCCSID) #if 0 static char sccsid[] = "@(#)history.c 8.1 (Berkeley) 6/4/93"; #else -static const char rcsid[] = "$OpenBSD: history.c,v 1.10 2003/06/02 20:18:40 millert Exp $"; +static const char rcsid[] = "$OpenBSD: history.c,v 1.11 2003/10/31 08:42:24 otto Exp $"; #endif #endif /* not lint && not SCCSID */ /* * hist.c: History access functions */ -#include "sys.h" - #include <string.h> #include <stdlib.h> #include <stdarg.h> +#ifdef HAVE_VIS_H +#include <vis.h> +#else +#include "np/vis.h" +#endif +#include <sys/stat.h> -static const char hist_cookie[] = "_HiStOrY_V1_\n"; +static const char hist_cookie[] = "_HiStOrY_V2_\n"; #include "histedit.h" -typedef const HistEvent * (*history_gfun_t)(ptr_t); -typedef const HistEvent * (*history_efun_t)(ptr_t, const char *); -typedef void (*history_vfun_t)(ptr_t); +typedef int (*history_gfun_t)(ptr_t, HistEvent *); +typedef int (*history_efun_t)(ptr_t, HistEvent *, const char *); +typedef void (*history_vfun_t)(ptr_t, HistEvent *); +typedef int (*history_sfun_t)(ptr_t, HistEvent *, const int); struct history { - ptr_t h_ref; /* Argument for history fcns */ - history_gfun_t h_first; /* Get the first element */ - history_gfun_t h_next; /* Get the next element */ - history_gfun_t h_last; /* Get the last element */ - history_gfun_t h_prev; /* Get the previous element */ - history_gfun_t h_curr; /* Get the current 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 */ + ptr_t h_ref; /* Argument for history fcns */ + int h_ent; /* Last entry point for history */ + history_gfun_t h_first; /* Get the first element */ + history_gfun_t h_next; /* Get the next element */ + history_gfun_t h_last; /* Get the last element */ + 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_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) (*(h)->h_next)((h)->h_ref) -#define HFIRST(h) (*(h)->h_first)((h)->h_ref) -#define HPREV(h) (*(h)->h_prev)((h)->h_ref) -#define HLAST(h) (*(h)->h_last)((h)->h_ref) -#define HCURR(h) (*(h)->h_curr)((h)->h_ref) -#define HCLEAR(h) (*(h)->h_clear)((h)->h_ref) -#define HENTER(h, str) (*(h)->h_enter)((h)->h_ref, str) -#define HADD(h, str) (*(h)->h_add)((h)->h_ref, str) +#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) +#define HLAST(h, ev) (*(h)->h_last)((h)->h_ref, ev) +#define HCURR(h, ev) (*(h)->h_curr)((h)->h_ref, ev) +#define HSET(h, ev, n) (*(h)->h_set)((h)->h_ref, ev, n) +#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 h_malloc(a) malloc(a) +#define h_realloc(a, b) realloc((a), (b)) +#define h_free(a) free(a) -#define h_malloc(a) malloc(a) -#define h_free(a) free(a) +typedef struct { + int num; + char *str; +} HistEventPrivate; -private int history_set_num(History *, int); -private int history_set_fun(History *, History *); -private int history_load(History *, const char *); -private int history_save(History *, const char *); -private const HistEvent *history_prev_event(History *, int); -private const HistEvent *history_next_event(History *, int); -private const HistEvent *history_next_string(History *, const char *); -private const HistEvent *history_prev_string(History *, const char *); + +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 *); +private int history_prev_event(History *, HistEvent *, int); +private int history_next_event(History *, HistEvent *, int); +private int history_next_string(History *, HistEvent *, const char *); +private int history_prev_string(History *, HistEvent *, const char *); /***********************************************************************/ @@ -99,227 +118,351 @@ private const HistEvent *history_prev_string(History *, const char *); * Builtin- history implementation */ typedef struct hentry_t { - HistEvent ev; /* What we return */ - struct hentry_t *next; /* Next entry */ - struct hentry_t *prev; /* Previous entry */ + HistEvent ev; /* What we return */ + struct hentry_t *next; /* Next entry */ + struct hentry_t *prev; /* Previous entry */ } 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 */ - int eventno; /* Current event number */ + 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 */ + int flags; /* History flags */ +#define H_UNIQUE 1 /* Store only unique elements */ } history_t; -private const HistEvent *history_def_first(ptr_t); -private const HistEvent *history_def_last(ptr_t); -private const HistEvent *history_def_next(ptr_t); -private const HistEvent *history_def_prev(ptr_t); -private const HistEvent *history_def_curr(ptr_t); -private const HistEvent *history_def_enter(ptr_t, const char *); -private const HistEvent *history_def_add(ptr_t, const char *); -private void history_def_init(ptr_t *, int); -private void history_def_clear(ptr_t); -private const HistEvent *history_def_insert(history_t *, const char *); -private void history_def_delete(history_t *, hentry_t *); - -#define history_def_set(p, num) (void)(((history_t *) p)->max = (num)) - +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_prev(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_enter(ptr_t, HistEvent *, const char *); +private int history_def_add(ptr_t, HistEvent *, const char *); +private int history_def_init(ptr_t *, HistEvent *, int); +private void history_def_clear(ptr_t, HistEvent *); +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_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) {\ + evp->num = code;\ + evp->str = he_strerror(code);\ + } + +/* error messages */ +static const char *const he_errlist[] = { + "OK", + "unknown error", + "malloc() failed", + "first event not found", + "last event not found", + "empty list", + "no next event", + "no previous event", + "current event is invalid", + "event not found", + "can't read history from file", + "can't write history", + "required parameter(s) not supplied", + "history size negative", + "function not allowed with other history-functions-set the default", + "bad parameters" +}; +/* error codes */ +#define _HE_OK 0 +#define _HE_UNKNOWN 1 +#define _HE_MALLOC_FAILED 2 +#define _HE_FIRST_NOTFOUND 3 +#define _HE_LAST_NOTFOUND 4 +#define _HE_EMPTY_LIST 5 +#define _HE_END_REACHED 6 +#define _HE_START_REACHED 7 +#define _HE_CURR_INVALID 8 +#define _HE_NOT_FOUND 9 +#define _HE_HIST_READ 10 +#define _HE_HIST_WRITE 11 +#define _HE_PARAM_MISSING 12 +#define _HE_SIZE_NEGATIVE 13 +#define _HE_NOT_ALLOWED 14 +#define _HE_BAD_PARAM 15 /* history_def_first(): * Default function to return the first event in the history. */ -private const HistEvent * -history_def_first(p) - ptr_t p; +private int +history_def_first(ptr_t p, HistEvent *ev) { - history_t *h = (history_t *) p; - h->cursor = h->list.next; - if (h->cursor != &h->list) - return &h->cursor->ev; - else - return NULL; + history_t *h = (history_t *) p; + + h->cursor = h->list.next; + if (h->cursor != &h->list) + *ev = h->cursor->ev; + else { + he_seterrev(ev, _HE_FIRST_NOTFOUND); + return (-1); + } + + return (0); } + /* history_def_last(): * Default function to return the last event in the history. */ -private const HistEvent * -history_def_last(p) - ptr_t p; +private int +history_def_last(ptr_t p, HistEvent *ev) { - history_t *h = (history_t *) p; - h->cursor = h->list.prev; - if (h->cursor != &h->list) - return &h->cursor->ev; - else - return NULL; + history_t *h = (history_t *) p; + + h->cursor = h->list.prev; + if (h->cursor != &h->list) + *ev = h->cursor->ev; + else { + he_seterrev(ev, _HE_LAST_NOTFOUND); + return (-1); + } + + return (0); } + /* history_def_next(): * Default function to return the next event in the history. */ -private const HistEvent * -history_def_next(p) - ptr_t p; +private int +history_def_next(ptr_t p, HistEvent *ev) { - history_t *h = (history_t *) p; + history_t *h = (history_t *) p; + + if (h->cursor != &h->list) + h->cursor = h->cursor->next; + else { + he_seterrev(ev, _HE_EMPTY_LIST); + return (-1); + } - if (h->cursor != &h->list) - h->cursor = h->cursor->next; - else - return NULL; + if (h->cursor != &h->list) + *ev = h->cursor->ev; + else { + he_seterrev(ev, _HE_END_REACHED); + return (-1); + } - if (h->cursor != &h->list) - return &h->cursor->ev; - else - return NULL; + return (0); } /* history_def_prev(): * Default function to return the previous event in the history. */ -private const HistEvent * -history_def_prev(p) - ptr_t p; +private int +history_def_prev(ptr_t p, HistEvent *ev) { - history_t *h = (history_t *) p; + history_t *h = (history_t *) p; + + if (h->cursor != &h->list) + h->cursor = h->cursor->prev; + else { + he_seterrev(ev, + (h->cur > 0) ? _HE_END_REACHED : _HE_EMPTY_LIST); + return (-1); + } - if (h->cursor != &h->list) - h->cursor = h->cursor->prev; - else - return NULL; + if (h->cursor != &h->list) + *ev = h->cursor->ev; + else { + he_seterrev(ev, _HE_START_REACHED); + return (-1); + } - if (h->cursor != &h->list) - return &h->cursor->ev; - else - return NULL; + return (0); } /* history_def_curr(): * Default function to return the current event in the history. */ -private const HistEvent * -history_def_curr(p) - ptr_t p; +private int +history_def_curr(ptr_t p, HistEvent *ev) +{ + history_t *h = (history_t *) p; + + if (h->cursor != &h->list) + *ev = h->cursor->ev; + else { + he_seterrev(ev, + (h->cur > 0) ? _HE_CURR_INVALID : _HE_EMPTY_LIST); + return (-1); + } + + return (0); +} + + +/* history_def_set(): + * Default function to set the current event in the history to the + * given one. + */ +private int +history_def_set(ptr_t p, HistEvent *ev, const int n) { - history_t *h = (history_t *) p; + history_t *h = (history_t *) p; - if (h->cursor != &h->list) - return &h->cursor->ev; - else - return NULL; + if (h->cur == 0) { + he_seterrev(ev, _HE_EMPTY_LIST); + return (-1); + } + if (h->cursor == &h->list || h->cursor->ev.num != n) { + for (h->cursor = h->list.next; h->cursor != &h->list; + h->cursor = h->cursor->next) + if (h->cursor->ev.num == n) + break; + } + if (h->cursor == &h->list) { + he_seterrev(ev, _HE_NOT_FOUND); + return (-1); + } + return (0); } + /* history_def_add(): * Append string to element */ -private const HistEvent * -history_def_add(p, str) - ptr_t p; - const char *str; +private int +history_def_add(ptr_t p, HistEvent *ev, const char *str) { - history_t *h = (history_t *) p; - size_t len; - char *s; - - if (h->cursor == &h->list) - return (history_def_enter(p, str)); - len = strlen(h->cursor->ev.str) + strlen(str) + 1; - s = (char *) h_malloc(len); - (void)strlcpy(s, h->cursor->ev.str, len); - (void)strlcat(s, str, len); - h_free((ptr_t) h->cursor->ev.str); - h->cursor->ev.str = s; - return &h->cursor->ev; + 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(evp->str) + strlen(str) + 1; + s = (char *) h_malloc(len); + if (s == NULL) { + he_seterrev(ev, _HE_MALLOC_FAILED); + return (-1); + } + (void) strlcpy(s, h->cursor->ev.str, len); + (void) strlcat(s, str, len); + h_free((ptr_t)evp->str); + evp->str = s; + *ev = h->cursor->ev; + return (0); } /* history_def_delete(): * Delete element hp of the h list */ +/* ARGSUSED */ private void -history_def_delete(h, hp) - history_t *h; - hentry_t *hp; +history_def_delete(history_t *h, + HistEvent *ev __attribute__((__unused__)), hentry_t *hp) { - if (hp == &h->list) - abort(); - hp->prev->next = hp->next; - hp->next->prev = hp->prev; - h_free((ptr_t) hp->ev.str); - h_free(hp); - h->cur--; + HistEventPrivate *evp = (void *)&hp->ev; + if (hp == &h->list) + abort(); + hp->prev->next = hp->next; + hp->next->prev = hp->prev; + h_free((ptr_t) evp->str); + h_free(hp); + h->cur--; } /* history_def_insert(): * Insert element with string str in the h list */ -private const HistEvent * -history_def_insert(h, str) - history_t *h; - const char *str; +private int +history_def_insert(history_t *h, HistEvent *ev, const char *str) { - h->cursor = (hentry_t *) h_malloc(sizeof(hentry_t)); - h->cursor->ev.str = strdup(str); - h->cursor->next = h->list.next; - h->cursor->prev = &h->list; - h->list.next->prev = h->cursor; - h->list.next = h->cursor; - h->cur++; - - return &h->cursor->ev; + + h->cursor = (hentry_t *) h_malloc(sizeof(hentry_t)); + if (h->cursor == NULL) + goto oomem; + if ((h->cursor->ev.str = strdup(str)) == NULL) { + h_free((ptr_t)h->cursor); + goto oomem; + } + h->cursor->ev.num = ++h->eventid; + h->cursor->next = h->list.next; + h->cursor->prev = &h->list; + h->list.next->prev = h->cursor; + h->list.next = h->cursor; + h->cur++; + + *ev = h->cursor->ev; + return (0); +oomem: + he_seterrev(ev, _HE_MALLOC_FAILED); + return (-1); } /* history_def_enter(): * Default function to enter an item in the history */ -private const HistEvent * -history_def_enter(p, str) - ptr_t p; - const char *str; +private int +history_def_enter(ptr_t p, HistEvent *ev, const char *str) { - history_t *h = (history_t *) p; - const HistEvent *ev; + 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 */ - ev = history_def_insert(h, str); - ((HistEvent*) ev)->num = ++h->eventno; + /* + * Always keep at least one entry. + * This way we don't have to check for the empty list. + */ + while (h->cur > h->max && h->cur > 0) + history_def_delete(h, ev, h->list.prev); - /* - * Always keep at least one entry. - * This way we don't have to check for the empty list. - */ - while (h->cur > h->max + 1) - history_def_delete(h, h->list.prev); - return ev; + return (1); } /* history_def_init(): * Default history initialization function */ -private void -history_def_init(p, n) - ptr_t *p; - int n; +/* ARGSUSED */ +private int +history_def_init(ptr_t *p, HistEvent *ev __attribute__((__unused__)), int n) { - history_t *h = (history_t *) h_malloc(sizeof(history_t)); - if (n <= 0) - n = 0; - h->eventno = 0; - h->cur = 0; - h->max = n; - h->list.next = h->list.prev = &h->list; - h->list.ev.str = NULL; - h->list.ev.num = 0; - h->cursor = &h->list; - *p = (ptr_t) h; + history_t *h = (history_t *) h_malloc(sizeof(history_t)); + if (h == NULL) + return -1; + + if (n <= 0) + n = 0; + h->eventid = 0; + h->cur = 0; + h->max = n; + h->list.next = h->list.prev = &h->list; + h->list.ev.str = NULL; + h->list.ev.num = 0; + h->cursor = &h->list; + h->flags = 0; + *p = (ptr_t) h; + return 0; } @@ -327,15 +470,14 @@ history_def_init(p, n) * Default history cleanup function */ private void -history_def_clear(p) - ptr_t p; +history_def_clear(ptr_t p, HistEvent *ev) { - history_t *h = (history_t *) p; + history_t *h = (history_t *) p; - while (h->list.prev != &h->list) - history_def_delete(h, h->list.prev); - h->eventno = 0; - h->cur = 0; + while (h->list.prev != &h->list) + history_def_delete(h, ev, h->list.prev); + h->eventid = 0; + h->cur = 0; } @@ -347,22 +489,29 @@ history_def_clear(p) * Initialization function. */ public History * -history_init() +history_init(void) { - History *h = (History *) h_malloc(sizeof(History)); - - history_def_init(&h->h_ref, 0); - - h->h_next = history_def_next; - h->h_first = history_def_first; - h->h_last = history_def_last; - h->h_prev = history_def_prev; - h->h_curr = history_def_curr; - h->h_clear = history_def_clear; - h->h_enter = history_def_enter; - h->h_add = history_def_add; - - return h; + HistEvent ev; + History *h = (History *) h_malloc(sizeof(History)); + if (h == NULL) + return NULL; + + 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; + h->h_last = history_def_last; + h->h_prev = history_def_prev; + h->h_curr = history_def_curr; + h->h_set = history_def_set; + h->h_clear = history_def_clear; + h->h_enter = history_def_enter; + h->h_add = history_def_add; + + return (h); } @@ -370,27 +519,83 @@ history_init() * clean up history; */ public void -history_end(h) - History *h; +history_end(History *h) { - if (h->h_next == history_def_next) - history_def_clear(h->h_ref); + HistEvent ev; + + if (h->h_next == history_def_next) + history_def_clear(h->h_ref, &ev); } -/* history_set_num(): +/* history_setsize(): * Set history number of events */ private int -history_set_num(h, num) - History *h; - int num; +history_setsize(History *h, HistEvent *ev, int num) { - if (h->h_next != history_def_next || num < 0) - return -1; - history_def_set(h->h_ref, num); - return 0; + + if (h->h_next != history_def_next) { + he_seterrev(ev, _HE_NOT_ALLOWED); + return (-1); + } + if (num < 0) { + he_seterrev(ev, _HE_BAD_PARAM); + return (-1); + } + history_def_setsize(h->h_ref, num); + return (0); +} + + +/* history_getsize(): + * Get number of events currently in history + */ +private int +history_getsize(History *h, HistEvent *ev) +{ + if (h->h_next != history_def_next) { + he_seterrev(ev, _HE_NOT_ALLOWED); + return (-1); + } + ev->num = history_def_getsize(h->h_ref); + if (ev->num < -1) { + he_seterrev(ev, _HE_SIZE_NEGATIVE); + return (-1); + } + 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); } @@ -398,40 +603,43 @@ history_set_num(h, num) * Set history functions */ private int -history_set_fun(h, nh) - History *h, *nh; +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_enter == NULL || nh->h_add == NULL || nh->h_clear == NULL || - nh->h_ref == NULL) { - if (h->h_next != history_def_next) { - history_def_init(&h->h_ref, 0); - h->h_first = history_def_first; - h->h_next = history_def_next; - h->h_last = history_def_last; - h->h_prev = history_def_prev; - h->h_curr = history_def_curr; - h->h_clear = history_def_clear; - h->h_enter = history_def_enter; - h->h_add = history_def_add; + HistEvent ev; + + 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) { + if (h->h_next != history_def_next) { + history_def_init(&h->h_ref, &ev, 0); + h->h_first = history_def_first; + h->h_next = history_def_next; + h->h_last = history_def_last; + h->h_prev = history_def_prev; + h->h_curr = history_def_curr; + h->h_set = history_def_set; + h->h_clear = history_def_clear; + h->h_enter = history_def_enter; + h->h_add = history_def_add; + } + return (-1); } - return -1; - } - - if (h->h_next == history_def_next) - history_def_clear(h->h_ref); - - h->h_first = nh->h_first; - h->h_next = nh->h_next; - h->h_last = nh->h_last; - h->h_prev = nh->h_prev; - h->h_curr = nh->h_curr; - h->h_clear = nh->h_clear; - h->h_enter = nh->h_enter; - h->h_add = nh->h_add; - - return 0; + if (h->h_next == history_def_next) + history_def_clear(h->h_ref, &ev); + + h->h_ent = -1; + h->h_first = nh->h_first; + h->h_next = nh->h_next; + h->h_last = nh->h_last; + h->h_prev = nh->h_prev; + h->h_curr = nh->h_curr; + h->h_set = nh->h_set; + h->h_clear = nh->h_clear; + h->h_enter = nh->h_enter; + h->h_add = nh->h_add; + + return (0); } @@ -439,34 +647,57 @@ history_set_fun(h, nh) * History load function */ private int -history_load(h, fname) - History *h; - const char *fname; +history_load(History *h, const char *fname) { - FILE *fp; - char *line; - size_t sz; - int i = -1; - - if ((fp = fopen(fname, "r")) == NULL) - return i; - - if ((line = fgetln(fp, &sz)) == NULL) - goto done; - - if (strncmp(line, hist_cookie, sz) != 0) - goto done; - - for (i = 0; (line = fgetln(fp, &sz)) != NULL; i++) { - char c = line[sz]; - line[sz] = '\0'; - HENTER(h, line); - line[sz] = c; - } - + FILE *fp; + char *line; + size_t sz, max_size; + char *ptr; + int i = -1; + HistEvent ev; + + if ((fp = fopen(fname, "r")) == NULL) + return (i); + + if ((line = fgetln(fp, &sz)) == NULL) + goto done; + + if (strncmp(line, hist_cookie, sz) != 0) + 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]; + + if (sz != 0 && line[sz - 1] == '\n') + line[--sz] = '\0'; + else + line[sz] = '\0'; + + if (max_size < sz) { + char *nptr; + max_size = (sz + 1023) & ~1023; + nptr = h_realloc(ptr, max_size); + if (nptr == NULL) { + i = -1; + goto oomem; + } + ptr = nptr; + } + (void) strunvis(ptr, line); + line[sz] = c; + if (HENTER(h, &ev, ptr) == -1) { + h_free((ptr_t)ptr); + return -1; + } + } +oomem: + h_free((ptr_t)ptr); done: - (void)fclose(fp); - return i; + (void) fclose(fp); + return (i); } @@ -474,203 +705,255 @@ done: * History save function */ private int -history_save(h, fname) - History *h; - const char *fname; +history_save(History *h, const char *fname) { - FILE *fp; - const HistEvent *ev; - int i = 0; - - if ((fp = fopen(fname, "w")) == NULL) - return -1; - - (void)fputs(hist_cookie, fp); - for (ev = HLAST(h); ev != NULL; ev = HPREV(h), i++) - (void)fprintf(fp, "%s", ev->str); - (void)fclose(fp); - return i; + FILE *fp; + HistEvent ev; + int i = -1, retval; + size_t len, max_size; + char *ptr; + + if ((fp = fopen(fname, "w")) == NULL) + return (-1); + + 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); + 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) { + char *nptr; + max_size = (len + 1023) & 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); + } +oomem: + h_free((ptr_t)ptr); +done: + (void) fclose(fp); + return (i); } /* history_prev_event(): * Find the previous event, with number given */ -private const HistEvent * -history_prev_event(h, num) - History *h; - int num; +private int +history_prev_event(History *h, HistEvent *ev, int num) { - const HistEvent *ev; - for (ev = HCURR(h); ev != NULL; ev = HPREV(h)) - if (ev->num == num) - return ev; - return NULL; + int retval; + + for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev)) + if (ev->num == num) + return (0); + + he_seterrev(ev, _HE_NOT_FOUND); + return (-1); } /* history_next_event(): * Find the next event, with number given */ -private const HistEvent * -history_next_event(h, num) - History *h; - int num; +private int +history_next_event(History *h, HistEvent *ev, int num) { - const HistEvent *ev; - for (ev = HCURR(h); ev != NULL; ev = HNEXT(h)) - if (ev->num == num) - return ev; - return NULL; + int retval; + + for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev)) + if (ev->num == num) + return (0); + + he_seterrev(ev, _HE_NOT_FOUND); + return (-1); } /* history_prev_string(): * Find the previous event beginning with string */ -private const HistEvent * -history_prev_string(h, str) - History *h; - const char* str; +private int +history_prev_string(History *h, HistEvent *ev, const char *str) { - const HistEvent *ev; - size_t len = strlen(str); - - for (ev = HCURR(h); ev != NULL; ev = HNEXT(h)) - if (strncmp(str, ev->str, len) == 0) - return ev; - return NULL; -} + size_t len = strlen(str); + int retval; + for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev)) + if (strncmp(str, ev->str, len) == 0) + return (0); + he_seterrev(ev, _HE_NOT_FOUND); + return (-1); +} /* history_next_string(): * Find the next event beginning with string */ -private const HistEvent * -history_next_string(h, str) - History *h; - const char* str; +private int +history_next_string(History *h, HistEvent *ev, const char *str) { - const HistEvent *ev; - size_t len = strlen(str); + size_t len = strlen(str); + int retval; + + for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev)) + if (strncmp(str, ev->str, len) == 0) + return (0); - for (ev = HCURR(h); ev != NULL; ev = HPREV(h)) - if (strncmp(str, ev->str, len) == 0) - return ev; - return NULL; + he_seterrev(ev, _HE_NOT_FOUND); + return (-1); } /* history(): * User interface to history functions. */ -const HistEvent * -history(History *h, int fun, ...) +int +history(History *h, HistEvent *ev, int fun, ...) { - va_list va; - const HistEvent *ev = NULL; - const char *str; - static HistEvent sev = { 0, "" }; - - va_start(va, fun); - - switch (fun) { - case H_ADD: - str = va_arg(va, const char *); - ev = HADD(h, str); - break; - - case H_ENTER: - str = va_arg(va, const char *); - ev = HENTER(h, str); - break; - - case H_FIRST: - ev = HFIRST(h); - break; - - case H_NEXT: - ev = HNEXT(h); - break; - - case H_LAST: - ev = HLAST(h); - break; - - case H_PREV: - ev = HPREV(h); - break; - - case H_CURR: - ev = HCURR(h); - break; - - case H_CLEAR: - HCLEAR(h); - break; - - case H_LOAD: - sev.num = history_load(h, va_arg(va, const char *)); - ev = &sev; - break; - - case H_SAVE: - sev.num = history_save(h, va_arg(va, const char *)); - ev = &sev; - break; - - case H_PREV_EVENT: - ev = history_prev_event(h, va_arg(va, int)); - break; - - case H_NEXT_EVENT: - ev = history_next_event(h, va_arg(va, int)); - break; - - case H_PREV_STR: - ev = history_prev_string(h, va_arg(va, const char*)); - break; - - case H_NEXT_STR: - ev = history_next_string(h, va_arg(va, const char*)); - break; - - case H_EVENT: - if (history_set_num(h, va_arg(va, int)) == 0) { - sev.num = -1; - ev = &sev; - } - break; - - case H_FUNC: + va_list va; + const char *str; + int retval; + + va_start(va, fun); + + he_seterrev(ev, _HE_OK); + + switch (fun) { + case H_GETSIZE: + retval = history_getsize(h, ev); + break; + + case H_SETSIZE: + 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_ENTER: + str = va_arg(va, const char *); + if ((retval = HENTER(h, ev, str)) != -1) + h->h_ent = ev->num; + break; + + case H_APPEND: + str = va_arg(va, const char *); + if ((retval = HSET(h, ev, h->h_ent)) != -1) + retval = HADD(h, ev, str); + break; + + case H_FIRST: + retval = HFIRST(h, ev); + break; + + case H_NEXT: + retval = HNEXT(h, ev); + break; + + case H_LAST: + retval = HLAST(h, ev); + break; + + case H_PREV: + retval = HPREV(h, ev); + break; + + case H_CURR: + retval = HCURR(h, ev); + break; + + case H_SET: + retval = HSET(h, ev, va_arg(va, const int)); + break; + + case H_CLEAR: + HCLEAR(h, ev); + retval = 0; + break; + + case H_LOAD: + retval = history_load(h, va_arg(va, const char *)); + if (retval == -1) + he_seterrev(ev, _HE_HIST_READ); + break; + + case H_SAVE: + retval = history_save(h, va_arg(va, const char *)); + if (retval == -1) + he_seterrev(ev, _HE_HIST_WRITE); + break; + + case H_PREV_EVENT: + retval = history_prev_event(h, ev, va_arg(va, int)); + break; + + case H_NEXT_EVENT: + retval = history_next_event(h, ev, va_arg(va, int)); + break; + + case H_PREV_STR: + retval = history_prev_string(h, ev, va_arg(va, const char *)); + break; + + case H_NEXT_STR: + retval = history_next_string(h, ev, va_arg(va, const char *)); + break; + + case H_FUNC: { - History hf; - hf.h_ref = va_arg(va, ptr_t); - hf.h_first = va_arg(va, history_gfun_t); - hf.h_next = va_arg(va, history_gfun_t); - hf.h_last = va_arg(va, history_gfun_t); - hf.h_prev = va_arg(va, history_gfun_t); - hf.h_curr = va_arg(va, history_gfun_t); - 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); - - if (history_set_fun(h, &hf) == 0) { - sev.num = -1; - ev = &sev; - } + History hf; + + hf.h_ref = va_arg(va, ptr_t); + h->h_ent = -1; + hf.h_first = va_arg(va, history_gfun_t); + hf.h_next = va_arg(va, history_gfun_t); + hf.h_last = va_arg(va, history_gfun_t); + hf.h_prev = va_arg(va, history_gfun_t); + hf.h_curr = va_arg(va, history_gfun_t); + hf.h_set = va_arg(va, history_sfun_t); + 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); + + if ((retval = history_set_fun(h, &hf)) == -1) + he_seterrev(ev, _HE_PARAM_MISSING); + break; } - break; - case H_END: - history_end(h); - break; + case H_END: + history_end(h); + retval = 0; + break; - default: - break; - } - va_end(va); - return ev; + default: + retval = -1; + he_seterrev(ev, _HE_UNKNOWN); + break; + } + va_end(va); + return (retval); } diff --git a/lib/libedit/key.c b/lib/libedit/key.c index 04152e9c7be..215ee4987dd 100644 --- a/lib/libedit/key.c +++ b/lib/libedit/key.c @@ -1,5 +1,5 @@ -/* $OpenBSD: key.c,v 1.7 2003/06/02 20:18:40 millert Exp $ */ -/* $NetBSD: key.c,v 1.2 1997/01/11 06:47:58 lukem Exp $ */ +/* $OpenBSD: key.c,v 1.8 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: key.c,v 1.14 2003/08/07 16:44:31 agc Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -33,11 +33,12 @@ * SUCH DAMAGE. */ +#include "config.h" #if !defined(lint) && !defined(SCCSID) #if 0 static char sccsid[] = "@(#)key.c 8.1 (Berkeley) 6/4/93"; #else -static const char rcsid[] = "$OpenBSD: key.c,v 1.7 2003/06/02 20:18:40 millert Exp $"; +static const char rcsid[] = "$OpenBSD: key.c,v 1.8 2003/10/31 08:42:24 otto Exp $"; #endif #endif /* not lint && not SCCSID */ @@ -45,10 +46,10 @@ static const char rcsid[] = "$OpenBSD: key.c,v 1.7 2003/06/02 20:18:40 millert E * key.c: This module contains the procedures for maintaining * the extended-key map. * - * An extended-key (key) is a sequence of keystrokes introduced - * with an sequence introducer and consisting of an arbitrary - * number of characters. This module maintains a map (the el->el_key.map) - * to convert these extended-key sequences into input strs + * An extended-key (key) is a sequence of keystrokes introduced + * with an sequence introducer and consisting of an arbitrary + * number of characters. This module maintains a map (the el->el_key.map) + * to convert these extended-key sequences into input strs * (XK_STR), editor functions (XK_CMD), or unix commands (XK_EXE). * * Warning: @@ -62,76 +63,78 @@ static const char rcsid[] = "$OpenBSD: key.c,v 1.7 2003/06/02 20:18:40 millert E * 1) It is not possible to have one key that is a * substr of another. */ -#include "sys.h" #include <string.h> #include <stdlib.h> #include "el.h" -/* - * The Nodes of the el->el_key.map. The el->el_key.map is a linked list +/* + * The Nodes of the el->el_key.map. The el->el_key.map is a linked list * of these node elements */ struct key_node_t { - char ch; /* single character of key */ - int type; /* node type */ - key_value_t val; /* command code or pointer to str, */ - /* if this is a leaf */ - struct key_node_t *next; /* ptr to next char of this key */ - struct key_node_t *sibling; /* ptr to another key with same prefix */ + char ch; /* single character of key */ + int type; /* node type */ + key_value_t val; /* command code or pointer to str, */ + /* if this is a leaf */ + struct key_node_t *next; /* ptr to next char of this key */ + struct key_node_t *sibling; /* ptr to another key with same prefix*/ }; -private int node_trav(EditLine *, key_node_t *, char *, - key_value_t *); -private int node__try(key_node_t *, char *, key_value_t *, int); -private key_node_t *node__get(int); -private void node__put(key_node_t *); -private int node__delete(key_node_t **, char *); -private int node_lookup (EditLine *, char *, key_node_t *, int); -private int node_enum(EditLine *, key_node_t *, int); -private int key__decode_char(char *, int, int); +private int node_trav(EditLine *, key_node_t *, char *, + key_value_t *); +private int node__try(EditLine *, key_node_t *, const char *, + key_value_t *, int); +private key_node_t *node__get(int); +private void node__put(EditLine *, key_node_t *); +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); -#define KEY_BUFSIZ EL_BUFSIZ +#define KEY_BUFSIZ EL_BUFSIZ /* key_init(): * Initialize the key maps */ protected int -key_init(el) - EditLine *el; +key_init(EditLine *el) { - el->el_key.buf = (char *) el_malloc(KEY_BUFSIZ); - el->el_key.map = NULL; - key_reset(el); - return 0; -} + + el->el_key.buf = (char *) el_malloc(KEY_BUFSIZ); + if (el->el_key.buf == NULL) + return (-1); + el->el_key.map = NULL; + key_reset(el); + return (0); +} /* key_end(): * Free the key maps */ protected void -key_end(el) - EditLine *el; +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; -} + + 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; +} /* key_map_cmd(): * Associate cmd with a key value */ protected key_value_t * -key_map_cmd(el, cmd) - EditLine *el; - int cmd; +key_map_cmd(EditLine *el, int cmd) { - el->el_key.val.cmd = (el_action_t) cmd; - return &el->el_key.val; + + el->el_key.val.cmd = (el_action_t) cmd; + return (&el->el_key.val); } @@ -139,12 +142,11 @@ key_map_cmd(el, cmd) * Associate str with a key value */ protected key_value_t * -key_map_str(el, str) - EditLine *el; - char *str; +key_map_str(EditLine *el, char *str) { - el->el_key.val.str = str; - return &el->el_key.val; + + el->el_key.val.str = str; + return (&el->el_key.val); } @@ -154,12 +156,12 @@ key_map_str(el, str) * [Always bind the ansi arrow keys?] */ protected void -key_reset(el) - EditLine *el; +key_reset(EditLine *el) { - node__put(el->el_key.map); - el->el_key.map = NULL; - return; + + node__put(el, el->el_key.map); + el->el_key.map = NULL; + return; } @@ -168,18 +170,15 @@ key_reset(el) * Looks up *ch in map and then reads characters until a * complete match is found or a mismatch occurs. Returns the * type of the match found (XK_STR, XK_CMD, or XK_EXE). - * Returns NULL in val.str and XK_STR for no match. + * Returns NULL in val.str and XK_STR for no match. * The last character read is returned in *ch. */ protected int -key_get(el, ch, val) - EditLine *el; - char *ch; - key_value_t *val; +key_get(EditLine *el, char *ch, key_value_t *val) { - return node_trav(el, el->el_key.map, ch, val); -} + return (node_trav(el, el->el_key.map, ch, val)); +} /* key_add(): @@ -189,31 +188,27 @@ key_get(el, ch, val) * out str or a unix command. */ protected void -key_add(el, key, val, ntype) - EditLine *el; - char *key; - key_value_t *val; - int ntype; +key_add(EditLine *el, const char *key, key_value_t *val, int ntype) { - if (key[0] == '\0') { - (void)fprintf(el->el_errfile, - "key_add: Null extended-key not allowed.\n"); - return; - } - if (ntype == XK_CMD && val->cmd == ED_SEQUENCE_LEAD_IN) { - (void)fprintf(el->el_errfile, - "key_add: sequence-lead-in command not allowed\n"); - return; - } - - if (el->el_key.map == NULL) - /* tree is initially empty. Set up new node to match key[0] */ - el->el_key.map = node__get(key[0]); /* it is properly initialized */ + if (key[0] == '\0') { + (void) fprintf(el->el_errfile, + "key_add: Null extended-key not allowed.\n"); + return; + } + if (ntype == XK_CMD && val->cmd == ED_SEQUENCE_LEAD_IN) { + (void) fprintf(el->el_errfile, + "key_add: sequence-lead-in command not allowed\n"); + return; + } + if (el->el_key.map == NULL) + /* tree is initially empty. Set up new node to match key[0] */ + el->el_key.map = node__get(key[0]); + /* it is properly initialized */ - /* Now recurse through el->el_key.map */ - (void)node__try(el->el_key.map, key, val, ntype); - return; + /* Now recurse through el->el_key.map */ + (void) node__try(el, el->el_key.map, key, val, ntype); + return; } @@ -221,17 +216,15 @@ key_add(el, key, val, ntype) * */ protected void -key_clear(el, map, in) - 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) && - ((map == el->el_map.key && - el->el_map.alt[(unsigned char) *in] != ED_SEQUENCE_LEAD_IN) || - (map == el->el_map.alt && - el->el_map.key[(unsigned char) *in] != ED_SEQUENCE_LEAD_IN))) - (void)key_delete(el, in); + + if ((map[(unsigned char)*in] == ED_SEQUENCE_LEAD_IN) && + ((map == el->el_map.key && + el->el_map.alt[(unsigned char)*in] != ED_SEQUENCE_LEAD_IN) || + (map == el->el_map.alt && + el->el_map.key[(unsigned char)*in] != ED_SEQUENCE_LEAD_IN))) + (void) key_delete(el, in); } @@ -240,21 +233,19 @@ key_clear(el, map, in) * they exists. */ protected int -key_delete(el, key) - EditLine *el; - char *key; +key_delete(EditLine *el, const char *key) { - if (key[0] == '\0') { - (void)fprintf(el->el_errfile, - "key_delete: Null extended-key not allowed.\n"); - return -1; - } - if (el->el_key.map == NULL) - return 0; + if (key[0] == '\0') { + (void) fprintf(el->el_errfile, + "key_delete: Null extended-key not allowed.\n"); + return (-1); + } + if (el->el_key.map == NULL) + return (0); - (void)node__delete(&el->el_key.map, key); - return 0; + (void) node__delete(el, &el->el_key.map, key); + return (0); } @@ -263,19 +254,19 @@ key_delete(el, key) * Print entire el->el_key.map if null */ protected void -key_print(el, key) - EditLine *el; - char *key; +key_print(EditLine *el, const char *key) { - /* do nothing if el->el_key.map is empty and null key specified */ - if (el->el_key.map == NULL && *key == 0) - return; - el->el_key.buf[0] = '"'; - if (node_lookup(el, key, el->el_key.map, 1) <= -1) - /* key is not bound */ - (void)fprintf(el->el_errfile, "Unbound extended key \"%s\"\n", key); - return; + /* do nothing if el->el_key.map is empty and null key specified */ + if (el->el_key.map == NULL && *key == 0) + return; + + el->el_key.buf[0] = '"'; + if (node_lookup(el, key, el->el_key.map, 1) <= -1) + /* key is not bound */ + (void) fprintf(el->el_errfile, "Unbound extended key \"%s\"\n", + key); + return; } @@ -284,41 +275,36 @@ key_print(el, key) * found. May read in more characters. */ private int -node_trav(el, ptr, ch, val) - EditLine *el; - key_node_t *ptr; - char *ch; - key_value_t *val; +node_trav(EditLine *el, key_node_t *ptr, char *ch, key_value_t *val) { - if (ptr->ch == *ch) { - /* match found */ - if (ptr->next) { - /* key not complete so get next char */ - if (el_getc(el, ch) != 1) { /* if EOF or error */ - val->cmd = ED_END_OF_FILE; - return XK_CMD;/* PWP: Pretend we just read an end-of-file */ - } - return node_trav(el, ptr->next, ch, val); - } - else { - *val = ptr->val; - if (ptr->type != XK_CMD) - *ch = '\0'; - return ptr->type; - } - } - else { - /* no match found here */ - if (ptr->sibling) { - /* try next sibling */ - return node_trav(el, ptr->sibling, ch, val); - } - else { - /* no next sibling -- mismatch */ - val->str = NULL; - return XK_STR; + + if (ptr->ch == *ch) { + /* match found */ + if (ptr->next) { + /* key not complete so get next char */ + if (el_getc(el, ch) != 1) { /* if EOF or error */ + val->cmd = ED_END_OF_FILE; + return (XK_CMD); + /* PWP: Pretend we just read an end-of-file */ + } + return (node_trav(el, ptr->next, ch, val)); + } else { + *val = ptr->val; + if (ptr->type != XK_CMD) + *ch = '\0'; + return (ptr->type); + } + } else { + /* no match found here */ + if (ptr->sibling) { + /* try next sibling */ + return (node_trav(el, ptr->sibling, ch, val)); + } else { + /* no next sibling -- mismatch */ + val->str = NULL; + return (XK_STR); + } } - } } @@ -326,63 +312,60 @@ node_trav(el, ptr, ch, val) * Find a node that matches *str or allocate a new one */ private int -node__try(ptr, str, val, ntype) - key_node_t *ptr; - char *str; - key_value_t *val; - int ntype; +node__try(EditLine *el, key_node_t *ptr, const char *str, key_value_t *val, int ntype) { - if (ptr->ch != *str) { - key_node_t *xm; - for (xm = ptr; xm->sibling != NULL; xm = xm->sibling) - if (xm->sibling->ch == *str) - break; - if (xm->sibling == NULL) - xm->sibling = node__get(*str); /* setup new node */ - ptr = xm->sibling; - } + if (ptr->ch != *str) { + key_node_t *xm; - if (*++str == '\0') { - /* we're there */ - if (ptr->next != NULL) { - node__put(ptr->next); /* lose longer keys with this prefix */ - ptr->next = NULL; - } - switch (ptr->type) { - case XK_CMD: - case XK_NOD: - break; - case XK_STR: - case XK_EXE: - if (ptr->val.str) - el_free((ptr_t) ptr->val.str); - break; - default: - abort(); - break; + for (xm = ptr; xm->sibling != NULL; xm = xm->sibling) + if (xm->sibling->ch == *str) + break; + if (xm->sibling == NULL) + xm->sibling = node__get(*str); /* setup new node */ + ptr = xm->sibling; } + if (*++str == '\0') { + /* we're there */ + if (ptr->next != NULL) { + node__put(el, ptr->next); + /* lose longer keys with this prefix */ + ptr->next = NULL; + } + switch (ptr->type) { + case XK_CMD: + case XK_NOD: + break; + case XK_STR: + case XK_EXE: + if (ptr->val.str) + el_free((ptr_t) ptr->val.str); + break; + default: + EL_ABORT((el->el_errfile, "Bad XK_ type %d\n", + ptr->type)); + break; + } - switch (ptr->type = ntype) { - case XK_CMD: - ptr->val = *val; - break; - case XK_STR: - case XK_EXE: - ptr->val.str = strdup(val->str); - break; - default: - abort(); - break; + switch (ptr->type = ntype) { + case XK_CMD: + ptr->val = *val; + break; + case XK_STR: + case XK_EXE: + ptr->val.str = strdup(val->str); + break; + default: + EL_ABORT((el->el_errfile, "Bad XK_ type %d\n", ntype)); + break; + } + } else { + /* still more chars to go */ + if (ptr->next == NULL) + ptr->next = node__get(*str); /* setup new node */ + (void) node__try(el, ptr->next, str, val, ntype); } - } - else { - /* still more chars to go */ - if (ptr->next == NULL) - ptr->next = node__get(*str); /* setup new node */ - (void)node__try(ptr->next, str, val, ntype); - } - return 0; + return (0); } @@ -390,84 +373,79 @@ node__try(ptr, str, val, ntype) * Delete node that matches str */ private int -node__delete(inptr, str) - 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; + key_node_t *ptr; + key_node_t *prev_ptr = NULL; - ptr = *inptr; + ptr = *inptr; - if (ptr->ch != *str) { - key_node_t *xm; + if (ptr->ch != *str) { + key_node_t *xm; - for (xm = ptr; xm->sibling != NULL; xm = xm->sibling) - if (xm->sibling->ch == *str) - break; - if (xm->sibling == NULL) - return 0; - prev_ptr = xm; - ptr = xm->sibling; - } - - if (*++str == '\0') { - /* we're there */ - if (prev_ptr == NULL) - *inptr = ptr->sibling; - else - prev_ptr->sibling = ptr->sibling; - ptr->sibling = NULL; - node__put(ptr); - return 1; - } - else if (ptr->next != NULL && node__delete(&ptr->next, str) == 1) { - if (ptr->next != NULL) - return 0; - if (prev_ptr == NULL) - *inptr = ptr->sibling; - else - prev_ptr->sibling = ptr->sibling; - ptr->sibling = NULL; - node__put(ptr); - return 1; - } - else { - return 0; - } + for (xm = ptr; xm->sibling != NULL; xm = xm->sibling) + if (xm->sibling->ch == *str) + break; + if (xm->sibling == NULL) + return (0); + prev_ptr = xm; + ptr = xm->sibling; + } + if (*++str == '\0') { + /* we're there */ + if (prev_ptr == NULL) + *inptr = ptr->sibling; + else + prev_ptr->sibling = ptr->sibling; + ptr->sibling = NULL; + node__put(el, ptr); + return (1); + } else if (ptr->next != NULL && + node__delete(el, &ptr->next, str) == 1) { + if (ptr->next != NULL) + return (0); + if (prev_ptr == NULL) + *inptr = ptr->sibling; + else + prev_ptr->sibling = ptr->sibling; + ptr->sibling = NULL; + node__put(el, ptr); + return (1); + } else { + return (0); + } } + /* node__put(): * Puts a tree of nodes onto free list using free(3). */ private void -node__put(ptr) - key_node_t *ptr; +node__put(EditLine *el, key_node_t *ptr) { - if (ptr == NULL) - return; + if (ptr == NULL) + return; - if (ptr->next != NULL) { - node__put(ptr->next); - ptr->next = NULL; - } - - node__put(ptr->sibling); - - switch (ptr->type) { - case XK_CMD: - case XK_NOD: - break; - case XK_EXE: - case XK_STR: - if (ptr->val.str != NULL) - el_free((ptr_t) ptr->val.str); - break; - default: - abort(); - break; - } - el_free((ptr_t) ptr); + if (ptr->next != NULL) { + node__put(el, ptr->next); + ptr->next = NULL; + } + node__put(el, ptr->sibling); + + switch (ptr->type) { + case XK_CMD: + case XK_NOD: + break; + case XK_EXE: + case XK_STR: + if (ptr->val.str != NULL) + el_free((ptr_t) ptr->val.str); + break; + default: + EL_ABORT((el->el_errfile, "Bad XK_ type %d\n", ptr->type)); + break; + } + el_free((ptr_t) ptr); } @@ -475,18 +453,19 @@ node__put(ptr) * Returns pointer to an key_node_t for ch. */ private key_node_t * -node__get(ch) - int ch; +node__get(int ch) { - key_node_t *ptr; - - ptr = (key_node_t *) el_malloc((size_t) sizeof(key_node_t)); - ptr->ch = ch; - ptr->type = XK_NOD; - ptr->val.str = NULL; - ptr->next = NULL; - ptr->sibling = NULL; - return ptr; + key_node_t *ptr; + + ptr = (key_node_t *) el_malloc((size_t) sizeof(key_node_t)); + if (ptr == NULL) + return NULL; + ptr->ch = ch; + ptr->type = XK_NOD; + ptr->val.str = NULL; + ptr->next = NULL; + ptr->sibling = NULL; + return (ptr); } @@ -496,51 +475,48 @@ node__get(ch) * Print if last node */ private int -node_lookup(el, str, ptr, cnt) - 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; - - if (ptr == NULL) - return -1; /* cannot have null ptr */ - - if (*str == 0) { - /* no more chars in str. node_enum from here. */ - (void)node_enum(el, ptr, cnt); - return 0; - } - else { - /* If match put this char into el->el_key.buf. Recurse */ - if (ptr->ch == *str) { - /* match found */ - ncnt = key__decode_char(el->el_key.buf, cnt, - (unsigned char) ptr->ch); - if (ptr->next != NULL) - /* not yet at leaf */ - return node_lookup(el, str + 1, ptr->next, ncnt + 1); - else { - /* next node is null so key should be complete */ - if (str[1] == 0) { - el->el_key.buf[ncnt + 1] = '"'; - el->el_key.buf[ncnt + 2] = '\0'; - key_kprint(el, el->el_key.buf, &ptr->val, ptr->type); - return 0; + int ncnt; + + if (ptr == NULL) + return (-1); /* cannot have null ptr */ + + if (*str == 0) { + /* no more chars in str. node_enum from here. */ + (void) node_enum(el, ptr, cnt); + return (0); + } else { + /* If match put this char into el->el_key.buf. Recurse */ + if (ptr->ch == *str) { + /* match found */ + ncnt = key__decode_char(el->el_key.buf, cnt, + (unsigned char) ptr->ch); + if (ptr->next != NULL) + /* not yet at leaf */ + return (node_lookup(el, str + 1, ptr->next, + ncnt + 1)); + else { + /* next node is null so key should be complete */ + if (str[1] == 0) { + el->el_key.buf[ncnt + 1] = '"'; + el->el_key.buf[ncnt + 2] = '\0'; + key_kprint(el, el->el_key.buf, + &ptr->val, ptr->type); + return (0); + } else + return (-1); + /* mismatch -- str still has chars */ + } + } else { + /* no match found try sibling */ + if (ptr->sibling) + return (node_lookup(el, str, ptr->sibling, + cnt)); + else + return (-1); } - else - return -1;/* mismatch -- str still has chars */ - } - } - else { - /* no match found try sibling */ - if (ptr->sibling) - return node_lookup(el, str, ptr->sibling, cnt); - else - return -1; } - } } @@ -548,44 +524,39 @@ node_lookup(el, str, ptr, cnt) * Traverse the node printing the characters it is bound in buffer */ private int -node_enum(el, ptr, cnt) - EditLine *el; - key_node_t *ptr; - int cnt; +node_enum(EditLine *el, key_node_t *ptr, int cnt) { - int ncnt; + int ncnt; - if (cnt >= KEY_BUFSIZ - 5) { /* buffer too small */ - el->el_key.buf[++cnt] = '"'; - el->el_key.buf[++cnt] = '\0'; - (void)fprintf(el->el_errfile, + if (cnt >= KEY_BUFSIZ - 5) { /* buffer too small */ + el->el_key.buf[++cnt] = '"'; + el->el_key.buf[++cnt] = '\0'; + (void) fprintf(el->el_errfile, "Some extended keys too long for internal print buffer"); - (void)fprintf(el->el_errfile, " \"%s...\"\n", el->el_key.buf); - return 0; - } - - if (ptr == NULL) { + (void) fprintf(el->el_errfile, " \"%s...\"\n", el->el_key.buf); + return (0); + } + if (ptr == NULL) { #ifdef DEBUG_EDIT - (void)fprintf(el->el_errfile, "node_enum: BUG!! Null ptr passed\n!"); + (void) fprintf(el->el_errfile, + "node_enum: BUG!! Null ptr passed\n!"); #endif - return -1; - } - - /* put this char at end of str */ - ncnt = key__decode_char(el->el_key.buf, cnt, (unsigned char) ptr->ch); - if (ptr->next == NULL) { - /* print this key and function */ - el->el_key.buf[ncnt + 1] = '"'; - el->el_key.buf[ncnt + 2] = '\0'; - key_kprint(el, el->el_key.buf, &ptr->val, ptr->type); - } - else - (void)node_enum(el, ptr->next, ncnt + 1); - - /* go to sibling if there is one */ - if (ptr->sibling) - (void)node_enum(el, ptr->sibling, cnt); - return 0; + return (-1); + } + /* put this char at end of str */ + ncnt = key__decode_char(el->el_key.buf, cnt, (unsigned char) ptr->ch); + if (ptr->next == NULL) { + /* print this key and function */ + el->el_key.buf[ncnt + 1] = '"'; + el->el_key.buf[ncnt + 2] = '\0'; + key_kprint(el, el->el_key.buf, &ptr->val, ptr->type); + } else + (void) node_enum(el, ptr->next, ncnt + 1); + + /* go to sibling if there is one */ + if (ptr->sibling) + (void) node_enum(el, ptr->sibling, cnt); + return (0); } @@ -594,42 +565,40 @@ node_enum(el, ptr, cnt) * function specified by val */ protected void -key_kprint(el, key, val, ntype) - 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]; - static char *fmt = "%-15s-> %s\n"; - - if (val != NULL) - switch (ntype) { - case XK_STR: - case XK_EXE: - (void)fprintf(el->el_errfile, fmt, key, - key__decode_str(val->str, unparsbuf, - ntype == XK_STR ? "\"\"" : "[]")); - break; - case XK_CMD: - for (fp = el->el_map.help; fp->name; fp++) - if (val->cmd == fp->func) { - (void)fprintf(el->el_errfile, fmt, key, fp->name); - break; - } + el_bindings_t *fp; + char unparsbuf[EL_BUFSIZ]; + static const char fmt[] = "%-15s-> %s\n"; + + if (val != NULL) + switch (ntype) { + case XK_STR: + case XK_EXE: + (void) fprintf(el->el_outfile, fmt, key, + key__decode_str(val->str, unparsbuf, + ntype == XK_STR ? "\"\"" : "[]")); + break; + case XK_CMD: + for (fp = el->el_map.help; fp->name; fp++) + if (val->cmd == fp->func) { + (void) fprintf(el->el_outfile, fmt, + key, fp->name); + break; + } #ifdef DEBUG_KEY - if (fp->name == NULL) - (void)fprintf(el->el_errfile, "BUG! Command not found.\n"); + if (fp->name == NULL) + (void) fprintf(el->el_outfile, + "BUG! Command not found.\n"); #endif - break; - default: - abort(); - break; - } - else - (void)fprintf(el->el_errfile, fmt, key, "no input"); + break; + default: + EL_ABORT((el->el_errfile, "Bad XK_ type %d\n", ntype)); + break; + } + else + (void) fprintf(el->el_outfile, fmt, key, "no input"); } @@ -637,91 +606,79 @@ key_kprint(el, key, val, ntype) * Put a printable form of char in buf. */ private int -key__decode_char(buf, cnt, ch) - char *buf; - int cnt, ch; +key__decode_char(char *buf, int cnt, int ch) { - if (ch == 0) { - buf[cnt++] = '^'; - buf[cnt] = '@'; - return cnt; - } - - if (iscntrl(ch)) { - buf[cnt++] = '^'; - if (ch == '\177') - buf[cnt] = '?'; - else - buf[cnt] = ch | 0100; - } - else if (ch == '^') { - buf[cnt++] = '\\'; - buf[cnt] = '^'; - } - else if (ch == '\\') { - buf[cnt++] = '\\'; - buf[cnt] = '\\'; - } - else if (ch == ' ' || (isprint(ch) && !isspace(ch))) { - buf[cnt] = ch; - } - else { - buf[cnt++] = '\\'; - buf[cnt++] = ((ch >> 6) & 7) + '0'; - buf[cnt++] = ((ch >> 3) & 7) + '0'; - buf[cnt] = (ch & 7) + '0'; - } - return cnt; + if (ch == 0) { + buf[cnt++] = '^'; + buf[cnt] = '@'; + return (cnt); + } + if (iscntrl(ch)) { + buf[cnt++] = '^'; + if (ch == '\177') + buf[cnt] = '?'; + else + buf[cnt] = ch | 0100; + } else if (ch == '^') { + buf[cnt++] = '\\'; + buf[cnt] = '^'; + } else if (ch == '\\') { + buf[cnt++] = '\\'; + buf[cnt] = '\\'; + } else if (ch == ' ' || (isprint(ch) && !isspace(ch))) { + buf[cnt] = ch; + } else { + buf[cnt++] = '\\'; + buf[cnt++] = (((unsigned int) ch >> 6) & 7) + '0'; + buf[cnt++] = (((unsigned int) ch >> 3) & 7) + '0'; + buf[cnt] = (ch & 7) + '0'; + } + return (cnt); } + /* key__decode_str(): * Make a printable version of the ey */ protected char * -key__decode_str(str, buf, sep) - char *str; - char *buf; - char *sep; +key__decode_str(const char *str, char *buf, const char *sep) { - char *b, *p; - - b = buf; - if (sep[0] != '\0') - *b++ = sep[0]; - if (*str == 0) { - *b++ = '^'; - *b++ = '@'; - if (sep[0] != '\0' && sep[1] != '\0') - *b++ = sep[1]; - *b++ = 0; - return buf; - } - - for (p = str; *p != 0; p++) { - if (iscntrl((unsigned char) *p)) { - *b++ = '^'; - if (*p == '\177') - *b++ = '?'; - else - *b++ = *p | 0100; - } - else if (*p == '^' || *p == '\\') { - *b++ = '\\'; - *b++ = *p; - } - else if (*p == ' ' || (isprint((unsigned char) *p) && - !isspace((unsigned char) *p))) { - *b++ = *p; + char *b; + const char *p; + + b = buf; + if (sep[0] != '\0') + *b++ = sep[0]; + if (*str == 0) { + *b++ = '^'; + *b++ = '@'; + if (sep[0] != '\0' && sep[1] != '\0') + *b++ = sep[1]; + *b++ = 0; + return (buf); } - else { - *b++ = '\\'; - *b++ = ((*p >> 6) & 7) + '0'; - *b++ = ((*p >> 3) & 7) + '0'; - *b++ = (*p & 7) + '0'; + for (p = str; *p != 0; p++) { + if (iscntrl((unsigned char) *p)) { + *b++ = '^'; + if (*p == '\177') + *b++ = '?'; + else + *b++ = *p | 0100; + } else if (*p == '^' || *p == '\\') { + *b++ = '\\'; + *b++ = *p; + } else if (*p == ' ' || (isprint((unsigned char) *p) && + !isspace((unsigned char) *p))) { + *b++ = *p; + } else { + *b++ = '\\'; + *b++ = (((unsigned int) *p >> 6) & 7) + '0'; + *b++ = (((unsigned int) *p >> 3) & 7) + '0'; + *b++ = (*p & 7) + '0'; + } } - } - if (sep[0] != '\0' && sep[1] != '\0') - *b++ = sep[1]; - *b++ = 0; - return buf; /* should check for overflow */ + if (sep[0] != '\0' && sep[1] != '\0') + *b++ = sep[1]; + *b++ = 0; + return (buf); /* should check for overflow */ } diff --git a/lib/libedit/key.h b/lib/libedit/key.h index 95eb8edb319..86584417253 100644 --- a/lib/libedit/key.h +++ b/lib/libedit/key.h @@ -1,5 +1,5 @@ -/* $OpenBSD: key.h,v 1.6 2003/06/02 20:18:40 millert Exp $ */ -/* $NetBSD: key.h,v 1.2 1997/01/11 06:47:59 lukem Exp $ */ +/* $OpenBSD: key.h,v 1.7 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: key.h,v 1.8 2003/08/07 16:44:32 agc Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -39,37 +39,42 @@ * el.key.h: Key macro header */ #ifndef _h_el_key -#define _h_el_key +#define _h_el_key typedef union key_value_t { - el_action_t cmd; /* If it is a command the # */ - char *str; /* If it is a string... */ + el_action_t cmd; /* If it is a command the # */ + char *str; /* If it is a string... */ } key_value_t; typedef struct key_node_t key_node_t; typedef struct el_key_t { - char *buf; /* Key print buffer */ - key_node_t *map; /* Key map */ - key_value_t val; /* Local conversion buffer */ + char *buf; /* Key print buffer */ + key_node_t *map; /* Key map */ + key_value_t val; /* Local conversion buffer */ } el_key_t; -#define XK_CMD 0 -#define XK_STR 1 -#define XK_NOD 2 -#define XK_EXE 3 +#define XK_CMD 0 +#define XK_STR 1 +#define XK_NOD 2 +#define XK_EXE 3 -protected int key_init(EditLine *); -protected void key_end(EditLine *); -protected key_value_t * key_map_cmd(EditLine *, int); -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 *, 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 *); +#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); +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 *, 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 b56b4adaebf..a9a1b607139 100644 --- a/lib/libedit/makelist +++ b/lib/libedit/makelist @@ -1,6 +1,6 @@ #!/bin/sh - -# $OpenBSD: makelist,v 1.5 2003/06/02 20:18:40 millert Exp $ -# $NetBSD: makelist,v 1.3 1997/01/11 06:48:00 lukem Exp $ +# $OpenBSD: makelist,v 1.6 2003/10/31 08:42:24 otto Exp $ +# $NetBSD: makelist,v 1.8 2003/03/10 21:21:10 christos Exp $ # # Copyright (c) 1992, 1993 # The Regents of the University of California. All rights reserved. @@ -16,7 +16,11 @@ # 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. Neither the name of the University nor the names of its contributors +# 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. # @@ -36,8 +40,8 @@ # makelist.sh: Automatically generate header files... -AWK=/usr/bin/awk -USAGE="Usage: $0 -h|-e|-fc|-fh|-bc|-bh <filenames>" +AWK=awk +USAGE="Usage: $0 -h|-e|-fc|-fh|-bc|-bh|-m <filenames>" if [ "x$1" = "x" ] then @@ -51,6 +55,9 @@ shift FILES="$@" case $FLAG in + +# generate foo.h file from foo.c +# -h) set - `echo $FILES | sed -e 's/\\./_/g'` hdr="_h_`basename $1`" @@ -63,18 +70,26 @@ case $FLAG in pr = substr($2, 1, 2); if (pr == "vi" || pr == "em" || pr == "ed") { name = substr($2, 1, length($2) - 3); - printf("protected el_action_t\t%-25.25s(EditLine *, int);\n", name); +# +# XXX: need a space between name and prototype so that -fc and -fh +# parsing is much easier +# + printf("protected el_action_t\t%s (EditLine *, int);\n", name); } } END { printf("#endif /* %s */\n", "'$hdr'"); - }';; + }' + ;; + +# generate help.c from various .c files +# -bc) cat $FILES | $AWK ' BEGIN { printf("/* Automatically generated file, do not edit */\n"); printf("#include \"sys.h\"\n#include \"el.h\"\n"); - printf("private struct el_bindings_t el_func_help[] = {\n"); + printf("private const struct el_bindings_t el_func_help[] = {\n"); low = "abcdefghijklmnopqrstuvwxyz_"; high = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_"; for (i = 1; i <= length(low); i++) @@ -93,9 +108,9 @@ case $FLAG in s = "-"; fname = fname s; } - + printf(" { %-30.30s %-30.30s\n","\"" fname "\",", uname ","); - ok = 1; + ok = 1; } } /^ \*/ { @@ -110,41 +125,53 @@ case $FLAG in END { printf(" { NULL, 0, NULL }\n"); printf("};\n"); - printf("\nprotected el_bindings_t* help__get()"); + printf("\nprotected const el_bindings_t* help__get()"); printf("{ return el_func_help; }\n"); - }';; + }' + ;; + +# generate help.h from various .c files +# -bh) $AWK ' - BEGIN { + BEGIN { printf("/* Automatically generated file, do not edit */\n"); printf("#ifndef _h_help_c\n#define _h_help_c\n"); - printf("protected el_bindings_t *help__get\t(void);\n"); + printf("protected const el_bindings_t *help__get(void);\n"); printf("#endif /* _h_help_c */\n"); - }' /dev/null;; + }' /dev/null + ;; + +# generate fcns.h from various .h files +# -fh) cat $FILES | $AWK '/el_action_t/ { print $3 }' | \ sort | tr '[a-z]' '[A-Z]' | $AWK ' - BEGIN { + BEGIN { printf("/* Automatically generated file, do not edit */\n"); printf("#ifndef _h_fcns_c\n#define _h_fcns_c\n"); - count = 0; + count = 0; } - { + { printf("#define\t%-30.30s\t%3d\n", $1, count++); } END { printf("#define\t%-30.30s\t%3d\n", "EL_NUM_FCNS", count); printf("typedef el_action_t (*el_func_t)(EditLine *, int);"); - printf("\nprotected el_func_t* func__get(void);\n"); + printf("\nprotected const el_func_t* func__get(void);\n"); printf("#endif /* _h_fcns_c */\n"); - }';; + }' + ;; + +# generate fcns.c from various .h files +# -fc) cat $FILES | $AWK '/el_action_t/ { print $3 }' | sort | $AWK ' BEGIN { printf("/* Automatically generated file, do not edit */\n"); printf("#include \"sys.h\"\n#include \"el.h\"\n"); - printf("private el_func_t el_func[] = {"); + printf("private const el_func_t el_func[] = {"); maxlen = 80; needn = 1; len = 0; @@ -152,7 +179,7 @@ case $FLAG in { clen = 25 + 2; len += clen; - if (len >= maxlen) + if (len >= maxlen) needn = 1; if (needn) { printf("\n "); @@ -164,8 +191,12 @@ case $FLAG in } END { printf("\n};\n"); - printf("\nprotected el_func_t* func__get() { return el_func; }\n"); - }';; + printf("\nprotected const el_func_t* func__get() { return el_func; }\n"); + }' + ;; + +# generate editline.c from various .c files +# -e) echo "$FILES" | tr ' ' '\012' | $AWK ' BEGIN { @@ -175,8 +206,50 @@ case $FLAG in } { printf("#include \"%s\"\n", $1); - }';; + }' + ;; + +# generate man page fragment from various .c files +# +-m) + cat $FILES | $AWK ' + BEGIN { + printf(".\\\" Section automatically generated with makelist\n"); + printf(".Bl -tag -width 4n\n"); + } + /\(\):/ { + pr = substr($2, 1, 2); + if (pr == "vi" || pr == "em" || pr == "ed") { + name = substr($2, 1, length($2) - 3); + fname = ""; + for (i = 1; i <= length(name); i++) { + s = substr(name, i, 1); + if (s == "_") + s = "-"; + fname = fname s; + } + + printf(".It Ic %s\n", fname); + ok = 1; + } + } + /^ \*/ { + if (ok) { + for (i = 2; i < NF; i++) + printf("%s ", $i); + printf("%s.\n", $i); + ok = 0; + } + } + END { + printf(".El\n"); + printf(".\\\" End of section automatically generated with makelist\n"); + }' + ;; + *) echo $USAGE 1>&2 - exit 1;; + exit 1 + ;; + esac diff --git a/lib/libedit/map.c b/lib/libedit/map.c index a7c4e5939da..0e5d50f0639 100644 --- a/lib/libedit/map.c +++ b/lib/libedit/map.c @@ -1,5 +1,5 @@ -/* $OpenBSD: map.c,v 1.8 2003/06/02 20:18:40 millert Exp $ */ -/* $NetBSD: map.c,v 1.3 1997/01/11 06:48:00 lukem Exp $ */ +/* $OpenBSD: map.c,v 1.9 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: map.c,v 1.19 2003/08/07 16:44:32 agc Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -33,848 +33,857 @@ * SUCH DAMAGE. */ +#include "config.h" #if !defined(lint) && !defined(SCCSID) #if 0 static char sccsid[] = "@(#)map.c 8.1 (Berkeley) 6/4/93"; #else -static const char rcsid[] = "$OpenBSD: map.c,v 1.8 2003/06/02 20:18:40 millert Exp $"; +static const char rcsid[] = "$OpenBSD: map.c,v 1.9 2003/10/31 08:42:24 otto Exp $"; #endif #endif /* not lint && not SCCSID */ /* - * map.c: Editor function definitions + * map.c: Editor function definitions */ -#include "sys.h" #include <stdlib.h> #include "el.h" -#define N_KEYS 256 +#define N_KEYS 256 -private void map_print_key(EditLine *, el_action_t *, 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 *); -private void map_init_meta(EditLine *); +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 *); +private void map_init_meta(EditLine *); /* keymap tables ; should be N_KEYS*sizeof(KEYCMD) bytes long */ -private el_action_t el_map_emacs[] = { - /* 0 */ EM_SET_MARK, /* ^@ */ - /* 1 */ ED_MOVE_TO_BEG, /* ^A */ - /* 2 */ ED_PREV_CHAR, /* ^B */ - /* 3 */ ED_TTY_SIGINT, /* ^C */ - /* 4 */ EM_DELETE_OR_LIST, /* ^D */ - /* 5 */ ED_MOVE_TO_END, /* ^E */ - /* 6 */ ED_NEXT_CHAR, /* ^F */ - /* 7 */ ED_UNASSIGNED, /* ^G */ - /* 8 */ ED_DELETE_PREV_CHAR, /* ^H */ - /* 9 */ ED_UNASSIGNED, /* ^I */ - /* 10 */ ED_NEWLINE, /* ^J */ - /* 11 */ ED_KILL_LINE, /* ^K */ - /* 12 */ ED_CLEAR_SCREEN, /* ^L */ - /* 13 */ ED_NEWLINE, /* ^M */ - /* 14 */ ED_NEXT_HISTORY, /* ^N */ - /* 15 */ ED_TTY_FLUSH_OUTPUT, /* ^O */ - /* 16 */ ED_PREV_HISTORY, /* ^P */ - /* 17 */ ED_TTY_START_OUTPUT, /* ^Q */ - /* 18 */ ED_REDISPLAY, /* ^R */ - /* 19 */ ED_TTY_STOP_OUTPUT, /* ^S */ - /* 20 */ ED_TRANSPOSE_CHARS, /* ^T */ - /* 21 */ EM_KILL_LINE, /* ^U */ - /* 22 */ ED_QUOTED_INSERT, /* ^V */ - /* 23 */ EM_KILL_REGION, /* ^W */ - /* 24 */ ED_SEQUENCE_LEAD_IN, /* ^X */ - /* 25 */ EM_YANK, /* ^Y */ - /* 26 */ ED_TTY_SIGTSTP, /* ^Z */ - /* 27 */ EM_META_NEXT, /* ^[ */ - /* 28 */ ED_TTY_SIGQUIT, /* ^\ */ - /* 29 */ ED_TTY_DSUSP, /* ^] */ - /* 30 */ ED_UNASSIGNED, /* ^^ */ - /* 31 */ ED_UNASSIGNED, /* ^_ */ - /* 32 */ ED_INSERT, /* SPACE */ - /* 33 */ ED_INSERT, /* ! */ - /* 34 */ ED_INSERT, /* " */ - /* 35 */ ED_INSERT, /* # */ - /* 36 */ ED_INSERT, /* $ */ - /* 37 */ ED_INSERT, /* % */ - /* 38 */ ED_INSERT, /* & */ - /* 39 */ ED_INSERT, /* ' */ - /* 40 */ ED_INSERT, /* ( */ - /* 41 */ ED_INSERT, /* ) */ - /* 42 */ ED_INSERT, /* * */ - /* 43 */ ED_INSERT, /* + */ - /* 44 */ ED_INSERT, /* , */ - /* 45 */ ED_INSERT, /* - */ - /* 46 */ ED_INSERT, /* . */ - /* 47 */ ED_INSERT, /* / */ - /* 48 */ ED_DIGIT, /* 0 */ - /* 49 */ ED_DIGIT, /* 1 */ - /* 50 */ ED_DIGIT, /* 2 */ - /* 51 */ ED_DIGIT, /* 3 */ - /* 52 */ ED_DIGIT, /* 4 */ - /* 53 */ ED_DIGIT, /* 5 */ - /* 54 */ ED_DIGIT, /* 6 */ - /* 55 */ ED_DIGIT, /* 7 */ - /* 56 */ ED_DIGIT, /* 8 */ - /* 57 */ ED_DIGIT, /* 9 */ - /* 58 */ ED_INSERT, /* : */ - /* 59 */ ED_INSERT, /* ; */ - /* 60 */ ED_INSERT, /* < */ - /* 61 */ ED_INSERT, /* = */ - /* 62 */ ED_INSERT, /* > */ - /* 63 */ ED_INSERT, /* ? */ - /* 64 */ ED_INSERT, /* @ */ - /* 65 */ ED_INSERT, /* A */ - /* 66 */ ED_INSERT, /* B */ - /* 67 */ ED_INSERT, /* C */ - /* 68 */ ED_INSERT, /* D */ - /* 69 */ ED_INSERT, /* E */ - /* 70 */ ED_INSERT, /* F */ - /* 71 */ ED_INSERT, /* G */ - /* 72 */ ED_INSERT, /* H */ - /* 73 */ ED_INSERT, /* I */ - /* 74 */ ED_INSERT, /* J */ - /* 75 */ ED_INSERT, /* K */ - /* 76 */ ED_INSERT, /* L */ - /* 77 */ ED_INSERT, /* M */ - /* 78 */ ED_INSERT, /* N */ - /* 79 */ ED_INSERT, /* O */ - /* 80 */ ED_INSERT, /* P */ - /* 81 */ ED_INSERT, /* Q */ - /* 82 */ ED_INSERT, /* R */ - /* 83 */ ED_INSERT, /* S */ - /* 84 */ ED_INSERT, /* T */ - /* 85 */ ED_INSERT, /* U */ - /* 86 */ ED_INSERT, /* V */ - /* 87 */ ED_INSERT, /* W */ - /* 88 */ ED_INSERT, /* X */ - /* 89 */ ED_INSERT, /* Y */ - /* 90 */ ED_INSERT, /* Z */ - /* 91 */ ED_INSERT, /* [ */ - /* 92 */ ED_INSERT, /* \ */ - /* 93 */ ED_INSERT, /* ] */ - /* 94 */ ED_INSERT, /* ^ */ - /* 95 */ ED_INSERT, /* _ */ - /* 96 */ ED_INSERT, /* ` */ - /* 97 */ ED_INSERT, /* a */ - /* 98 */ ED_INSERT, /* b */ - /* 99 */ ED_INSERT, /* c */ - /* 100 */ ED_INSERT, /* d */ - /* 101 */ ED_INSERT, /* e */ - /* 102 */ ED_INSERT, /* f */ - /* 103 */ ED_INSERT, /* g */ - /* 104 */ ED_INSERT, /* h */ - /* 105 */ ED_INSERT, /* i */ - /* 106 */ ED_INSERT, /* j */ - /* 107 */ ED_INSERT, /* k */ - /* 108 */ ED_INSERT, /* l */ - /* 109 */ ED_INSERT, /* m */ - /* 110 */ ED_INSERT, /* n */ - /* 111 */ ED_INSERT, /* o */ - /* 112 */ ED_INSERT, /* p */ - /* 113 */ ED_INSERT, /* q */ - /* 114 */ ED_INSERT, /* r */ - /* 115 */ ED_INSERT, /* s */ - /* 116 */ ED_INSERT, /* t */ - /* 117 */ ED_INSERT, /* u */ - /* 118 */ ED_INSERT, /* v */ - /* 119 */ ED_INSERT, /* w */ - /* 120 */ ED_INSERT, /* x */ - /* 121 */ ED_INSERT, /* y */ - /* 122 */ ED_INSERT, /* z */ - /* 123 */ ED_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_DELETE_PREV_WORD, /* M-^H */ - /* 137 */ ED_UNASSIGNED, /* M-^I */ - /* 138 */ ED_UNASSIGNED, /* M-^J */ - /* 139 */ ED_UNASSIGNED, /* M-^K */ - /* 140 */ ED_CLEAR_SCREEN, /* 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 */ EM_COPY_PREV_WORD, /* 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_ARGUMENT_DIGIT, /* M-0 */ - /* 177 */ ED_ARGUMENT_DIGIT, /* M-1 */ - /* 178 */ ED_ARGUMENT_DIGIT, /* M-2 */ - /* 179 */ ED_ARGUMENT_DIGIT, /* M-3 */ - /* 180 */ ED_ARGUMENT_DIGIT, /* M-4 */ - /* 181 */ ED_ARGUMENT_DIGIT, /* M-5 */ - /* 182 */ ED_ARGUMENT_DIGIT, /* M-6 */ - /* 183 */ ED_ARGUMENT_DIGIT, /* M-7 */ - /* 184 */ ED_ARGUMENT_DIGIT, /* M-8 */ - /* 185 */ ED_ARGUMENT_DIGIT, /* 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_PREV_WORD, /* M-B */ - /* 195 */ EM_CAPITOL_CASE, /* M-C */ - /* 196 */ EM_DELETE_NEXT_WORD, /* M-D */ - /* 197 */ ED_UNASSIGNED, /* M-E */ - /* 198 */ EM_NEXT_WORD, /* 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 */ EM_LOWER_CASE, /* M-L */ - /* 205 */ ED_UNASSIGNED, /* M-M */ - /* 206 */ ED_SEARCH_NEXT_HISTORY, /* M-N */ - /* 207 */ ED_SEQUENCE_LEAD_IN, /* M-O */ - /* 208 */ ED_SEARCH_PREV_HISTORY, /* M-P */ - /* 209 */ ED_UNASSIGNED, /* M-Q */ - /* 210 */ ED_UNASSIGNED, /* M-R */ - /* 211 */ ED_UNASSIGNED, /* M-S */ - /* 212 */ ED_UNASSIGNED, /* M-T */ - /* 213 */ EM_UPPER_CASE, /* M-U */ - /* 214 */ ED_UNASSIGNED, /* M-V */ - /* 215 */ EM_COPY_REGION, /* M-W */ - /* 216 */ ED_COMMAND, /* M-X */ - /* 217 */ ED_UNASSIGNED, /* M-Y */ - /* 218 */ ED_UNASSIGNED, /* M-Z */ - /* 219 */ ED_SEQUENCE_LEAD_IN, /* M-[ */ - /* 220 */ ED_UNASSIGNED, /* M-\ */ - /* 221 */ ED_UNASSIGNED, /* M-] */ - /* 222 */ ED_UNASSIGNED, /* M-^ */ - /* 223 */ ED_UNASSIGNED, /* M-_ */ - /* 223 */ ED_UNASSIGNED, /* M-` */ - /* 224 */ ED_UNASSIGNED, /* M-a */ - /* 225 */ ED_PREV_WORD, /* M-b */ - /* 226 */ EM_CAPITOL_CASE, /* M-c */ - /* 227 */ EM_DELETE_NEXT_WORD, /* M-d */ - /* 228 */ ED_UNASSIGNED, /* M-e */ - /* 229 */ EM_NEXT_WORD, /* M-f */ - /* 230 */ ED_UNASSIGNED, /* M-g */ - /* 231 */ ED_UNASSIGNED, /* M-h */ - /* 232 */ ED_UNASSIGNED, /* M-i */ - /* 233 */ ED_UNASSIGNED, /* M-j */ - /* 234 */ ED_UNASSIGNED, /* M-k */ - /* 235 */ EM_LOWER_CASE, /* M-l */ - /* 236 */ ED_UNASSIGNED, /* M-m */ - /* 237 */ ED_SEARCH_NEXT_HISTORY, /* M-n */ - /* 238 */ ED_UNASSIGNED, /* M-o */ - /* 239 */ ED_SEARCH_PREV_HISTORY, /* M-p */ - /* 240 */ ED_UNASSIGNED, /* M-q */ - /* 241 */ ED_UNASSIGNED, /* M-r */ - /* 242 */ ED_UNASSIGNED, /* M-s */ - /* 243 */ ED_UNASSIGNED, /* M-t */ - /* 244 */ EM_UPPER_CASE, /* M-u */ - /* 245 */ ED_UNASSIGNED, /* M-v */ - /* 246 */ EM_COPY_REGION, /* M-w */ - /* 247 */ ED_COMMAND, /* M-x */ - /* 248 */ ED_UNASSIGNED, /* M-y */ - /* 249 */ ED_UNASSIGNED, /* M-z */ - /* 250 */ ED_UNASSIGNED, /* M-{ */ - /* 251 */ ED_UNASSIGNED, /* M-| */ - /* 252 */ ED_UNASSIGNED, /* M-} */ - /* 253 */ ED_UNASSIGNED, /* M-~ */ - /* 254 */ ED_DELETE_PREV_WORD /* M-^? */ - /* 255 */ + +private const el_action_t el_map_emacs[] = { + /* 0 */ EM_SET_MARK, /* ^@ */ + /* 1 */ ED_MOVE_TO_BEG, /* ^A */ + /* 2 */ ED_PREV_CHAR, /* ^B */ + /* 3 */ ED_TTY_SIGINT, /* ^C */ + /* 4 */ EM_DELETE_OR_LIST, /* ^D */ + /* 5 */ ED_MOVE_TO_END, /* ^E */ + /* 6 */ ED_NEXT_CHAR, /* ^F */ + /* 7 */ ED_UNASSIGNED, /* ^G */ + /* 8 */ ED_DELETE_PREV_CHAR, /* ^H */ + /* 9 */ ED_UNASSIGNED, /* ^I */ + /* 10 */ ED_NEWLINE, /* ^J */ + /* 11 */ ED_KILL_LINE, /* ^K */ + /* 12 */ ED_CLEAR_SCREEN, /* ^L */ + /* 13 */ ED_NEWLINE, /* ^M */ + /* 14 */ ED_NEXT_HISTORY, /* ^N */ + /* 15 */ ED_TTY_FLUSH_OUTPUT, /* ^O */ + /* 16 */ ED_PREV_HISTORY, /* ^P */ + /* 17 */ ED_TTY_START_OUTPUT, /* ^Q */ + /* 18 */ ED_REDISPLAY, /* ^R */ + /* 19 */ ED_TTY_STOP_OUTPUT, /* ^S */ + /* 20 */ ED_TRANSPOSE_CHARS, /* ^T */ + /* 21 */ EM_KILL_LINE, /* ^U */ + /* 22 */ ED_QUOTED_INSERT, /* ^V */ + /* 23 */ EM_KILL_REGION, /* ^W */ + /* 24 */ ED_SEQUENCE_LEAD_IN, /* ^X */ + /* 25 */ EM_YANK, /* ^Y */ + /* 26 */ ED_TTY_SIGTSTP, /* ^Z */ + /* 27 */ EM_META_NEXT, /* ^[ */ + /* 28 */ ED_TTY_SIGQUIT, /* ^\ */ + /* 29 */ ED_TTY_DSUSP, /* ^] */ + /* 30 */ ED_UNASSIGNED, /* ^^ */ + /* 31 */ ED_UNASSIGNED, /* ^_ */ + /* 32 */ ED_INSERT, /* SPACE */ + /* 33 */ ED_INSERT, /* ! */ + /* 34 */ ED_INSERT, /* " */ + /* 35 */ ED_INSERT, /* # */ + /* 36 */ ED_INSERT, /* $ */ + /* 37 */ ED_INSERT, /* % */ + /* 38 */ ED_INSERT, /* & */ + /* 39 */ ED_INSERT, /* ' */ + /* 40 */ ED_INSERT, /* ( */ + /* 41 */ ED_INSERT, /* ) */ + /* 42 */ ED_INSERT, /* * */ + /* 43 */ ED_INSERT, /* + */ + /* 44 */ ED_INSERT, /* , */ + /* 45 */ ED_INSERT, /* - */ + /* 46 */ ED_INSERT, /* . */ + /* 47 */ ED_INSERT, /* / */ + /* 48 */ ED_DIGIT, /* 0 */ + /* 49 */ ED_DIGIT, /* 1 */ + /* 50 */ ED_DIGIT, /* 2 */ + /* 51 */ ED_DIGIT, /* 3 */ + /* 52 */ ED_DIGIT, /* 4 */ + /* 53 */ ED_DIGIT, /* 5 */ + /* 54 */ ED_DIGIT, /* 6 */ + /* 55 */ ED_DIGIT, /* 7 */ + /* 56 */ ED_DIGIT, /* 8 */ + /* 57 */ ED_DIGIT, /* 9 */ + /* 58 */ ED_INSERT, /* : */ + /* 59 */ ED_INSERT, /* ; */ + /* 60 */ ED_INSERT, /* < */ + /* 61 */ ED_INSERT, /* = */ + /* 62 */ ED_INSERT, /* > */ + /* 63 */ ED_INSERT, /* ? */ + /* 64 */ ED_INSERT, /* @ */ + /* 65 */ ED_INSERT, /* A */ + /* 66 */ ED_INSERT, /* B */ + /* 67 */ ED_INSERT, /* C */ + /* 68 */ ED_INSERT, /* D */ + /* 69 */ ED_INSERT, /* E */ + /* 70 */ ED_INSERT, /* F */ + /* 71 */ ED_INSERT, /* G */ + /* 72 */ ED_INSERT, /* H */ + /* 73 */ ED_INSERT, /* I */ + /* 74 */ ED_INSERT, /* J */ + /* 75 */ ED_INSERT, /* K */ + /* 76 */ ED_INSERT, /* L */ + /* 77 */ ED_INSERT, /* M */ + /* 78 */ ED_INSERT, /* N */ + /* 79 */ ED_INSERT, /* O */ + /* 80 */ ED_INSERT, /* P */ + /* 81 */ ED_INSERT, /* Q */ + /* 82 */ ED_INSERT, /* R */ + /* 83 */ ED_INSERT, /* S */ + /* 84 */ ED_INSERT, /* T */ + /* 85 */ ED_INSERT, /* U */ + /* 86 */ ED_INSERT, /* V */ + /* 87 */ ED_INSERT, /* W */ + /* 88 */ ED_INSERT, /* X */ + /* 89 */ ED_INSERT, /* Y */ + /* 90 */ ED_INSERT, /* Z */ + /* 91 */ ED_INSERT, /* [ */ + /* 92 */ ED_INSERT, /* \ */ + /* 93 */ ED_INSERT, /* ] */ + /* 94 */ ED_INSERT, /* ^ */ + /* 95 */ ED_INSERT, /* _ */ + /* 96 */ ED_INSERT, /* ` */ + /* 97 */ ED_INSERT, /* a */ + /* 98 */ ED_INSERT, /* b */ + /* 99 */ ED_INSERT, /* c */ + /* 100 */ ED_INSERT, /* d */ + /* 101 */ ED_INSERT, /* e */ + /* 102 */ ED_INSERT, /* f */ + /* 103 */ ED_INSERT, /* g */ + /* 104 */ ED_INSERT, /* h */ + /* 105 */ ED_INSERT, /* i */ + /* 106 */ ED_INSERT, /* j */ + /* 107 */ ED_INSERT, /* k */ + /* 108 */ ED_INSERT, /* l */ + /* 109 */ ED_INSERT, /* m */ + /* 110 */ ED_INSERT, /* n */ + /* 111 */ ED_INSERT, /* o */ + /* 112 */ ED_INSERT, /* p */ + /* 113 */ ED_INSERT, /* q */ + /* 114 */ ED_INSERT, /* r */ + /* 115 */ ED_INSERT, /* s */ + /* 116 */ ED_INSERT, /* t */ + /* 117 */ ED_INSERT, /* u */ + /* 118 */ ED_INSERT, /* v */ + /* 119 */ ED_INSERT, /* w */ + /* 120 */ ED_INSERT, /* x */ + /* 121 */ ED_INSERT, /* y */ + /* 122 */ ED_INSERT, /* z */ + /* 123 */ ED_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_DELETE_PREV_WORD, /* M-^H */ + /* 137 */ ED_UNASSIGNED, /* M-^I */ + /* 138 */ ED_UNASSIGNED, /* M-^J */ + /* 139 */ ED_UNASSIGNED, /* M-^K */ + /* 140 */ ED_CLEAR_SCREEN, /* 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 */ EM_COPY_PREV_WORD, /* 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_ARGUMENT_DIGIT, /* M-0 */ + /* 177 */ ED_ARGUMENT_DIGIT, /* M-1 */ + /* 178 */ ED_ARGUMENT_DIGIT, /* M-2 */ + /* 179 */ ED_ARGUMENT_DIGIT, /* M-3 */ + /* 180 */ ED_ARGUMENT_DIGIT, /* M-4 */ + /* 181 */ ED_ARGUMENT_DIGIT, /* M-5 */ + /* 182 */ ED_ARGUMENT_DIGIT, /* M-6 */ + /* 183 */ ED_ARGUMENT_DIGIT, /* M-7 */ + /* 184 */ ED_ARGUMENT_DIGIT, /* M-8 */ + /* 185 */ ED_ARGUMENT_DIGIT, /* 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_PREV_WORD, /* M-B */ + /* 195 */ EM_CAPITOL_CASE, /* M-C */ + /* 196 */ EM_DELETE_NEXT_WORD, /* M-D */ + /* 197 */ ED_UNASSIGNED, /* M-E */ + /* 198 */ EM_NEXT_WORD, /* 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 */ EM_LOWER_CASE, /* M-L */ + /* 205 */ ED_UNASSIGNED, /* M-M */ + /* 206 */ ED_SEARCH_NEXT_HISTORY, /* M-N */ + /* 207 */ ED_SEQUENCE_LEAD_IN, /* M-O */ + /* 208 */ ED_SEARCH_PREV_HISTORY, /* M-P */ + /* 209 */ ED_UNASSIGNED, /* M-Q */ + /* 210 */ ED_UNASSIGNED, /* M-R */ + /* 211 */ ED_UNASSIGNED, /* M-S */ + /* 212 */ ED_UNASSIGNED, /* M-T */ + /* 213 */ EM_UPPER_CASE, /* M-U */ + /* 214 */ ED_UNASSIGNED, /* M-V */ + /* 215 */ EM_COPY_REGION, /* M-W */ + /* 216 */ ED_COMMAND, /* M-X */ + /* 217 */ ED_UNASSIGNED, /* M-Y */ + /* 218 */ ED_UNASSIGNED, /* M-Z */ + /* 219 */ ED_SEQUENCE_LEAD_IN, /* M-[ */ + /* 220 */ ED_UNASSIGNED, /* M-\ */ + /* 221 */ ED_UNASSIGNED, /* M-] */ + /* 222 */ ED_UNASSIGNED, /* M-^ */ + /* 223 */ ED_UNASSIGNED, /* M-_ */ + + /* 224 */ ED_UNASSIGNED, /* M-a */ + /* 225 */ ED_PREV_WORD, /* M-b */ + /* 226 */ EM_CAPITOL_CASE, /* M-c */ + /* 227 */ EM_DELETE_NEXT_WORD, /* M-d */ + /* 228 */ ED_UNASSIGNED, /* M-e */ + /* 229 */ EM_NEXT_WORD, /* M-f */ + /* 230 */ ED_UNASSIGNED, /* M-g */ + /* 231 */ ED_UNASSIGNED, /* M-h */ + /* 232 */ ED_UNASSIGNED, /* M-i */ + /* 233 */ ED_UNASSIGNED, /* M-j */ + /* 234 */ ED_UNASSIGNED, /* M-k */ + /* 235 */ EM_LOWER_CASE, /* M-l */ + /* 236 */ ED_UNASSIGNED, /* M-m */ + /* 237 */ ED_SEARCH_NEXT_HISTORY, /* M-n */ + /* 238 */ ED_UNASSIGNED, /* M-o */ + /* 239 */ ED_SEARCH_PREV_HISTORY, /* M-p */ + /* 240 */ ED_UNASSIGNED, /* M-q */ + /* 241 */ ED_UNASSIGNED, /* M-r */ + /* 242 */ ED_UNASSIGNED, /* M-s */ + /* 243 */ ED_UNASSIGNED, /* M-t */ + /* 244 */ EM_UPPER_CASE, /* M-u */ + /* 245 */ ED_UNASSIGNED, /* M-v */ + /* 246 */ EM_COPY_REGION, /* M-w */ + /* 247 */ ED_COMMAND, /* M-x */ + /* 248 */ ED_UNASSIGNED, /* M-y */ + /* 249 */ ED_UNASSIGNED, /* M-z */ + /* 250 */ ED_UNASSIGNED, /* M-{ */ + /* 251 */ ED_UNASSIGNED, /* M-| */ + /* 252 */ ED_UNASSIGNED, /* M-} */ + /* 253 */ ED_UNASSIGNED, /* M-~ */ + /* 254 */ ED_DELETE_PREV_WORD /* M-^? */ + /* 255 */ }; + /* * keymap table for vi. Each index into above tbl; should be * N_KEYS entries long. Vi mode uses a sticky-extend to do command mode: * insert mode characters are in the normal keymap, and command mode * in the extended keymap. */ -private el_action_t el_map_vi_insert[] = { +private const el_action_t el_map_vi_insert[] = { #ifdef KSHVI - /* 0 */ ED_UNASSIGNED, /* ^@ */ - /* 1 */ ED_INSERT, /* ^A */ - /* 2 */ ED_INSERT, /* ^B */ - /* 3 */ ED_INSERT, /* ^C */ - /* 4 */ VI_LIST_OR_EOF, /* ^D */ - /* 5 */ ED_INSERT, /* ^E */ - /* 6 */ ED_INSERT, /* ^F */ - /* 7 */ ED_INSERT, /* ^G */ - /* 8 */ VI_DELETE_PREV_CHAR, /* ^H */ /* BackSpace key */ - /* 9 */ ED_INSERT, /* ^I */ /* Tab Key */ - /* 10 */ ED_NEWLINE, /* ^J */ - /* 11 */ ED_INSERT, /* ^K */ - /* 12 */ ED_INSERT, /* ^L */ - /* 13 */ ED_NEWLINE, /* ^M */ - /* 14 */ ED_INSERT, /* ^N */ - /* 15 */ ED_INSERT, /* ^O */ - /* 16 */ ED_INSERT, /* ^P */ - /* 17 */ ED_TTY_START_OUTPUT, /* ^Q */ - /* 18 */ ED_INSERT, /* ^R */ - /* 19 */ ED_TTY_STOP_OUTPUT, /* ^S */ - /* 20 */ ED_INSERT, /* ^T */ - /* 21 */ VI_KILL_LINE_PREV, /* ^U */ - /* 22 */ ED_QUOTED_INSERT, /* ^V */ - /* 23 */ ED_DELETE_PREV_WORD, /* ^W */ /* Only until strt edit pos */ - /* 24 */ ED_INSERT, /* ^X */ - /* 25 */ ED_INSERT, /* ^Y */ - /* 26 */ ED_INSERT, /* ^Z */ - /* 27 */ VI_COMMAND_MODE, /* ^[ */ /* [ Esc ] key */ - /* 28 */ ED_TTY_SIGQUIT, /* ^\ */ - /* 29 */ ED_INSERT, /* ^] */ - /* 30 */ ED_INSERT, /* ^^ */ - /* 31 */ ED_INSERT, /* ^_ */ + /* 0 */ ED_UNASSIGNED, /* ^@ */ + /* 1 */ ED_INSERT, /* ^A */ + /* 2 */ ED_INSERT, /* ^B */ + /* 3 */ ED_INSERT, /* ^C */ + /* 4 */ VI_LIST_OR_EOF, /* ^D */ + /* 5 */ ED_INSERT, /* ^E */ + /* 6 */ ED_INSERT, /* ^F */ + /* 7 */ ED_INSERT, /* ^G */ + /* 8 */ VI_DELETE_PREV_CHAR, /* ^H */ /* BackSpace key */ + /* 9 */ ED_INSERT, /* ^I */ /* Tab Key */ + /* 10 */ ED_NEWLINE, /* ^J */ + /* 11 */ ED_INSERT, /* ^K */ + /* 12 */ ED_INSERT, /* ^L */ + /* 13 */ ED_NEWLINE, /* ^M */ + /* 14 */ ED_INSERT, /* ^N */ + /* 15 */ ED_INSERT, /* ^O */ + /* 16 */ ED_INSERT, /* ^P */ + /* 17 */ ED_TTY_START_OUTPUT, /* ^Q */ + /* 18 */ ED_INSERT, /* ^R */ + /* 19 */ ED_TTY_STOP_OUTPUT, /* ^S */ + /* 20 */ ED_INSERT, /* ^T */ + /* 21 */ VI_KILL_LINE_PREV, /* ^U */ + /* 22 */ ED_QUOTED_INSERT, /* ^V */ + /* 23 */ ED_DELETE_PREV_WORD, /* ^W */ + /* ED_DELETE_PREV_WORD: Only until strt edit pos */ + /* 24 */ ED_INSERT, /* ^X */ + /* 25 */ ED_INSERT, /* ^Y */ + /* 26 */ ED_INSERT, /* ^Z */ + /* 27 */ VI_COMMAND_MODE, /* ^[ */ /* [ Esc ] key */ + /* 28 */ ED_TTY_SIGQUIT, /* ^\ */ + /* 29 */ ED_INSERT, /* ^] */ + /* 30 */ ED_INSERT, /* ^^ */ + /* 31 */ ED_INSERT, /* ^_ */ #else /* !KSHVI */ - /* 0 */ ED_UNASSIGNED, /* ^@ */ /* NOTE: These mappings do */ - /* 1 */ ED_MOVE_TO_BEG, /* ^A */ /* NOT Correspond well to */ - /* 2 */ ED_PREV_CHAR, /* ^B */ /* the KSH VI editing as- */ - /* 3 */ ED_TTY_SIGINT, /* ^C */ /* signments. On the other */ - /* 4 */ VI_LIST_OR_EOF, /* ^D */ /* hand they are convenient*/ - /* 5 */ ED_MOVE_TO_END, /* ^E */ /* and many people have */ - /* 6 */ ED_NEXT_CHAR, /* ^F */ /* have gotten used to them*/ - /* 7 */ ED_UNASSIGNED, /* ^G */ - /* 8 */ ED_DELETE_PREV_CHAR, /* ^H */ /* BackSpace key */ - /* 9 */ ED_UNASSIGNED, /* ^I */ /* Tab Key */ - /* 10 */ ED_NEWLINE, /* ^J */ - /* 11 */ ED_KILL_LINE, /* ^K */ - /* 12 */ ED_CLEAR_SCREEN, /* ^L */ - /* 13 */ ED_NEWLINE, /* ^M */ - /* 14 */ ED_NEXT_HISTORY, /* ^N */ - /* 15 */ ED_TTY_FLUSH_OUTPUT, /* ^O */ - /* 16 */ ED_PREV_HISTORY, /* ^P */ - /* 17 */ ED_TTY_START_OUTPUT, /* ^Q */ - /* 18 */ ED_REDISPLAY, /* ^R */ - /* 19 */ ED_TTY_STOP_OUTPUT, /* ^S */ - /* 20 */ ED_TRANSPOSE_CHARS, /* ^T */ - /* 21 */ VI_KILL_LINE_PREV, /* ^U */ - /* 22 */ ED_QUOTED_INSERT, /* ^V */ - /* 23 */ ED_DELETE_PREV_WORD, /* ^W */ - /* 24 */ ED_UNASSIGNED, /* ^X */ - /* 25 */ ED_TTY_DSUSP, /* ^Y */ - /* 26 */ ED_TTY_SIGTSTP, /* ^Z */ - /* 27 */ VI_COMMAND_MODE, /* ^[ */ - /* 28 */ ED_TTY_SIGQUIT, /* ^\ */ - /* 29 */ ED_UNASSIGNED, /* ^] */ - /* 30 */ ED_UNASSIGNED, /* ^^ */ - /* 31 */ ED_UNASSIGNED, /* ^_ */ + /* + * NOTE: These mappings do NOT Correspond well + * to the KSH VI editing assignments. + * On the other and they are convenient and + * many people have have gotten used to them. + */ + /* 0 */ ED_UNASSIGNED, /* ^@ */ + /* 1 */ ED_MOVE_TO_BEG, /* ^A */ + /* 2 */ ED_PREV_CHAR, /* ^B */ + /* 3 */ ED_TTY_SIGINT, /* ^C */ + /* 4 */ VI_LIST_OR_EOF, /* ^D */ + /* 5 */ ED_MOVE_TO_END, /* ^E */ + /* 6 */ ED_NEXT_CHAR, /* ^F */ + /* 7 */ ED_UNASSIGNED, /* ^G */ + /* 8 */ VI_DELETE_PREV_CHAR, /* ^H */ /* BackSpace key */ + /* 9 */ ED_UNASSIGNED, /* ^I */ /* Tab Key */ + /* 10 */ ED_NEWLINE, /* ^J */ + /* 11 */ ED_KILL_LINE, /* ^K */ + /* 12 */ ED_CLEAR_SCREEN, /* ^L */ + /* 13 */ ED_NEWLINE, /* ^M */ + /* 14 */ ED_NEXT_HISTORY, /* ^N */ + /* 15 */ ED_TTY_FLUSH_OUTPUT, /* ^O */ + /* 16 */ ED_PREV_HISTORY, /* ^P */ + /* 17 */ ED_TTY_START_OUTPUT, /* ^Q */ + /* 18 */ ED_REDISPLAY, /* ^R */ + /* 19 */ ED_TTY_STOP_OUTPUT, /* ^S */ + /* 20 */ ED_TRANSPOSE_CHARS, /* ^T */ + /* 21 */ VI_KILL_LINE_PREV, /* ^U */ + /* 22 */ ED_QUOTED_INSERT, /* ^V */ + /* 23 */ ED_DELETE_PREV_WORD, /* ^W */ + /* 24 */ ED_UNASSIGNED, /* ^X */ + /* 25 */ ED_TTY_DSUSP, /* ^Y */ + /* 26 */ ED_TTY_SIGTSTP, /* ^Z */ + /* 27 */ VI_COMMAND_MODE, /* ^[ */ + /* 28 */ ED_TTY_SIGQUIT, /* ^\ */ + /* 29 */ ED_UNASSIGNED, /* ^] */ + /* 30 */ ED_UNASSIGNED, /* ^^ */ + /* 31 */ ED_UNASSIGNED, /* ^_ */ #endif /* KSHVI */ - /* 32 */ ED_INSERT, /* SPACE */ - /* 33 */ ED_INSERT, /* ! */ - /* 34 */ ED_INSERT, /* " */ - /* 35 */ ED_INSERT, /* # */ - /* 36 */ ED_INSERT, /* $ */ - /* 37 */ ED_INSERT, /* % */ - /* 38 */ ED_INSERT, /* & */ - /* 39 */ ED_INSERT, /* ' */ - /* 40 */ ED_INSERT, /* ( */ - /* 41 */ ED_INSERT, /* ) */ - /* 42 */ ED_INSERT, /* * */ - /* 43 */ ED_INSERT, /* + */ - /* 44 */ ED_INSERT, /* , */ - /* 45 */ ED_INSERT, /* - */ - /* 46 */ ED_INSERT, /* . */ - /* 47 */ ED_INSERT, /* / */ - /* 48 */ ED_INSERT, /* 0 */ - /* 49 */ ED_INSERT, /* 1 */ - /* 50 */ ED_INSERT, /* 2 */ - /* 51 */ ED_INSERT, /* 3 */ - /* 52 */ ED_INSERT, /* 4 */ - /* 53 */ ED_INSERT, /* 5 */ - /* 54 */ ED_INSERT, /* 6 */ - /* 55 */ ED_INSERT, /* 7 */ - /* 56 */ ED_INSERT, /* 8 */ - /* 57 */ ED_INSERT, /* 9 */ - /* 58 */ ED_INSERT, /* : */ - /* 59 */ ED_INSERT, /* ; */ - /* 60 */ ED_INSERT, /* < */ - /* 61 */ ED_INSERT, /* = */ - /* 62 */ ED_INSERT, /* > */ - /* 63 */ ED_INSERT, /* ? */ - /* 64 */ ED_INSERT, /* @ */ - /* 65 */ ED_INSERT, /* A */ - /* 66 */ ED_INSERT, /* B */ - /* 67 */ ED_INSERT, /* C */ - /* 68 */ ED_INSERT, /* D */ - /* 69 */ ED_INSERT, /* E */ - /* 70 */ ED_INSERT, /* F */ - /* 71 */ ED_INSERT, /* G */ - /* 72 */ ED_INSERT, /* H */ - /* 73 */ ED_INSERT, /* I */ - /* 74 */ ED_INSERT, /* J */ - /* 75 */ ED_INSERT, /* K */ - /* 76 */ ED_INSERT, /* L */ - /* 77 */ ED_INSERT, /* M */ - /* 78 */ ED_INSERT, /* N */ - /* 79 */ ED_INSERT, /* O */ - /* 80 */ ED_INSERT, /* P */ - /* 81 */ ED_INSERT, /* Q */ - /* 82 */ ED_INSERT, /* R */ - /* 83 */ ED_INSERT, /* S */ - /* 84 */ ED_INSERT, /* T */ - /* 85 */ ED_INSERT, /* U */ - /* 86 */ ED_INSERT, /* V */ - /* 87 */ ED_INSERT, /* W */ - /* 88 */ ED_INSERT, /* X */ - /* 89 */ ED_INSERT, /* Y */ - /* 90 */ ED_INSERT, /* Z */ - /* 91 */ ED_INSERT, /* [ */ - /* 92 */ ED_INSERT, /* \ */ - /* 93 */ ED_INSERT, /* ] */ - /* 94 */ ED_INSERT, /* ^ */ - /* 95 */ ED_INSERT, /* _ */ - /* 96 */ ED_INSERT, /* ` */ - /* 97 */ ED_INSERT, /* a */ - /* 98 */ ED_INSERT, /* b */ - /* 99 */ ED_INSERT, /* c */ - /* 100 */ ED_INSERT, /* d */ - /* 101 */ ED_INSERT, /* e */ - /* 102 */ ED_INSERT, /* f */ - /* 103 */ ED_INSERT, /* g */ - /* 104 */ ED_INSERT, /* h */ - /* 105 */ ED_INSERT, /* i */ - /* 106 */ ED_INSERT, /* j */ - /* 107 */ ED_INSERT, /* k */ - /* 108 */ ED_INSERT, /* l */ - /* 109 */ ED_INSERT, /* m */ - /* 110 */ ED_INSERT, /* n */ - /* 111 */ ED_INSERT, /* o */ - /* 112 */ ED_INSERT, /* p */ - /* 113 */ ED_INSERT, /* q */ - /* 114 */ ED_INSERT, /* r */ - /* 115 */ ED_INSERT, /* s */ - /* 116 */ ED_INSERT, /* t */ - /* 117 */ ED_INSERT, /* u */ - /* 118 */ ED_INSERT, /* v */ - /* 119 */ ED_INSERT, /* w */ - /* 120 */ ED_INSERT, /* x */ - /* 121 */ ED_INSERT, /* y */ - /* 122 */ ED_INSERT, /* z */ - /* 123 */ ED_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-^? */ + /* 32 */ ED_INSERT, /* SPACE */ + /* 33 */ ED_INSERT, /* ! */ + /* 34 */ ED_INSERT, /* " */ + /* 35 */ ED_INSERT, /* # */ + /* 36 */ ED_INSERT, /* $ */ + /* 37 */ ED_INSERT, /* % */ + /* 38 */ ED_INSERT, /* & */ + /* 39 */ ED_INSERT, /* ' */ + /* 40 */ ED_INSERT, /* ( */ + /* 41 */ ED_INSERT, /* ) */ + /* 42 */ ED_INSERT, /* * */ + /* 43 */ ED_INSERT, /* + */ + /* 44 */ ED_INSERT, /* , */ + /* 45 */ ED_INSERT, /* - */ + /* 46 */ ED_INSERT, /* . */ + /* 47 */ ED_INSERT, /* / */ + /* 48 */ ED_INSERT, /* 0 */ + /* 49 */ ED_INSERT, /* 1 */ + /* 50 */ ED_INSERT, /* 2 */ + /* 51 */ ED_INSERT, /* 3 */ + /* 52 */ ED_INSERT, /* 4 */ + /* 53 */ ED_INSERT, /* 5 */ + /* 54 */ ED_INSERT, /* 6 */ + /* 55 */ ED_INSERT, /* 7 */ + /* 56 */ ED_INSERT, /* 8 */ + /* 57 */ ED_INSERT, /* 9 */ + /* 58 */ ED_INSERT, /* : */ + /* 59 */ ED_INSERT, /* ; */ + /* 60 */ ED_INSERT, /* < */ + /* 61 */ ED_INSERT, /* = */ + /* 62 */ ED_INSERT, /* > */ + /* 63 */ ED_INSERT, /* ? */ + /* 64 */ ED_INSERT, /* @ */ + /* 65 */ ED_INSERT, /* A */ + /* 66 */ ED_INSERT, /* B */ + /* 67 */ ED_INSERT, /* C */ + /* 68 */ ED_INSERT, /* D */ + /* 69 */ ED_INSERT, /* E */ + /* 70 */ ED_INSERT, /* F */ + /* 71 */ ED_INSERT, /* G */ + /* 72 */ ED_INSERT, /* H */ + /* 73 */ ED_INSERT, /* I */ + /* 74 */ ED_INSERT, /* J */ + /* 75 */ ED_INSERT, /* K */ + /* 76 */ ED_INSERT, /* L */ + /* 77 */ ED_INSERT, /* M */ + /* 78 */ ED_INSERT, /* N */ + /* 79 */ ED_INSERT, /* O */ + /* 80 */ ED_INSERT, /* P */ + /* 81 */ ED_INSERT, /* Q */ + /* 82 */ ED_INSERT, /* R */ + /* 83 */ ED_INSERT, /* S */ + /* 84 */ ED_INSERT, /* T */ + /* 85 */ ED_INSERT, /* U */ + /* 86 */ ED_INSERT, /* V */ + /* 87 */ ED_INSERT, /* W */ + /* 88 */ ED_INSERT, /* X */ + /* 89 */ ED_INSERT, /* Y */ + /* 90 */ ED_INSERT, /* Z */ + /* 91 */ ED_INSERT, /* [ */ + /* 92 */ ED_INSERT, /* \ */ + /* 93 */ ED_INSERT, /* ] */ + /* 94 */ ED_INSERT, /* ^ */ + /* 95 */ ED_INSERT, /* _ */ + /* 96 */ ED_INSERT, /* ` */ + /* 97 */ ED_INSERT, /* a */ + /* 98 */ ED_INSERT, /* b */ + /* 99 */ ED_INSERT, /* c */ + /* 100 */ ED_INSERT, /* d */ + /* 101 */ ED_INSERT, /* e */ + /* 102 */ ED_INSERT, /* f */ + /* 103 */ ED_INSERT, /* g */ + /* 104 */ ED_INSERT, /* h */ + /* 105 */ ED_INSERT, /* i */ + /* 106 */ ED_INSERT, /* j */ + /* 107 */ ED_INSERT, /* k */ + /* 108 */ ED_INSERT, /* l */ + /* 109 */ ED_INSERT, /* m */ + /* 110 */ ED_INSERT, /* n */ + /* 111 */ ED_INSERT, /* o */ + /* 112 */ ED_INSERT, /* p */ + /* 113 */ ED_INSERT, /* q */ + /* 114 */ ED_INSERT, /* r */ + /* 115 */ ED_INSERT, /* s */ + /* 116 */ ED_INSERT, /* t */ + /* 117 */ ED_INSERT, /* u */ + /* 118 */ ED_INSERT, /* v */ + /* 119 */ ED_INSERT, /* w */ + /* 120 */ ED_INSERT, /* x */ + /* 121 */ ED_INSERT, /* y */ + /* 122 */ ED_INSERT, /* z */ + /* 123 */ ED_INSERT, /* { */ + /* 124 */ ED_INSERT, /* | */ + /* 125 */ ED_INSERT, /* } */ + /* 126 */ ED_INSERT, /* ~ */ + /* 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 el_action_t el_map_vi_command[] = { - /* 0 */ ED_UNASSIGNED, /* ^@ */ - /* 1 */ ED_MOVE_TO_BEG, /* ^A */ - /* 2 */ ED_UNASSIGNED, /* ^B */ - /* 3 */ ED_TTY_SIGINT, /* ^C */ - /* 4 */ ED_UNASSIGNED, /* ^D */ - /* 5 */ ED_MOVE_TO_END, /* ^E */ - /* 6 */ ED_UNASSIGNED, /* ^F */ - /* 7 */ ED_UNASSIGNED, /* ^G */ - /* 8 */ ED_PREV_CHAR, /* ^H */ - /* 9 */ ED_UNASSIGNED, /* ^I */ - /* 10 */ ED_NEWLINE, /* ^J */ - /* 11 */ ED_KILL_LINE, /* ^K */ - /* 12 */ ED_CLEAR_SCREEN, /* ^L */ - /* 13 */ ED_NEWLINE, /* ^M */ - /* 14 */ ED_NEXT_HISTORY, /* ^N */ - /* 15 */ ED_TTY_FLUSH_OUTPUT, /* ^O */ - /* 16 */ ED_PREV_HISTORY, /* ^P */ - /* 17 */ ED_TTY_START_OUTPUT, /* ^Q */ - /* 18 */ ED_REDISPLAY, /* ^R */ - /* 19 */ ED_TTY_STOP_OUTPUT, /* ^S */ - /* 20 */ ED_UNASSIGNED, /* ^T */ - /* 21 */ VI_KILL_LINE_PREV, /* ^U */ - /* 22 */ ED_UNASSIGNED, /* ^V */ - /* 23 */ ED_DELETE_PREV_WORD, /* ^W */ - /* 24 */ ED_UNASSIGNED, /* ^X */ - /* 25 */ ED_UNASSIGNED, /* ^Y */ - /* 26 */ ED_UNASSIGNED, /* ^Z */ - /* 27 */ EM_META_NEXT, /* ^[ */ - /* 28 */ ED_TTY_SIGQUIT, /* ^\ */ - /* 29 */ ED_UNASSIGNED, /* ^] */ - /* 30 */ ED_UNASSIGNED, /* ^^ */ - /* 31 */ ED_UNASSIGNED, /* ^_ */ - /* 32 */ ED_NEXT_CHAR, /* SPACE */ - /* 33 */ ED_UNASSIGNED, /* ! */ - /* 34 */ ED_UNASSIGNED, /* " */ - /* 35 */ ED_UNASSIGNED, /* # */ - /* 36 */ ED_MOVE_TO_END, /* $ */ - /* 37 */ ED_UNASSIGNED, /* % */ - /* 38 */ ED_UNASSIGNED, /* & */ - /* 39 */ ED_UNASSIGNED, /* ' */ - /* 40 */ ED_UNASSIGNED, /* ( */ - /* 41 */ ED_UNASSIGNED, /* ) */ - /* 42 */ ED_UNASSIGNED, /* * */ - /* 43 */ ED_NEXT_HISTORY, /* + */ - /* 44 */ VI_REPEAT_PREV_CHAR, /* , */ - /* 45 */ ED_PREV_HISTORY, /* - */ - /* 46 */ ED_UNASSIGNED, /* . */ - /* 47 */ VI_SEARCH_PREV, /* / */ - /* 48 */ VI_ZERO, /* 0 */ - /* 49 */ ED_ARGUMENT_DIGIT, /* 1 */ - /* 50 */ ED_ARGUMENT_DIGIT, /* 2 */ - /* 51 */ ED_ARGUMENT_DIGIT, /* 3 */ - /* 52 */ ED_ARGUMENT_DIGIT, /* 4 */ - /* 53 */ ED_ARGUMENT_DIGIT, /* 5 */ - /* 54 */ ED_ARGUMENT_DIGIT, /* 6 */ - /* 55 */ ED_ARGUMENT_DIGIT, /* 7 */ - /* 56 */ ED_ARGUMENT_DIGIT, /* 8 */ - /* 57 */ ED_ARGUMENT_DIGIT, /* 9 */ - /* 58 */ ED_COMMAND, /* : */ - /* 59 */ VI_REPEAT_NEXT_CHAR, /* ; */ - /* 60 */ ED_UNASSIGNED, /* < */ - /* 61 */ ED_UNASSIGNED, /* = */ - /* 62 */ ED_UNASSIGNED, /* > */ - /* 63 */ VI_SEARCH_NEXT, /* ? */ - /* 64 */ ED_UNASSIGNED, /* @ */ - /* 65 */ VI_ADD_AT_EOL, /* A */ - /* 66 */ VI_PREV_SPACE_WORD, /* B */ - /* 67 */ VI_CHANGE_TO_EOL, /* C */ - /* 68 */ ED_KILL_LINE, /* D */ - /* 69 */ VI_TO_END_WORD, /* E */ - /* 70 */ VI_PREV_CHAR, /* F */ - /* 71 */ ED_UNASSIGNED, /* G */ - /* 72 */ ED_UNASSIGNED, /* H */ - /* 73 */ VI_INSERT_AT_BOL, /* I */ - /* 74 */ ED_SEARCH_NEXT_HISTORY, /* J */ - /* 75 */ ED_SEARCH_PREV_HISTORY, /* K */ - /* 76 */ ED_UNASSIGNED, /* L */ - /* 77 */ ED_UNASSIGNED, /* M */ - /* 78 */ VI_REPEAT_SEARCH_PREV, /* N */ - /* 79 */ ED_SEQUENCE_LEAD_IN, /* O */ - /* 80 */ VI_PASTE_PREV, /* P */ - /* 81 */ ED_UNASSIGNED, /* Q */ - /* 82 */ VI_REPLACE_MODE, /* R */ - /* 83 */ VI_SUBSTITUTE_LINE, /* S */ - /* 84 */ VI_TO_PREV_CHAR, /* T */ - /* 85 */ ED_UNASSIGNED, /* U */ - /* 86 */ ED_UNASSIGNED, /* V */ - /* 87 */ VI_NEXT_SPACE_WORD, /* W */ - /* 88 */ ED_DELETE_PREV_CHAR, /* X */ - /* 89 */ ED_UNASSIGNED, /* Y */ - /* 90 */ ED_UNASSIGNED, /* Z */ - /* 91 */ ED_SEQUENCE_LEAD_IN, /* [ */ - /* 92 */ ED_UNASSIGNED, /* \ */ - /* 93 */ ED_UNASSIGNED, /* ] */ - /* 94 */ ED_MOVE_TO_BEG, /* ^ */ - /* 95 */ ED_UNASSIGNED, /* _ */ - /* 96 */ ED_UNASSIGNED, /* ` */ - /* 97 */ VI_ADD, /* a */ - /* 98 */ VI_PREV_WORD, /* b */ - /* 99 */ VI_CHANGE_META, /* c */ - /* 100 */ VI_DELETE_META, /* d */ - /* 101 */ VI_END_WORD, /* e */ - /* 102 */ VI_NEXT_CHAR, /* f */ - /* 103 */ ED_UNASSIGNED, /* g */ - /* 104 */ ED_PREV_CHAR, /* h */ - /* 105 */ VI_INSERT, /* i */ - /* 106 */ ED_NEXT_HISTORY, /* j */ - /* 107 */ ED_PREV_HISTORY, /* k */ - /* 108 */ ED_NEXT_CHAR, /* l */ - /* 109 */ ED_UNASSIGNED, /* m */ - /* 110 */ VI_REPEAT_SEARCH_NEXT, /* n */ - /* 111 */ ED_UNASSIGNED, /* o */ - /* 112 */ VI_PASTE_NEXT, /* p */ - /* 113 */ ED_UNASSIGNED, /* q */ - /* 114 */ VI_REPLACE_CHAR, /* r */ - /* 115 */ VI_SUBSTITUTE_CHAR, /* s */ - /* 116 */ VI_TO_NEXT_CHAR, /* t */ - /* 117 */ VI_UNDO, /* u */ - /* 118 */ ED_UNASSIGNED, /* v */ - /* 119 */ VI_NEXT_WORD, /* w */ - /* 120 */ ED_DELETE_NEXT_CHAR, /* x */ - /* 121 */ ED_UNASSIGNED, /* y */ - /* 122 */ ED_UNASSIGNED, /* z */ - /* 123 */ ED_UNASSIGNED, /* { */ - /* 124 */ ED_UNASSIGNED, /* | */ - /* 125 */ ED_UNASSIGNED, /* } */ - /* 126 */ VI_CHANGE_CASE, /* ~ */ - /* 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_SEQUENCE_LEAD_IN, /* 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_SEQUENCE_LEAD_IN, /* 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-^? */ +private const el_action_t el_map_vi_command[] = { + /* 0 */ ED_UNASSIGNED, /* ^@ */ + /* 1 */ ED_MOVE_TO_BEG, /* ^A */ + /* 2 */ ED_UNASSIGNED, /* ^B */ + /* 3 */ ED_TTY_SIGINT, /* ^C */ + /* 4 */ ED_UNASSIGNED, /* ^D */ + /* 5 */ ED_MOVE_TO_END, /* ^E */ + /* 6 */ ED_UNASSIGNED, /* ^F */ + /* 7 */ ED_UNASSIGNED, /* ^G */ + /* 8 */ ED_DELETE_PREV_CHAR, /* ^H */ + /* 9 */ ED_UNASSIGNED, /* ^I */ + /* 10 */ ED_NEWLINE, /* ^J */ + /* 11 */ ED_KILL_LINE, /* ^K */ + /* 12 */ ED_CLEAR_SCREEN, /* ^L */ + /* 13 */ ED_NEWLINE, /* ^M */ + /* 14 */ ED_NEXT_HISTORY, /* ^N */ + /* 15 */ ED_TTY_FLUSH_OUTPUT, /* ^O */ + /* 16 */ ED_PREV_HISTORY, /* ^P */ + /* 17 */ ED_TTY_START_OUTPUT, /* ^Q */ + /* 18 */ ED_REDISPLAY, /* ^R */ + /* 19 */ ED_TTY_STOP_OUTPUT, /* ^S */ + /* 20 */ ED_UNASSIGNED, /* ^T */ + /* 21 */ VI_KILL_LINE_PREV, /* ^U */ + /* 22 */ ED_UNASSIGNED, /* ^V */ + /* 23 */ ED_DELETE_PREV_WORD, /* ^W */ + /* 24 */ ED_UNASSIGNED, /* ^X */ + /* 25 */ ED_UNASSIGNED, /* ^Y */ + /* 26 */ ED_UNASSIGNED, /* ^Z */ + /* 27 */ EM_META_NEXT, /* ^[ */ + /* 28 */ ED_TTY_SIGQUIT, /* ^\ */ + /* 29 */ ED_UNASSIGNED, /* ^] */ + /* 30 */ ED_UNASSIGNED, /* ^^ */ + /* 31 */ ED_UNASSIGNED, /* ^_ */ + /* 32 */ ED_NEXT_CHAR, /* SPACE */ + /* 33 */ ED_UNASSIGNED, /* ! */ + /* 34 */ ED_UNASSIGNED, /* " */ + /* 35 */ VI_COMMENT_OUT, /* # */ + /* 36 */ ED_MOVE_TO_END, /* $ */ + /* 37 */ VI_MATCH, /* % */ + /* 38 */ ED_UNASSIGNED, /* & */ + /* 39 */ ED_UNASSIGNED, /* ' */ + /* 40 */ ED_UNASSIGNED, /* ( */ + /* 41 */ ED_UNASSIGNED, /* ) */ + /* 42 */ ED_UNASSIGNED, /* * */ + /* 43 */ ED_NEXT_HISTORY, /* + */ + /* 44 */ VI_REPEAT_PREV_CHAR, /* , */ + /* 45 */ ED_PREV_HISTORY, /* - */ + /* 46 */ VI_REDO, /* . */ + /* 47 */ VI_SEARCH_PREV, /* / */ + /* 48 */ VI_ZERO, /* 0 */ + /* 49 */ ED_ARGUMENT_DIGIT, /* 1 */ + /* 50 */ ED_ARGUMENT_DIGIT, /* 2 */ + /* 51 */ ED_ARGUMENT_DIGIT, /* 3 */ + /* 52 */ ED_ARGUMENT_DIGIT, /* 4 */ + /* 53 */ ED_ARGUMENT_DIGIT, /* 5 */ + /* 54 */ ED_ARGUMENT_DIGIT, /* 6 */ + /* 55 */ ED_ARGUMENT_DIGIT, /* 7 */ + /* 56 */ ED_ARGUMENT_DIGIT, /* 8 */ + /* 57 */ ED_ARGUMENT_DIGIT, /* 9 */ + /* 58 */ ED_COMMAND, /* : */ + /* 59 */ VI_REPEAT_NEXT_CHAR, /* ; */ + /* 60 */ ED_UNASSIGNED, /* < */ + /* 61 */ ED_UNASSIGNED, /* = */ + /* 62 */ ED_UNASSIGNED, /* > */ + /* 63 */ VI_SEARCH_NEXT, /* ? */ + /* 64 */ VI_ALIAS, /* @ */ + /* 65 */ VI_ADD_AT_EOL, /* A */ + /* 66 */ VI_PREV_BIG_WORD, /* B */ + /* 67 */ VI_CHANGE_TO_EOL, /* C */ + /* 68 */ ED_KILL_LINE, /* D */ + /* 69 */ VI_END_BIG_WORD, /* E */ + /* 70 */ VI_PREV_CHAR, /* F */ + /* 71 */ VI_TO_HISTORY_LINE, /* G */ + /* 72 */ ED_UNASSIGNED, /* H */ + /* 73 */ VI_INSERT_AT_BOL, /* I */ + /* 74 */ ED_SEARCH_NEXT_HISTORY, /* J */ + /* 75 */ ED_SEARCH_PREV_HISTORY, /* K */ + /* 76 */ ED_UNASSIGNED, /* L */ + /* 77 */ ED_UNASSIGNED, /* M */ + /* 78 */ VI_REPEAT_SEARCH_PREV, /* N */ + /* 79 */ ED_SEQUENCE_LEAD_IN, /* O */ + /* 80 */ VI_PASTE_PREV, /* P */ + /* 81 */ ED_UNASSIGNED, /* Q */ + /* 82 */ VI_REPLACE_MODE, /* R */ + /* 83 */ VI_SUBSTITUTE_LINE, /* S */ + /* 84 */ VI_TO_PREV_CHAR, /* T */ + /* 85 */ VI_UNDO_LINE, /* U */ + /* 86 */ ED_UNASSIGNED, /* V */ + /* 87 */ VI_NEXT_BIG_WORD, /* W */ + /* 88 */ ED_DELETE_PREV_CHAR, /* X */ + /* 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 */ VI_HISTORY_WORD, /* _ */ + /* 96 */ ED_UNASSIGNED, /* ` */ + /* 97 */ VI_ADD, /* a */ + /* 98 */ VI_PREV_WORD, /* b */ + /* 99 */ VI_CHANGE_META, /* c */ + /* 100 */ VI_DELETE_META, /* d */ + /* 101 */ VI_END_WORD, /* e */ + /* 102 */ VI_NEXT_CHAR, /* f */ + /* 103 */ ED_UNASSIGNED, /* g */ + /* 104 */ ED_PREV_CHAR, /* h */ + /* 105 */ VI_INSERT, /* i */ + /* 106 */ ED_NEXT_HISTORY, /* j */ + /* 107 */ ED_PREV_HISTORY, /* k */ + /* 108 */ ED_NEXT_CHAR, /* l */ + /* 109 */ ED_UNASSIGNED, /* m */ + /* 110 */ VI_REPEAT_SEARCH_NEXT, /* n */ + /* 111 */ ED_UNASSIGNED, /* o */ + /* 112 */ VI_PASTE_NEXT, /* p */ + /* 113 */ ED_UNASSIGNED, /* q */ + /* 114 */ VI_REPLACE_CHAR, /* r */ + /* 115 */ VI_SUBSTITUTE_CHAR, /* s */ + /* 116 */ VI_TO_NEXT_CHAR, /* t */ + /* 117 */ VI_UNDO, /* u */ + /* 118 */ VI_HISTEDIT, /* v */ + /* 119 */ VI_NEXT_WORD, /* w */ + /* 120 */ ED_DELETE_NEXT_CHAR, /* x */ + /* 121 */ VI_YANK, /* y */ + /* 122 */ ED_UNASSIGNED, /* z */ + /* 123 */ ED_UNASSIGNED, /* { */ + /* 124 */ VI_TO_COLUMN, /* | */ + /* 125 */ ED_UNASSIGNED, /* } */ + /* 126 */ VI_CHANGE_CASE, /* ~ */ + /* 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_SEQUENCE_LEAD_IN, /* 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_SEQUENCE_LEAD_IN, /* 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-^? */ }; @@ -882,41 +891,49 @@ private el_action_t el_map_vi_command[] = { * Initialize and allocate the maps */ protected int -map_init(el) - EditLine *el; +map_init(EditLine *el) { - - /* - * Make sure those are correct before starting. - */ + + /* + * Make sure those are correct before starting. + */ #ifdef MAP_DEBUG - if (sizeof(el_map_emacs) != N_KEYS * sizeof(el_action_t)) - abort(); - if (sizeof(el_map_vi_command) != N_KEYS * sizeof(el_action_t)) - abort(); - if (sizeof(el_map_vi_insert) != N_KEYS * sizeof(el_action_t)) - abort(); + if (sizeof(el_map_emacs) != N_KEYS * sizeof(el_action_t)) + EL_ABORT((el->errfile, "Emacs map incorrect\n")); + if (sizeof(el_map_vi_command) != N_KEYS * sizeof(el_action_t)) + EL_ABORT((el->errfile, "Vi command map incorrect\n")); + if (sizeof(el_map_vi_insert) != N_KEYS * sizeof(el_action_t)) + EL_ABORT((el->errfile, "Vi insert map incorrect\n")); #endif - el->el_map.alt = (el_action_t *) el_malloc(sizeof(el_action_t) * N_KEYS); - el->el_map.key = (el_action_t *) el_malloc(sizeof(el_action_t) * N_KEYS); - el->el_map.emacs = el_map_emacs; - el->el_map.vic = el_map_vi_command; - el->el_map.vii = el_map_vi_insert; - el->el_map.help = (el_bindings_t *) el_malloc(sizeof(el_bindings_t) * - EL_NUM_FCNS); - (void)memcpy(el->el_map.help, help__get(), - sizeof(el_bindings_t) * EL_NUM_FCNS); - el->el_map.func = (el_func_t *) el_malloc(sizeof(el_func_t) * EL_NUM_FCNS); - memcpy(el->el_map.func, func__get(), sizeof(el_func_t) * EL_NUM_FCNS); - el->el_map.nfunc = EL_NUM_FCNS; + el->el_map.alt = (el_action_t *)el_malloc(sizeof(el_action_t) * N_KEYS); + if (el->el_map.alt == NULL) + return (-1); + el->el_map.key = (el_action_t *)el_malloc(sizeof(el_action_t) * N_KEYS); + if (el->el_map.key == NULL) + return (-1); + el->el_map.emacs = el_map_emacs; + el->el_map.vic = el_map_vi_command; + el->el_map.vii = el_map_vi_insert; + el->el_map.help = (el_bindings_t *) el_malloc(sizeof(el_bindings_t) * + EL_NUM_FCNS); + if (el->el_map.help == NULL) + return (-1); + (void) memcpy(el->el_map.help, help__get(), + sizeof(el_bindings_t) * EL_NUM_FCNS); + el->el_map.func = (el_func_t *)el_malloc(sizeof(el_func_t) * + EL_NUM_FCNS); + if (el->el_map.func == NULL) + return (-1); + memcpy(el->el_map.func, func__get(), sizeof(el_func_t) * EL_NUM_FCNS); + el->el_map.nfunc = EL_NUM_FCNS; #ifdef VIDEFAULT - map_init_vi(el); + map_init_vi(el); #else - map_init_emacs(el); + map_init_emacs(el); #endif /* VIDEFAULT */ - return 0; + return (0); } @@ -924,20 +941,20 @@ map_init(el) * Free the space taken by the editor maps */ protected void -map_end(el) - EditLine *el; +map_end(EditLine *el) { - el_free((ptr_t) el->el_map.alt); - el->el_map.alt = NULL; - el_free((ptr_t) el->el_map.key); - el->el_map.key = NULL; - el->el_map.emacs = NULL; - el->el_map.vic = NULL; - el->el_map.vii = NULL; - el_free((ptr_t) el->el_map.help); - el->el_map.help = NULL; - el_free((ptr_t) el->el_map.func); - el->el_map.func = NULL; + + el_free((ptr_t) el->el_map.alt); + el->el_map.alt = NULL; + el_free((ptr_t) el->el_map.key); + el->el_map.key = NULL; + el->el_map.emacs = NULL; + el->el_map.vic = NULL; + el->el_map.vii = NULL; + el_free((ptr_t) el->el_map.help); + el->el_map.help = NULL; + el_free((ptr_t) el->el_map.func); + el->el_map.func = NULL; } @@ -945,15 +962,15 @@ map_end(el) * Find all the printable keys and bind them to self insert */ private void -map_init_nls(el) - EditLine *el; +map_init_nls(EditLine *el) { - int i; - el_action_t *map = el->el_map.key; + int i; + + el_action_t *map = el->el_map.key; - for (i = 0200; i <= 0377; i++) - if (isprint(i)) - map[i] = ED_INSERT; + for (i = 0200; i <= 0377; i++) + if (isprint(i)) + map[i] = ED_INSERT; } @@ -961,42 +978,40 @@ map_init_nls(el) * Bind all the meta keys to the appropriate ESC-<key> sequence */ private void -map_init_meta(el) - EditLine *el; +map_init_meta(EditLine *el) { - unsigned char buf[3]; - register int i; - el_action_t *map = el->el_map.key; - el_action_t *alt = el->el_map.alt; + char buf[3]; + int i; + el_action_t *map = el->el_map.key; + el_action_t *alt = el->el_map.alt; - for (i = 0; i <= 0377 && map[i] != EM_META_NEXT; i++) - continue; + for (i = 0; i <= 0377 && map[i] != EM_META_NEXT; i++) + continue; - if (i > 0377) { - for (i = 0; i <= 0377 && alt[i] != EM_META_NEXT; i++) - continue; if (i > 0377) { - i = 033; - if (el->el_map.type == MAP_VI) - map = alt; + for (i = 0; i <= 0377 && alt[i] != EM_META_NEXT; i++) + continue; + if (i > 0377) { + i = 033; + if (el->el_map.type == MAP_VI) + map = alt; + } else + map = alt; } - else - map = alt; - } - buf[0] = (unsigned char) i; - buf[2] = 0; - for (i = 0200; i <= 0377; i++) - switch (map[i]) { - case ED_INSERT: - case ED_UNASSIGNED: - case ED_SEQUENCE_LEAD_IN: - break; - default: - buf[1] = i & 0177; - key_add(el, buf, key_map_cmd(el, (int) map[i]), XK_CMD); - break; - } - map[buf[0]] = ED_SEQUENCE_LEAD_IN; + buf[0] = (char) i; + buf[2] = 0; + for (i = 0200; i <= 0377; i++) + switch (map[i]) { + case ED_INSERT: + case ED_UNASSIGNED: + case ED_SEQUENCE_LEAD_IN: + break; + default: + buf[1] = i & 0177; + key_add(el, buf, key_map_cmd(el, (int) map[i]), XK_CMD); + break; + } + map[(int) buf[0]] = ED_SEQUENCE_LEAD_IN; } @@ -1004,33 +1019,29 @@ map_init_meta(el) * Initialize the vi bindings */ protected void -map_init_vi(el) - EditLine *el; +map_init_vi(EditLine *el) { - register int i; - el_action_t *key = el->el_map.key; - el_action_t *alt = el->el_map.alt; - el_action_t *vii = el->el_map.vii; - el_action_t *vic = el->el_map.vic; + int i; + el_action_t *key = el->el_map.key; + el_action_t *alt = el->el_map.alt; + const el_action_t *vii = el->el_map.vii; + const el_action_t *vic = el->el_map.vic; - el->el_map.type = MAP_VI; - el->el_map.current = el->el_map.key; + el->el_map.type = MAP_VI; + el->el_map.current = el->el_map.key; - key_reset(el); + key_reset(el); - for (i = 0; i < N_KEYS; i++) { - key[i] = vii[i]; - alt[i] = vic[i]; - } + for (i = 0; i < N_KEYS; i++) { + key[i] = vii[i]; + alt[i] = vic[i]; + } - map_init_meta(el); -#ifdef notyet - if (0 /* XXX: USER has set LC_CTYPE */) + map_init_meta(el); map_init_nls(el); -#endif - tty_bind_char(el, 1); - term_bind_arrow(el); + tty_bind_char(el, 1); + term_bind_arrow(el); } @@ -1038,58 +1049,73 @@ map_init_vi(el) * Initialize the emacs bindings */ protected void -map_init_emacs(el) - EditLine *el; +map_init_emacs(EditLine *el) { - int i; - char buf[3]; - el_action_t *key = el->el_map.key; - el_action_t *alt = el->el_map.alt; - el_action_t *emacs = el->el_map.emacs; - - el->el_map.type = MAP_EMACS; - el->el_map.current = el->el_map.key; - key_reset(el); - - for (i = 0; i < N_KEYS; i++) { - key[i] = emacs[i]; - alt[i] = ED_UNASSIGNED; - } - - map_init_meta(el); -#ifdef notyet - if (0 /* XXX: USER has set LC_CTYPE */) + int i; + char buf[3]; + el_action_t *key = el->el_map.key; + el_action_t *alt = el->el_map.alt; + const el_action_t *emacs = el->el_map.emacs; + + el->el_map.type = MAP_EMACS; + el->el_map.current = el->el_map.key; + key_reset(el); + + for (i = 0; i < N_KEYS; i++) { + key[i] = emacs[i]; + alt[i] = ED_UNASSIGNED; + } + + map_init_meta(el); map_init_nls(el); -#endif - map_init_nls(el); - - buf[0] = CONTROL('X'); - buf[1] = CONTROL('X'); - buf[2] = 0; - key_add(el, buf, key_map_cmd(el, EM_EXCHANGE_MARK), XK_CMD); - - tty_bind_char(el, 1); - term_bind_arrow(el); + + buf[0] = CONTROL('X'); + buf[1] = CONTROL('X'); + buf[2] = 0; + key_add(el, buf, key_map_cmd(el, EM_EXCHANGE_MARK), XK_CMD); + + tty_bind_char(el, 1); + term_bind_arrow(el); } /* map_set_editor(): - * Set the editor + * Set the editor */ protected int -map_set_editor(el, editor) - EditLine *el; - char *editor; +map_set_editor(EditLine *el, char *editor) { - if (strcmp(editor, "emacs") == 0) { - map_init_emacs(el); - return 0; - } - if (strcmp(editor, "vi") == 0) { - map_init_vi(el); - return 0; - } - return -1; + + if (strcmp(editor, "emacs") == 0) { + map_init_emacs(el); + return (0); + } + if (strcmp(editor, "vi") == 0) { + map_init_vi(el); + return (0); + } + return (-1); +} + + +/* map_get_editor(): + * Retrieve the editor + */ +protected int +map_get_editor(EditLine *el, const char **editor) +{ + + if (editor == NULL) + return (-1); + switch (el->el_map.type) { + case MAP_EMACS: + *editor = "emacs"; + return (0); + case MAP_VI: + *editor = "vi"; + return (0); + } + return (-1); } @@ -1097,25 +1123,21 @@ map_set_editor(el, editor) * Print the function description for 1 key */ private void -map_print_key(el, map, in) - 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; - - if (in[0] == '\0' || in[1] == '\0') { - (void)key__decode_str(in, outbuf, ""); - for (bp = el->el_map.help; bp->name != NULL; bp++) - if (bp->func == map[(unsigned char) *in]) { - (void)fprintf(el->el_outfile, - "%s\t->\t%s\n", outbuf, bp->name); - return; - } - } - else - key_print(el, in); + char outbuf[EL_BUFSIZ]; + el_bindings_t *bp; + + if (in[0] == '\0' || in[1] == '\0') { + (void) key__decode_str(in, outbuf, ""); + for (bp = el->el_map.help; bp->name != NULL; bp++) + if (bp->func == map[(unsigned char) *in]) { + (void) fprintf(el->el_outfile, + "%s\t->\t%s\n", outbuf, bp->name); + return; + } + } else + key_print(el, in); } @@ -1123,57 +1145,55 @@ map_print_key(el, map, in) * Print keys from first to last */ private void -map_print_some_keys(el, map, first, last) - EditLine *el; - el_action_t *map; - int first, last; +map_print_some_keys(EditLine *el, el_action_t *map, int first, int last) { - el_bindings_t *bp; - char firstbuf[2], lastbuf[2]; - char unparsbuf[EL_BUFSIZ], extrabuf[EL_BUFSIZ]; - - firstbuf[0] = first; - firstbuf[1] = 0; - lastbuf[0] = last; - lastbuf[1] = 0; - if (map[first] == ED_UNASSIGNED) { - if (first == last) - (void)fprintf(el->el_outfile, "%-15s-> is undefined\n", - key__decode_str(firstbuf, unparsbuf, STRQQ)); - return; - } - - for (bp = el->el_map.help; bp->name != NULL; bp++) { - if (bp->func == map[first]) { - if (first == last) { - (void)fprintf(el->el_outfile, "%-15s-> %s\n", - key__decode_str(firstbuf, unparsbuf, STRQQ), - bp->name); - } - else { - (void)fprintf(el->el_outfile, "%-4s to %-7s-> %s\n", - key__decode_str(firstbuf, unparsbuf, STRQQ), - key__decode_str(lastbuf, extrabuf, STRQQ), - bp->name); - } - return; + el_bindings_t *bp; + char firstbuf[2], lastbuf[2]; + char unparsbuf[EL_BUFSIZ], extrabuf[EL_BUFSIZ]; + + firstbuf[0] = first; + firstbuf[1] = 0; + lastbuf[0] = last; + lastbuf[1] = 0; + if (map[first] == ED_UNASSIGNED) { + if (first == last) + (void) fprintf(el->el_outfile, + "%-15s-> is undefined\n", + key__decode_str(firstbuf, unparsbuf, STRQQ)); + return; + } + for (bp = el->el_map.help; bp->name != NULL; bp++) { + if (bp->func == map[first]) { + if (first == last) { + (void) fprintf(el->el_outfile, "%-15s-> %s\n", + key__decode_str(firstbuf, unparsbuf, STRQQ), + bp->name); + } else { + (void) fprintf(el->el_outfile, + "%-4s to %-7s-> %s\n", + key__decode_str(firstbuf, unparsbuf, STRQQ), + key__decode_str(lastbuf, extrabuf, STRQQ), + bp->name); + } + return; + } } - } #ifdef MAP_DEBUG - if (map == el->el_map.key) { - (void)fprintf(el->el_outfile, "BUG!!! %s isn't bound to anything.\n", - key__decode_str(firstbuf, unparsbuf, STRQQ)); - (void)fprintf(el->el_outfile, "el->el_map.key[%d] == %d\n", - first, el->el_map.key[first]); - } - else { - (void)fprintf(el->el_outfile, "BUG!!! %s isn't bound to anything.\n", - key__decode_str(firstbuf, unparsbuf, STRQQ)); - (void)fprintf(el->el_outfile, "el->el_map.alt[%d] == %d\n", - first, el->el_map.alt[first]); - } + if (map == el->el_map.key) { + (void) fprintf(el->el_outfile, + "BUG!!! %s isn't bound to anything.\n", + key__decode_str(firstbuf, unparsbuf, STRQQ)); + (void) fprintf(el->el_outfile, "el->el_map.key[%d] == %d\n", + first, el->el_map.key[first]); + } else { + (void) fprintf(el->el_outfile, + "BUG!!! %s isn't bound to anything.\n", + key__decode_str(firstbuf, unparsbuf, STRQQ)); + (void) fprintf(el->el_outfile, "el->el_map.alt[%d] == %d\n", + first, el->el_map.alt[first]); + } #endif - abort(); + EL_ABORT((el->el_errfile, "Error printing keys\n")); } @@ -1181,35 +1201,34 @@ map_print_some_keys(el, map, first, last) * Print the function description for all keys. */ private void -map_print_all_keys(el) - EditLine *el; +map_print_all_keys(EditLine *el) { - int prev, i; - - (void)fprintf(el->el_outfile, "Standard key bindings\n"); - prev = 0; - for (i = 0; i < N_KEYS; i++) { - if (el->el_map.key[prev] == el->el_map.key[i]) - continue; + int prev, i; + + (void) fprintf(el->el_outfile, "Standard key bindings\n"); + prev = 0; + for (i = 0; i < N_KEYS; i++) { + if (el->el_map.key[prev] == el->el_map.key[i]) + continue; + map_print_some_keys(el, el->el_map.key, prev, i - 1); + prev = i; + } map_print_some_keys(el, el->el_map.key, prev, i - 1); - prev = i; - } - map_print_some_keys(el, el->el_map.key, prev, i - 1); - - (void)fprintf(el->el_outfile, "Alternative key bindings\n"); - prev = 0; - for (i = 0; i < N_KEYS; i++) { - if (el->el_map.alt[prev] == el->el_map.alt[i]) - continue; + + (void) fprintf(el->el_outfile, "Alternative key bindings\n"); + prev = 0; + for (i = 0; i < N_KEYS; i++) { + if (el->el_map.alt[prev] == el->el_map.alt[i]) + continue; + map_print_some_keys(el, el->el_map.alt, prev, i - 1); + prev = i; + } map_print_some_keys(el, el->el_map.alt, prev, i - 1); - prev = i; - } - map_print_some_keys(el, el->el_map.alt, prev, i - 1); - - (void)fprintf(el->el_outfile, "Multi-character bindings\n"); - key_print(el, ""); - (void)fprintf(el->el_outfile, "Arrow key bindings\n"); - term_print_arrow(el, ""); + + (void) fprintf(el->el_outfile, "Multi-character bindings\n"); + key_print(el, ""); + (void) fprintf(el->el_outfile, "Arrow key bindings\n"); + term_print_arrow(el, ""); } @@ -1217,154 +1236,149 @@ map_print_all_keys(el) * Add/remove/change bindings */ protected int -map_bind(el, argc, argv) - EditLine *el; - int argc; - char **argv; +map_bind(EditLine *el, int argc, const char **argv) { - el_action_t *map; - int ntype, remove; - char *p; - char inbuf[EL_BUFSIZ]; - char outbuf[EL_BUFSIZ]; - char *in = NULL; - char *out = NULL; - el_bindings_t *bp; - int cmd; - int key; - - if (argv == NULL) - return -1; - - map = el->el_map.key; - ntype = XK_CMD; - key = remove = 0; - for (argc = 1; (p = argv[argc]) != NULL; argc++) - if (p[0] == '-') - switch (p[1]) { - case 'a': - map = el->el_map.alt; - break; - - case 's': - ntype = XK_STR; - break; + el_action_t *map; + int ntype, rem; + const char *p; + char inbuf[EL_BUFSIZ]; + char outbuf[EL_BUFSIZ]; + const char *in = NULL; + char *out = NULL; + el_bindings_t *bp; + int cmd; + int key; + + if (argv == NULL) + return (-1); + + map = el->el_map.key; + ntype = XK_CMD; + key = rem = 0; + for (argc = 1; (p = argv[argc]) != NULL; argc++) + if (p[0] == '-') + switch (p[1]) { + case 'a': + map = el->el_map.alt; + break; + + case 's': + ntype = XK_STR; + break; #ifdef notyet - case 'c': - ntype = XK_EXE; - break; + case 'c': + ntype = XK_EXE; + break; #endif - case 'k': - key = 1; - break; - - case 'r': - remove = 1; - break; - - case 'v': - map_init_vi(el); - return 0; - - case 'e': - map_init_emacs(el); - return 0; - - case 'l': - for (bp = el->el_map.help; bp->name != NULL; bp++) - (void)fprintf(el->el_outfile, "%s\n\t%s\n", - bp->name, bp->description); - return 0; - default: - (void)fprintf(el->el_errfile, "%s: Invalid switch `%c'.\n", - argv[0], p[1]); - } - else - break; - - if (argv[argc] == NULL) { - map_print_all_keys(el); - return 0; - } - - if (key) - in = argv[argc++]; - else - if ((in = parse__string(inbuf, argv[argc++])) == NULL) { - (void)fprintf(el->el_errfile, "%s: Invalid \\ or ^ in instring.\n", - argv[0]); - return -1; - } - - if (remove) { - if (key) { - (void)term_clear_arrow(el, in); - return -1; + case 'k': + key = 1; + break; + + case 'r': + rem = 1; + break; + + case 'v': + map_init_vi(el); + return (0); + + case 'e': + map_init_emacs(el); + return (0); + + case 'l': + for (bp = el->el_map.help; bp->name != NULL; + bp++) + (void) fprintf(el->el_outfile, + "%s\n\t%s\n", + bp->name, bp->description); + return (0); + default: + (void) fprintf(el->el_errfile, + "%s: Invalid switch `%c'.\n", + argv[0], p[1]); + } + else + break; + + if (argv[argc] == NULL) { + map_print_all_keys(el); + return (0); } - if (in[1]) - (void)key_delete(el, in); - else if (map[(unsigned char) *in] == ED_SEQUENCE_LEAD_IN) - (void)key_delete(el, in); - else - map[(unsigned char) *in] = ED_UNASSIGNED; - return 0; - } - - if (argv[argc] == NULL) { if (key) - term_print_arrow(el, in); - else - map_print_key(el, map, in); - return 0; - } - + in = argv[argc++]; + else if ((in = parse__string(inbuf, argv[argc++])) == NULL) { + (void) fprintf(el->el_errfile, + "%s: Invalid \\ or ^ in instring.\n", + argv[0]); + return (-1); + } + if (rem) { + if (key) { + (void) term_clear_arrow(el, in); + return (-1); + } + if (in[1]) + (void) key_delete(el, in); + else if (map[(unsigned char) *in] == ED_SEQUENCE_LEAD_IN) + (void) key_delete(el, in); + else + map[(unsigned char) *in] = ED_UNASSIGNED; + return (0); + } + if (argv[argc] == NULL) { + if (key) + term_print_arrow(el, in); + else + map_print_key(el, map, in); + return (0); + } #ifdef notyet - if (argv[argc + 1] != NULL) { - bindkey_usage(); - return -1; - } + if (argv[argc + 1] != NULL) { + bindkey_usage(); + return (-1); + } #endif - switch (ntype) { - case XK_STR: - case XK_EXE: - if ((out = parse__string(outbuf, argv[argc])) == NULL) { - (void)fprintf(el->el_errfile, - "%s: Invalid \\ or ^ in outstring.\n", argv[0]); - return -1; - } - if (key) - term_set_arrow(el, in, key_map_str(el, out), ntype); - else - key_add(el, in, key_map_str(el, out), ntype); - map[(unsigned char) *in] = ED_SEQUENCE_LEAD_IN; - break; - - case XK_CMD: - if ((cmd = parse_cmd(el, argv[argc])) == -1) { - (void)fprintf(el->el_errfile, - "%s: Invalid command `%s'.\n", argv[0], argv[argc]); - return -1; - } - if (key) - term_set_arrow(el, in, key_map_str(el, out), ntype); - else { - if (in[1]) { - key_add(el, in, key_map_cmd(el, cmd), ntype); + switch (ntype) { + case XK_STR: + case XK_EXE: + if ((out = parse__string(outbuf, argv[argc])) == NULL) { + (void) fprintf(el->el_errfile, + "%s: Invalid \\ or ^ in outstring.\n", argv[0]); + return (-1); + } + if (key) + term_set_arrow(el, in, key_map_str(el, out), ntype); + else + key_add(el, in, key_map_str(el, out), ntype); map[(unsigned char) *in] = ED_SEQUENCE_LEAD_IN; - } - else { - key_clear(el, map, in); - map[(unsigned char) *in] = cmd; - } - } - break; + break; - default: - abort(); - break; - } - return 0; + case XK_CMD: + if ((cmd = parse_cmd(el, argv[argc])) == -1) { + (void) fprintf(el->el_errfile, + "%s: Invalid command `%s'.\n", argv[0], argv[argc]); + return (-1); + } + if (key) + term_set_arrow(el, in, key_map_str(el, out), ntype); + else { + if (in[1]) { + key_add(el, in, key_map_cmd(el, cmd), ntype); + map[(unsigned char) *in] = ED_SEQUENCE_LEAD_IN; + } else { + key_clear(el, map, in); + map[(unsigned char) *in] = cmd; + } + } + break; + + default: + EL_ABORT((el->el_errfile, "Bad XK_ type\n", ntype)); + break; + } + return (0); } @@ -1372,33 +1386,30 @@ map_bind(el, argc, argv) * add a user defined function */ protected int -map_addfunc(el, name, help, func) - EditLine *el; - const char *name; - const char *help; - el_func_t func; +map_addfunc(EditLine *el, const char *name, const char *help, el_func_t func) { - void *p; - int nf = el->el_map.nfunc + 2; - if (name == NULL || help == NULL || func == NULL) - return -1; - - if ((p = el_realloc(el->el_map.func, nf * sizeof(el_func_t))) == NULL) - return -1; - el->el_map.func = (el_func_t *) p; - - if ((p = el_realloc(el->el_map.help, nf * sizeof(el_bindings_t))) == NULL) - return -1; - el->el_map.help = (el_bindings_t *) p; - - nf = el->el_map.nfunc; - el->el_map.func[nf] = func; - - el->el_map.help[nf].name = name; - el->el_map.help[nf].func = nf; - el->el_map.help[nf].description = help; - el->el_map.help[++nf].name = NULL; - el->el_map.nfunc++; - - return 0; + void *p; + int nf = el->el_map.nfunc + 2; + + if (name == NULL || help == NULL || func == NULL) + return (-1); + + if ((p = el_realloc(el->el_map.func, nf * sizeof(el_func_t))) == NULL) + return (-1); + el->el_map.func = (el_func_t *) p; + if ((p = el_realloc(el->el_map.help, nf * sizeof(el_bindings_t))) + == NULL) + return (-1); + el->el_map.help = (el_bindings_t *) p; + + nf = el->el_map.nfunc; + el->el_map.func[nf] = func; + + el->el_map.help[nf].name = name; + el->el_map.help[nf].func = nf; + el->el_map.help[nf].description = help; + el->el_map.help[++nf].name = NULL; + el->el_map.nfunc++; + + return (0); } diff --git a/lib/libedit/map.h b/lib/libedit/map.h index 47dd84975e4..5eacd97512d 100644 --- a/lib/libedit/map.h +++ b/lib/libedit/map.h @@ -1,5 +1,5 @@ -/* $OpenBSD: map.h,v 1.6 2003/06/02 20:18:40 millert Exp $ */ -/* $NetBSD: map.h,v 1.2 1997/01/11 06:48:01 lukem Exp $ */ +/* $OpenBSD: map.h,v 1.7 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: map.h,v 1.8 2003/08/07 16:44:32 agc Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -39,37 +39,38 @@ * el.map.h: Editor maps */ #ifndef _h_el_map -#define _h_el_map +#define _h_el_map typedef struct el_bindings_t { /* for the "bind" shell command */ - const char *name; /* function name for bind command */ - int func; /* function numeric value */ - const char *description; /* description of function */ + const char *name; /* function name for bind command */ + int func; /* function numeric value */ + const char *description; /* description of function */ } el_bindings_t; typedef struct el_map_t { - el_action_t *alt; /* The current alternate key map */ - el_action_t *key; /* The current normal key map */ - el_action_t *current; /* The keymap we are using */ - el_action_t *emacs; /* The default emacs key map */ - el_action_t *vic; /* The vi command mode key map */ - el_action_t *vii; /* The vi insert mode key map */ - int type; /* Emacs or vi */ - el_bindings_t *help; /* The help for the editor functions */ - el_func_t *func; /* List of available functions */ - int nfunc; /* The number of functions/help items */ + el_action_t *alt; /* The current alternate key map */ + el_action_t *key; /* The current normal key map */ + el_action_t *current; /* The keymap we are using */ + const el_action_t *emacs; /* The default emacs key map */ + const el_action_t *vic; /* The vi command mode key map */ + const el_action_t *vii; /* The vi insert mode key map */ + int type; /* Emacs or vi */ + el_bindings_t *help; /* The help for the editor functions */ + el_func_t *func; /* List of available functions */ + int nfunc; /* The number of functions/help items */ } el_map_t; -#define MAP_EMACS 0 -#define MAP_VI 1 +#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 *); protected void map_init_emacs(EditLine *); protected int map_set_editor(EditLine *, char *); +protected int map_get_editor(EditLine *, const char **); protected int map_addfunc(EditLine *, const char *, const char *, el_func_t); #endif /* _h_el_map */ diff --git a/lib/libedit/parse.c b/lib/libedit/parse.c index 3720b9a46be..a884e8bc866 100644 --- a/lib/libedit/parse.c +++ b/lib/libedit/parse.c @@ -1,5 +1,5 @@ -/* $OpenBSD: parse.c,v 1.6 2003/06/02 20:18:40 millert Exp $ */ -/* $NetBSD: parse.c,v 1.5 1997/01/11 09:57:08 lukem Exp $ */ +/* $OpenBSD: parse.c,v 1.7 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: parse.c,v 1.17 2003/08/07 16:44:32 agc Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -33,11 +33,12 @@ * SUCH DAMAGE. */ +#include "config.h" #if !defined(lint) && !defined(SCCSID) #if 0 static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/4/93"; #else -static const char rcsid[] = "$OpenBSD: parse.c,v 1.6 2003/06/02 20:18:40 millert Exp $"; +static const char rcsid[] = "$OpenBSD: parse.c,v 1.7 2003/10/31 08:42:24 otto Exp $"; #endif #endif /* not lint && not SCCSID */ @@ -48,26 +49,28 @@ static const char rcsid[] = "$OpenBSD: parse.c,v 1.6 2003/06/02 20:18:40 millert * * bind * echotc + * edit * gettc * history * settc * setty */ -#include "sys.h" #include "el.h" #include "tokenizer.h" +#include <stdlib.h> -private struct { - char *name; - int (*func)(EditLine *, int, char **); +private const struct { + const char *name; + int (*func)(EditLine *, int, const char **); } cmds[] = { - { "bind", map_bind }, - { "echotc", term_echotc }, - { "history", hist_list }, - { "telltc", term_telltc }, - { "settc", term_settc }, - { "setty", tty_stty }, - { NULL, NULL } + { "bind", map_bind }, + { "echotc", term_echotc }, + { "edit", el_editmode }, + { "history", hist_command }, + { "telltc", term_telltc }, + { "settc", term_settc }, + { "setty", tty_stty }, + { NULL, NULL } }; @@ -75,51 +78,58 @@ private struct { * Parse a line and dispatch it */ protected int -parse_line(el, line) - EditLine *el; - const char *line; +parse_line(EditLine *el, const char *line) { - char **argv; - int argc; - Tokenizer *tok; - - tok = tok_init(NULL); - tok_line(tok, line, &argc, &argv); - argc = el_parse(el, argc, argv); - tok_end(tok); - return argc; + const char **argv; + int argc; + Tokenizer *tok; + + tok = tok_init(NULL); + tok_line(tok, line, &argc, &argv); + argc = el_parse(el, argc, argv); + tok_end(tok); + return (argc); } + /* el_parse(): * Command dispatcher */ public int -el_parse(el, argc, argv) - EditLine *el; - int argc; - char *argv[]; +el_parse(EditLine *el, int argc, const char *argv[]) { - char *ptr; - int i; - - if (argc < 1) - return -1; - ptr = strchr(argv[0], ':'); - if (ptr != NULL) { - *ptr++ = '\0'; - if (! el_match(el->el_prog, argv[0])) - return 0; - } - else - ptr = argv[0]; - - for (i = 0; cmds[i].name != NULL; i++) - if (strcmp(cmds[i].name, ptr) == 0) { - i = (*cmds[i].func)(el, argc, argv); - return -i; - } - - return -1; + const char *ptr; + int i; + + if (argc < 1) + return (-1); + ptr = strchr(argv[0], ':'); + if (ptr != NULL) { + char *tprog; + size_t l; + + if (ptr == argv[0]) + return (0); + l = ptr - argv[0] - 1; + tprog = (char *) el_malloc(l + 1); + if (tprog == NULL) + return (0); + (void) strncpy(tprog, argv[0], l); + tprog[l] = '\0'; + ptr++; + l = el_match(el->el_prog, tprog); + el_free(tprog); + if (!l) + return (0); + } else + ptr = argv[0]; + + for (i = 0; cmds[i].name != NULL; i++) + if (strcmp(cmds[i].name, ptr) == 0) { + i = (*cmds[i].func) (el, argc, argv); + return (-i); + } + return (-1); } @@ -128,125 +138,119 @@ el_parse(el, argc, argv) * the appropriate character or -1 if the escape is not valid */ protected int -parse__escape(ptr) - const char ** const ptr; +parse__escape(const char **const ptr) { - const char *p; - int c; - - p = *ptr; - - if (p[1] == 0) - return -1; - - if (*p == '\\') { - p++; - switch (*p) { - case 'a': - c = '\007'; /* Bell */ - break; - case 'b': - c = '\010'; /* Backspace */ - break; - case 't': - c = '\011'; /* Horizontal Tab */ - break; - case 'n': - c = '\012'; /* New Line */ - break; - case 'v': - c = '\013'; /* Vertical Tab */ - break; - case 'f': - c = '\014'; /* Form Feed */ - break; - case 'r': - c = '\015'; /* Carriage Return */ - break; - case 'e': - c = '\033'; /* Escape */ - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - { - int cnt, ch; - - for (cnt = 0, c = 0; cnt < 3; cnt++) { - ch = *p++; - if (ch < '0' || ch > '7') { - p--; + const char *p; + int c; + + p = *ptr; + + if (p[1] == 0) + return (-1); + + if (*p == '\\') { + p++; + switch (*p) { + case 'a': + c = '\007'; /* Bell */ + break; + case 'b': + c = '\010'; /* Backspace */ + break; + case 't': + c = '\011'; /* Horizontal Tab */ + break; + case 'n': + c = '\012'; /* New Line */ + break; + case 'v': + c = '\013'; /* Vertical Tab */ + break; + case 'f': + c = '\014'; /* Form Feed */ + break; + case 'r': + c = '\015'; /* Carriage Return */ + break; + case 'e': + c = '\033'; /* Escape */ + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + { + int cnt, ch; + + for (cnt = 0, c = 0; cnt < 3; cnt++) { + ch = *p++; + if (ch < '0' || ch > '7') { + p--; + break; + } + c = (c << 3) | (ch - '0'); + } + if ((c & 0xffffff00) != 0) + return (-1); + --p; break; - } - c = (c << 3) | (ch - '0'); } - if ((c & 0xffffff00) != 0) - return -1; - --p; - } - break; - default: - c = *p; - break; - } - } - else if (*p == '^' && isalpha((unsigned char) p[1])) { - p++; - c = (*p == '?') ? '\177' : (*p & 0237); - } - else - c = *p; - *ptr = ++p; - return c; + default: + c = *p; + break; + } + } else if (*p == '^' && isalpha((unsigned char) p[1])) { + p++; + c = (*p == '?') ? '\177' : (*p & 0237); + } else + c = *p; + *ptr = ++p; + return (c); } - /* parse__string(): * Parse the escapes from in and put the raw string out */ protected char * -parse__string(out, in) - char *out; - const char *in; +parse__string(char *out, const char *in) { - char *rv = out; - int n; - for (;;) - switch (*in) { - case '\0': - *out = '\0'; - return rv; - - case '\\': - case '^': - if ((n = parse__escape(&in)) == -1) - return NULL; - *out++ = n; - break; - - default: - *out++ = *in++; - break; - } + char *rv = out; + int n; + + for (;;) + switch (*in) { + case '\0': + *out = '\0'; + return (rv); + + case '\\': + case '^': + if ((n = parse__escape(&in)) == -1) + return (NULL); + *out++ = n; + break; + + default: + *out++ = *in++; + break; + } } + /* parse_cmd(): * Return the command number for the command string given * or -1 if one is not found */ protected int -parse_cmd(el, cmd) - EditLine *el; - const char *cmd; +parse_cmd(EditLine *el, const char *cmd) { - el_bindings_t *b; + el_bindings_t *b; - for (b = el->el_map.help; b->name != NULL; b++) - if (strcmp(b->name, cmd) == 0) - return b->func; - return -1; + for (b = el->el_map.help; b->name != NULL; b++) + if (strcmp(b->name, cmd) == 0) + return (b->func); + return (-1); } diff --git a/lib/libedit/parse.h b/lib/libedit/parse.h index f2a2ed2a539..51b1207c89a 100644 --- a/lib/libedit/parse.h +++ b/lib/libedit/parse.h @@ -1,5 +1,5 @@ -/* $OpenBSD: parse.h,v 1.5 2003/06/02 20:18:40 millert Exp $ */ -/* $NetBSD: parse.h,v 1.2 1997/01/11 06:48:03 lukem Exp $ */ +/* $OpenBSD: parse.h,v 1.6 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: parse.h,v 1.5 2003/08/07 16:44:32 agc Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -39,11 +39,11 @@ * el.parse.h: Parser functions */ #ifndef _h_el_parse -#define _h_el_parse +#define _h_el_parse -protected int parse_line(EditLine *, const char *); -protected int parse__escape(const char ** const); -protected char * parse__string(char *, const char *); -protected int parse_cmd(EditLine *, const char *); +protected int parse_line(EditLine *, const char *); +protected int parse__escape(const char ** const); +protected char *parse__string(char *, const char *); +protected int parse_cmd(EditLine *, const char *); #endif /* _h_el_parse */ diff --git a/lib/libedit/prompt.c b/lib/libedit/prompt.c index 9fe65adaa12..a7454a1d599 100644 --- a/lib/libedit/prompt.c +++ b/lib/libedit/prompt.c @@ -1,5 +1,5 @@ -/* $OpenBSD: prompt.c,v 1.6 2003/06/02 20:18:40 millert Exp $ */ -/* $NetBSD: prompt.c,v 1.2 1997/01/11 06:48:04 lukem Exp $ */ +/* $OpenBSD: prompt.c,v 1.7 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: prompt.c,v 1.11 2003/08/07 16:44:32 agc Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -33,33 +33,47 @@ * SUCH DAMAGE. */ +#include "config.h" #if !defined(lint) && !defined(SCCSID) #if 0 static char sccsid[] = "@(#)prompt.c 8.1 (Berkeley) 6/4/93"; #else -static const char rcsid[] = "$OpenBSD: prompt.c,v 1.6 2003/06/02 20:18:40 millert Exp $"; +static const char rcsid[] = "$OpenBSD: prompt.c,v 1.7 2003/10/31 08:42:24 otto Exp $"; #endif #endif /* not lint && not SCCSID */ /* * prompt.c: Prompt printing functions */ -#include "sys.h" #include <stdio.h> #include "el.h" -private char *prompt_default(EditLine *); +private char *prompt_default(EditLine *); +private char *prompt_default_r(EditLine *); /* prompt_default(): * Just a default prompt, in case the user did not provide one */ private char * /*ARGSUSED*/ -prompt_default(el) - EditLine *el; +prompt_default(EditLine *el __attribute__((__unused__))) { - static char a[3] = { '?', ' ', '\0' }; - return a; + static char a[3] = {'?', ' ', '\0'}; + + return (a); +} + + +/* prompt_default_r(): + * Just a default rprompt, in case the user did not provide one + */ +private char * +/*ARGSUSED*/ +prompt_default_r(EditLine *el __attribute__((__unused__))) +{ + static char a[1] = {'\0'}; + + return (a); } @@ -70,57 +84,88 @@ prompt_default(el) * bit to flag them */ protected void -prompt_print(el) - EditLine *el; +prompt_print(EditLine *el, int op) { - char *p = (*el->el_prompt.p_func)(el); - while (*p) - re_putc(el, *p++); + el_prompt_t *elp; + char *p; - el->el_prompt.p_pos.v = el->el_refresh.r_cursor.v; - el->el_prompt.p_pos.h = el->el_refresh.r_cursor.h; + if (op == EL_PROMPT) + elp = &el->el_prompt; + else + elp = &el->el_rprompt; + p = (elp->p_func) (el); + while (*p) + re_putc(el, *p++, 1); -} /* end prompt_print */ + elp->p_pos.v = el->el_refresh.r_cursor.v; + elp->p_pos.h = el->el_refresh.r_cursor.h; +} /* prompt_init(): * Initialize the prompt stuff */ -protected int -prompt_init(el) - EditLine *el; +protected int +prompt_init(EditLine *el) { - el->el_prompt.p_func = prompt_default; - el->el_prompt.p_pos.v = 0; - el->el_prompt.p_pos.h = 0; - return 0; -} /* end prompt_init */ + + el->el_prompt.p_func = prompt_default; + el->el_prompt.p_pos.v = 0; + el->el_prompt.p_pos.h = 0; + el->el_rprompt.p_func = prompt_default_r; + el->el_rprompt.p_pos.v = 0; + el->el_rprompt.p_pos.h = 0; + return (0); +} /* prompt_end(): * Clean up the prompt stuff */ protected void -/*ARGSUSED*/ -prompt_end(el) - EditLine *el; +/*ARGSUSED*/ +prompt_end(EditLine *el __attribute__((__unused__))) { -} /* end prompt_end */ +} /* prompt_set(): * Install a prompt printing function */ -protected int -prompt_set(el, prf) - EditLine *el; - el_pfunc_t prf; +protected int +prompt_set(EditLine *el, el_pfunc_t prf, int op) { - if (prf == NULL) - el->el_prompt.p_func = prompt_default; - else - el->el_prompt.p_func = prf; - el->el_prompt.p_pos.v = 0; - el->el_prompt.p_pos.h = 0; - return 0; -} /* end prompt_set */ + el_prompt_t *p; + + if (op == EL_PROMPT) + p = &el->el_prompt; + else + p = &el->el_rprompt; + if (prf == NULL) { + if (op == EL_PROMPT) + p->p_func = prompt_default; + else + p->p_func = prompt_default_r; + } else + p->p_func = prf; + p->p_pos.v = 0; + p->p_pos.h = 0; + return (0); +} + + +/* prompt_get(): + * Retrieve the prompt printing function + */ +protected int +prompt_get(EditLine *el, el_pfunc_t *prf, int op) +{ + + if (prf == NULL) + return (-1); + if (op == EL_PROMPT) + *prf = el->el_prompt.p_func; + else + *prf = el->el_rprompt.p_func; + return (0); +} diff --git a/lib/libedit/prompt.h b/lib/libedit/prompt.h index 6318315b925..9236fcbffc0 100644 --- a/lib/libedit/prompt.h +++ b/lib/libedit/prompt.h @@ -1,5 +1,5 @@ -/* $OpenBSD: prompt.h,v 1.5 2003/06/02 20:18:40 millert Exp $ */ -/* $NetBSD: prompt.h,v 1.2 1997/01/11 06:48:05 lukem Exp $ */ +/* $OpenBSD: prompt.h,v 1.6 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: prompt.h,v 1.6 2003/08/07 16:44:32 agc Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -39,20 +39,21 @@ * el.prompt.h: Prompt printing stuff */ #ifndef _h_el_prompt -#define _h_el_prompt +#define _h_el_prompt #include "histedit.h" typedef char * (*el_pfunc_t)(EditLine*); typedef struct el_prompt_t { - el_pfunc_t p_func; /* Function to return the prompt */ - coord_t p_pos; /* position in the line after prompt */ + el_pfunc_t p_func; /* Function to return the prompt */ + coord_t p_pos; /* position in the line after prompt */ } el_prompt_t; -protected void prompt_print(EditLine *); -protected int prompt_set(EditLine *, el_pfunc_t); -protected int prompt_init(EditLine *); -protected void prompt_end(EditLine *); +protected void prompt_print(EditLine *, int); +protected int prompt_set(EditLine *, el_pfunc_t, int); +protected int prompt_get(EditLine *, el_pfunc_t *, int); +protected int prompt_init(EditLine *); +protected void prompt_end(EditLine *); #endif /* _h_el_prompt */ diff --git a/lib/libedit/read.c b/lib/libedit/read.c index 81ae6446fda..0eedfeea778 100644 --- a/lib/libedit/read.c +++ b/lib/libedit/read.c @@ -1,5 +1,5 @@ -/* $OpenBSD: read.c,v 1.9 2003/06/02 20:18:40 millert Exp $ */ -/* $NetBSD: read.c,v 1.4 1997/04/11 17:52:47 christos Exp $ */ +/* $OpenBSD: read.c,v 1.10 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: read.c,v 1.28 2003/09/26 17:44:51 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -33,11 +33,12 @@ * SUCH DAMAGE. */ +#include "config.h" #if !defined(lint) && !defined(SCCSID) #if 0 static char sccsid[] = "@(#)read.c 8.1 (Berkeley) 6/4/93"; #else -static const char rcsid[] = "$OpenBSD: read.c,v 1.9 2003/06/02 20:18:40 millert Exp $"; +static const char rcsid[] = "$OpenBSD: read.c,v 1.10 2003/10/31 08:42:24 otto Exp $"; #endif #endif /* not lint && not SCCSID */ @@ -45,92 +46,137 @@ static const char rcsid[] = "$OpenBSD: read.c,v 1.9 2003/06/02 20:18:40 millert * read.c: Clean this junk up! This is horrible code. * Terminal read functions */ -#include "sys.h" -#include <sys/errno.h> +#include <errno.h> +#include <fcntl.h> #include <unistd.h> #include <stdlib.h> -extern int errno; #include "el.h" -#define OKCMD -1 +#define OKCMD -1 -private int read__fixio(int, int); -private int read_preread(EditLine *); -private int read_getcmd(EditLine *, el_action_t *, char *); +private int read__fixio(int, int); +private int read_preread(EditLine *); +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 -read_debug(el) - EditLine *el; +read_debug(EditLine *el) { - if (el->el_line.cursor > el->el_line.lastchar) - (void)fprintf(el->el_errfile, "cursor > lastchar\r\n"); - if (el->el_line.cursor < el->el_line.buffer) - (void)fprintf(el->el_errfile, "cursor < buffer\r\n"); - if (el->el_line.cursor > el->el_line.limit) - (void)fprintf(el->el_errfile, "cursor > limit\r\n"); - if (el->el_line.lastchar > el->el_line.limit) - (void)fprintf(el->el_errfile, "lastchar > limit\r\n"); - if (el->el_line.limit != &el->el_line.buffer[EL_BUFSIZ - 2]) - (void)fprintf(el->el_errfile, "limit != &buffer[EL_BUFSIZ-2]\r\n"); + if (el->el_line.cursor > el->el_line.lastchar) + (void) fprintf(el->el_errfile, "cursor > lastchar\r\n"); + if (el->el_line.cursor < el->el_line.buffer) + (void) fprintf(el->el_errfile, "cursor < buffer\r\n"); + if (el->el_line.cursor > el->el_line.limit) + (void) fprintf(el->el_errfile, "cursor > limit\r\n"); + if (el->el_line.lastchar > el->el_line.limit) + (void) fprintf(el->el_errfile, "lastchar > limit\r\n"); + if (el->el_line.limit != &el->el_line.buffer[EL_BUFSIZ - 2]) + (void) fprintf(el->el_errfile, "limit != &buffer[EL_BUFSIZ-2]\r\n"); } #endif /* DEBUG_EDIT */ + /* read__fixio(): * Try to recover from a read error */ +/* ARGSUSED */ private int -read__fixio(fd, e) - int fd, e; +read__fixio(int fd __attribute__((__unused__)), int e) { - switch (e) { - case -1: /* Make sure that the code is reachable */ + + switch (e) { + case -1: /* Make sure that the code is reachable */ #ifdef EWOULDBLOCK - case EWOULDBLOCK: -# ifndef TRY_AGAIN -# define TRY_AGAIN -# endif + case EWOULDBLOCK: +#ifndef TRY_AGAIN +#define TRY_AGAIN +#endif #endif /* EWOULDBLOCK */ #if defined(POSIX) && defined(EAGAIN) -# if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN - case EAGAIN: -# ifndef TRY_AGAIN -# define TRY_AGAIN -# endif -# endif /* EWOULDBLOCK && EWOULDBLOCK != EAGAIN */ +#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN + case EAGAIN: +#ifndef TRY_AGAIN +#define TRY_AGAIN +#endif +#endif /* EWOULDBLOCK && EWOULDBLOCK != EAGAIN */ #endif /* POSIX && EAGAIN */ - e = 0; + e = 0; #ifdef TRY_AGAIN -# if defined(F_SETFL) && defined(O_NDELAY) - if ((e = fcntl(fd, F_GETFL, 0)) == -1) - return -1; - - if (fcntl(fd, F_SETFL, e & ~O_NDELAY) == -1) - return -1; - else - e = 1; -# endif /* F_SETFL && O_NDELAY */ - -# ifdef FIONBIO - if (ioctl(fd, FIONBIO, (ioctl_t) &e) == -1) - return -1; - else - e = 1; -# endif /* FIONBIO */ +#if defined(F_SETFL) && defined(O_NDELAY) + if ((e = fcntl(fd, F_GETFL, 0)) == -1) + return (-1); + + if (fcntl(fd, F_SETFL, e & ~O_NDELAY) == -1) + return (-1); + else + e = 1; +#endif /* F_SETFL && O_NDELAY */ + +#ifdef FIONBIO + { + int zero = 0; + + if (ioctl(fd, FIONBIO, (ioctl_t) & zero) == -1) + return (-1); + else + e = 1; + } +#endif /* FIONBIO */ #endif /* TRY_AGAIN */ - return e ? 0 : -1; + return (e ? 0 : -1); - case EINTR: - return 0; + case EINTR: + return (0); - default: - return -1; - } + default: + return (-1); + } } @@ -138,34 +184,33 @@ read__fixio(fd, e) * Try to read the stuff in the input queue; */ private int -read_preread(el) - EditLine *el; +read_preread(EditLine *el) { - int chrs = 0; + 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; + 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); #ifdef FIONREAD - (void)ioctl(el->el_infd, FIONREAD, (ioctl_t) &chrs); - if (chrs > 0) { - char buf[EL_BUFSIZ]; - - chrs = read(el->el_infd, buf, (size_t) MIN(chrs, EL_BUFSIZ - 1)); + (void) ioctl(el->el_infd, FIONREAD, (ioctl_t) & chrs); if (chrs > 0) { - buf[chrs] = '\0'; - el->el_chared.c_macro.nline = strdup(buf); - el_push(el, el->el_chared.c_macro.nline); + char buf[EL_BUFSIZ]; + + chrs = read(el->el_infd, buf, + (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); + } } - } -#endif /* FIONREAD */ +#endif /* FIONREAD */ - return chrs > 0; + return (chrs > 0); } @@ -173,20 +218,17 @@ read_preread(el) * Push a macro */ public void -el_push(el, str) - 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++; - ma->macro[ma->level] = (char *) str; - } - else { - term_beep(el); - term__flush(); - } + c_macro_t *ma = &el->el_chared.c_macro; + + if (str != NULL && ma->level + 1 < EL_MAXMACRO) { + ma->level++; + ma->macro[ma->level] = str; + } else { + term_beep(el); + term__flush(); + } } @@ -194,57 +236,74 @@ el_push(el, str) * Return next command from the input stream. */ private int -read_getcmd(el, cmdnum, ch) - EditLine *el; - el_action_t *cmdnum; - char *ch; +read_getcmd(EditLine *el, el_action_t *cmdnum, char *ch) { - el_action_t cmd = 0; - int num; + el_action_t cmd; + int num; - while (cmd == 0 || cmd == ED_SEQUENCE_LEAD_IN) { - if ((num = el_getc(el, ch)) != 1) /* if EOF or error */ - return num; + do { + if ((num = el_getc(el, ch)) != 1) /* if EOF or error */ + return (num); #ifdef KANJI - if ((*ch & 0200)) { - el->el_state.metanext = 0; - cmd = CcViMap[' ']; - break; - } - else + if ((*ch & 0200)) { + el->el_state.metanext = 0; + cmd = CcViMap[' ']; + break; + } else #endif /* KANJI */ - if (el->el_state.metanext) { - el->el_state.metanext = 0; - *ch |= 0200; - } - cmd = el->el_map.current[(unsigned char) *ch]; - if (cmd == ED_SEQUENCE_LEAD_IN) { - key_value_t val; - switch (key_get(el, ch, &val)) { - case XK_CMD: - cmd = val.cmd; - break; - case XK_STR: - el_push(el, val.str); - break; + if (el->el_state.metanext) { + el->el_state.metanext = 0; + *ch |= 0200; + } + cmd = el->el_map.current[(unsigned char) *ch]; + if (cmd == ED_SEQUENCE_LEAD_IN) { + key_value_t val; + switch (key_get(el, ch, &val)) { + case XK_CMD: + cmd = val.cmd; + break; + case XK_STR: + el_push(el, val.str); + break; #ifdef notyet - case XK_EXE: - /* XXX: In the future to run a user function */ - RunCommand(val.str); - break; + case XK_EXE: + /* XXX: In the future to run a user function */ + RunCommand(val.str); + break; #endif - default: - abort(); - break; - } - } - if (el->el_map.alt == NULL) - el->el_map.current = el->el_map.key; - } - *cmdnum = cmd; - return OKCMD; + default: + EL_ABORT((el->el_errfile, "Bad XK_ type \n")); + break; + } + } + if (el->el_map.alt == NULL) + el->el_map.current = el->el_map.key; + } while (cmd == ED_SEQUENCE_LEAD_IN); + *cmdnum = cmd; + return (OKCMD); +} + + +/* read_char(): + * Read a character from the tty. + */ +private int +read_char(EditLine *el, char *cp) +{ + int num_read; + int tried = 0; + + while ((num_read = read(el->el_infd, cp, 1)) == -1) + if (!tried && read__fixio(el->el_infd, errno) == 0) + tried = 1; + else { + *cp = '\0'; + return (-1); + } + + return (num_read); } @@ -252,201 +311,292 @@ read_getcmd(el, cmdnum, ch) * Read a character */ public int -el_getc(el, cp) - EditLine *el; - char *cp; +el_getc(EditLine *el, char *cp) { - int num_read; - unsigned char tcp; - int tried = 0; - - c_macro_t *ma = &el->el_chared.c_macro; + int num_read; + c_macro_t *ma = &el->el_chared.c_macro; - term__flush(); - for (;;) { - if (ma->level < 0) { - if (!read_preread(el)) - break; - } - if (ma->level < 0) - break; - - if (*ma->macro[ma->level] == 0) { - ma->level--; - continue; - } - *cp = *ma->macro[ma->level]++ & 0377; - if (*ma->macro[ma->level] == 0) { /* Needed for QuoteMode On */ - ma->level--; + term__flush(); + for (;;) { + if (ma->level < 0) { + if (!read_preread(el)) + break; + } + if (ma->level < 0) + break; + + if (*ma->macro[ma->level] == 0) { + ma->level--; + continue; + } + *cp = *ma->macro[ma->level]++ & 0377; + if (*ma->macro[ma->level] == 0) { /* Needed for QuoteMode + * On */ + ma->level--; + } + return (1); } - return 1; - } #ifdef DEBUG_READ - (void)fprintf(el->el_errfile, "Turning raw mode on\n"); + (void) fprintf(el->el_errfile, "Turning raw mode on\n"); #endif /* DEBUG_READ */ - if (tty_rawmode(el) < 0) /* make sure the tty is set up correctly */ - return 0; + if (tty_rawmode(el) < 0)/* make sure the tty is set up correctly */ + return (0); #ifdef DEBUG_READ - (void)fprintf(el->el_errfile, "Reading a character\n"); + (void) fprintf(el->el_errfile, "Reading a character\n"); #endif /* DEBUG_READ */ - while ((num_read = read(el->el_infd, (char *) &tcp, 1)) == -1) - if (!tried && read__fixio(el->el_infd, errno) == 0) - tried = 1; - else { - *cp = '\0'; - return -1; - } + num_read = (*el->el_read.read_char)(el, cp); #ifdef DEBUG_READ - (void)fprintf(el->el_errfile, "Got it %c\n", tcp); + (void) fprintf(el->el_errfile, "Got it %c\n", *cp); #endif /* DEBUG_READ */ - *cp = tcp; - return num_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); + re_refresh(el); /* print the prompt */ +} +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(el, nread) - EditLine *el; - int *nread; +el_gets(EditLine *el, int *nread) { - int retval; - el_action_t cmdnum = 0; - int num; /* how many chars we have read at NL */ - char ch; + int retval; + 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; + 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 ((*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); + if (!ch_enlargebufs(el, 2)) + break; + cp = &el->el_line.buffer[idx]; + } + cp++; + if (el->el_flags & UNBUFFERED) + break; + if (cp[-1] == '\r' || cp[-1] == '\n') + break; + } + + el->el_line.cursor = el->el_line.lastchar = cp; + *cp = '\0'; + if (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) { - int chrs = 0; - - (void)ioctl(el->el_infd, FIONREAD, (ioctl_t) &chrs); - if (chrs == 0) { - if (tty_rawmode(el) < 0) { - if (nread) - *nread = 0; - return NULL; - } + if (el->el_tty.t_mode == EX_IO && ma->level < 0) { + long chrs = 0; + + (void) ioctl(el->el_infd, FIONREAD, (ioctl_t) & chrs); + if (chrs == 0) { + if (tty_rawmode(el) < 0) { + if (nread) + *nread = 0; + return (NULL); + } + } } - } #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; + size_t idx; + + term__flush(); + + 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); + if (!ch_enlargebufs(el, 2)) + break; + cp = &el->el_line.buffer[idx]; + } + if (*cp == 4) /* ought to be stty eof */ + break; + cp++; + crlf = cp[-1] == '\r' || cp[-1] == '\n'; + if (el->el_flags & UNBUFFERED) + break; + if (crlf) + break; + } + + el->el_line.cursor = el->el_line.lastchar = cp; + *cp = '\0'; + if (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 */ + for (num = OKCMD; num == OKCMD;) { /* while still editing this + * line */ #ifdef DEBUG_EDIT - read_debug(el); + read_debug(el); #endif /* DEBUG_EDIT */ - /* if EOF or error */ - if ((num = read_getcmd(el, &cmdnum, &ch)) != OKCMD) { + /* if EOF or error */ + if ((num = read_getcmd(el, &cmdnum, &ch)) != OKCMD) { #ifdef DEBUG_READ - (void)fprintf(el->el_errfile, "Returning from el_gets %d\n", num); + (void) fprintf(el->el_errfile, + "Returning from el_gets %d\n", num); #endif /* DEBUG_READ */ - break; - } - - if (cmdnum >= el->el_map.nfunc) { /* BUG CHECK command */ + break; + } + if ((uint)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); + (void) fprintf(el->el_errfile, + "ERROR: illegal command from key 0%o\r\n", ch); #endif /* DEBUG_EDIT */ - continue; /* try again */ - } - - /* now do the real command */ + continue; /* try again */ + } + /* now do the real command */ #ifdef DEBUG_READ - { - el_bindings_t *b; - for (b = el->el_map.help; b->name; b++) - if (b->func == cmdnum) - break; - if (b->name) - (void)fprintf(el->el_errfile, "Executing %s\n", b->name); - else - (void)fprintf(el->el_errfile, "Error command = %d\n", cmdnum); - } + { + el_bindings_t *b; + for (b = el->el_map.help; b->name; b++) + if (b->func == cmdnum) + break; + if (b->name) + (void) fprintf(el->el_errfile, + "Executing %s\n", b->name); + else + (void) fprintf(el->el_errfile, + "Error command = %d\n", cmdnum); + } #endif /* DEBUG_READ */ - retval = (*el->el_map.func[cmdnum])(el, ch); - - /* save the last command here */ - el->el_state.lastcmd = cmdnum; - - /* use any return value */ - switch (retval) { - case CC_CURSOR: - el->el_state.argument = 1; - el->el_state.doingarg = 0; - re_refresh_cursor(el); - break; - - case CC_REDISPLAY: - re_clear_lines(el); - re_clear_display(el); - /* FALLTHROUGH */ - - case CC_REFRESH: - el->el_state.argument = 1; - el->el_state.doingarg = 0; - re_refresh(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 */ - /* <rsalz@pineapple.bbn.com> */ - break; /* keep going... */ - - case CC_EOF: /* end of file typed */ - num = 0; - break; - - case CC_NEWLINE: /* normal end of line */ - num = el->el_line.lastchar - el->el_line.buffer; - break; - - case CC_FATAL: /* fatal error, reset to known state */ + /* 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(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, "*** editor fatal ERROR ***\r\n\n"); + (void) fprintf(el->el_errfile, + "Returned state %d\n", retval ); #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 */ - re_refresh(el); /* print the prompt again */ - el->el_state.argument = 1; - el->el_state.doingarg = 0; - break; - - case CC_ERROR: - default: /* functions we don't know about */ + + /* save the last command here */ + el->el_state.lastcmd = cmdnum; + + /* use any return value */ + switch (retval) { + case CC_CURSOR: + re_refresh_cursor(el); + break; + + case CC_REDISPLAY: + re_clear_lines(el); + re_clear_display(el); + /* FALLTHROUGH */ + + case CC_REFRESH: + re_refresh(el); + break; + + case CC_REFRESH_BEEP: + re_refresh(el); + term_beep(el); + break; + + case CC_NORM: /* normal char */ + break; + + case CC_ARGHACK: /* Suggested by Rich Salz */ + /* <rsalz@pineapple.bbn.com> */ + continue; /* keep going... */ + + case CC_EOF: /* end of file typed */ + num = 0; + break; + + case CC_NEWLINE: /* normal end of line */ + num = el->el_line.lastchar - el->el_line.buffer; + break; + + case CC_FATAL: /* fatal error, reset to known state */ +#ifdef DEBUG_READ + (void) fprintf(el->el_errfile, + "*** editor fatal ERROR ***\r\n\n"); +#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 */ + re_refresh(el); /* print the prompt again */ + break; + + case CC_ERROR: + default: /* functions we don't know about */ #ifdef DEBUG_READ - (void)fprintf(el->el_errfile, "*** editor ERROR ***\r\n\n"); + (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; + 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 */ + 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; } - } - - (void)tty_cookedmode(el); /* make sure the tty is set up correctly */ - term__flush(); /* flush any buffered output */ - if (el->el_flags & HANDLE_SIGNALS) - sig_clr(el); - if (nread) - *nread = num; - return num ? el->el_line.buffer : NULL; + return (num ? el->el_line.buffer : NULL); } diff --git a/lib/libedit/read.h b/lib/libedit/read.h new file mode 100644 index 00000000000..1db1092efbb --- /dev/null +++ b/lib/libedit/read.h @@ -0,0 +1,58 @@ +/* $OpenBSD: read.h,v 1.1 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: read.h,v 1.2 2003/09/26 17:44:51 christos Exp $ */ + +/*- + * 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. + */ + +/* + * 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/readline.c b/lib/libedit/readline.c new file mode 100644 index 00000000000..88077a275c6 --- /dev/null +++ b/lib/libedit/readline.c @@ -0,0 +1,1908 @@ +/* $OpenBSD: readline.c,v 1.1 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: readline.c,v 1.35 2003/09/26 17:44:51 christos Exp $ */ + +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jaromir Dolecek. + * + * 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. + */ + +#include "config.h" +#if !defined(lint) && !defined(SCCSID) +static const char rcsid[] = "$OpenBSD: readline.c,v 1.1 2003/10/31 08:42:24 otto Exp $"; +#endif /* not lint && not SCCSID */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <stdio.h> +#include <dirent.h> +#include <string.h> +#include <pwd.h> +#include <ctype.h> +#include <stdlib.h> +#include <unistd.h> +#include <limits.h> +#include <vis.h> +#ifdef HAVE_ALLOCA_H +#include <alloca.h> +#endif +#include "histedit.h" +#include "readline/readline.h" +#include "el.h" +#include "fcns.h" /* for EL_NUM_FCNS */ + +/* for rl_complete() */ +#define TAB '\r' + +/* see comment at the #ifdef for sense of this */ +#define GDB_411_HACK + +/* readline compatibility stuff - look at readline sources/documentation */ +/* to see what these variables mean */ +const char *rl_library_version = "EditLine wrapper"; +static char empty[] = { '\0' }; +static char expand_chars[] = { ' ', '\t', '\n', '=', '(', '\0' }; +static char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', '$', + '>', '<', '=', ';', '|', '&', '{', '(', '\0' }; +char *rl_readline_name = empty; +FILE *rl_instream = NULL; +FILE *rl_outstream = NULL; +int rl_point = 0; +int rl_end = 0; +char *rl_line_buffer = NULL; +VFunction *rl_linefunc = NULL; + +int history_base = 1; /* probably never subject to change */ +int history_length = 0; +int max_input_history = 0; +char history_expansion_char = '!'; +char history_subst_char = '^'; +char *history_no_expand_chars = expand_chars; +Function *history_inhibit_expansion_function = NULL; + +int rl_inhibit_completion = 0; +int rl_attempted_completion_over = 0; +char *rl_basic_word_break_characters = break_chars; +char *rl_completer_word_break_characters = NULL; +char *rl_completer_quote_characters = NULL; +Function *rl_completion_entry_function = NULL; +CPPFunction *rl_attempted_completion_function = NULL; +Function *rl_pre_input_hook = NULL; +Function *rl_startup1_hook = NULL; +Function *rl_getc_function = NULL; +char *rl_terminal_name = NULL; +int rl_already_prompted = 0; +int rl_filename_completion_desired = 0; +int rl_ignore_completion_duplicates = 0; +VFunction *rl_redisplay_function = NULL; +Function *rl_startup_hook = NULL; +VFunction *rl_completion_display_matches_hook = NULL; +VFunction *rl_prep_term_function = NULL; +VFunction *rl_deprep_term_function = NULL; + +/* + * The current prompt string. + */ +char *rl_prompt = NULL; +/* + * This is set to character indicating type of completion being done by + * rl_complete_internal(); this is available for application completion + * functions. + */ +int rl_completion_type = 0; + +/* + * If more than this number of items results from query for possible + * completions, we ask user if they are sure to really display the list. + */ +int rl_completion_query_items = 100; + +/* + * List of characters which are word break characters, but should be left + * in the parsed text when it is passed to the completion function. + * Shell uses this to help determine what kind of completing to do. + */ +char *rl_special_prefixes = (char *)NULL; + +/* + * This is the character appended to the completed words if at the end of + * the line. Default is ' ' (a space). + */ +int rl_completion_append_character = ' '; + +/* stuff below is used internally by libedit for readline emulation */ + +/* if not zero, non-unique completions always show list of possible matches */ +static int _rl_complete_show_all = 0; + +static History *h = NULL; +static EditLine *e = NULL; +static Function *map[256]; +static int el_rl_complete_cmdnum = 0; + +/* internal functions */ +static unsigned char _el_rl_complete(EditLine *, int); +static char *_get_prompt(EditLine *); +static HIST_ENTRY *_move_history(int); +static int _history_search_gen(const char *, int, int); +static int _history_expand_command(const char *, size_t, char **); +static char *_rl_compat_sub(const char *, const char *, + const char *, int); +static int rl_complete_internal(int); +static int _rl_qsort_string_compare(const void *, const void *); + + +/* ARGSUSED */ +static char * +_get_prompt(EditLine *el __attribute__((__unused__))) +{ + rl_already_prompted = 1; + return (rl_prompt); +} + + +/* + * generic function for moving around history + */ +static HIST_ENTRY * +_move_history(int op) +{ + HistEvent ev; + static HIST_ENTRY rl_he; + + if (history(h, &ev, op) != 0) + return (HIST_ENTRY *) NULL; + + rl_he.line = ev.str; + rl_he.data = ""; + + return (&rl_he); +} + + +/* + * READLINE compatibility stuff + */ + +/* + * initialize rl compat stuff + */ +int +rl_initialize(void) +{ + HistEvent ev; + const LineInfo *li; + int i; + int editmode = 1; + struct termios t; + + if (e != NULL) + el_end(e); + if (h != NULL) + history_end(h); + + if (!rl_instream) + rl_instream = stdin; + if (!rl_outstream) + rl_outstream = stdout; + + /* + * See if we don't really want to run the editor + */ + if (tcgetattr(fileno(rl_instream), &t) != -1 && (t.c_lflag & ECHO) == 0) + editmode = 0; + + e = el_init(rl_readline_name, rl_instream, rl_outstream, stderr); + + if (!editmode) + el_set(e, EL_EDITMODE, 0); + + h = history_init(); + if (!e || !h) + return (-1); + + history(h, &ev, H_SETSIZE, INT_MAX); /* unlimited */ + history_length = 0; + max_input_history = INT_MAX; + el_set(e, EL_HIST, history, h); + + /* for proper prompt printing in readline() */ + rl_prompt = strdup(""); + if (rl_prompt == NULL) { + history_end(h); + el_end(e); + return -1; + } + el_set(e, EL_PROMPT, _get_prompt); + el_set(e, EL_SIGNAL, 1); + + /* set default mode to "emacs"-style and read setting afterwards */ + /* so this can be overriden */ + el_set(e, EL_EDITOR, "emacs"); + if (rl_terminal_name != NULL) + el_set(e, EL_TERMINAL, rl_terminal_name); + else + el_get(e, EL_TERMINAL, &rl_terminal_name); + + /* + * Word completion - this has to go AFTER rebinding keys + * to emacs-style. + */ + el_set(e, EL_ADDFN, "rl_complete", + "ReadLine compatible completion function", + _el_rl_complete); + el_set(e, EL_BIND, "^I", "rl_complete", NULL); + /* + * Find out where the rl_complete function was added; this is + * used later to detect that lastcmd was also rl_complete. + */ + for(i=EL_NUM_FCNS; i < e->el_map.nfunc; i++) { + if (e->el_map.func[i] == _el_rl_complete) { + el_rl_complete_cmdnum = i; + break; + } + } + + /* read settings from configuration file */ + el_source(e, NULL); + + /* + * Unfortunately, some applications really do use rl_point + * and rl_line_buffer directly. + */ + li = el_line(e); + /* a cheesy way to get rid of const cast. */ + rl_line_buffer = memchr(li->buffer, *li->buffer, 1); + rl_point = rl_end = 0; + + if (rl_startup_hook) + (*rl_startup_hook)(NULL, 0); + + return (0); +} + + +/* + * read one line from input stream and return it, chomping + * trailing newline (if there is any) + */ +char * +readline(const char *prompt) +{ + HistEvent ev; + int count; + const char *ret; + char *buf; + + if (e == NULL || h == NULL) + rl_initialize(); + + /* update prompt accordingly to what has been passed */ + if (!prompt) + prompt = ""; + if (strcmp(rl_prompt, prompt) != 0) { + free(rl_prompt); + rl_prompt = strdup(prompt); + if (rl_prompt == NULL) + return NULL; + } + + if (rl_pre_input_hook) + (*rl_pre_input_hook)(NULL, 0); + + rl_already_prompted = 0; + + /* get one line from input stream */ + ret = el_gets(e, &count); + + if (ret && count > 0) { + int lastidx; + + buf = strdup(ret); + if (buf == NULL) + return NULL; + lastidx = count - 1; + if (buf[lastidx] == '\n') + buf[lastidx] = '\0'; + } else + buf = NULL; + + history(h, &ev, H_GETSIZE); + history_length = ev.num; + + return buf; +} + +/* + * history functions + */ + +/* + * is normally called before application starts to use + * history expansion functions + */ +void +using_history(void) +{ + if (h == NULL || e == NULL) + rl_initialize(); +} + + +/* + * substitute ``what'' with ``with'', returning resulting string; if + * globally == 1, substitutes all occurrences of what, otherwise only the + * first one + */ +static char * +_rl_compat_sub(const char *str, const char *what, const char *with, + int globally) +{ + char *result; + const char *temp, *new; + size_t len, with_len, what_len, add; + size_t size, i; + + result = malloc((size = 16)); + if (result == NULL) + return NULL; + temp = str; + with_len = strlen(with); + what_len = strlen(what); + len = 0; + do { + new = strstr(temp, what); + if (new) { + i = new - temp; + add = i + with_len; + if (i + add + 1 >= size) { + char *nresult; + size += add + 1; + nresult = realloc(result, size); + if (nresult == NULL) { + free(result); + return NULL; + } + result = nresult; + } + (void) strncpy(&result[len], temp, i); + len += i; + (void) strlcpy(&result[len], with, size - len); + len += with_len; + temp = new + what_len; + } else { + add = strlen(temp); + if (len + add + 1 >= size) { + char *nresult; + size += add + 1; + nresult = realloc(result, size); + if (nresult == NULL) { + free(result); + return NULL; + } + result = nresult; + } + (void) strlcpy(&result[len], temp, size - len); + len += add; + temp = NULL; + } + } while (temp && globally); + result[len] = '\0'; + + return (result); +} + + +/* + * the real function doing history expansion - takes as argument command + * to do and data upon which the command should be executed + * does expansion the way I've understood readline documentation + * word designator ``%'' isn't supported (yet ?) + * + * returns 0 if data was not modified, 1 if it was and 2 if the string + * should be only printed and not executed; in case of error, + * returns -1 and *result points to NULL + * it's callers responsibility to free() string returned in *result + */ +static int +_history_expand_command(const char *command, size_t cmdlen, char **result) +{ + char **arr, *tempcmd, *line, *search = NULL, *cmd; + const char *event_data = NULL; + static char *from = NULL, *to = NULL; + int start = -1, end = -1, max, i, idx; + int h_on = 0, t_on = 0, r_on = 0, e_on = 0, p_on = 0, g_on = 0; + int event_num = 0, retval; + size_t cmdsize; + + *result = NULL; + + cmd = alloca(cmdlen + 1); + (void) strncpy(cmd, command, cmdlen); + cmd[cmdlen] = 0; + + idx = 1; + /* find out which event to take */ + if (cmd[idx] == history_expansion_char) { + event_num = history_length; + idx++; + } else { + int off, num; + size_t len; + off = idx; + while (cmd[off] && !strchr(":^$*-%", cmd[off])) + off++; + num = atoi(&cmd[idx]); + if (num != 0) { + event_num = num; + if (num < 0) + event_num += history_length + 1; + } else { + int prefix = 1, curr_num; + HistEvent ev; + + len = off - idx; + if (cmd[idx] == '?') { + idx++, len--; + if (cmd[off - 1] == '?') + len--; + else if (cmd[off] != '\n' && cmd[off] != '\0') + return (-1); + prefix = 0; + } + search = alloca(len + 1); + (void) strncpy(search, &cmd[idx], len); + search[len] = '\0'; + + if (history(h, &ev, H_CURR) != 0) + return (-1); + curr_num = ev.num; + + if (prefix) + retval = history_search_prefix(search, -1); + else + retval = history_search(search, -1); + + if (retval == -1) { + fprintf(rl_outstream, "%s: Event not found\n", + search); + return (-1); + } + if (history(h, &ev, H_CURR) != 0) + return (-1); + event_data = ev.str; + + /* roll back to original position */ + history(h, &ev, H_NEXT_EVENT, curr_num); + } + idx = off; + } + + if (!event_data && event_num >= 0) { + HIST_ENTRY *rl_he; + rl_he = history_get(event_num); + if (!rl_he) + return (0); + event_data = rl_he->line; + } else + return (-1); + + if (cmd[idx] != ':') + return (-1); + cmd += idx + 1; + + /* recognize cmd */ + if (*cmd == '^') + start = end = 1, cmd++; + else if (*cmd == '$') + start = end = -1, cmd++; + else if (*cmd == '*') + start = 1, end = -1, cmd++; + else if (isdigit((unsigned char) *cmd)) { + const char *temp; + int shifted = 0; + + start = atoi(cmd); + temp = cmd; + for (; isdigit((unsigned char) *cmd); cmd++); + if (temp != cmd) + shifted = 1; + if (shifted && *cmd == '-') { + if (!isdigit((unsigned char) *(cmd + 1))) + end = -2; + else { + end = atoi(cmd + 1); + for (; isdigit((unsigned char) *cmd); cmd++); + } + } else if (shifted && *cmd == '*') + end = -1, cmd++; + else if (shifted) + end = start; + } + if (*cmd == ':') + cmd++; + + line = strdup(event_data); + if (line == NULL) + return 0; + for (; *cmd; cmd++) { + if (*cmd == ':') + continue; + else if (*cmd == 'h') + h_on = 1 | g_on, g_on = 0; + else if (*cmd == 't') + t_on = 1 | g_on, g_on = 0; + else if (*cmd == 'r') + r_on = 1 | g_on, g_on = 0; + else if (*cmd == 'e') + e_on = 1 | g_on, g_on = 0; + else if (*cmd == 'p') + p_on = 1 | g_on, g_on = 0; + else if (*cmd == 'g') + g_on = 2; + else if (*cmd == 's' || *cmd == '&') { + char *what, *with, delim; + size_t len, from_len; + size_t size; + + if (*cmd == '&' && (from == NULL || to == NULL)) + continue; + else if (*cmd == 's') { + delim = *(++cmd), cmd++; + size = 16; + what = realloc(from, size); + if (what == NULL) { + free(from); + return 0; + } + len = 0; + for (; *cmd && *cmd != delim; cmd++) { + if (*cmd == '\\' + && *(cmd + 1) == delim) + cmd++; + if (len >= size) { + char *nwhat; + nwhat = realloc(what, + (size <<= 1)); + if (nwhat == NULL) { + free(what); + return 0; + } + what = nwhat; + } + what[len++] = *cmd; + } + what[len] = '\0'; + from = what; + if (*what == '\0') { + free(what); + if (search) { + from = strdup(search); + if (from == NULL) + return 0; + } else { + from = NULL; + return (-1); + } + } + cmd++; /* shift after delim */ + if (!*cmd) + continue; + + size = 16; + with = realloc(to, size); + if (with == NULL) { + free(to); + return -1; + } + len = 0; + from_len = strlen(from); + for (; *cmd && *cmd != delim; cmd++) { + if (len + from_len + 1 >= size) { + char *nwith; + size += from_len + 1; + nwith = realloc(with, size); + if (nwith == NULL) { + free(with); + return -1; + } + with = nwith; + } + if (*cmd == '&') { + /* safe */ + (void) strlcpy(&with[len], + from, size - len); + len += from_len; + continue; + } + if (*cmd == '\\' + && (*(cmd + 1) == delim + || *(cmd + 1) == '&')) + cmd++; + with[len++] = *cmd; + } + with[len] = '\0'; + to = with; + + tempcmd = _rl_compat_sub(line, from, to, + (g_on) ? 1 : 0); + if (tempcmd) { + free(line); + line = tempcmd; + } + g_on = 0; + } + } + } + + arr = history_tokenize(line); + free(line); /* no more needed */ + if (arr && *arr == NULL) + free(arr), arr = NULL; + if (!arr) + return (-1); + + /* find out max valid idx to array of array */ + max = 0; + for (i = 0; arr[i]; i++) + max++; + max--; + + /* set boundaries to something relevant */ + if (start < 0) + start = 1; + if (end < 0) + end = max - ((end < -1) ? 1 : 0); + + /* check boundaries ... */ + if (start > max || end > max || start > end) + return (-1); + + for (i = 0; i <= max; i++) { + char *temp; + if (h_on && (i == 1 || h_on > 1) && + (temp = strrchr(arr[i], '/'))) + *(temp + 1) = '\0'; + if (t_on && (i == 1 || t_on > 1) && + (temp = strrchr(arr[i], '/'))) + (void) strlcpy(arr[i], temp + 1, strlen(arr[i]) + 1); + if (r_on && (i == 1 || r_on > 1) && + (temp = strrchr(arr[i], '.'))) + *temp = '\0'; + if (e_on && (i == 1 || e_on > 1) && + (temp = strrchr(arr[i], '.'))) + (void) strlcpy(arr[i], temp, strlen(arr[i]) + 1); + } + + cmdsize = 1, cmdlen = 0; + if ((tempcmd = malloc(cmdsize)) == NULL) + return 0; + for (i = start; start <= i && i <= end; i++) { + int arr_len; + + arr_len = strlen(arr[i]); + if (cmdlen + arr_len + 1 >= cmdsize) { + char *ntempcmd; + cmdsize += arr_len + 1; + ntempcmd = realloc(tempcmd, cmdsize); + if (ntempcmd == NULL) { + free(tempcmd); + return 0; + } + tempcmd = ntempcmd; + } + (void) strlcpy(&tempcmd[cmdlen], arr[i], cmdsize); + cmdlen += arr_len; + tempcmd[cmdlen++] = ' '; /* add a space */ + } + while (cmdlen > 0 && isspace((unsigned char) tempcmd[cmdlen - 1])) + cmdlen--; + tempcmd[cmdlen] = '\0'; + + *result = tempcmd; + + for (i = 0; i <= max; i++) + free(arr[i]); + free(arr), arr = (char **) NULL; + return (p_on) ? 2 : 1; +} + + +/* + * csh-style history expansion + */ +int +history_expand(char *str, char **output) +{ + int i, retval = 0, idx; + size_t size; + char *temp, *result; + + if (h == NULL || e == NULL) + rl_initialize(); + + *output = strdup(str); /* do it early */ + if (*output == NULL) + return 0; + + if (str[0] == history_subst_char) { + /* ^foo^foo2^ is equivalent to !!:s^foo^foo2^ */ + size_t sz = 4 + strlen(str) + 1; + temp = alloca(sz); + temp[0] = temp[1] = history_expansion_char; + temp[2] = ':'; + temp[3] = 's'; + (void) strlcpy(temp + 4, str, sz - 4); + str = temp; + } +#define ADD_STRING(what, len) \ + { \ + if (idx + len + 1 > size) { \ + char *nresult = realloc(result, (size += len + 1));\ + if (nresult == NULL) { \ + free(*output); \ + return 0; \ + } \ + result = nresult; \ + } \ + (void)strncpy(&result[idx], what, len); \ + idx += len; \ + result[idx] = '\0'; \ + } + + result = NULL; + size = idx = 0; + for (i = 0; str[i];) { + int start, j, loop_again; + size_t len; + + loop_again = 1; + start = j = i; +loop: + for (; str[j]; j++) { + if (str[j] == '\\' && + str[j + 1] == history_expansion_char) { + size_t sz = strlen(&str[j]) + 1; + (void) strlcpy(&str[j], &str[j + 1], sz); + continue; + } + if (!loop_again) { + if (str[j] == '?') { + while (str[j] && str[++j] != '?'); + if (str[j] == '?') + j++; + } else if (isspace((unsigned char) str[j])) + break; + } + if (str[j] == history_expansion_char + && !strchr(history_no_expand_chars, str[j + 1]) + && (!history_inhibit_expansion_function || + (*history_inhibit_expansion_function)(str, j) == 0)) + break; + } + + if (str[j] && str[j + 1] != '#' && loop_again) { + i = j; + j++; + if (str[j] == history_expansion_char) + j++; + loop_again = 0; + goto loop; + } + len = i - start; + temp = &str[start]; + ADD_STRING(temp, len); + + if (str[i] == '\0' || str[i] != history_expansion_char + || str[i + 1] == '#') { + len = j - i; + temp = &str[i]; + ADD_STRING(temp, len); + if (start == 0) + retval = 0; + else + retval = 1; + break; + } + retval = _history_expand_command(&str[i], (size_t) (j - i), + &temp); + if (retval != -1) { + len = strlen(temp); + ADD_STRING(temp, len); + } + i = j; + } /* for(i ...) */ + + if (retval == 2) { + add_history(temp); +#ifdef GDB_411_HACK + /* gdb 4.11 has been shipped with readline, where */ + /* history_expand() returned -1 when the line */ + /* should not be executed; in readline 2.1+ */ + /* it should return 2 in such a case */ + retval = -1; +#endif + } + free(*output); + *output = result; + + return (retval); +} + + +/* + * Parse the string into individual tokens, similarily to how shell would do it. + */ +char ** +history_tokenize(const char *str) +{ + int size = 1, result_idx = 0, i, start; + size_t len; + char **result = NULL, *temp, delim = '\0'; + + for (i = 0; str[i]; i++) { + while (isspace((unsigned char) str[i])) + i++; + start = i; + for (; str[i]; i++) { + if (str[i] == '\\') { + if (str[i+1] != '\0') + i++; + } else if (str[i] == delim) + delim = '\0'; + else if (!delim && + (isspace((unsigned char) str[i]) || + strchr("()<>;&|$", str[i]))) + break; + else if (!delim && strchr("'`\"", str[i])) + delim = str[i]; + } + + if (result_idx + 2 >= size) { + char **nresult; + size <<= 1; + nresult = realloc(result, size * sizeof(char *)); + if (nresult == NULL) { + free(result); + return NULL; + } + result = nresult; + } + len = i - start; + temp = malloc(len + 1); + if (temp == NULL) { + free(result); + return NULL; + } + (void) strncpy(temp, &str[start], len); + temp[len] = '\0'; + result[result_idx++] = temp; + result[result_idx] = NULL; + } + + return (result); +} + + +/* + * limit size of history record to ``max'' events + */ +void +stifle_history(int max) +{ + HistEvent ev; + + if (h == NULL || e == NULL) + rl_initialize(); + + if (history(h, &ev, H_SETSIZE, max) == 0) + max_input_history = max; +} + + +/* + * "unlimit" size of history - set the limit to maximum allowed int value + */ +int +unstifle_history(void) +{ + HistEvent ev; + int omax; + + history(h, &ev, H_SETSIZE, INT_MAX); + omax = max_input_history; + max_input_history = INT_MAX; + return (omax); /* some value _must_ be returned */ +} + + +int +history_is_stifled(void) +{ + + /* cannot return true answer */ + return (max_input_history != INT_MAX); +} + + +/* + * read history from a file given + */ +int +read_history(const char *filename) +{ + HistEvent ev; + + if (h == NULL || e == NULL) + rl_initialize(); + return (history(h, &ev, H_LOAD, filename)); +} + + +/* + * write history to a file given + */ +int +write_history(const char *filename) +{ + HistEvent ev; + + if (h == NULL || e == NULL) + rl_initialize(); + return (history(h, &ev, H_SAVE, filename)); +} + + +/* + * returns history ``num''th event + * + * returned pointer points to static variable + */ +HIST_ENTRY * +history_get(int num) +{ + static HIST_ENTRY she; + HistEvent ev; + int i = 1, curr_num; + + if (h == NULL || e == NULL) + rl_initialize(); + + /* rewind to beginning */ + if (history(h, &ev, H_CURR) != 0) + return (NULL); + curr_num = ev.num; + if (history(h, &ev, H_LAST) != 0) + return (NULL); /* error */ + while (i < num && history(h, &ev, H_PREV) == 0) + i++; + if (i != num) + return (NULL); /* not so many entries */ + + she.line = ev.str; + she.data = NULL; + + /* rewind history to the same event it was before */ + (void) history(h, &ev, H_FIRST); + (void) history(h, &ev, H_NEXT_EVENT, curr_num); + + return (&she); +} + + +/* + * add the line to history table + */ +int +add_history(const char *line) +{ + HistEvent ev; + + if (h == NULL || e == NULL) + rl_initialize(); + + (void) history(h, &ev, H_ENTER, line); + if (history(h, &ev, H_GETSIZE) == 0) + history_length = ev.num; + + return (!(history_length > 0)); /* return 0 if all is okay */ +} + + +/* + * clear the history list - delete all entries + */ +void +clear_history(void) +{ + HistEvent ev; + + history(h, &ev, H_CLEAR); +} + + +/* + * returns offset of the current history event + */ +int +where_history(void) +{ + HistEvent ev; + int curr_num, off; + + if (history(h, &ev, H_CURR) != 0) + return (0); + curr_num = ev.num; + + history(h, &ev, H_FIRST); + off = 1; + while (ev.num != curr_num && history(h, &ev, H_NEXT) == 0) + off++; + + return (off); +} + + +/* + * returns current history event or NULL if there is no such event + */ +HIST_ENTRY * +current_history(void) +{ + + return (_move_history(H_CURR)); +} + + +/* + * returns total number of bytes history events' data are using + */ +int +history_total_bytes(void) +{ + HistEvent ev; + int curr_num, size; + + if (history(h, &ev, H_CURR) != 0) + return (-1); + curr_num = ev.num; + + history(h, &ev, H_FIRST); + size = 0; + do + size += strlen(ev.str); + while (history(h, &ev, H_NEXT) == 0); + + /* get to the same position as before */ + history(h, &ev, H_PREV_EVENT, curr_num); + + return (size); +} + + +/* + * sets the position in the history list to ``pos'' + */ +int +history_set_pos(int pos) +{ + HistEvent ev; + int off, curr_num; + + if (pos > history_length || pos < 0) + return (-1); + + history(h, &ev, H_CURR); + curr_num = ev.num; + history(h, &ev, H_FIRST); + off = 0; + while (off < pos && history(h, &ev, H_NEXT) == 0) + off++; + + if (off != pos) { /* do a rollback in case of error */ + history(h, &ev, H_FIRST); + history(h, &ev, H_NEXT_EVENT, curr_num); + return (-1); + } + return (0); +} + + +/* + * returns previous event in history and shifts pointer accordingly + */ +HIST_ENTRY * +previous_history(void) +{ + + return (_move_history(H_PREV)); +} + + +/* + * returns next event in history and shifts pointer accordingly + */ +HIST_ENTRY * +next_history(void) +{ + + return (_move_history(H_NEXT)); +} + + +/* + * generic history search function + */ +static int +_history_search_gen(const char *str, int direction, int pos) +{ + HistEvent ev; + const char *strp; + int curr_num; + + if (history(h, &ev, H_CURR) != 0) + return (-1); + curr_num = ev.num; + + for (;;) { + strp = strstr(ev.str, str); + if (strp && (pos < 0 || &ev.str[pos] == strp)) + return (int) (strp - ev.str); + if (history(h, &ev, direction < 0 ? H_PREV : H_NEXT) != 0) + break; + } + + history(h, &ev, direction < 0 ? H_NEXT_EVENT : H_PREV_EVENT, curr_num); + + return (-1); +} + + +/* + * searches for first history event containing the str + */ +int +history_search(const char *str, int direction) +{ + + return (_history_search_gen(str, direction, -1)); +} + + +/* + * searches for first history event beginning with str + */ +int +history_search_prefix(const char *str, int direction) +{ + + return (_history_search_gen(str, direction, 0)); +} + + +/* + * search for event in history containing str, starting at offset + * abs(pos); continue backward, if pos<0, forward otherwise + */ +/* ARGSUSED */ +int +history_search_pos(const char *str, + int direction __attribute__((__unused__)), int pos) +{ + HistEvent ev; + int curr_num, off; + + off = (pos > 0) ? pos : -pos; + pos = (pos > 0) ? 1 : -1; + + if (history(h, &ev, H_CURR) != 0) + return (-1); + curr_num = ev.num; + + if (history_set_pos(off) != 0 || history(h, &ev, H_CURR) != 0) + return (-1); + + + for (;;) { + if (strstr(ev.str, str)) + return (off); + if (history(h, &ev, (pos < 0) ? H_PREV : H_NEXT) != 0) + break; + } + + /* set "current" pointer back to previous state */ + history(h, &ev, (pos < 0) ? H_NEXT_EVENT : H_PREV_EVENT, curr_num); + + return (-1); +} + + +/********************************/ +/* completion functions */ + +/* + * does tilde expansion of strings of type ``~user/foo'' + * if ``user'' isn't valid user name or ``txt'' doesn't start + * w/ '~', returns pointer to strdup()ed copy of ``txt'' + * + * it's callers's responsibility to free() returned string + */ +char * +tilde_expand(char *txt) +{ + struct passwd *pass; + char *temp; + size_t len = 0; + + if (txt[0] != '~') + return (strdup(txt)); + + temp = strchr(txt + 1, '/'); + if (temp == NULL) { + temp = strdup(txt + 1); + if (temp == NULL) + return NULL; + } else { + len = temp - txt + 1; /* text until string after slash */ + temp = malloc(len); + if (temp == NULL) + return NULL; + (void) strncpy(temp, txt + 1, len - 2); + temp[len - 2] = '\0'; + } + pass = getpwnam(temp); + free(temp); /* value no more needed */ + if (pass == NULL) + return (strdup(txt)); + + /* update pointer txt to point at string immedially following */ + /* first slash */ + txt += len; + + len = strlen(pass->pw_dir) + 1 + strlen(txt) + 1; + temp = malloc(len); + if (temp == NULL) + return NULL; + (void) snprintf(temp, len, "%s/%s", pass->pw_dir, txt); + + return (temp); +} + + +/* + * return first found file name starting by the ``text'' or NULL if no + * such file can be found + * value of ``state'' is ignored + * + * it's caller's responsibility to free returned string + */ +char * +filename_completion_function(const char *text, int state) +{ + static DIR *dir = NULL; + static char *filename = NULL, *dirname = NULL; + static size_t filename_len = 0; + struct dirent *entry; + char *temp; + size_t len; + + if (state == 0 || dir == NULL) { + temp = strrchr(text, '/'); + if (temp) { + char *nptr; + size_t sz; + temp++; + sz = strlen(temp) + 1; + nptr = realloc(filename, sz); + if (nptr == NULL) { + free(filename); + return NULL; + } + filename = nptr; + (void) strlcpy(filename, temp, sz); + len = temp - text; /* including last slash */ + nptr = realloc(dirname, len + 1); + if (nptr == NULL) { + free(filename); + return NULL; + } + dirname = nptr; + (void) strncpy(dirname, text, len); + dirname[len] = '\0'; + } else { + filename = strdup(text); + if (filename == NULL) + return NULL; + dirname = NULL; + } + + /* support for ``~user'' syntax */ + if (dirname && *dirname == '~') { + char *nptr; + size_t sz; + temp = tilde_expand(dirname); + if (temp == NULL) + return NULL; + sz = strlen(temp) + 1; + nptr = realloc(dirname, sz); + if (nptr == NULL) { + free(dirname); + return NULL; + } + dirname = nptr; + (void) strlcpy(dirname, temp, sz); + free(temp); /* no longer needed */ + } + /* will be used in cycle */ + filename_len = strlen(filename); + if (filename_len == 0) + return (NULL); /* no expansion possible */ + + if (dir != NULL) { + (void)closedir(dir); + dir = NULL; + } + dir = opendir(dirname ? dirname : "."); + if (!dir) + return (NULL); /* cannot open the directory */ + } + /* find the match */ + while ((entry = readdir(dir)) != NULL) { + /* otherwise, get first entry where first */ + /* filename_len characters are equal */ + if (entry->d_name[0] == filename[0] +#if defined(__SVR4) || defined(__linux__) + && strlen(entry->d_name) >= filename_len +#else + && entry->d_namlen >= filename_len +#endif + && strncmp(entry->d_name, filename, + filename_len) == 0) + break; + } + + if (entry) { /* match found */ + + struct stat stbuf; +#if defined(__SVR4) || defined(__linux__) + len = strlen(entry->d_name) + +#else + len = entry->d_namlen + +#endif + ((dirname) ? strlen(dirname) : 0) + 1 + 1; + temp = malloc(len); + if (temp == NULL) + return NULL; + (void) snprintf(temp, len, "%s%s", + dirname ? dirname : "", entry->d_name); + + /* test, if it's directory */ + if (stat(temp, &stbuf) == 0 && S_ISDIR(stbuf.st_mode)) + strlcat(temp, "/", len); + } else { + (void)closedir(dir); + dir = NULL; + temp = NULL; + } + + return (temp); +} + + +/* + * a completion generator for usernames; returns _first_ username + * which starts with supplied text + * text contains a partial username preceded by random character + * (usually '~'); state is ignored + * it's callers responsibility to free returned value + */ +char * +username_completion_function(const char *text, int state) +{ + struct passwd *pwd; + + if (text[0] == '\0') + return (NULL); + + if (*text == '~') + text++; + + if (state == 0) + setpwent(); + + while ((pwd = getpwent()) && text[0] == pwd->pw_name[0] + && strcmp(text, pwd->pw_name) == 0); + + if (pwd == NULL) { + endpwent(); + return (NULL); + } + return (strdup(pwd->pw_name)); +} + + +/* + * el-compatible wrapper around rl_complete; needed for key binding + */ +/* ARGSUSED */ +static unsigned char +_el_rl_complete(EditLine *el __attribute__((__unused__)), int ch) +{ + return (unsigned char) rl_complete(0, ch); +} + + +/* + * returns list of completions for text given + */ +char ** +completion_matches(const char *text, CPFunction *genfunc) +{ + char **match_list = NULL, *retstr, *prevstr; + size_t match_list_len, max_equal, which, i; + size_t matches; + + if (h == NULL || e == NULL) + rl_initialize(); + + matches = 0; + match_list_len = 1; + while ((retstr = (*genfunc) (text, (int)matches)) != NULL) { + /* allow for list terminator here */ + if (matches + 3 >= match_list_len) { + char **nmatch_list; + while (matches + 3 >= match_list_len) + match_list_len <<= 1; + nmatch_list = realloc(match_list, + match_list_len * sizeof(char *)); + if (nmatch_list == NULL) { + free(match_list); + return NULL; + } + match_list = nmatch_list; + + } + match_list[++matches] = retstr; + } + + if (!match_list) + return NULL; /* nothing found */ + + /* find least denominator and insert it to match_list[0] */ + which = 2; + prevstr = match_list[1]; + max_equal = strlen(prevstr); + for (; which <= matches; which++) { + for (i = 0; i < max_equal && + prevstr[i] == match_list[which][i]; i++) + continue; + max_equal = i; + } + + retstr = malloc(max_equal + 1); + if (retstr == NULL) { + free(match_list); + return NULL; + } + (void) strncpy(retstr, match_list[1], max_equal); + retstr[max_equal] = '\0'; + match_list[0] = retstr; + + /* add NULL as last pointer to the array */ + match_list[matches + 1] = (char *) NULL; + + return (match_list); +} + +/* + * Sort function for qsort(). Just wrapper around strcasecmp(). + */ +static int +_rl_qsort_string_compare(i1, i2) + const void *i1, *i2; +{ + const char *s1 = ((const char * const *)i1)[0]; + const char *s2 = ((const char * const *)i2)[0]; + + return strcasecmp(s1, s2); +} + +/* + * Display list of strings in columnar format on readline's output stream. + * 'matches' is list of strings, 'len' is number of strings in 'matches', + * 'max' is maximum length of string in 'matches'. + */ +void +rl_display_match_list (matches, len, max) + char **matches; + int len, max; +{ + int i, idx, limit, count; + int screenwidth = e->el_term.t_size.h; + + /* + * Find out how many entries can be put on one line, count + * with two spaces between strings. + */ + limit = screenwidth / (max + 2); + if (limit == 0) + limit = 1; + + /* how many lines of output */ + count = len / limit; + if (count * limit < len) + count++; + + /* Sort the items if they are not already sorted. */ + qsort(&matches[1], (size_t)(len - 1), sizeof(char *), + _rl_qsort_string_compare); + + idx = 1; + for(; count > 0; count--) { + for(i=0; i < limit && matches[idx]; i++, idx++) + fprintf(e->el_outfile, "%-*s ", max, matches[idx]); + fprintf(e->el_outfile, "\n"); + } +} + +/* + * Complete the word at or before point, called by rl_complete() + * 'what_to_do' says what to do with the completion. + * `?' means list the possible completions. + * TAB means do standard completion. + * `*' means insert all of the possible completions. + * `!' means to do standard completion, and list all possible completions if + * there is more than one. + * + * Note: '*' support is not implemented + */ +static int +rl_complete_internal(int what_to_do) +{ + Function *complet_func; + const LineInfo *li; + char *temp, **matches; + const char *ctemp; + size_t len; + + rl_completion_type = what_to_do; + + if (h == NULL || e == NULL) + rl_initialize(); + + complet_func = rl_completion_entry_function; + if (!complet_func) + complet_func = (Function *)(void *)filename_completion_function; + + /* We now look backwards for the start of a filename/variable word */ + li = el_line(e); + ctemp = (const char *) li->cursor; + while (ctemp > li->buffer + && !strchr(rl_basic_word_break_characters, ctemp[-1]) + && (!rl_special_prefixes + || !strchr(rl_special_prefixes, ctemp[-1]) ) ) + ctemp--; + + len = li->cursor - ctemp; + temp = alloca(len + 1); + (void) strncpy(temp, ctemp, len); + temp[len] = '\0'; + + /* these can be used by function called in completion_matches() */ + /* or (*rl_attempted_completion_function)() */ + rl_point = li->cursor - li->buffer; + rl_end = li->lastchar - li->buffer; + + if (!rl_attempted_completion_function) + matches = completion_matches(temp, (CPFunction *)complet_func); + else { + int end = li->cursor - li->buffer; + matches = (*rl_attempted_completion_function) (temp, (int) + (end - len), end); + } + + if (matches) { + int i, retval = CC_REFRESH; + int matches_num, maxlen, match_len, match_display=1; + + /* + * Only replace the completed string with common part of + * possible matches if there is possible completion. + */ + if (matches[0][0] != '\0') { + el_deletestr(e, (int) len); + el_insertstr(e, matches[0]); + } + + if (what_to_do == '?') + goto display_matches; + + if (matches[2] == NULL && strcmp(matches[0], matches[1]) == 0) { + /* + * We found exact match. Add a space after + * it, unless we do filename completion and the + * object is a directory. + */ + size_t alen = strlen(matches[0]); + if ((complet_func != + (Function *)filename_completion_function + || (alen > 0 && (matches[0])[alen - 1] != '/')) + && rl_completion_append_character) { + char buf[2]; + buf[0] = rl_completion_append_character; + buf[1] = '\0'; + el_insertstr(e, buf); + } + } else if (what_to_do == '!') { + display_matches: + /* + * More than one match and requested to list possible + * matches. + */ + + for(i=1, maxlen=0; matches[i]; i++) { + match_len = strlen(matches[i]); + if (match_len > maxlen) + maxlen = match_len; + } + matches_num = i - 1; + + /* newline to get on next line from command line */ + fprintf(e->el_outfile, "\n"); + + /* + * If there are too many items, ask user for display + * confirmation. + */ + if (matches_num > rl_completion_query_items) { + fprintf(e->el_outfile, + "Display all %d possibilities? (y or n) ", + matches_num); + fflush(e->el_outfile); + if (getc(stdin) != 'y') + match_display = 0; + fprintf(e->el_outfile, "\n"); + } + + if (match_display) + rl_display_match_list(matches, matches_num, + maxlen); + retval = CC_REDISPLAY; + } else if (matches[0][0]) { + /* + * There was some common match, but the name was + * not complete enough. Next tab will print possible + * completions. + */ + el_beep(e); + } else { + /* lcd is not a valid object - further specification */ + /* is needed */ + el_beep(e); + retval = CC_NORM; + } + + /* free elements of array and the array itself */ + for (i = 0; matches[i]; i++) + free(matches[i]); + free(matches), matches = NULL; + + return (retval); + } + return (CC_NORM); +} + + +/* + * complete word at current point + */ +int +rl_complete(int ignore, int invoking_key) +{ + if (h == NULL || e == NULL) + rl_initialize(); + + if (rl_inhibit_completion) { + rl_insert(ignore, invoking_key); + return (CC_REFRESH); + } else if (e->el_state.lastcmd == el_rl_complete_cmdnum) + return rl_complete_internal('?'); + else if (_rl_complete_show_all) + return rl_complete_internal('!'); + else + return (rl_complete_internal(TAB)); +} + + +/* + * misc other functions + */ + +/* + * bind key c to readline-type function func + */ +int +rl_bind_key(int c, int func(int, int)) +{ + int retval = -1; + + if (h == NULL || e == NULL) + rl_initialize(); + + if (func == rl_insert) { + /* XXX notice there is no range checking of ``c'' */ + e->el_map.key[c] = ED_INSERT; + retval = 0; + } + return (retval); +} + + +/* + * read one key from input - handles chars pushed back + * to input stream also + */ +int +rl_read_key(void) +{ + char fooarr[2 * sizeof(int)]; + + if (e == NULL || h == NULL) + rl_initialize(); + + return (el_getc(e, fooarr)); +} + + +/* + * reset the terminal + */ +/* ARGSUSED */ +void +rl_reset_terminal(const char *p __attribute__((__unused__))) +{ + + if (h == NULL || e == NULL) + rl_initialize(); + el_reset(e); +} + + +/* + * insert character ``c'' back into input stream, ``count'' times + */ +int +rl_insert(int count, int c) +{ + char arr[2]; + + if (h == NULL || e == NULL) + rl_initialize(); + + /* XXX - int -> char conversion can lose on multichars */ + arr[0] = c; + arr[1] = '\0'; + + for (; count > 0; count--) + el_push(e, arr); + + return (0); +} + +/*ARGSUSED*/ +int +rl_newline(int count, int c) +{ + /* + * Readline-4.0 appears to ignore the args. + */ + return rl_insert(1, '\n'); +} + +/*ARGSUSED*/ +static unsigned char +rl_bind_wrapper(EditLine *el, unsigned char c) +{ + if (map[c] == NULL) + return CC_ERROR; + (*map[c])(NULL, c); + return CC_NORM; +} + +int +rl_add_defun(const char *name, Function *fun, int c) +{ + char dest[8]; + if (c >= sizeof(map) / sizeof(map[0]) || c < 0) + return -1; + map[(unsigned char)c] = fun; + el_set(e, EL_ADDFN, name, name, rl_bind_wrapper); + el_set(e, EL_BIND, vis(dest, c, VIS_WHITE, 0), name); + return 0; +} + +void +rl_callback_read_char() +{ + int count = 0; + const char *buf = el_gets(e, &count); + char *wbuf; + + if (buf == NULL || count-- <= 0) + return; + if ((buf[count] == '\n' || buf[count] == '\r') && rl_linefunc != NULL) { + el_set(e, EL_UNBUFFERED, 0); + if ((wbuf = strdup(buf)) != NULL) + wbuf[count] = '\0'; + (*(void (*)(const char *))rl_linefunc)(wbuf); + } +} + +void +rl_callback_handler_install (const char *prompt, VFunction *linefunc) +{ + if (e == NULL) { + rl_initialize(); + } + if (rl_prompt) + free(rl_prompt); + rl_prompt = prompt ? strdup(strchr(prompt, *prompt)) : NULL; + rl_linefunc = linefunc; + el_set(e, EL_UNBUFFERED, 1); +} + +void +rl_callback_handler_remove(void) +{ + el_set(e, EL_UNBUFFERED, 0); +} + +void +rl_redisplay(void) +{ + char a[2]; + a[0] = CTRL('r'); + a[1] = '\0'; + el_push(e, a); +} + +int +rl_get_previous_history(int count, int key) +{ + char a[2]; + a[0] = key; + a[1] = '\0'; + while (count--) + el_push(e, a); + return 0; +} diff --git a/lib/libedit/readline/Makefile b/lib/libedit/readline/Makefile new file mode 100644 index 00000000000..770325a0769 --- /dev/null +++ b/lib/libedit/readline/Makefile @@ -0,0 +1,18 @@ +# $OpenBSD: Makefile,v 1.1 2003/10/31 08:42:24 otto Exp $ +# $NetBSD: Makefile,v 1.7 2003/08/03 09:23:15 lukem Exp $ + +NOOBJ= # defined + +.include <bsd.own.mk> + +includes: + ${INSTALL} -d -o ${BINOWN} -g ${BINGRP} -m 755 \ + ${DESTDIR}/usr/include/readline + -cd ${.CURDIR}; cmp -s readline.h ${DESTDIR}/usr/include/readline/readline.h > \ + /dev/null 2>&1 || \ + ${INSTALL} ${INSTALL_COPY} -o ${BINOWN} -g ${BINGRP} -m 444 readline.h \ + ${DESTDIR}/usr/include/readline + rm -f ${DESTDIR}/usr/include/readline/history.h + cd ${DESTDIR}/usr/include/readline && ln -s readline.h history.h + +.include <bsd.prog.mk> diff --git a/lib/libedit/readline/readline.h b/lib/libedit/readline/readline.h new file mode 100644 index 00000000000..18f70a85d03 --- /dev/null +++ b/lib/libedit/readline/readline.h @@ -0,0 +1,182 @@ +/* $OpenBSD: readline.h,v 1.1 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: readline.h,v 1.8 2003/09/26 17:44:51 christos Exp $ */ + +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jaromir Dolecek. + * + * 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. + */ +#ifndef _READLINE_H_ +#define _READLINE_H_ + +#include <sys/types.h> + +/* list of readline stuff supported by editline library's readline wrapper */ + +/* typedefs */ +typedef int Function(const char *, int); +typedef void VFunction(void); +typedef char *CPFunction(const char *, int); +typedef char **CPPFunction(const char *, int, int); + +typedef struct _hist_entry { + const char *line; + const char *data; +} HIST_ENTRY; + +typedef struct _keymap_entry { + char type; +#define ISFUNC 0 +#define ISKMAP 1 +#define ISMACR 2 + Function *function; +} KEYMAP_ENTRY; + +#define KEYMAP_SIZE 256 + +typedef KEYMAP_ENTRY KEYMAP_ENTRY_ARRAY[KEYMAP_SIZE]; +typedef KEYMAP_ENTRY *Keymap; + +#define control_character_threshold 0x20 +#define control_character_bit 0x40 + +#ifndef CTRL +#include <sys/ioctl.h> +#include <sys/ttydefaults.h> +#ifndef CTRL +#define CTRL(c) ((c) & 037) +#endif +#endif +#ifndef UNCTRL +#define UNCTRL(c) (((c) - 'a' + 'A')|control_character_bit) +#endif + +#define RUBOUT 0x7f +#define ABORT_CHAR CTRL('G') + +/* global variables used by readline enabled applications */ +#ifdef __cplusplus +extern "C" { +#endif +extern const char *rl_library_version; +extern char *rl_readline_name; +extern FILE *rl_instream; +extern FILE *rl_outstream; +extern char *rl_line_buffer; +extern int rl_point, rl_end; +extern int history_base, history_length; +extern int max_input_history; +extern char *rl_basic_word_break_characters; +extern char *rl_completer_word_break_characters; +extern char *rl_completer_quote_characters; +extern Function *rl_completion_entry_function; +extern CPPFunction *rl_attempted_completion_function; +extern int rl_completion_type; +extern int rl_completion_query_items; +extern char *rl_special_prefixes; +extern int rl_completion_append_character; +extern Function *rl_pre_input_hook; +extern Function *rl_startup_hook; +extern char *rl_terminal_name; +extern int rl_already_prompted; +extern char *rl_prompt; +/* + * The following is not implemented + */ +extern KEYMAP_ENTRY_ARRAY emacs_standard_keymap, + emacs_meta_keymap, + emacs_ctlx_keymap; +extern int rl_filename_completion_desired; +extern int rl_ignore_completion_duplicates; +extern Function *rl_getc_function; +extern VFunction *rl_redisplay_function; +extern VFunction *rl_completion_display_matches_hook; +extern VFunction *rl_prep_term_function; +extern VFunction *rl_deprep_term_function; + +/* supported functions */ +char *readline(const char *); +int rl_initialize(void); + +void using_history(void); +int add_history(const char *); +void clear_history(void); +void stifle_history(int); +int unstifle_history(void); +int history_is_stifled(void); +int where_history(void); +HIST_ENTRY *current_history(void); +HIST_ENTRY *history_get(int); +int history_total_bytes(void); +int history_set_pos(int); +HIST_ENTRY *previous_history(void); +HIST_ENTRY *next_history(void); +int history_search(const char *, int); +int history_search_prefix(const char *, int); +int history_search_pos(const char *, int, int); +int read_history(const char *); +int write_history(const char *); +int history_expand(char *, char **); +char **history_tokenize(const char *); + +char *tilde_expand(char *); +char *filename_completion_function(const char *, int); +char *username_completion_function(const char *, int); +int rl_complete(int, int); +int rl_read_key(void); +char **completion_matches(const char *, CPFunction *); +void rl_display_match_list(char **, int, int); + +int rl_insert(int, int); +void rl_reset_terminal(const char *); +int rl_bind_key(int, int (*)(int, int)); +int rl_newline(int, int); +void rl_callback_read_char(void); +void rl_callback_handler_install(const char *, VFunction *); +void rl_callback_handler_remove(void); +void rl_redisplay(void); +int rl_get_previous_history(int, int); + +/* + * The following are not implemented + */ +Keymap rl_get_keymap(void); +Keymap rl_make_bare_keymap(void); +int rl_add_defun(const char *, Function *, int); +int rl_generic_bind(int, const char *, const char *, Keymap); +int rl_bind_key_in_map(int, Function *, Keymap); +#ifdef __cplusplus +} +#endif + +#endif /* _READLINE_H_ */ diff --git a/lib/libedit/refresh.c b/lib/libedit/refresh.c index 1842000ec55..2f644d32e05 100644 --- a/lib/libedit/refresh.c +++ b/lib/libedit/refresh.c @@ -1,5 +1,5 @@ -/* $OpenBSD: refresh.c,v 1.8 2003/06/02 20:18:40 millert Exp $ */ -/* $NetBSD: refresh.c,v 1.2 1997/01/11 06:48:07 lukem Exp $ */ +/* $OpenBSD: refresh.c,v 1.9 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: refresh.c,v 1.26 2003/08/07 16:44:33 agc Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -33,18 +33,18 @@ * SUCH DAMAGE. */ +#include "config.h" #if !defined(lint) && !defined(SCCSID) #if 0 static char sccsid[] = "@(#)refresh.c 8.1 (Berkeley) 6/4/93"; #else -static const char rcsid[] = "$OpenBSD: refresh.c,v 1.8 2003/06/02 20:18:40 millert Exp $"; +static const char rcsid[] = "$OpenBSD: refresh.c,v 1.9 2003/10/31 08:42:24 otto Exp $"; #endif #endif /* not lint && not SCCSID */ /* * refresh.c: Lower level screen refreshing functions */ -#include "sys.h" #include <stdio.h> #include <ctype.h> #include <unistd.h> @@ -52,40 +52,40 @@ static const char rcsid[] = "$OpenBSD: refresh.c,v 1.8 2003/06/02 20:18:40 mille #include "el.h" -private void re_addc(EditLine *, int); -private void re_update_line(EditLine *, char *, char *, int); -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_addc(EditLine *, int); +private void re_update_line(EditLine *, char *, char *, int); +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 *, const char *, size_t); #ifdef DEBUG_REFRESH -private void re_printstr(EditLine *, char *, char *, char *); -# define __F el->el_errfile -# define RE_DEBUG(a, b, c) do \ - if (a) { \ - (void)fprintf b; \ +private void re_printstr(EditLine *, const char *, char *, char *); +#define __F el->el_errfile +#define ELRE_ASSERT(a, b, c) do \ + 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(el, str, f, t) - EditLine *el; - char *str; - char *f, *t; +re_printstr(EditLine *el, const char *str, char *f, char *t) { - RE_DEBUG(1,(__F, "%s:\"", str),); - while (f < t) - RE_DEBUG(1,(__F, "%c", *f++ & 0177),); - RE_DEBUG(1,(__F, "\"\r\n"),); -} + + ELRE_DEBUG(1, (__F, "%s:\"", str)); + while (f < t) + ELRE_DEBUG(1, (__F, "%c", *f++ & 0177)); + ELRE_DEBUG(1, (__F, "\"\r\n")); +} #else -# define RE_DEBUG(a, b, c) +#define ELRE_ASSERT(a, b, c) +#define ELRE_DEBUG(a, b) #endif @@ -93,66 +93,87 @@ re_printstr(el, str, f, t) * Draw c, expanding tabs, control chars etc. */ private void -re_addc(el, c) - EditLine *el; - int c; +re_addc(EditLine *el, int c) { - if (isprint(c)) { - re_putc(el, c); - return; - } - if (c == '\n') { /* expand the newline */ - re_putc(el, '\0'); /* assure end of line */ - el->el_refresh.r_cursor.h = 0; /* reset cursor pos */ - el->el_refresh.r_cursor.v++; - return; - } - if (c == '\t') { /* expand the tab */ - for (;;) { - re_putc(el, ' '); - if ((el->el_refresh.r_cursor.h & 07) == 0) - break; /* go until tab stop */ + + if (isprint(c)) { + re_putc(el, c, 1); + return; + } + if (c == '\n') { /* expand the newline */ + int oldv = el->el_refresh.r_cursor.v; + re_putc(el, '\0', 0); /* assure end of line */ + if (oldv == el->el_refresh.r_cursor.v) { /* XXX */ + el->el_refresh.r_cursor.h = 0; /* reset cursor pos */ + el->el_refresh.r_cursor.v++; + } + return; + } + if (c == '\t') { /* expand the tab */ + for (;;) { + re_putc(el, ' ', 1); + if ((el->el_refresh.r_cursor.h & 07) == 0) + break; /* go until tab stop */ + } + } else if (iscntrl(c)) { + re_putc(el, '^', 1); + if (c == '\177') + re_putc(el, '?', 1); + else + /* uncontrolify it; works only for iso8859-1 like sets */ + re_putc(el, (c | 0100), 1); + } else { + re_putc(el, '\\', 1); + re_putc(el, (int) ((((unsigned int) c >> 6) & 07) + '0'), 1); + re_putc(el, (int) ((((unsigned int) c >> 3) & 07) + '0'), 1); + re_putc(el, (c & 07) + '0', 1); } - } - else if (iscntrl(c)) { - re_putc(el, '^'); - if (c == '\177') - re_putc(el, '?'); - else - /* uncontrolify it; works only for iso8859-1 like sets */ - re_putc(el, (c | 0100)); - } - else { - re_putc(el, '\\'); - re_putc(el, ((c >> 6) & 07) + '0'); - re_putc(el, ((c >> 3) & 07) + '0'); - re_putc(el, (c & 07) + '0'); - } -} /* end re_addc */ +} /* re_putc(): * Draw the character given */ protected void -re_putc(el, c) - EditLine *el; - int c; +re_putc(EditLine *el, int c, int shift) { - RE_DEBUG(1,(__F, "printing %3.3o '%c'\r\n", c, c),); - - el->el_vdisplay[el->el_refresh.r_cursor.v][el->el_refresh.r_cursor.h] = c; - el->el_refresh.r_cursor.h++; /* advance to next place */ - if (el->el_refresh.r_cursor.h >= el->el_term.t_size.h) { - el->el_vdisplay[el->el_refresh.r_cursor.v][el->el_term.t_size.h] = '\0'; - /* assure end of line */ - el->el_refresh.r_cursor.h = 0; /* reset it. */ - el->el_refresh.r_cursor.v++; - RE_DEBUG(el->el_refresh.r_cursor.v >= el->el_term.t_size.v, - (__F, "\r\nre_putc: overflow! r_cursor.v == %d > %d\r\n", - el->el_refresh.r_cursor.v, el->el_term.t_size.v), abort()); - } -} /* end re_putc */ + + ELRE_DEBUG(1, (__F, "printing %3.3o '%c'\r\n", c, c)); + + el->el_vdisplay[el->el_refresh.r_cursor.v][el->el_refresh.r_cursor.h] = c; + if (!shift) + return; + + el->el_refresh.r_cursor.h++; /* advance to next place */ + if (el->el_refresh.r_cursor.h >= el->el_term.t_size.h) { + el->el_vdisplay[el->el_refresh.r_cursor.v][el->el_term.t_size.h] = '\0'; + /* assure end of line */ + el->el_refresh.r_cursor.h = 0; /* reset it. */ + + /* + * If we would overflow (input is longer than terminal size), + * emulate scroll by dropping first line and shuffling the rest. + * We do this via pointer shuffling - it's safe in this case + * and we avoid memcpy(). + */ + if (el->el_refresh.r_cursor.v + 1 >= el->el_term.t_size.v) { + int i, lins = el->el_term.t_size.v; + char *firstline = el->el_vdisplay[0]; + + for(i=1; i < lins; i++) + el->el_vdisplay[i-1] = el->el_vdisplay[i]; + + firstline[0] = '\0'; /* empty the string */ + el->el_vdisplay[i-1] = firstline; + } else + el->el_refresh.r_cursor.v++; + + ELRE_ASSERT(el->el_refresh.r_cursor.v >= el->el_term.t_size.v, + (__F, "\r\nre_putc: overflow! r_cursor.v == %d > %d\r\n", + el->el_refresh.r_cursor.v, el->el_term.t_size.v), + abort()); + } +} /* re_refresh(): @@ -162,196 +183,244 @@ re_putc(el, c) * easily in hopes of a smarter one being placed there. */ protected void -re_refresh(el) - EditLine *el; +re_refresh(EditLine *el) { - int i; - char *cp; - coord_t cur; + int i, rhdiff; + char *cp, *st; + coord_t cur; +#ifdef notyet + size_t termsz; +#endif - RE_DEBUG(1,(__F, "el->el_line.buffer = :%s:\r\n", el->el_line.buffer),); + ELRE_DEBUG(1, (__F, "el->el_line.buffer = :%s:\r\n", + el->el_line.buffer)); - /* reset the Drawing cursor */ - el->el_refresh.r_cursor.h = 0; - el->el_refresh.r_cursor.v = 0; + /* reset the Drawing cursor */ + el->el_refresh.r_cursor.h = 0; + el->el_refresh.r_cursor.v = 0; - cur.h = -1; /* set flag in case I'm not set */ - cur.v = 0; + /* temporarily draw rprompt to calculate its size */ + prompt_print(el, EL_RPROMPT); - prompt_print(el); + /* reset the Drawing cursor */ + el->el_refresh.r_cursor.h = 0; + el->el_refresh.r_cursor.v = 0; - /* draw the current input buffer */ - for (cp = el->el_line.buffer; cp < el->el_line.lastchar; cp++) { - if (cp == el->el_line.cursor) { - cur.h = el->el_refresh.r_cursor.h; /* save for later */ - cur.v = el->el_refresh.r_cursor.v; + 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; } - re_addc(el, *cp); - } - - if (cur.h == -1) { /* if I haven't been set yet, I'm at the end */ - cur.h = el->el_refresh.r_cursor.h; - cur.v = el->el_refresh.r_cursor.v; - } - /* must be done BEFORE the NUL is written */ - el->el_refresh.r_newcv = el->el_refresh.r_cursor.v; - re_putc(el, '\0'); /* put NUL on end */ - - RE_DEBUG(1,(__F, - "term.h=%d vcur.h=%d vcur.v=%d vdisplay[0]=\r\n:%80.80s:\r\n", - el->el_term.t_size.h, el->el_refresh.r_cursor.h, - el->el_refresh.r_cursor.v, el->el_vdisplay[0]),); - - RE_DEBUG(1,(__F, "updating %d lines.\r\n", el->el_refresh.r_newcv),); - for (i = 0; i <= el->el_refresh.r_newcv; i++) { - /* NOTE THAT re_update_line MAY CHANGE el_display[i] */ - re_update_line(el, el->el_display[i], el->el_vdisplay[i], i); - /* - * Copy the new line to be the current one, and pad out with spaces - * to the full width of the terminal so that if we try moving the - * cursor by writing the character that is at the end of the - * screen line, it won't be a NUL or some old leftover stuff. - */ - re__copy_and_pad(el->el_display[i], el->el_vdisplay[i], - el->el_term.t_size.h); - } - RE_DEBUG(1,(__F, - "\r\nel->el_refresh.r_cursor.v=%d,el->el_refresh.r_oldcv=%d i=%d\r\n", - el->el_refresh.r_cursor.v, el->el_refresh.r_oldcv, i),); - - if (el->el_refresh.r_oldcv > el->el_refresh.r_newcv) - for (; i <= el->el_refresh.r_oldcv; i++) { - term_move_to_line(el, i); - term_move_to_char(el, 0); - term_clear_EOL(el, strlen(el->el_display[i])); + cur.h = -1; /* set flag in case I'm not set */ + cur.v = 0; + + prompt_print(el, EL_PROMPT); + + /* draw the current input buffer */ +#if notyet + termsz = el->el_term.t_size.h * el->el_term.t_size.v; + if (el->el_line.lastchar - el->el_line.buffer > termsz) { + /* + * If line is longer than terminal, process only part + * of line which would influence display. + */ + size_t rem = (el->el_line.lastchar-el->el_line.buffer)%termsz; + + st = el->el_line.lastchar - rem + - (termsz - (((rem / el->el_term.t_size.v) - 1) + * el->el_term.t_size.v)); + } else +#endif + st = el->el_line.buffer; + + for (cp = st; cp < el->el_line.lastchar; cp++) { + if (cp == el->el_line.cursor) { + /* save for later */ + cur.h = el->el_refresh.r_cursor.h; + cur.v = el->el_refresh.r_cursor.v; + } + re_addc(el, (unsigned char) *cp); + } + + if (cur.h == -1) { /* if I haven't been set yet, I'm at the end */ + cur.h = el->el_refresh.r_cursor.h; + cur.v = el->el_refresh.r_cursor.v; + } + rhdiff = el->el_term.t_size.h - el->el_refresh.r_cursor.h - + el->el_rprompt.p_pos.h; + if (el->el_rprompt.p_pos.h && !el->el_rprompt.p_pos.v && + !el->el_refresh.r_cursor.v && rhdiff > 1) { + /* + * have a right-hand side prompt that will fit + * on the end of the first line with at least + * one character gap to the input buffer. + */ + while (--rhdiff > 0) /* pad out with spaces */ + re_putc(el, ' ', 1); + prompt_print(el, EL_RPROMPT); + } else { + el->el_rprompt.p_pos.h = 0; /* flag "not using rprompt" */ + el->el_rprompt.p_pos.v = 0; + } + + re_putc(el, '\0', 0); /* make line ended with NUL, no cursor shift */ + + el->el_refresh.r_newcv = el->el_refresh.r_cursor.v; + + ELRE_DEBUG(1, (__F, + "term.h=%d vcur.h=%d vcur.v=%d vdisplay[0]=\r\n:%80.80s:\r\n", + el->el_term.t_size.h, el->el_refresh.r_cursor.h, + el->el_refresh.r_cursor.v, el->el_vdisplay[0])); + + ELRE_DEBUG(1, (__F, "updating %d lines.\r\n", el->el_refresh.r_newcv)); + for (i = 0; i <= el->el_refresh.r_newcv; i++) { + /* NOTE THAT re_update_line MAY CHANGE el_display[i] */ + re_update_line(el, el->el_display[i], el->el_vdisplay[i], i); + + /* + * Copy the new line to be the current one, and pad out with + * spaces to the full width of the terminal so that if we try + * moving the cursor by writing the character that is at the + * end of the screen line, it won't be a NUL or some old + * leftover stuff. + */ + re__copy_and_pad(el->el_display[i], el->el_vdisplay[i], + (size_t) el->el_term.t_size.h); + } + ELRE_DEBUG(1, (__F, + "\r\nel->el_refresh.r_cursor.v=%d,el->el_refresh.r_oldcv=%d i=%d\r\n", + el->el_refresh.r_cursor.v, el->el_refresh.r_oldcv, i)); + + if (el->el_refresh.r_oldcv > el->el_refresh.r_newcv) + for (; i <= el->el_refresh.r_oldcv; i++) { + term_move_to_line(el, i); + term_move_to_char(el, 0); + term_clear_EOL(el, (int) strlen(el->el_display[i])); #ifdef DEBUG_REFRESH - term_overwrite(el, "C\b", 2); + term_overwrite(el, "C\b", 2); #endif /* DEBUG_REFRESH */ - *el->el_display[i] = '\0'; - } - - el->el_refresh.r_oldcv = el->el_refresh.r_newcv; /* set for next time */ - RE_DEBUG(1,(__F, - "\r\ncursor.h = %d, cursor.v = %d, cur.h = %d, cur.v = %d\r\n", - el->el_refresh.r_cursor.h, el->el_refresh.r_cursor.v, - cur.h, cur.v),); - term_move_to_line(el, cur.v); /* go to where the cursor is */ - term_move_to_char(el, cur.h); -} /* end re_refresh */ + el->el_display[i][0] = '\0'; + } + + el->el_refresh.r_oldcv = el->el_refresh.r_newcv; /* set for next time */ + ELRE_DEBUG(1, (__F, + "\r\ncursor.h = %d, cursor.v = %d, cur.h = %d, cur.v = %d\r\n", + el->el_refresh.r_cursor.h, el->el_refresh.r_cursor.v, + cur.h, cur.v)); + term_move_to_line(el, cur.v); /* go to where the cursor is */ + term_move_to_char(el, cur.h); +} /* re_goto_bottom(): - * used to go to last used screen line + * used to go to last used screen line */ protected void -re_goto_bottom(el) - EditLine *el; +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(); -} /* end re_goto_bottom */ + + term_move_to_line(el, el->el_refresh.r_oldcv); + term__putc('\n'); + re_clear_display(el); + term__flush(); +} /* re_insert(): * insert num characters of s into d (in front of the character) - * at dat, maximum length of d is dlen + * at dat, maximum length of d is dlen */ private void /*ARGSUSED*/ -re_insert(el, d, dat, dlen, s, num) - EditLine *el; - char *d; - int dat, dlen; - char *s; - int num; +re_insert(EditLine *el __attribute__((__unused__)), + char *d, int dat, int dlen, char *s, int num) { - char *a, *b; - - if (num <= 0) - return; - if (num > dlen - dat) - num = dlen - dat; - - RE_DEBUG(1,(__F, "re_insert() starting: %d at %d max %d, d == \"%s\"\n", - num, dat, dlen, d),); - RE_DEBUG(1,(__F, "s == \"%s\"n", s),); - - /* open up the space for num chars */ - if (num > 0) { - b = d + dlen - 1; - a = b - num; - while (a >= &d[dat]) - *b-- = *a--; - d[dlen] = '\0'; /* just in case */ - } - RE_DEBUG(1,(__F, + char *a, *b; + + if (num <= 0) + return; + if (num > dlen - dat) + num = dlen - dat; + + ELRE_DEBUG(1, + (__F, "re_insert() starting: %d at %d max %d, d == \"%s\"\n", + num, dat, dlen, d)); + ELRE_DEBUG(1, (__F, "s == \"%s\"n", s)); + + /* open up the space for num chars */ + if (num > 0) { + b = d + dlen - 1; + a = b - num; + while (a >= &d[dat]) + *b-- = *a--; + d[dlen] = '\0'; /* just in case */ + } + ELRE_DEBUG(1, (__F, "re_insert() after insert: %d at %d max %d, d == \"%s\"\n", - num, dat, dlen, d),); - RE_DEBUG(1,(__F, "s == \"%s\"n", s),); + num, dat, dlen, d)); + ELRE_DEBUG(1, (__F, "s == \"%s\"n", s)); - /* copy the characters */ - for (a = d + dat; (a < d + dlen) && (num > 0); num--) - *a++ = *s++; + /* copy the characters */ + for (a = d + dat; (a < d + dlen) && (num > 0); num--) + *a++ = *s++; - RE_DEBUG(1,(__F, "re_insert() after copy: %d at %d max %d, %s == \"%s\"\n", - num, dat, dlen, d, s),); - RE_DEBUG(1,(__F, "s == \"%s\"n", s),); -} /* end re_insert */ + ELRE_DEBUG(1, + (__F, "re_insert() after copy: %d at %d max %d, %s == \"%s\"\n", + num, dat, dlen, d, s)); + ELRE_DEBUG(1, (__F, "s == \"%s\"n", s)); +} /* re_delete(): - * delete num characters d at dat, maximum length of d is dlen + * delete num characters d at dat, maximum length of d is dlen */ private void /*ARGSUSED*/ -re_delete(el, d, dat, dlen, num) - EditLine *el; - char *d; - int dat, dlen, num; +re_delete(EditLine *el __attribute__((__unused__)), + char *d, int dat, int dlen, int num) { - char *a, *b; - - if (num <= 0) - return; - if (dat + num >= dlen) { - d[dat] = '\0'; - return; - } - - RE_DEBUG(1,(__F, "re_delete() starting: %d at %d max %d, d == \"%s\"\n", - num, dat, dlen, d),); - - /* open up the space for num chars */ - if (num > 0) { - b = d + dat; - a = b + num; - while (a < &d[dlen]) - *b++ = *a++; - d[dlen] = '\0'; /* just in case */ - } - RE_DEBUG(1,(__F, "re_delete() after delete: %d at %d max %d, d == \"%s\"\n", - num, dat, dlen, d),); -} /* end re_delete */ + char *a, *b; + + if (num <= 0) + return; + if (dat + num >= dlen) { + d[dat] = '\0'; + return; + } + ELRE_DEBUG(1, + (__F, "re_delete() starting: %d at %d max %d, d == \"%s\"\n", + num, dat, dlen, d)); + + /* open up the space for num chars */ + if (num > 0) { + b = d + dat; + a = b + num; + while (a < &d[dlen]) + *b++ = *a++; + d[dlen] = '\0'; /* just in case */ + } + ELRE_DEBUG(1, + (__F, "re_delete() after delete: %d at %d max %d, d == \"%s\"\n", + num, dat, dlen, d)); +} /* re__strncopy(): * Like strncpy without padding. */ private void -re__strncopy(a, b, n) - char *a, *b; - size_t n; +re__strncopy(char *a, char *b, size_t n) { - while (n-- && *b) - *a++ = *b++; -} /* end re__strncopy */ + + while (n-- && *b) + *a++ = *b++; +} -/* **************************************************************** +/***************************************************************** re_update_line() is based on finding the middle difference of each line on the screen; vis: @@ -373,641 +442,677 @@ new: eddie> Oh, my little buggy says to me, as lurgid as * going back out. This should really be calculated from the termcap * data... For the moment, a good number for ANSI terminals. */ -#define MIN_END_KEEP 4 +#define MIN_END_KEEP 4 private void -re_update_line(el, old, new, i) - EditLine *el; - char *old, *new; - int i; +re_update_line(EditLine *el, char *old, char *new, int i) { - char *o, *n, *p, c; - char *ofd, *ols, *oe, *nfd, *nls, *ne; - char *osb, *ose, *nsb, *nse; - int fx, sx; - - /* - * find first diff - */ - for (o = old, n = new; *o && (*o == *n); o++, n++) - continue; - ofd = o; - nfd = n; - - /* - * Find the end of both old and new - */ - while (*o) - o++; - /* - * Remove any trailing blanks off of the end, being careful not to - * back up past the beginning. - */ - while (ofd < o) { - if (o[-1] != ' ') - break; - o--; - } - oe = o; - *oe = '\0'; - - while (*n) - n++; - - /* remove blanks from end of new */ - while (nfd < n) { - if (n[-1] != ' ') - break; - n--; - } - ne = n; - *ne = '\0'; - - /* - * if no diff, continue to next line of redraw - */ - if (*ofd == '\0' && *nfd == '\0') { - RE_DEBUG(1,(__F, "no difference.\r\n"),); - return; - } - - /* - * find last same pointer - */ - while ((o > ofd) && (n > nfd) && (*--o == *--n)) - continue; - ols = ++o; - nls = ++n; - - /* - * find same begining and same end - */ - osb = ols; - nsb = nls; - ose = ols; - nse = nls; - - /* - * case 1: insert: scan from nfd to nls looking for *ofd - */ - if (*ofd) { - for (c = *ofd, n = nfd; n < nls; n++) { - if (c == *n) { - for (o = ofd, p = n; p < nls && o < ols && *o == *p; o++, p++) - continue; - /* - * if the new match is longer and it's worth keeping, then we - * take it - */ - if (((nse - nsb) < (p - n)) && (2 * (p - n) > n - nfd)) { - nsb = n; - nse = p; - osb = ofd; - ose = o; - } - } - } - } - - /* - * case 2: delete: scan from ofd to ols looking for *nfd - */ - if (*nfd) { - for (c = *nfd, o = ofd; o < ols; o++) { - if (c == *o) { - for (n = nfd, p = o; p < ols && n < nls && *p == *n; p++, n++) - continue; - /* - * if the new match is longer and it's worth keeping, then we - * take it - */ - if (((ose - osb) < (p - o)) && (2 * (p - o) > o - ofd)) { - nsb = nfd; - nse = n; - osb = o; - ose = p; - } - } - } - } - - /* - * Pragmatics I: If old trailing whitespace or not enough characters to - * save to be worth it, then don't save the last same info. - */ - if ((oe - ols) < MIN_END_KEEP) { - ols = oe; - nls = ne; - } - - /* - * Pragmatics II: if the terminal isn't smart enough, make the data dumber - * so the smart update doesn't try anything fancy - */ - - /* - * fx is the number of characters we need to insert/delete: in the - * beginning to bring the two same begins together - */ - fx = (nsb - nfd) - (osb - ofd); - /* - * sx is the number of characters we need to insert/delete: in the end to - * bring the two same last parts together - */ - sx = (nls - nse) - (ols - ose); - - if (!EL_CAN_INSERT) { - if (fx > 0) { - osb = ols; - ose = ols; - nsb = nls; - nse = nls; - } - if (sx > 0) { - ols = oe; - nls = ne; - } - if ((ols - ofd) < (nls - nfd)) { - ols = oe; - nls = ne; - } - } - if (!EL_CAN_DELETE) { - if (fx < 0) { - osb = ols; - ose = ols; - nsb = nls; - nse = nls; + char *o, *n, *p, c; + char *ofd, *ols, *oe, *nfd, *nls, *ne; + char *osb, *ose, *nsb, *nse; + int fx, sx; + + /* + * find first diff + */ + for (o = old, n = new; *o && (*o == *n); o++, n++) + continue; + ofd = o; + nfd = n; + + /* + * Find the end of both old and new + */ + while (*o) + o++; + /* + * Remove any trailing blanks off of the end, being careful not to + * back up past the beginning. + */ + while (ofd < o) { + if (o[-1] != ' ') + break; + o--; } - if (sx < 0) { - ols = oe; - nls = ne; + oe = o; + *oe = '\0'; + + while (*n) + n++; + + /* remove blanks from end of new */ + while (nfd < n) { + if (n[-1] != ' ') + break; + n--; } - if ((ols - ofd) > (nls - nfd)) { - ols = oe; - nls = ne; + ne = n; + *ne = '\0'; + + /* + * if no diff, continue to next line of redraw + */ + if (*ofd == '\0' && *nfd == '\0') { + ELRE_DEBUG(1, (__F, "no difference.\r\n")); + return; } - } - - /* - * Pragmatics III: make sure the middle shifted pointers are correct if - * they don't point to anything (we may have moved ols or nls). - */ - /* if the change isn't worth it, don't bother */ - /* was: if (osb == ose) */ - if ((ose - osb) < MIN_END_KEEP) { + /* + * find last same pointer + */ + while ((o > ofd) && (n > nfd) && (*--o == *--n)) + continue; + ols = ++o; + nls = ++n; + + /* + * find same begining and same end + */ osb = ols; - ose = ols; nsb = nls; + ose = ols; nse = nls; - } - - /* - * Now that we are done with pragmatics we recompute fx, sx - */ - fx = (nsb - nfd) - (osb - ofd); - sx = (nls - nse) - (ols - ose); - - RE_DEBUG(1,(__F, "\n"),); - RE_DEBUG(1,(__F, "ofd %d, osb %d, ose %d, ols %d, oe %d\n", - ofd - old, osb - old, ose - old, ols - old, oe - old),); - RE_DEBUG(1,(__F, "nfd %d, nsb %d, nse %d, nls %d, ne %d\n", - nfd - new, nsb - new, nse - new, nls - new, ne - new),); - RE_DEBUG(1,(__F, - "xxx-xxx:\"00000000001111111111222222222233333333334\"\r\n"),); - RE_DEBUG(1,(__F, - "xxx-xxx:\"01234567890123456789012345678901234567890\"\r\n"),); -#ifdef DEBUG_REFRESH - re_printstr(el, "old- oe", old, oe); - re_printstr(el, "new- ne", new, ne); - re_printstr(el, "old-ofd", old, ofd); - re_printstr(el, "new-nfd", new, nfd); - re_printstr(el, "ofd-osb", ofd, osb); - re_printstr(el, "nfd-nsb", nfd, nsb); - re_printstr(el, "osb-ose", osb, ose); - re_printstr(el, "nsb-nse", nsb, nse); - re_printstr(el, "ose-ols", ose, ols); - re_printstr(el, "nse-nls", nse, nls); - re_printstr(el, "ols- oe", ols, oe); - re_printstr(el, "nls- ne", nls, ne); -#endif /* DEBUG_REFRESH */ - /* - * el_cursor.v to this line i MUST be in this routine so that if we - * don't have to change the line, we don't move to it. el_cursor.h to first - * diff char - */ - term_move_to_line(el, i); - - /* - * at this point we have something like this: - * - * /old /ofd /osb /ose /ols /oe - * v.....................v v..................v v........v - * eddie> Oh, my fredded gruntle-buggy is to me, as foo var lurgid as - * eddie> Oh, my fredded quiux buggy is to me, as gruntle-lurgid as - * ^.....................^ ^..................^ ^........^ - * \new \nfd \nsb \nse \nls \ne - * - * fx is the difference in length between the chars between nfd and - * nsb, and the chars between ofd and osb, and is thus the number of - * characters to delete if < 0 (new is shorter than old, as above), - * or insert (new is longer than short). - * - * sx is the same for the second differences. - */ - - /* - * if we have a net insert on the first difference, AND inserting the net - * amount ((nsb-nfd) - (osb-ofd)) won't push the last useful character - * (which is ne if nls != ne, otherwise is nse) off the edge of the screen - * (el->el_term.t_size.h) else we do the deletes first so that we keep everything we need - * to. - */ - - /* - * if the last same is the same like the end, there is no last same part, - * otherwise we want to keep the last same part set p to the last useful - * old character - */ - p = (ols != oe) ? oe : ose; - - /* - * if (There is a diffence in the beginning) && (we need to insert - * characters) && (the number of characters to insert is less than the term - * width) We need to do an insert! else if (we need to delete characters) - * We need to delete characters! else No insert or delete - */ - if ((nsb != nfd) && fx > 0 && ((p - old) + fx <= el->el_term.t_size.h)) { - RE_DEBUG(1,(__F, "first diff insert at %d...\r\n", nfd - new),); - /* - * Move to the first char to insert, where the first diff is. - */ - term_move_to_char(el, nfd - new); /* - * Check if we have stuff to keep at end - */ - if (nsb != ne) { - RE_DEBUG(1,(__F, "with stuff to keep at end\r\n"),); - /* - * insert fx chars of new starting at nfd - */ - if (fx > 0) { - RE_DEBUG(!EL_CAN_INSERT, - (__F, "ERROR: cannot insert in early first diff\n"),); - term_insertwrite(el, nfd, fx); - re_insert(el, old, ofd - old, el->el_term.t_size.h, nfd, fx); - } - /* - * write (nsb-nfd) - fx chars of new starting at (nfd + fx) - */ - term_overwrite(el, nfd + fx, (nsb - nfd) - fx); - re__strncopy(ofd + fx, nfd + fx, (nsb - nfd) - fx); + * case 1: insert: scan from nfd to nls looking for *ofd + */ + if (*ofd) { + for (c = *ofd, n = nfd; n < nls; n++) { + if (c == *n) { + for (o = ofd, p = n; + p < nls && o < ols && *o == *p; + o++, p++) + continue; + /* + * if the new match is longer and it's worth + * keeping, then we take it + */ + if (((nse - nsb) < (p - n)) && + (2 * (p - n) > n - nfd)) { + nsb = n; + nse = p; + osb = ofd; + ose = o; + } + } + } } - else { - RE_DEBUG(1,(__F, "without anything to save\r\n"),); - term_overwrite(el, nfd, (nsb - nfd)); - re__strncopy(ofd, nfd, (nsb - nfd)); - /* - * Done - */ - return; + /* + * case 2: delete: scan from ofd to ols looking for *nfd + */ + if (*nfd) { + for (c = *nfd, o = ofd; o < ols; o++) { + if (c == *o) { + for (n = nfd, p = o; + p < ols && n < nls && *p == *n; + p++, n++) + continue; + /* + * if the new match is longer and it's worth + * keeping, then we take it + */ + if (((ose - osb) < (p - o)) && + (2 * (p - o) > o - ofd)) { + nsb = nfd; + nse = n; + osb = o; + ose = p; + } + } + } } - } - else if (fx < 0) { - RE_DEBUG(1,(__F, "first diff delete at %d...\r\n", ofd - old),); /* - * move to the first char to delete where the first diff is - */ - term_move_to_char(el, ofd - old); + * Pragmatics I: If old trailing whitespace or not enough characters to + * save to be worth it, then don't save the last same info. + */ + if ((oe - ols) < MIN_END_KEEP) { + ols = oe; + nls = ne; + } /* - * Check if we have stuff to save - */ - if (osb != oe) { - RE_DEBUG(1,(__F, "with stuff to save at end\r\n"),); - /* - * fx is less than zero *always* here but we check for code - * symmetry - */ - if (fx < 0) { - RE_DEBUG(!EL_CAN_DELETE, - (__F, "ERROR: cannot delete in first diff\n"),); - term_deletechars(el, -fx); - re_delete(el, old, ofd - old, el->el_term.t_size.h, -fx); - } - /* - * write (nsb-nfd) chars of new starting at nfd - */ - term_overwrite(el, nfd, (nsb - nfd)); - re__strncopy(ofd, nfd, (nsb - nfd)); + * Pragmatics II: if the terminal isn't smart enough, make the data + * dumber so the smart update doesn't try anything fancy + */ + /* + * fx is the number of characters we need to insert/delete: in the + * beginning to bring the two same begins together + */ + fx = (nsb - nfd) - (osb - ofd); + /* + * sx is the number of characters we need to insert/delete: in the + * end to bring the two same last parts together + */ + sx = (nls - nse) - (ols - ose); + + if (!EL_CAN_INSERT) { + if (fx > 0) { + osb = ols; + ose = ols; + nsb = nls; + nse = nls; + } + if (sx > 0) { + ols = oe; + nls = ne; + } + if ((ols - ofd) < (nls - nfd)) { + ols = oe; + nls = ne; + } } - else { - RE_DEBUG(1,(__F, "but with nothing left to save\r\n"),); - /* - * write (nsb-nfd) chars of new starting at nfd - */ - term_overwrite(el, nfd, (nsb - nfd)); - RE_DEBUG(1,(__F, "cleareol %d\n", (oe - old) - (ne - new)),); - term_clear_EOL(el, (oe - old) - (ne - new)); - /* - * Done - */ - return; + if (!EL_CAN_DELETE) { + if (fx < 0) { + osb = ols; + ose = ols; + nsb = nls; + nse = nls; + } + if (sx < 0) { + ols = oe; + nls = ne; + } + if ((ols - ofd) > (nls - nfd)) { + ols = oe; + nls = ne; + } } - } - else - fx = 0; + /* + * Pragmatics III: make sure the middle shifted pointers are correct if + * they don't point to anything (we may have moved ols or nls). + */ + /* if the change isn't worth it, don't bother */ + /* was: if (osb == ose) */ + if ((ose - osb) < MIN_END_KEEP) { + osb = ols; + ose = ols; + nsb = nls; + nse = nls; + } + /* + * Now that we are done with pragmatics we recompute fx, sx + */ + fx = (nsb - nfd) - (osb - ofd); + sx = (nls - nse) - (ols - ose); + + ELRE_DEBUG(1, (__F, "\n")); + ELRE_DEBUG(1, (__F, "ofd %d, osb %d, ose %d, ols %d, oe %d\n", + ofd - old, osb - old, ose - old, ols - old, oe - old)); + ELRE_DEBUG(1, (__F, "nfd %d, nsb %d, nse %d, nls %d, ne %d\n", + nfd - new, nsb - new, nse - new, nls - new, ne - new)); + ELRE_DEBUG(1, (__F, + "xxx-xxx:\"00000000001111111111222222222233333333334\"\r\n")); + ELRE_DEBUG(1, (__F, + "xxx-xxx:\"01234567890123456789012345678901234567890\"\r\n")); +#ifdef DEBUG_REFRESH + re_printstr(el, "old- oe", old, oe); + re_printstr(el, "new- ne", new, ne); + re_printstr(el, "old-ofd", old, ofd); + re_printstr(el, "new-nfd", new, nfd); + re_printstr(el, "ofd-osb", ofd, osb); + re_printstr(el, "nfd-nsb", nfd, nsb); + re_printstr(el, "osb-ose", osb, ose); + re_printstr(el, "nsb-nse", nsb, nse); + re_printstr(el, "ose-ols", ose, ols); + re_printstr(el, "nse-nls", nse, nls); + re_printstr(el, "ols- oe", ols, oe); + re_printstr(el, "nls- ne", nls, ne); +#endif /* DEBUG_REFRESH */ - if (sx < 0) { - RE_DEBUG(1,(__F, "second diff delete at %d...\r\n", (ose - old) + fx),); /* - * Check if we have stuff to delete - */ + * el_cursor.v to this line i MUST be in this routine so that if we + * don't have to change the line, we don't move to it. el_cursor.h to + * first diff char + */ + term_move_to_line(el, i); + /* - * fx is the number of characters inserted (+) or deleted (-) - */ + * at this point we have something like this: + * + * /old /ofd /osb /ose /ols /oe + * v.....................v v..................v v........v + * eddie> Oh, my fredded gruntle-buggy is to me, as foo var lurgid as + * eddie> Oh, my fredded quiux buggy is to me, as gruntle-lurgid as + * ^.....................^ ^..................^ ^........^ + * \new \nfd \nsb \nse \nls \ne + * + * fx is the difference in length between the chars between nfd and + * nsb, and the chars between ofd and osb, and is thus the number of + * characters to delete if < 0 (new is shorter than old, as above), + * or insert (new is longer than short). + * + * sx is the same for the second differences. + */ - term_move_to_char(el, (ose - old) + fx); /* - * Check if we have stuff to save - */ - if (ols != oe) { - RE_DEBUG(1,(__F, "with stuff to save at end\r\n"),); - /* - * Again a duplicate test. - */ - if (sx < 0) { - RE_DEBUG(!EL_CAN_DELETE, - (__F, "ERROR: cannot delete in second diff\n"),); - term_deletechars(el, -sx); - } - - /* - * write (nls-nse) chars of new starting at nse - */ - term_overwrite(el, nse, (nls - nse)); - } - else { - RE_DEBUG(1,(__F, "but with nothing left to save\r\n"),); - term_overwrite(el, nse, (nls - nse)); - RE_DEBUG(1,(__F, "cleareol %d\n", (oe - old) - (ne - new)),); - term_clear_EOL(el, (oe - old) - (ne - new)); - } - } + * if we have a net insert on the first difference, AND inserting the + * net amount ((nsb-nfd) - (osb-ofd)) won't push the last useful + * character (which is ne if nls != ne, otherwise is nse) off the edge + * of the screen (el->el_term.t_size.h) else we do the deletes first + * so that we keep everything we need to. + */ - /* - * if we have a first insert AND WE HAVEN'T ALREADY DONE IT... - */ - if ((nsb != nfd) && (osb - ofd) <= (nsb - nfd) && (fx == 0)) { - RE_DEBUG(1,(__F, "late first diff insert at %d...\r\n", nfd - new),); + /* + * if the last same is the same like the end, there is no last same + * part, otherwise we want to keep the last same part set p to the + * last useful old character + */ + p = (ols != oe) ? oe : ose; - term_move_to_char(el, nfd - new); /* - * Check if we have stuff to keep at the end - */ - if (nsb != ne) { - RE_DEBUG(1,(__F, "with stuff to keep at end\r\n"),); - /* - * We have to recalculate fx here because we set it - * to zero above as a flag saying that we hadn't done - * an early first insert. - */ - fx = (nsb - nfd) - (osb - ofd); - if (fx > 0) { + * if (There is a diffence in the beginning) && (we need to insert + * characters) && (the number of characters to insert is less than + * the term width) + * We need to do an insert! + * else if (we need to delete characters) + * We need to delete characters! + * else + * No insert or delete + */ + if ((nsb != nfd) && fx > 0 && + ((p - old) + fx <= el->el_term.t_size.h)) { + ELRE_DEBUG(1, + (__F, "first diff insert at %d...\r\n", nfd - new)); /* - * insert fx chars of new starting at nfd + * Move to the first char to insert, where the first diff is. */ - RE_DEBUG(!EL_CAN_INSERT, - (__F, "ERROR: cannot insert in late first diff\n"),); - term_insertwrite(el, nfd, fx); - re_insert(el, old, ofd - old, el->el_term.t_size.h, nfd, fx); - } - - /* - * write (nsb-nfd) - fx chars of new starting at (nfd + fx) - */ - term_overwrite(el, nfd + fx, (nsb - nfd) - fx); - re__strncopy(ofd + fx, nfd + fx, (nsb - nfd) - fx); - } - else { - RE_DEBUG(1,(__F, "without anything to save\r\n"),); - term_overwrite(el, nfd, (nsb - nfd)); - re__strncopy(ofd, nfd, (nsb - nfd)); + term_move_to_char(el, nfd - new); + /* + * Check if we have stuff to keep at end + */ + if (nsb != ne) { + ELRE_DEBUG(1, (__F, "with stuff to keep at end\r\n")); + /* + * insert fx chars of new starting at nfd + */ + if (fx > 0) { + ELRE_DEBUG(!EL_CAN_INSERT, (__F, + "ERROR: cannot insert in early first diff\n")); + term_insertwrite(el, nfd, fx); + re_insert(el, old, ofd - old, + el->el_term.t_size.h, nfd, fx); + } + /* + * write (nsb-nfd) - fx chars of new starting at + * (nfd + fx) + */ + term_overwrite(el, nfd + fx, (nsb - nfd) - fx); + re__strncopy(ofd + fx, nfd + fx, + (size_t) ((nsb - nfd) - fx)); + } else { + ELRE_DEBUG(1, (__F, "without anything to save\r\n")); + term_overwrite(el, nfd, (nsb - nfd)); + re__strncopy(ofd, nfd, (size_t) (nsb - nfd)); + /* + * Done + */ + return; + } + } else if (fx < 0) { + ELRE_DEBUG(1, + (__F, "first diff delete at %d...\r\n", ofd - old)); + /* + * move to the first char to delete where the first diff is + */ + term_move_to_char(el, ofd - old); + /* + * Check if we have stuff to save + */ + if (osb != oe) { + ELRE_DEBUG(1, (__F, "with stuff to save at end\r\n")); + /* + * fx is less than zero *always* here but we check + * for code symmetry + */ + if (fx < 0) { + ELRE_DEBUG(!EL_CAN_DELETE, (__F, + "ERROR: cannot delete in first diff\n")); + term_deletechars(el, -fx); + re_delete(el, old, ofd - old, + el->el_term.t_size.h, -fx); + } + /* + * write (nsb-nfd) chars of new starting at nfd + */ + term_overwrite(el, nfd, (nsb - nfd)); + re__strncopy(ofd, nfd, (size_t) (nsb - nfd)); + + } else { + ELRE_DEBUG(1, (__F, + "but with nothing left to save\r\n")); + /* + * write (nsb-nfd) chars of new starting at nfd + */ + term_overwrite(el, nfd, (nsb - nfd)); + ELRE_DEBUG(1, (__F, + "cleareol %d\n", (oe - old) - (ne - new))); + term_clear_EOL(el, (oe - old) - (ne - new)); + /* + * Done + */ + return; + } + } else + fx = 0; + + if (sx < 0 && (ose - old) + fx < el->el_term.t_size.h) { + ELRE_DEBUG(1, (__F, + "second diff delete at %d...\r\n", (ose - old) + fx)); + /* + * Check if we have stuff to delete + */ + /* + * fx is the number of characters inserted (+) or deleted (-) + */ + + term_move_to_char(el, (ose - old) + fx); + /* + * Check if we have stuff to save + */ + if (ols != oe) { + ELRE_DEBUG(1, (__F, "with stuff to save at end\r\n")); + /* + * Again a duplicate test. + */ + if (sx < 0) { + ELRE_DEBUG(!EL_CAN_DELETE, (__F, + "ERROR: cannot delete in second diff\n")); + term_deletechars(el, -sx); + } + /* + * write (nls-nse) chars of new starting at nse + */ + term_overwrite(el, nse, (nls - nse)); + } else { + ELRE_DEBUG(1, (__F, + "but with nothing left to save\r\n")); + term_overwrite(el, nse, (nls - nse)); + ELRE_DEBUG(1, (__F, + "cleareol %d\n", (oe - old) - (ne - new))); + if ((oe - old) - (ne - new) != 0) + term_clear_EOL(el, (oe - old) - (ne - new)); + } } - } - - /* - * line is now NEW up to nse - */ - if (sx >= 0) { - RE_DEBUG(1,(__F, "second diff insert at %d...\r\n", nse - new),); - term_move_to_char(el, nse - new); - if (ols != oe) { - RE_DEBUG(1,(__F, "with stuff to keep at end\r\n"),); - if (sx > 0) { - /* insert sx chars of new starting at nse */ - RE_DEBUG(!EL_CAN_INSERT, - (__F, "ERROR: cannot insert in second diff\n"),); - term_insertwrite(el, nse, sx); - } - - /* - * write (nls-nse) - sx chars of new starting at (nse + sx) - */ - term_overwrite(el, nse + sx, (nls - nse) - sx); + /* + * if we have a first insert AND WE HAVEN'T ALREADY DONE IT... + */ + if ((nsb != nfd) && (osb - ofd) <= (nsb - nfd) && (fx == 0)) { + ELRE_DEBUG(1, (__F, "late first diff insert at %d...\r\n", + nfd - new)); + + term_move_to_char(el, nfd - new); + /* + * Check if we have stuff to keep at the end + */ + if (nsb != ne) { + ELRE_DEBUG(1, (__F, "with stuff to keep at end\r\n")); + /* + * We have to recalculate fx here because we set it + * to zero above as a flag saying that we hadn't done + * an early first insert. + */ + fx = (nsb - nfd) - (osb - ofd); + if (fx > 0) { + /* + * insert fx chars of new starting at nfd + */ + ELRE_DEBUG(!EL_CAN_INSERT, (__F, + "ERROR: cannot insert in late first diff\n")); + term_insertwrite(el, nfd, fx); + re_insert(el, old, ofd - old, + el->el_term.t_size.h, nfd, fx); + } + /* + * write (nsb-nfd) - fx chars of new starting at + * (nfd + fx) + */ + term_overwrite(el, nfd + fx, (nsb - nfd) - fx); + re__strncopy(ofd + fx, nfd + fx, + (size_t) ((nsb - nfd) - fx)); + } else { + ELRE_DEBUG(1, (__F, "without anything to save\r\n")); + term_overwrite(el, nfd, (nsb - nfd)); + re__strncopy(ofd, nfd, (size_t) (nsb - nfd)); + } } - else { - RE_DEBUG(1,(__F, "without anything to save\r\n"),); - term_overwrite(el, nse, (nls - nse)); - - /* - * No need to do a clear-to-end here because we were doing - * a second insert, so we will have over written all of the - * old string. - */ + /* + * line is now NEW up to nse + */ + if (sx >= 0) { + ELRE_DEBUG(1, (__F, + "second diff insert at %d...\r\n", nse - new)); + term_move_to_char(el, nse - new); + if (ols != oe) { + ELRE_DEBUG(1, (__F, "with stuff to keep at end\r\n")); + if (sx > 0) { + /* insert sx chars of new starting at nse */ + ELRE_DEBUG(!EL_CAN_INSERT, (__F, + "ERROR: cannot insert in second diff\n")); + term_insertwrite(el, nse, sx); + } + /* + * write (nls-nse) - sx chars of new starting at + * (nse + sx) + */ + term_overwrite(el, nse + sx, (nls - nse) - sx); + } else { + ELRE_DEBUG(1, (__F, "without anything to save\r\n")); + term_overwrite(el, nse, (nls - nse)); + + /* + * No need to do a clear-to-end here because we were + * doing a second insert, so we will have over + * written all of the old string. + */ + } } - } - RE_DEBUG(1,(__F, "done.\r\n"),); -} /* re_update_line */ + ELRE_DEBUG(1, (__F, "done.\r\n")); +} /* re__copy_and_pad(): * Copy string and pad with spaces */ private void -re__copy_and_pad(dst, src, width) - char *dst, *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') - break; - *dst++ = *src++; - } + for (i = 0; i < width; i++) { + if (*src == '\0') + break; + *dst++ = *src++; + } - while (i < width) { - *dst++ = ' '; - i++; - } - *dst = '\0'; -} /* end re__copy_and_pad */ + for (; i < width; i++) + *dst++ = ' '; + + *dst = '\0'; +} /* re_refresh_cursor(): * Move to the new cursor position */ protected void -re_refresh_cursor(el) - EditLine *el; +re_refresh_cursor(EditLine *el) { - char *cp, c; - int h, v, th; - - /* first we must find where the cursor is... */ - h = el->el_prompt.p_pos.h; - v = el->el_prompt.p_pos.v; - th = el->el_term.t_size.h; /* optimize for speed */ - - /* do input buffer to el->el_line.cursor */ - for (cp = el->el_line.buffer; cp < el->el_line.cursor; cp++) { - c = *cp; - h++; /* all chars at least this long */ - - if (c == '\n') { /* handle newline in data part too */ - h = 0; - v++; + 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; } - else { - if (c == '\t') { /* if a tab, to next tab stop */ - while (h & 07) { - h++; - } - } - else if (iscntrl(c)) { /* if control char */ - h++; - if (h > th) { /* if overflow, compensate */ - h = 1; - v++; - } - } - else if (!isprint(c)) { - h += 3; - if (h > th) { /* if overflow, compensate */ - h = h - th; - v++; + + /* first we must find where the cursor is... */ + h = el->el_prompt.p_pos.h; + v = el->el_prompt.p_pos.v; + th = el->el_term.t_size.h; /* optimize for speed */ + + /* do input buffer to el->el_line.cursor */ + for (cp = el->el_line.buffer; cp < el->el_line.cursor; cp++) { + c = *cp; + h++; /* all chars at least this long */ + + if (c == '\n') {/* handle newline in data part too */ + h = 0; + v++; + } else { + if (c == '\t') { /* if a tab, to next tab stop */ + while (h & 07) { + h++; + } + } else if (iscntrl((unsigned char) c)) { + /* if control char */ + h++; + if (h > th) { /* if overflow, compensate */ + h = 1; + v++; + } + } else if (!isprint((unsigned char) c)) { + h += 3; + if (h > th) { /* if overflow, compensate */ + h = h - th; + v++; + } + } } - } - } - if (h >= th) { /* check, extra long tabs picked up here also */ - h = 0; - v++; + if (h >= th) { /* check, extra long tabs picked up here also */ + h = 0; + v++; + } } - } - /* now go there */ - term_move_to_line(el, v); - term_move_to_char(el, h); - term__flush(); -} /* re_refresh_cursor */ + /* now go there */ + term_move_to_line(el, v); + term_move_to_char(el, h); + term__flush(); +} /* re_fastputc(): * Add a character fast. */ private void -re_fastputc(el, c) - EditLine *el; - int c; +re_fastputc(EditLine *el, int c) { - term__putc(c); - el->el_display[el->el_cursor.v][el->el_cursor.h++] = c; - if (el->el_cursor.h >= el->el_term.t_size.h) { - /* if we must overflow */ - el->el_cursor.h = 0; - el->el_cursor.v++; - el->el_refresh.r_oldcv++; - term__putc('\r'); - term__putc('\n'); - } -} /* end re_fastputc */ + + term__putc(c); + el->el_display[el->el_cursor.v][el->el_cursor.h++] = c; + if (el->el_cursor.h >= el->el_term.t_size.h) { + /* if we must overflow */ + el->el_cursor.h = 0; + + /* + * If we would overflow (input is longer than terminal size), + * emulate scroll by dropping first line and shuffling the rest. + * We do this via pointer shuffling - it's safe in this case + * and we avoid memcpy(). + */ + if (el->el_cursor.v + 1 >= el->el_term.t_size.v) { + int i, lins = el->el_term.t_size.v; + char *firstline = el->el_display[0]; + + for(i=1; i < lins; i++) + el->el_display[i-1] = el->el_display[i]; + + re__copy_and_pad(firstline, "", 0); + el->el_display[i-1] = firstline; + } else { + el->el_cursor.v++; + el->el_refresh.r_oldcv++; + } + if (EL_HAS_AUTO_MARGINS) { + if (EL_HAS_MAGIC_MARGINS) { + term__putc(' '); + term__putc('\b'); + } + } else { + term__putc('\r'); + term__putc('\n'); + } + } +} /* re_fastaddc(): * we added just one char, handle it fast. - * Assumes that screen cursor == real cursor + * Assumes that screen cursor == real cursor */ protected void -re_fastaddc(el) - EditLine *el; +re_fastaddc(EditLine *el) { - char c; - - c = el->el_line.cursor[-1]; - - if (c == '\t' || el->el_line.cursor != el->el_line.lastchar) { - re_refresh(el); /* too hard to handle */ - return; - } /* else (only do at end of line, no TAB) */ - - if (iscntrl(c)) { /* if control char, do caret */ - char mc = (c == '\177') ? '?' : (c | 0100); - re_fastputc(el, '^'); - re_fastputc(el, mc); - } - else if (isprint(c)) { /* normal char */ - re_fastputc(el, c); - } - else { - re_fastputc(el, '\\'); - re_fastputc(el, ((c >> 6) & 7) + '0'); - re_fastputc(el, ((c >> 3) & 7) + '0'); - re_fastputc(el, (c & 7) + '0'); - } - term__flush(); -} /* end re_fastaddc */ + char c; + int rhdiff; + + c = el->el_line.cursor[-1]; + + if (c == '\t' || el->el_line.cursor != el->el_line.lastchar) { + re_refresh(el); /* too hard to handle */ + return; + } + rhdiff = el->el_term.t_size.h - el->el_cursor.h - + el->el_rprompt.p_pos.h; + if (el->el_rprompt.p_pos.h && rhdiff < 3) { + re_refresh(el); /* clear out rprompt if less than 1 char gap */ + return; + } /* else (only do at end of line, no TAB) */ + if (iscntrl((unsigned char) c)) { /* if control char, do caret */ + char mc = (c == '\177') ? '?' : (c | 0100); + re_fastputc(el, '^'); + re_fastputc(el, mc); + } else if (isprint((unsigned char) c)) { /* normal char */ + re_fastputc(el, c); + } else { + re_fastputc(el, '\\'); + 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(); +} /* re_clear_display(): - * clear the screen buffers so that new new prompt starts fresh. + * clear the screen buffers so that new new prompt starts fresh. */ protected void -re_clear_display(el) - EditLine *el; +re_clear_display(EditLine *el) { - int i; + int i; - el->el_cursor.v = 0; - el->el_cursor.h = 0; - for (i = 0; i < el->el_term.t_size.v; i++) - el->el_display[i][0] = '\0'; - el->el_refresh.r_oldcv = 0; -} /* end re_clear_display */ + el->el_cursor.v = 0; + el->el_cursor.h = 0; + for (i = 0; i < el->el_term.t_size.v; i++) + el->el_display[i][0] = '\0'; + el->el_refresh.r_oldcv = 0; +} /* re_clear_lines(): - * Make sure all lines are *really* blank + * Make sure all lines are *really* blank */ protected void -re_clear_lines(el) - EditLine *el; +re_clear_lines(EditLine *el) { - if (EL_CAN_CEOL) { - int i; - term_move_to_char(el, 0); - for (i = 0; i <= el->el_refresh.r_oldcv; i++) { - /* for each line on the screen */ - term_move_to_line(el, i); - term_clear_EOL(el, el->el_term.t_size.h); + + if (EL_CAN_CEOL) { + int i; + term_move_to_char(el, 0); + for (i = 0; i <= el->el_refresh.r_oldcv; i++) { + /* for each line on the screen */ + term_move_to_line(el, i); + term_clear_EOL(el, el->el_term.t_size.h); + } + term_move_to_line(el, 0); + } else { + term_move_to_line(el, el->el_refresh.r_oldcv); + /* go to last line */ + term__putc('\r'); /* go to BOL */ + term__putc('\n'); /* go to new line */ } - term_move_to_line(el, 0); - } - else { - term_move_to_line(el, el->el_refresh.r_oldcv); /* go to last line */ - term__putc('\r'); /* go to BOL */ - term__putc('\n'); /* go to new line */ - } -} /* end re_clear_lines */ +} diff --git a/lib/libedit/refresh.h b/lib/libedit/refresh.h index bfa7b4627be..66f4ffc6a11 100644 --- a/lib/libedit/refresh.h +++ b/lib/libedit/refresh.h @@ -1,5 +1,5 @@ -/* $OpenBSD: refresh.h,v 1.5 2003/06/02 20:18:40 millert Exp $ */ -/* $NetBSD: refresh.h,v 1.2 1997/01/11 06:48:08 lukem Exp $ */ +/* $OpenBSD: refresh.h,v 1.6 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: refresh.h,v 1.5 2003/08/07 16:44:33 agc Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -39,16 +39,17 @@ * el.refresh.h: Screen refresh functions */ #ifndef _h_el_refresh -#define _h_el_refresh +#define _h_el_refresh #include "histedit.h" typedef struct { - coord_t r_cursor; /* Refresh cursor position */ - int r_oldcv, r_newcv; /* Vertical locations */ + coord_t r_cursor; /* Refresh cursor position */ + int r_oldcv; /* Vertical locations */ + int r_newcv; } el_refresh_t; -protected void re_putc(EditLine *, int); +protected void re_putc(EditLine *, int, int); protected void re_clear_lines(EditLine *); protected void re_clear_display(EditLine *); protected void re_refresh(EditLine *); diff --git a/lib/libedit/search.c b/lib/libedit/search.c index d33effbe9a7..84c8c24cf01 100644 --- a/lib/libedit/search.c +++ b/lib/libedit/search.c @@ -1,5 +1,5 @@ -/* $OpenBSD: search.c,v 1.8 2003/06/02 20:18:40 millert Exp $ */ -/* $NetBSD: search.c,v 1.4 1997/01/23 14:02:47 mrg Exp $ */ +/* $OpenBSD: search.c,v 1.9 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: search.c,v 1.15 2003/08/07 16:44:33 agc Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -33,18 +33,18 @@ * SUCH DAMAGE. */ +#include "config.h" #if !defined(lint) && !defined(SCCSID) #if 0 static char sccsid[] = "@(#)search.c 8.1 (Berkeley) 6/4/93"; #else -static const char rcsid[] = "$OpenBSD: search.c,v 1.8 2003/06/02 20:18:40 millert Exp $"; +static const char rcsid[] = "$OpenBSD: search.c,v 1.9 2003/10/31 08:42:24 otto Exp $"; #endif #endif /* not lint && not SCCSID */ /* * search.c: History and character search functions */ -#include "sys.h" #include <stdlib.h> #if defined(REGEX) #include <regex.h> @@ -56,7 +56,7 @@ static const char rcsid[] = "$OpenBSD: search.c,v 1.8 2003/06/02 20:18:40 miller /* * Adjust cursor in vi mode to include the character under it */ -#define EL_CURSOR(el) \ +#define EL_CURSOR(el) \ ((el)->el_line.cursor + (((el)->el_map.type == MAP_VI) && \ ((el)->el_map.current == (el)->el_map.alt))) @@ -64,15 +64,18 @@ static const char rcsid[] = "$OpenBSD: search.c,v 1.8 2003/06/02 20:18:40 miller * Initialize the search stuff */ protected int -search_init(el) - EditLine *el; +search_init(EditLine *el) { - el->el_search.patbuf = (char *) el_malloc(EL_BUFSIZ); - el->el_search.patlen = 0; - el->el_search.patdir = -1; - el->el_search.chacha = '\0'; - el->el_search.chadir = -1; - return 0; + + el->el_search.patbuf = (char *) el_malloc(EL_BUFSIZ); + if (el->el_search.patbuf == NULL) + return (-1); + el->el_search.patlen = 0; + el->el_search.patdir = -1; + el->el_search.chacha = '\0'; + el->el_search.chadir = CHAR_FWD; + el->el_search.chatflg = 0; + return (0); } @@ -80,68 +83,67 @@ search_init(el) * Initialize the search stuff */ protected void -search_end(el) - EditLine *el; +search_end(EditLine *el) { - el_free((ptr_t) el->el_search.patbuf); - el->el_search.patbuf = NULL; + + el_free((ptr_t) el->el_search.patbuf); + el->el_search.patbuf = NULL; } + #ifdef REGEXP /* regerror(): * Handle regular expression errors */ -public void +public void /*ARGSUSED*/ -regerror(msg) - const char *msg; +regerror(const char *msg) { } #endif + /* el_match(): * Return if string matches pattern */ protected int -el_match(str, pat) - const char *str; - const char *pat; +el_match(const char *str, const char *pat) { #if defined (REGEX) - regex_t re; - int rv; + regex_t re; + int rv; #elif defined (REGEXP) - regexp *rp; - int rv; -#else - extern char *re_comp(const char *); - extern int re_exec(const char *); + regexp *rp; + int rv; +#else + extern char *re_comp(const char *); + extern int re_exec(const char *); #endif - if (strstr(str, pat) != NULL) - return 1; + if (strstr(str, pat) != NULL) + return (1); #if defined(REGEX) - if (regcomp(&re, pat, 0) == 0) { - rv = regexec(&re, str, 0, NULL, 0) == 0; - regfree(&re); - } else { - rv = 0; - } - return rv; + if (regcomp(&re, pat, 0) == 0) { + rv = regexec(&re, str, 0, NULL, 0) == 0; + regfree(&re); + } else { + rv = 0; + } + return (rv); #elif defined(REGEXP) - if ((re = regcomp(pat)) != NULL) { - rv = regexec(re, str); - free((ptr_t) re); - } else { - rv = 0; - } - return rv; + if ((re = regcomp(pat)) != NULL) { + rv = regexec(re, str); + free((ptr_t) re); + } else { + rv = 0; + } + return (rv); #else - if (re_comp(pat) != NULL) - return 0; - else - return re_exec(str) == 1; + if (re_comp(pat) != NULL) + return (0); + else + return (re_exec(str) == 1); #endif } @@ -150,46 +152,44 @@ el_match(str, pat) * return True if the pattern matches the prefix */ protected int -c_hmatch(el, str) - EditLine *el; - const char *str; +c_hmatch(EditLine *el, const char *str) { #ifdef SDEBUG - (void)fprintf(el->el_errfile, "match `%s' with `%s'\n", - el->el_search.patbuf, str); + (void) fprintf(el->el_errfile, "match `%s' with `%s'\n", + el->el_search.patbuf, str); #endif /* SDEBUG */ - - return el_match(str, el->el_search.patbuf); + + return (el_match(str, el->el_search.patbuf)); } -/* c_setpat(): +/* c_setpat(): * Set the history seatch pattern */ protected void -c_setpat(el) - EditLine *el; +c_setpat(EditLine *el) { - if (el->el_state.lastcmd != ED_SEARCH_PREV_HISTORY && - el->el_state.lastcmd != ED_SEARCH_NEXT_HISTORY) { - el->el_search.patlen = EL_CURSOR(el) - el->el_line.buffer; - if (el->el_search.patlen >= EL_BUFSIZ) - el->el_search.patlen = EL_BUFSIZ -1; - if (el->el_search.patlen >= 0) { - (void)strncpy(el->el_search.patbuf, el->el_line.buffer, - el->el_search.patlen); - el->el_search.patbuf[el->el_search.patlen] = '\0'; + if (el->el_state.lastcmd != ED_SEARCH_PREV_HISTORY && + el->el_state.lastcmd != ED_SEARCH_NEXT_HISTORY) { + el->el_search.patlen = EL_CURSOR(el) - el->el_line.buffer; + if (el->el_search.patlen >= EL_BUFSIZ) + el->el_search.patlen = EL_BUFSIZ - 1; + if (el->el_search.patlen != 0) { + (void) strncpy(el->el_search.patbuf, el->el_line.buffer, + el->el_search.patlen); + el->el_search.patbuf[el->el_search.patlen] = '\0'; + } else + el->el_search.patlen = strlen(el->el_search.patbuf); } - else - el->el_search.patlen = strlen(el->el_search.patbuf); - } #ifdef SDEBUG - (void)fprintf(el->el_errfile, "\neventno = %d\n", el->el_history.eventno); - (void)fprintf(el->el_errfile, "patlen = %d\n", el->el_search.patlen); - (void)fprintf(el->el_errfile, "patbuf = \"%s\"\n", el->el_search.patbuf); - (void)fprintf(el->el_errfile, "cursor %d lastchar %d\n", - EL_CURSOR(el) - el->el_line.buffer, - el->el_line.lastchar - el->el_line.buffer); + (void) fprintf(el->el_errfile, "\neventno = %d\n", + el->el_history.eventno); + (void) fprintf(el->el_errfile, "patlen = %d\n", el->el_search.patlen); + (void) fprintf(el->el_errfile, "patbuf = \"%s\"\n", + el->el_search.patbuf); + (void) fprintf(el->el_errfile, "cursor %d lastchar %d\n", + EL_CURSOR(el) - el->el_line.buffer, + el->el_line.lastchar - el->el_line.buffer); #endif } @@ -198,218 +198,241 @@ c_setpat(el) * Emacs incremental search */ protected el_action_t -ce_inc_search(el, dir) - EditLine *el; - int dir; +ce_inc_search(EditLine *el, int dir) { - static char STRfwd[] = { 'f', 'w', 'd', '\0' }, - STRbck[] = { 'b', 'c', 'k', '\0' }; - static char pchar = ':'; /* ':' = normal, '?' = failed */ - static char endcmd[2] = { '\0', '\0' }; - char ch, *cp, *ocursor = el->el_line.cursor, oldpchar = pchar; + static const char STRfwd[] = {'f', 'w', 'd', '\0'}, + STRbck[] = {'b', 'c', 'k', '\0'}; + static char pchar = ':';/* ':' = normal, '?' = failed */ + static char endcmd[2] = {'\0', '\0'}; + char ch, *ocursor = el->el_line.cursor, oldpchar = pchar; + const char *cp; - el_action_t ret = CC_NORM; + el_action_t ret = CC_NORM; - int ohisteventno = el->el_history.eventno, - oldpatlen = el->el_search.patlen, - newdir = dir, - done, redo; + int ohisteventno = el->el_history.eventno; + int oldpatlen = el->el_search.patlen; + int newdir = dir; + int done, redo; - if (el->el_line.lastchar + sizeof(STRfwd) / sizeof(char) + 2 + - el->el_search.patlen >= el->el_line.limit) - return CC_ERROR; + if (el->el_line.lastchar + sizeof(STRfwd) / sizeof(char) + 2 + + el->el_search.patlen >= el->el_line.limit) + return (CC_ERROR); - for (;;) { + for (;;) { - if (el->el_search.patlen == 0) { /* first round */ - pchar = ':'; + if (el->el_search.patlen == 0) { /* first round */ + pchar = ':'; #ifdef ANCHOR - el->el_search.patbuf[el->el_search.patlen++] = '.'; - el->el_search.patbuf[el->el_search.patlen++] = '*'; + el->el_search.patbuf[el->el_search.patlen++] = '.'; + el->el_search.patbuf[el->el_search.patlen++] = '*'; #endif - } - done = redo = 0; - *el->el_line.lastchar++ = '\n'; - for (cp = newdir == ED_SEARCH_PREV_HISTORY ? STRbck : STRfwd; - *cp; *el->el_line.lastchar++ = *cp++) - continue; - *el->el_line.lastchar++ = pchar; - for (cp = &el->el_search.patbuf[1]; - cp < &el->el_search.patbuf[el->el_search.patlen]; - *el->el_line.lastchar++ = *cp++) - continue; - *el->el_line.lastchar = '\0'; - re_refresh(el); - - if (el_getc(el, &ch) != 1) - return ed_end_of_file(el, 0); - - switch (el->el_map.current[(unsigned char) ch]) { - case ED_INSERT: - case ED_DIGIT: - if (el->el_search.patlen > EL_BUFSIZ - 3) - term_beep(el); - else { - el->el_search.patbuf[el->el_search.patlen++] = ch; - *el->el_line.lastchar++ = ch; + } + done = redo = 0; + *el->el_line.lastchar++ = '\n'; + for (cp = (newdir == ED_SEARCH_PREV_HISTORY) ? STRbck : STRfwd; + *cp; *el->el_line.lastchar++ = *cp++) + continue; + *el->el_line.lastchar++ = pchar; + for (cp = &el->el_search.patbuf[1]; + cp < &el->el_search.patbuf[el->el_search.patlen]; + *el->el_line.lastchar++ = *cp++) + continue; *el->el_line.lastchar = '\0'; re_refresh(el); - } - break; - - case EM_INC_SEARCH_NEXT: - newdir = ED_SEARCH_NEXT_HISTORY; - redo++; - break; - - case EM_INC_SEARCH_PREV: - newdir = ED_SEARCH_PREV_HISTORY; - redo++; - break; - - case ED_DELETE_PREV_CHAR: - if (el->el_search.patlen > 1) - done++; - else - term_beep(el); - break; - default: - switch (ch) { - case 0007: /* ^G: Abort */ - ret = CC_ERROR; - done++; - break; - - 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]) { - el->el_line.cursor += el->el_search.patlen - 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_getc(el, &ch) != 1) + return (ed_end_of_file(el, 0)); + + switch (el->el_map.current[(unsigned char) ch]) { + case ED_INSERT: + case ED_DIGIT: + if (el->el_search.patlen > EL_BUFSIZ - 3) term_beep(el); - break; - } - el->el_search.patbuf[el->el_search.patlen++] = - *el->el_line.cursor; - *el->el_line.lastchar++ = *el->el_line.cursor++; + else { + el->el_search.patbuf[el->el_search.patlen++] = + ch; + *el->el_line.lastchar++ = ch; + *el->el_line.lastchar = '\0'; + re_refresh(el); } - el->el_line.cursor = ocursor; - *el->el_line.lastchar = '\0'; - re_refresh(el); break; - } else if (isglob(*cp)) { - term_beep(el); + + case EM_INC_SEARCH_NEXT: + newdir = ED_SEARCH_NEXT_HISTORY; + redo++; + break; + + case EM_INC_SEARCH_PREV: + newdir = ED_SEARCH_PREV_HISTORY; + redo++; break; - } - break; - - default: /* Terminate and execute cmd */ - endcmd[0] = ch; - el_push(el, endcmd); - /*FALLTHROUGH*/ - - case 0033: /* ESC: Terminate */ - ret = CC_REFRESH; - done++; - break; - } - break; - } - while (el->el_line.lastchar > el->el_line.buffer && - *el->el_line.lastchar != '\n') - *el->el_line.lastchar-- = '\0'; - *el->el_line.lastchar = '\0'; + case ED_DELETE_PREV_CHAR: + if (el->el_search.patlen > 1) + done++; + else + term_beep(el); + break; - if (!done) { + default: + switch (ch) { + case 0007: /* ^G: Abort */ + ret = CC_ERROR; + done++; + break; - /* Can't search if unmatched '[' */ - for (cp = &el->el_search.patbuf[el->el_search.patlen-1], ch = ']'; - cp > el->el_search.patbuf; cp--) - if (*cp == '[' || *cp == ']') { - ch = *cp; - break; - } + 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]) { + el->el_line.cursor += + el->el_search.patlen - 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) { + term_beep(el); + break; + } + el->el_search.patbuf[el->el_search.patlen++] = + *el->el_line.cursor; + *el->el_line.lastchar++ = + *el->el_line.cursor++; + } + el->el_line.cursor = ocursor; + *el->el_line.lastchar = '\0'; + re_refresh(el); + break; + } else if (isglob(*cp)) { + term_beep(el); + break; + } + break; - if (el->el_search.patlen > 1 && ch != '[') { - if (redo && newdir == dir) { - if (pchar == '?') { /* wrap around */ - el->el_history.eventno = - newdir == ED_SEARCH_PREV_HISTORY ? 0 : 0x7fffffff; - if (hist_get(el) == CC_ERROR) - /* el->el_history.eventno was fixed by first call */ - (void)hist_get(el); - el->el_line.cursor = newdir == ED_SEARCH_PREV_HISTORY ? - el->el_line.lastchar : el->el_line.buffer; - } else - el->el_line.cursor += - newdir == ED_SEARCH_PREV_HISTORY ? -1 : 1; - } -#ifdef ANCHOR - el->el_search.patbuf[el->el_search.patlen++] = '.'; - el->el_search.patbuf[el->el_search.patlen++] = '*'; -#endif - el->el_search.patbuf[el->el_search.patlen] = '\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) { - /* avoid c_setpat */ - el->el_state.lastcmd = (el_action_t) newdir; - ret = newdir == ED_SEARCH_PREV_HISTORY ? - ed_search_prev_history(el, 0) : - ed_search_next_history(el, 0); - if (ret != CC_ERROR) { - el->el_line.cursor = newdir == ED_SEARCH_PREV_HISTORY ? - 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] = '\0'; - if (ret == CC_ERROR) { - term_beep(el); - if (el->el_history.eventno != ohisteventno) { - el->el_history.eventno = ohisteventno; - if (hist_get(el) == CC_ERROR) - return CC_ERROR; - } - el->el_line.cursor = ocursor; - pchar = '?'; - } else { - pchar = ':'; + default: /* Terminate and execute cmd */ + endcmd[0] = ch; + el_push(el, endcmd); + /* FALLTHROUGH */ + + case 0033: /* ESC: Terminate */ + ret = CC_REFRESH; + done++; + break; + } + break; } - } - ret = ce_inc_search(el, newdir); + while (el->el_line.lastchar > el->el_line.buffer && + *el->el_line.lastchar != '\n') + *el->el_line.lastchar-- = '\0'; + *el->el_line.lastchar = '\0'; - if (ret == CC_ERROR && pchar == '?' && oldpchar == ':') - /* break abort of failed search at last non-failed */ - ret = CC_NORM; + if (!done) { + + /* Can't search if unmatched '[' */ + for (cp = &el->el_search.patbuf[el->el_search.patlen-1], + ch = ']'; + cp > el->el_search.patbuf; + cp--) + if (*cp == '[' || *cp == ']') { + ch = *cp; + break; + } + if (el->el_search.patlen > 1 && ch != '[') { + if (redo && newdir == dir) { + if (pchar == '?') { /* wrap around */ + el->el_history.eventno = + newdir == ED_SEARCH_PREV_HISTORY ? 0 : 0x7fffffff; + if (hist_get(el) == CC_ERROR) + /* el->el_history.event + * no was fixed by + * first call */ + (void) hist_get(el); + el->el_line.cursor = newdir == + ED_SEARCH_PREV_HISTORY ? + el->el_line.lastchar : + el->el_line.buffer; + } else + el->el_line.cursor += + newdir == + ED_SEARCH_PREV_HISTORY ? + -1 : 1; + } +#ifdef ANCHOR + el->el_search.patbuf[el->el_search.patlen++] = + '.'; + el->el_search.patbuf[el->el_search.patlen++] = + '*'; +#endif + el->el_search.patbuf[el->el_search.patlen] = + '\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) { + /* avoid c_setpat */ + el->el_state.lastcmd = + (el_action_t) newdir; + ret = newdir == ED_SEARCH_PREV_HISTORY ? + ed_search_prev_history(el, 0) : + ed_search_next_history(el, 0); + if (ret != CC_ERROR) { + el->el_line.cursor = newdir == + ED_SEARCH_PREV_HISTORY ? + 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] = + '\0'; + if (ret == CC_ERROR) { + term_beep(el); + if (el->el_history.eventno != + ohisteventno) { + el->el_history.eventno = + ohisteventno; + if (hist_get(el) == CC_ERROR) + return (CC_ERROR); + } + el->el_line.cursor = ocursor; + pchar = '?'; + } else { + pchar = ':'; + } + } + ret = ce_inc_search(el, newdir); - } + if (ret == CC_ERROR && pchar == '?' && oldpchar == ':') + /* + * break abort of failed search at last + * non-failed + */ + ret = CC_NORM; - if (ret == CC_NORM || (ret == CC_ERROR && oldpatlen == 0)) { - /* restore on normal return or error exit */ - pchar = oldpchar; - el->el_search.patlen = oldpatlen; - if (el->el_history.eventno != ohisteventno) { - el->el_history.eventno = ohisteventno; - if (hist_get(el) == CC_ERROR) - return CC_ERROR; - } - el->el_line.cursor = ocursor; - if (ret == CC_ERROR) - re_refresh(el); + } + if (ret == CC_NORM || (ret == CC_ERROR && oldpatlen == 0)) { + /* restore on normal return or error exit */ + pchar = oldpchar; + el->el_search.patlen = oldpatlen; + if (el->el_history.eventno != ohisteventno) { + el->el_history.eventno = ohisteventno; + if (hist_get(el) == CC_ERROR) + return (CC_ERROR); + } + el->el_line.cursor = ocursor; + if (ret == CC_ERROR) + re_refresh(el); + } + if (done || ret != CC_NORM) + return (ret); } - if (done || ret != CC_NORM) - return ret; - } } @@ -417,96 +440,76 @@ ce_inc_search(el, dir) * Vi search. */ protected el_action_t -cv_search(el, dir) - EditLine *el; - int dir; +cv_search(EditLine *el, int dir) { - char ch; - char tmpbuf[EL_BUFSIZ]; - int tmplen; + char ch; + char tmpbuf[EL_BUFSIZ]; + int tmplen; - tmplen = 0; #ifdef ANCHOR - tmpbuf[tmplen++] = '.'; - tmpbuf[tmplen++] = '*'; + tmpbuf[0] = '.'; + tmpbuf[1] = '*'; +#define LEN 2 +#else +#define LEN 0 #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; + 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); + tmplen = c_gets(el, &tmpbuf[LEN], + dir == ED_SEARCH_PREV_HISTORY ? "\n/" : "\n?" ); + if (tmplen == -1) + return CC_REFRESH; -#ifdef ANCHOR -# define LEN 2 -#else -# define LEN 0 -#endif + tmplen += LEN; + ch = tmpbuf[tmplen]; + tmpbuf[tmplen] = '\0'; - tmplen = c_gets(el, &tmpbuf[LEN]) + LEN; - ch = tmpbuf[tmplen]; - tmpbuf[tmplen] = '\0'; - - if (tmplen == LEN) { - /* - * 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; - } + if (tmplen == LEN) { + /* + * Use the old pattern, but wild-card it. + */ + if (el->el_search.patlen == 0) { + re_refresh(el); + return (CC_ERROR); + } #ifdef ANCHOR - if (el->el_search.patbuf[0] != '.' && el->el_search.patbuf[0] != '*') { - (void)strncpy(tmpbuf, el->el_search.patbuf, sizeof(tmpbuf) - 1); - tmpbuf[sizeof(tmpbuf) - 1] = '\0'; - el->el_search.patbuf[0] = '.'; - el->el_search.patbuf[1] = '*'; - (void)strncpy(&el->el_search.patbuf[2], tmpbuf, - EL_BUFSIZ - 3); - el->el_search.patbuf[EL_BUFSIZ - 1] = '\0'; - el->el_search.patlen++; - el->el_search.patbuf[el->el_search.patlen++] = '.'; - el->el_search.patbuf[el->el_search.patlen++] = '*'; - el->el_search.patbuf[el->el_search.patlen] = '\0'; - } + if (el->el_search.patbuf[0] != '.' && + el->el_search.patbuf[0] != '*') { + (void) strncpy(tmpbuf, el->el_search.patbuf, + sizeof(tmpbuf) - 1); + el->el_search.patbuf[0] = '.'; + el->el_search.patbuf[1] = '*'; + (void) strncpy(&el->el_search.patbuf[2], tmpbuf, + EL_BUFSIZ - 3); + el->el_search.patlen++; + el->el_search.patbuf[el->el_search.patlen++] = '.'; + el->el_search.patbuf[el->el_search.patlen++] = '*'; + el->el_search.patbuf[el->el_search.patlen] = '\0'; + } #endif - } - else { + } else { #ifdef ANCHOR - tmpbuf[tmplen++] = '.'; - tmpbuf[tmplen++] = '*'; + tmpbuf[tmplen++] = '.'; + tmpbuf[tmplen++] = '*'; #endif - tmpbuf[tmplen] = '\0'; - (void)strncpy(el->el_search.patbuf, tmpbuf, - EL_BUFSIZ - 1); - el->el_search.patbuf[EL_BUFSIZ - 1] = '\0'; - el->el_search.patlen = strlen(el->el_search.patbuf); - } - 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) { - re_refresh(el); - return CC_ERROR; - } - else { + tmpbuf[tmplen] = '\0'; + (void) strncpy(el->el_search.patbuf, tmpbuf, EL_BUFSIZ - 1); + el->el_search.patlen = tmplen; + } + 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) { + re_refresh(el); + return (CC_ERROR); + } if (ch == 0033) { - re_refresh(el); - *el->el_line.lastchar++ = '\n'; - *el->el_line.lastchar = '\0'; - re_goto_bottom(el); - return CC_NEWLINE; + re_refresh(el); + return ed_newline(el, 0); } - else - return CC_REFRESH; - } + return (CC_REFRESH); } @@ -514,29 +517,26 @@ cv_search(el, dir) * Look for a pattern inside a line */ protected el_action_t -ce_search_line(el, pattern, dir) - EditLine *el; - char *pattern; - int dir; +ce_search_line(EditLine *el, char *pattern, int dir) { - char *cp; - - if (dir == ED_SEARCH_PREV_HISTORY) { - for (cp = el->el_line.cursor; cp >= el->el_line.buffer; cp--) - if (el_match(cp, pattern)) { - el->el_line.cursor = cp; - return CC_NORM; - } - return CC_ERROR; - } else { - for (cp = el->el_line.cursor; *cp != '\0' && - cp < el->el_line.limit; cp++) - if (el_match(cp, pattern)) { - el->el_line.cursor = cp; - return CC_NORM; - } - return CC_ERROR; - } + char *cp; + + if (dir == ED_SEARCH_PREV_HISTORY) { + for (cp = el->el_line.cursor; cp >= el->el_line.buffer; cp--) + if (el_match(cp, pattern)) { + el->el_line.cursor = cp; + return (CC_NORM); + } + return (CC_ERROR); + } else { + for (cp = el->el_line.cursor; *cp != '\0' && + cp < el->el_line.limit; cp++) + if (el_match(cp, pattern)) { + el->el_line.cursor = cp; + return (CC_NORM); + } + return (CC_ERROR); + } } @@ -544,97 +544,75 @@ ce_search_line(el, pattern, dir) * Vi repeat search */ protected el_action_t -cv_repeat_srch(el, c) - EditLine *el; - int c; +cv_repeat_srch(EditLine *el, int c) { + #ifdef SDEBUG - (void)fprintf(el->el_errfile, "dir %d patlen %d patbuf %s\n", - c, el->el_search.patlen, el->el_search.patbuf); + (void) fprintf(el->el_errfile, "dir %d patlen %d patbuf %s\n", + c, el->el_search.patlen, el->el_search.patbuf); #endif - el->el_state.lastcmd = (el_action_t) c; /* Hack to stop c_setpat */ - el->el_line.lastchar = el->el_line.buffer; - - switch (c) { - case ED_SEARCH_NEXT_HISTORY: - return ed_search_next_history(el, 0); - case ED_SEARCH_PREV_HISTORY: - return ed_search_prev_history(el, 0); - default: - return CC_ERROR; - } + el->el_state.lastcmd = (el_action_t) c; /* Hack to stop c_setpat */ + el->el_line.lastchar = el->el_line.buffer; + + switch (c) { + case ED_SEARCH_NEXT_HISTORY: + return (ed_search_next_history(el, 0)); + case ED_SEARCH_PREV_HISTORY: + return (ed_search_prev_history(el, 0)); + default: + return (CC_ERROR); + } } -/* cv_csearch_back(): - * Vi character search reverse +/* cv_csearch(): + * Vi character search */ protected el_action_t -cv_csearch_back(el, ch, count, tflag) - EditLine *el; - int ch, count, 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 (cp < el->el_line.buffer || (cp == el->el_line.buffer && *cp != ch)) - return CC_ERROR; + char *cp; - if (*cp == ch && tflag) - cp++; + if (ch == 0) + return CC_ERROR; - el->el_line.cursor = cp; + if (ch == -1) { + char c; + if (el_getc(el, &c) != 1) + return ed_end_of_file(el, 0); + ch = c; + } - if (el->el_chared.c_vcmd.action & DELETE) { - el->el_line.cursor++; - cv_delfini(el); - return CC_REFRESH; - } + /* 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 += 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; + } + } - re_refresh_cursor(el); - return CC_NORM; -} + if (tflag) + cp -= direction; + el->el_line.cursor = cp; -/* cv_csearch_fwd(): - * Vi character search forward - */ -protected el_action_t -cv_csearch_fwd(el, ch, count, tflag) - EditLine *el; - int ch, count, tflag; -{ - char *cp; - - cp = el->el_line.cursor; - while (count--) { - if(*cp == ch) - cp++; - while (cp < el->el_line.lastchar && *cp != ch) - cp++; - } - - if (cp >= el->el_line.lastchar) - 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; - } - re_refresh_cursor(el); - return CC_NORM; + if (el->el_chared.c_vcmd.action != NOP) { + if (direction > 0) + el->el_line.cursor++; + cv_delfini(el); + return CC_REFRESH; + } + return CC_CURSOR; } diff --git a/lib/libedit/search.h b/lib/libedit/search.h index 6c006969c2f..8319fa7469e 100644 --- a/lib/libedit/search.h +++ b/lib/libedit/search.h @@ -1,5 +1,5 @@ -/* $OpenBSD: search.h,v 1.5 2003/06/02 20:18:40 millert Exp $ */ -/* $NetBSD: search.h,v 1.2 1997/01/11 06:48:09 lukem Exp $ */ +/* $OpenBSD: search.h,v 1.6 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: search.h,v 1.7 2003/08/07 16:44:33 agc Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -38,21 +38,22 @@ /* * el.search.h: Line and history searching utilities */ -#ifndef _h_el_search -#define _h_el_search +#ifndef _h_el_search +#define _h_el_search #include "histedit.h" typedef struct el_search_t { - char *patbuf; /* The pattern buffer */ - int patlen; /* Length of the pattern buffer */ - int patdir; /* Direction of the last search */ - int chadir; /* Character search direction */ - char chacha; /* Character we are looking for */ + char *patbuf; /* The pattern buffer */ + size_t patlen; /* Length of the pattern buffer */ + 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; -protected int el_match(const char *, const char *); +protected int el_match(const char *, const char *); protected int search_init(EditLine *); protected void search_end(EditLine *); protected int c_hmatch(EditLine *, const char *); @@ -61,7 +62,6 @@ 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 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/shlib_version b/lib/libedit/shlib_version index 1edea46de91..7d5f3990678 100644 --- a/lib/libedit/shlib_version +++ b/lib/libedit/shlib_version @@ -1,2 +1,5 @@ -major=1 +# $OpenBSD: shlib_version,v 1.3 2003/10/31 08:42:24 otto Exp $ +# $NetBSD: shlib_version,v 1.14 2003/09/26 17:44:51 christos Exp $ +# +major=2 minor=0 diff --git a/lib/libedit/sig.c b/lib/libedit/sig.c index 145b6c684f2..28ce610b0fe 100644 --- a/lib/libedit/sig.c +++ b/lib/libedit/sig.c @@ -1,5 +1,5 @@ -/* $OpenBSD: sig.c,v 1.9 2003/06/02 20:18:40 millert Exp $ */ -/* $NetBSD: sig.c,v 1.3 1997/04/11 17:52:48 christos Exp $ */ +/* $OpenBSD: sig.c,v 1.10 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: sig.c,v 1.11 2003/08/07 16:44:33 agc Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -33,11 +33,12 @@ * SUCH DAMAGE. */ +#include "config.h" #if !defined(lint) && !defined(SCCSID) #if 0 static char sccsid[] = "@(#)sig.c 8.1 (Berkeley) 6/4/93"; #else -static const char rcsid[] = "$OpenBSD: sig.c,v 1.9 2003/06/02 20:18:40 millert Exp $"; +static const char rcsid[] = "$OpenBSD: sig.c,v 1.10 2003/10/31 08:42:24 otto Exp $"; #endif #endif /* not lint && not SCCSID */ @@ -46,17 +47,16 @@ static const char rcsid[] = "$OpenBSD: sig.c,v 1.9 2003/06/02 20:18:40 millert E * our policy is to trap all signals, set a good state * and pass the ball to our caller. */ -#include "sys.h" #include "el.h" #include <stdlib.h> private EditLine *sel = NULL; -private int sighdl[] = { -#define _DO(a) (a), - ALLSIGS -#undef _DO - -1 +private const int sighdl[] = { +#define _DO(a) (a), + ALLSIGS +#undef _DO + - 1 }; private void sig_handler(int); @@ -67,42 +67,39 @@ private void sig_handler(int); * state in a private variable */ private void -sig_handler(signo) - int signo; +sig_handler(int signo) { - int save_errno = errno; - int i; - sigset_t nset, oset; - - (void)sigemptyset(&nset); - (void)sigaddset(&nset, signo); - (void)sigprocmask(SIG_BLOCK, &nset, &oset); - - switch (signo) { - case SIGCONT: - tty_rawmode(sel); /* XXX signal race */ - if (ed_redisplay(sel, 0) == CC_REFRESH) /* XXX signal race */ - re_refresh(sel); /* XXX signal race */ - term__flush(); /* XXX signal race */ - break; - - case SIGWINCH: - el_resize(sel); /* XXX signal race */ - break; - - default: - tty_cookedmode(sel); /* XXX signal race */ - break; - } - - for (i = 0; sighdl[i] != -1; i++) - if (signo == sighdl[i]) - break; - - (void)signal(signo, sel->el_signal[i]); - (void)sigprocmask(SIG_SETMASK, &oset, NULL); - (void)kill(0, signo); - errno = save_errno; + int i; + sigset_t nset, oset; + + (void) sigemptyset(&nset); + (void) sigaddset(&nset, signo); + (void) sigprocmask(SIG_BLOCK, &nset, &oset); + + switch (signo) { + case SIGCONT: + tty_rawmode(sel); + if (ed_redisplay(sel, 0) == CC_REFRESH) + re_refresh(sel); + term__flush(); + break; + + case SIGWINCH: + el_resize(sel); + break; + + default: + tty_cookedmode(sel); + break; + } + + for (i = 0; sighdl[i] != -1; i++) + if (signo == sighdl[i]) + break; + + (void) signal(signo, sel->el_signal[i]); + (void) sigprocmask(SIG_SETMASK, &oset, NULL); + (void) kill(0, signo); } @@ -110,27 +107,28 @@ sig_handler(signo) * Initialize all signal stuff */ protected int -sig_init(el) - EditLine *el; +sig_init(EditLine *el) { - int i; - sigset_t nset, oset; + int i; + sigset_t nset, oset; - (void)sigemptyset(&nset); -#define _DO(a) (void)sigaddset(&nset, a); - ALLSIGS -#undef _DO - (void)sigprocmask(SIG_BLOCK, &nset, &oset); + (void) sigemptyset(&nset); +#define _DO(a) (void) sigaddset(&nset, a); + ALLSIGS +#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); - for (i = 0; sighdl[i] != -1; i++) - el->el_signal[i] = SIG_ERR; + el->el_signal = (el_signalhandler_t *) el_malloc(SIGSIZE); + if (el->el_signal == NULL) + return (-1); + for (i = 0; sighdl[i] != -1; i++) + el->el_signal[i] = SIG_ERR; - (void)sigprocmask(SIG_SETMASK, &oset, NULL); + (void) sigprocmask(SIG_SETMASK, &oset, NULL); - return 0; + return (0); } @@ -138,11 +136,11 @@ sig_init(el) * Clear all signal stuff */ protected void -sig_end(el) - EditLine *el; +sig_end(EditLine *el) { - el_free((ptr_t) el->el_signal); - el->el_signal = NULL; + + el_free((ptr_t) el->el_signal); + el->el_signal = NULL; } @@ -150,26 +148,25 @@ sig_end(el) * set all the signal handlers */ protected void -sig_set(el) - EditLine *el; +sig_set(EditLine *el) { - int i; - sigset_t nset, oset; - - (void)sigemptyset(&nset); -#define _DO(a) (void)sigaddset(&nset, a); - ALLSIGS -#undef _DO - (void)sigprocmask(SIG_BLOCK, &nset, &oset); - - for (i = 0; sighdl[i] != -1; i++) { - sig_t s; - /* This could happen if we get interrupted */ - if ((s = signal(sighdl[i], sig_handler)) != sig_handler) - el->el_signal[i] = s; - } - sel = el; - (void)sigprocmask(SIG_SETMASK, &oset, NULL); + int i; + sigset_t nset, oset; + + (void) sigemptyset(&nset); +#define _DO(a) (void) sigaddset(&nset, a); + ALLSIGS +#undef _DO + (void) sigprocmask(SIG_BLOCK, &nset, &oset); + + for (i = 0; sighdl[i] != -1; i++) { + 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; + } + sel = el; + (void) sigprocmask(SIG_SETMASK, &oset, NULL); } @@ -177,22 +174,22 @@ sig_set(el) * clear all the signal handlers */ protected void -sig_clr(el) - EditLine *el; +sig_clr(EditLine *el) { - int i; - sigset_t nset, oset; - - (void)sigemptyset(&nset); -#define _DO(a) (void)sigaddset(&nset, a); - ALLSIGS -#undef _DO - (void)sigprocmask(SIG_BLOCK, &nset, &oset); - - for (i = 0; sighdl[i] != -1; i++) - if (el->el_signal[i] != SIG_ERR) - (void)signal(sighdl[i], el->el_signal[i]); - - sel = NULL; /* we are going to die if the handler is called */ - (void)sigprocmask(SIG_SETMASK, &oset, NULL); + int i; + sigset_t nset, oset; + + (void) sigemptyset(&nset); +#define _DO(a) (void) sigaddset(&nset, a); + ALLSIGS +#undef _DO + (void) sigprocmask(SIG_BLOCK, &nset, &oset); + + for (i = 0; sighdl[i] != -1; i++) + if (el->el_signal[i] != SIG_ERR) + (void) signal(sighdl[i], el->el_signal[i]); + + sel = NULL; /* we are going to die if the handler is + * called */ + (void) sigprocmask(SIG_SETMASK, &oset, NULL); } diff --git a/lib/libedit/sig.h b/lib/libedit/sig.h index 25594c03e23..34251f817a4 100644 --- a/lib/libedit/sig.h +++ b/lib/libedit/sig.h @@ -1,5 +1,5 @@ -/* $OpenBSD: sig.h,v 1.5 2003/06/02 20:18:40 millert Exp $ */ -/* $NetBSD: sig.h,v 1.2 1997/01/11 06:48:11 lukem Exp $ */ +/* $OpenBSD: sig.h,v 1.6 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: sig.h,v 1.5 2003/08/07 16:44:33 agc Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -39,7 +39,7 @@ * el.sig.h: Signal handling functions */ #ifndef _h_el_sig -#define _h_el_sig +#define _h_el_sig #include <signal.h> @@ -49,17 +49,18 @@ * Define here all the signals we are going to handle * The _DO macro is used to iterate in the source code */ -#define ALLSIGS \ - _DO(SIGINT) \ - _DO(SIGTSTP) \ - _DO(SIGSTOP) \ - _DO(SIGQUIT) \ - _DO(SIGHUP) \ - _DO(SIGTERM) \ - _DO(SIGCONT) \ - _DO(SIGWINCH) +#define ALLSIGS \ + _DO(SIGINT) \ + _DO(SIGTSTP) \ + _DO(SIGSTOP) \ + _DO(SIGQUIT) \ + _DO(SIGHUP) \ + _DO(SIGTERM) \ + _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 2cbde136889..1335d61c12b 100644 --- a/lib/libedit/sys.h +++ b/lib/libedit/sys.h @@ -1,5 +1,5 @@ -/* $OpenBSD: sys.h,v 1.7 2003/06/02 20:18:40 millert Exp $ */ -/* $NetBSD: sys.h,v 1.3 1997/01/11 06:48:12 lukem Exp $ */ +/* $OpenBSD: sys.h,v 1.8 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: sys.h,v 1.8 2003/08/07 16:44:33 agc Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -39,7 +39,15 @@ * sys.h: Put all the stupid compiler and system dependencies here... */ #ifndef _h_sys -#define _h_sys +#define _h_sys + +#ifdef HAVE_SYS_CDEFS_H +#include <sys/cdefs.h> +#endif + +#if !defined(__attribute__) && (defined(__cplusplus) || !defined(__GNUC__) || __GNUC__ == 2 && __GNUC_MINOR__ < 8) +# define __attribute__(A) +#endif #ifndef public # define public /* Externally visible functions/variables */ @@ -54,37 +62,54 @@ /* When we want to hide everything */ #endif -#include <sys/cdefs.h> - #ifndef _PTR_T # define _PTR_T -typedef void* ptr_t; +typedef void *ptr_t; #endif #ifndef _IOCTL_T # define _IOCTL_T -typedef void* ioctl_t; +typedef void *ioctl_t; #endif #include <stdio.h> +#ifndef HAVE_STRLCAT +#define strlcat libedit_strlcat +size_t strlcat(char *dst, const char *src, size_t size); +#endif + +#ifndef HAVE_STRLCPY +#define strlcpy libedit_strlcpy +size_t strlcpy(char *dst, const char *src, size_t size); +#endif + +#ifndef HAVE_FGETLN +#define fgetln libedit_fgetln +char *fgetln(FILE *fp, size_t *len); +#endif + #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 <malloc.h> -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 *); @@ -93,7 +118,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 <string.h> # define strerror(e) sys_errlist[e] # endif diff --git a/lib/libedit/term.c b/lib/libedit/term.c index 2a9e3ee6e4d..7e92256364a 100644 --- a/lib/libedit/term.c +++ b/lib/libedit/term.c @@ -1,5 +1,5 @@ -/* $OpenBSD: term.c,v 1.10 2003/06/02 20:18:40 millert Exp $ */ -/* $NetBSD: term.c,v 1.8 1997/01/23 14:02:49 mrg Exp $ */ +/* $OpenBSD: term.c,v 1.11 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: term.c,v 1.38 2003/09/14 21:48:55 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -33,11 +33,12 @@ * SUCH DAMAGE. */ +#include "config.h" #if !defined(lint) && !defined(SCCSID) #if 0 -static char sccsid[] = "@(#)term.c 8.1 (Berkeley) 6/4/93"; +static char sccsid[] = "@(#)term.c 8.2 (Berkeley) 4/30/95"; #else -static const char rcsid[] = "$OpenBSD: term.c,v 1.10 2003/06/02 20:18:40 millert Exp $"; +static const char rcsid[] = "$OpenBSD: term.c,v 1.11 2003/10/31 08:42:24 otto Exp $"; #endif #endif /* not lint && not SCCSID */ @@ -46,15 +47,26 @@ static const char rcsid[] = "$OpenBSD: term.c,v 1.10 2003/06/02 20:18:40 millert * We have to declare a static variable here, since the * termcap putchar routine does not take an argument! */ -#include "sys.h" #include <stdio.h> #include <signal.h> #include <string.h> #include <stdlib.h> #include <unistd.h> -#include "termcap.h" /* XXX: should be <termcap.h> */ -#include <sys/ioctl.h> +#ifdef HAVE_TERMCAP_H +#include <termcap.h> +#endif +#ifdef HAVE_CURSES_H +#include <curses.h> +#endif +#ifdef HAVE_NCURSES_H +#include <ncurses.h> +#endif +/* Solaris's term.h does horrid things. */ +#if (defined(HAVE_TERM_H) && !defined(SUNOS)) +#include <term.h> +#endif #include <sys/types.h> +#include <sys/ioctl.h> #include "el.h" @@ -65,192 +77,199 @@ static const char rcsid[] = "$OpenBSD: term.c,v 1.10 2003/06/02 20:18:40 millert * assumption... */ -#define TC_BUFSIZE 2048 +#define TC_BUFSIZE 2048 -#define GoodStr(a) (el->el_term.t_str[a] != NULL && \ - el->el_term.t_str[a][0] != '\0') -#define Str(a) el->el_term.t_str[a] -#define Val(a) el->el_term.t_val[a] +#define GoodStr(a) (el->el_term.t_str[a] != NULL && \ + el->el_term.t_str[a][0] != '\0') +#define Str(a) el->el_term.t_str[a] +#define Val(a) el->el_term.t_val[a] #ifdef notdef -private struct { - char *b_name; - int b_rate; +private const struct { + const char *b_name; + int b_rate; } baud_rate[] = { #ifdef B0 - { "0", B0 }, + { "0", B0 }, #endif #ifdef B50 - { "50", B50 }, + { "50", B50 }, #endif #ifdef B75 - { "75", B75 }, + { "75", B75 }, #endif #ifdef B110 - { "110", B110 }, + { "110", B110 }, #endif #ifdef B134 - { "134", B134 }, + { "134", B134 }, #endif #ifdef B150 - { "150", B150 }, + { "150", B150 }, #endif #ifdef B200 - { "200", B200 }, + { "200", B200 }, #endif #ifdef B300 - { "300", B300 }, + { "300", B300 }, #endif #ifdef B600 - { "600", B600 }, + { "600", B600 }, #endif #ifdef B900 - { "900", B900 }, + { "900", B900 }, #endif #ifdef B1200 - { "1200", B1200 }, + { "1200", B1200 }, #endif #ifdef B1800 - { "1800", B1800 }, + { "1800", B1800 }, #endif #ifdef B2400 - { "2400", B2400 }, + { "2400", B2400 }, #endif #ifdef B3600 - { "3600", B3600 }, + { "3600", B3600 }, #endif #ifdef B4800 - { "4800", B4800 }, + { "4800", B4800 }, #endif #ifdef B7200 - { "7200", B7200 }, + { "7200", B7200 }, #endif #ifdef B9600 - { "9600", B9600 }, + { "9600", B9600 }, #endif #ifdef EXTA - { "19200", EXTA }, + { "19200", EXTA }, #endif #ifdef B19200 - { "19200", B19200 }, + { "19200", B19200 }, #endif #ifdef EXTB - { "38400", EXTB }, + { "38400", EXTB }, #endif #ifdef B38400 - { "38400", B38400 }, + { "38400", B38400 }, #endif - { NULL, 0 } + { NULL, 0 } }; #endif -private struct termcapstr { - char *name; - char *long_name; +private const struct termcapstr { + const char *name; + const char *long_name; } tstr[] = { - -#define T_al 0 - { "al", "add new blank line" }, -#define T_bl 1 - { "bl", "audible bell" }, -#define T_cd 2 - { "cd", "clear to bottom" }, -#define T_ce 3 - { "ce", "clear to end of line" }, -#define T_ch 4 - { "ch", "cursor to horiz pos" }, -#define T_cl 5 - { "cl", "clear screen" }, +#define T_al 0 + { "al", "add new blank line" }, +#define T_bl 1 + { "bl", "audible bell" }, +#define T_cd 2 + { "cd", "clear to bottom" }, +#define T_ce 3 + { "ce", "clear to end of line" }, +#define T_ch 4 + { "ch", "cursor to horiz pos" }, +#define T_cl 5 + { "cl", "clear screen" }, #define T_dc 6 - { "dc", "delete a character" }, + { "dc", "delete a character" }, #define T_dl 7 - { "dl", "delete a line" }, + { "dl", "delete a line" }, #define T_dm 8 - { "dm", "start delete mode" }, + { "dm", "start delete mode" }, #define T_ed 9 - { "ed", "end delete mode" }, + { "ed", "end delete mode" }, #define T_ei 10 - { "ei", "end insert mode" }, + { "ei", "end insert mode" }, #define T_fs 11 - { "fs", "cursor from status line" }, + { "fs", "cursor from status line" }, #define T_ho 12 - { "ho", "home cursor" }, + { "ho", "home cursor" }, #define T_ic 13 - { "ic", "insert character" }, -#define T_im 14 - { "im", "start insert mode" }, + { "ic", "insert character" }, +#define T_im 14 + { "im", "start insert mode" }, #define T_ip 15 - { "ip", "insert padding" }, + { "ip", "insert padding" }, #define T_kd 16 - { "kd", "sends cursor down" }, + { "kd", "sends cursor down" }, #define T_kl 17 - { "kl", "sends cursor left" }, -#define T_kr 18 - { "kr", "sends cursor right" }, -#define T_ku 19 - { "ku", "sends cursor up" }, -#define T_md 20 - { "md", "begin bold" }, -#define T_me 21 - { "me", "end attributes" }, -#define T_nd 22 - { "nd", "non destructive space" }, -#define T_se 23 - { "se", "end standout" }, -#define T_so 24 - { "so", "begin standout" }, -#define T_ts 25 - { "ts", "cursor to status line" }, -#define T_up 26 - { "up", "cursor up one" }, -#define T_us 27 - { "us", "begin underline" }, -#define T_ue 28 - { "ue", "end underline" }, -#define T_vb 29 - { "vb", "visible bell" }, -#define T_DC 30 - { "DC", "delete multiple chars" }, -#define T_DO 31 - { "DO", "cursor down multiple" }, -#define T_IC 32 - { "IC", "insert multiple chars" }, -#define T_LE 33 - { "LE", "cursor left multiple" }, -#define T_RI 34 - { "RI", "cursor right multiple" }, -#define T_UP 35 - { "UP", "cursor up multiple" }, -#define T_str 36 - { NULL, NULL } + { "kl", "sends cursor left" }, +#define T_kr 18 + { "kr", "sends cursor right" }, +#define T_ku 19 + { "ku", "sends cursor up" }, +#define T_md 20 + { "md", "begin bold" }, +#define T_me 21 + { "me", "end attributes" }, +#define T_nd 22 + { "nd", "non destructive space" }, +#define T_se 23 + { "se", "end standout" }, +#define T_so 24 + { "so", "begin standout" }, +#define T_ts 25 + { "ts", "cursor to status line" }, +#define T_up 26 + { "up", "cursor up one" }, +#define T_us 27 + { "us", "begin underline" }, +#define T_ue 28 + { "ue", "end underline" }, +#define T_vb 29 + { "vb", "visible bell" }, +#define T_DC 30 + { "DC", "delete multiple chars" }, +#define T_DO 31 + { "DO", "cursor down multiple" }, +#define T_IC 32 + { "IC", "insert multiple chars" }, +#define T_LE 33 + { "LE", "cursor left multiple" }, +#define T_RI 34 + { "RI", "cursor right multiple" }, +#define T_UP 35 + { "UP", "cursor up multiple" }, +#define T_kh 36 + { "kh", "send cursor home" }, +#define T_at7 37 + { "@7", "send cursor end" }, +#define T_str 38 + { NULL, NULL } }; -private struct termcapval { - char *name; - char *long_name; +private const struct termcapval { + const char *name; + const char *long_name; } tval[] = { -#define T_pt 0 - { "pt", "has physical tabs" }, -#define T_li 1 - { "li", "Number of lines" }, -#define T_co 2 - { "co", "Number of columns" }, -#define T_km 3 - { "km", "Has meta key" }, -#define T_xt 4 - { "xt", "Tab chars destructive" }, -#define T_MT 5 - { "MT", "Has meta key" }, /* XXX? */ -#define T_val 6 - { NULL, NULL, } +#define T_am 0 + { "am", "has automatic margins" }, +#define T_pt 1 + { "pt", "has physical tabs" }, +#define T_li 2 + { "li", "Number of lines" }, +#define T_co 3 + { "co", "Number of columns" }, +#define T_km 4 + { "km", "Has meta key" }, +#define T_xt 5 + { "xt", "Tab chars destructive" }, +#define T_xn 6 + { "xn", "newline ignored at right margin" }, +#define T_MT 7 + { "MT", "Has meta key" }, /* XXX? */ +#define T_val 8 + { NULL, NULL, } }; - /* do two or more of the attributes use me */ -private void term_rebuffer_display(EditLine *); -private void term_free_display(EditLine *); -private void term_alloc_display(EditLine *); -private void term_alloc(EditLine *, struct termcapstr *, char *); +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 *, const char *); private void term_init_arrow(EditLine *); private void term_reset_arrow(EditLine *); @@ -262,39 +281,44 @@ private FILE *term_outfile = NULL; /* XXX: How do we fix that? */ * Set the terminal capability flags */ private void -term_setflags(el) - EditLine *el; +term_setflags(EditLine *el) { - EL_FLAGS = 0; - if (el->el_tty.t_tabs) - EL_FLAGS |= (Val(T_pt) && !Val(T_xt)) ? TERM_CAN_TAB : 0; - - EL_FLAGS |= (Val(T_km) || Val(T_MT)) ? TERM_HAS_META : 0; - EL_FLAGS |= GoodStr(T_ce) ? TERM_CAN_CEOL : 0; - EL_FLAGS |= (GoodStr(T_dc) || GoodStr(T_DC)) ? TERM_CAN_DELETE : 0; - EL_FLAGS |= (GoodStr(T_im) || GoodStr(T_ic) || GoodStr(T_IC)) ? - TERM_CAN_INSERT : 0; - EL_FLAGS |= (GoodStr(T_up) || GoodStr(T_UP)) ? TERM_CAN_UP : 0; - - if (GoodStr(T_me) && GoodStr(T_ue)) - EL_FLAGS |= (strcmp(Str(T_me), Str(T_ue)) == 0) ? TERM_CAN_ME : 0; - else - EL_FLAGS &= ~TERM_CAN_ME; - if (GoodStr(T_me) && GoodStr(T_se)) - EL_FLAGS |= (strcmp(Str(T_me), Str(T_se)) == 0) ? TERM_CAN_ME : 0; + EL_FLAGS = 0; + if (el->el_tty.t_tabs) + EL_FLAGS |= (Val(T_pt) && !Val(T_xt)) ? TERM_CAN_TAB : 0; + + EL_FLAGS |= (Val(T_km) || Val(T_MT)) ? TERM_HAS_META : 0; + EL_FLAGS |= GoodStr(T_ce) ? TERM_CAN_CEOL : 0; + EL_FLAGS |= (GoodStr(T_dc) || GoodStr(T_DC)) ? TERM_CAN_DELETE : 0; + EL_FLAGS |= (GoodStr(T_im) || GoodStr(T_ic) || GoodStr(T_IC)) ? + TERM_CAN_INSERT : 0; + EL_FLAGS |= (GoodStr(T_up) || GoodStr(T_UP)) ? TERM_CAN_UP : 0; + EL_FLAGS |= Val(T_am) ? TERM_HAS_AUTO_MARGINS : 0; + EL_FLAGS |= Val(T_xn) ? TERM_HAS_MAGIC_MARGINS : 0; + + if (GoodStr(T_me) && GoodStr(T_ue)) + EL_FLAGS |= (strcmp(Str(T_me), Str(T_ue)) == 0) ? + TERM_CAN_ME : 0; + else + EL_FLAGS &= ~TERM_CAN_ME; + if (GoodStr(T_me) && GoodStr(T_se)) + EL_FLAGS |= (strcmp(Str(T_me), Str(T_se)) == 0) ? + TERM_CAN_ME : 0; #ifdef DEBUG_SCREEN - if (!EL_CAN_UP) { - (void)fprintf(el->el_errfile, "WARNING: Your terminal cannot move up.\n"); - (void)fprintf(el->el_errfile, "Editing may be odd for long lines.\n"); - } - if (!EL_CAN_CEOL) - (void)fprintf(el->el_errfile, "no clear EOL capability.\n"); - if (!EL_CAN_DELETE) - (void)fprintf(el->el_errfile, "no delete char capability.\n"); - if (!EL_CAN_INSERT) - (void)fprintf(el->el_errfile, "no insert char capability.\n"); + if (!EL_CAN_UP) { + (void) fprintf(el->el_errfile, + "WARNING: Your terminal cannot move up.\n"); + (void) fprintf(el->el_errfile, + "Editing may be odd for long lines.\n"); + } + if (!EL_CAN_CEOL) + (void) fprintf(el->el_errfile, "no clear EOL capability.\n"); + if (!EL_CAN_DELETE) + (void) fprintf(el->el_errfile, "no delete char capability.\n"); + if (!EL_CAN_INSERT) + (void) fprintf(el->el_errfile, "no insert char capability.\n"); #endif /* DEBUG_SCREEN */ } @@ -303,40 +327,50 @@ term_setflags(el) * Initialize the terminal stuff */ protected int -term_init(el) - EditLine *el; +term_init(EditLine *el) { - el->el_term.t_buf = (char *) el_malloc(TC_BUFSIZE); - el->el_term.t_cap = (char *) el_malloc(TC_BUFSIZE); - el->el_term.t_fkey = (fkey_t *) el_malloc(4 * sizeof(fkey_t)); - el->el_term.t_loc = 0; - el->el_term.t_str = (char **) el_malloc(T_str * sizeof(char*)); - (void)memset(el->el_term.t_str, 0, T_str * sizeof(char*)); - el->el_term.t_val = (int *) el_malloc(T_val * sizeof(int)); - (void)memset(el->el_term.t_val, 0, T_val * sizeof(int)); - term_outfile = el->el_outfile; - (void)term_set(el, NULL); - term_init_arrow(el); - return 0; + + el->el_term.t_buf = (char *) el_malloc(TC_BUFSIZE); + if (el->el_term.t_buf == NULL) + return (-1); + el->el_term.t_cap = (char *) el_malloc(TC_BUFSIZE); + if (el->el_term.t_cap == NULL) + return (-1); + el->el_term.t_fkey = (fkey_t *) el_malloc(A_K_NKEYS * sizeof(fkey_t)); + if (el->el_term.t_fkey == NULL) + return (-1); + el->el_term.t_loc = 0; + el->el_term.t_str = (char **) el_malloc(T_str * sizeof(char *)); + if (el->el_term.t_str == NULL) + return (-1); + (void) memset(el->el_term.t_str, 0, T_str * sizeof(char *)); + el->el_term.t_val = (int *) el_malloc(T_val * sizeof(int)); + if (el->el_term.t_val == NULL) + return (-1); + (void) memset(el->el_term.t_val, 0, T_val * sizeof(int)); + term_outfile = el->el_outfile; + (void) term_set(el, NULL); + term_init_arrow(el); + return (0); } /* term_end(): * Clean up the terminal stuff */ protected void -term_end(el) - EditLine *el; +term_end(EditLine *el) { - el_free((ptr_t) el->el_term.t_buf); - el->el_term.t_buf = NULL; - el_free((ptr_t) el->el_term.t_cap); - el->el_term.t_cap = NULL; - el->el_term.t_loc = 0; - el_free((ptr_t) el->el_term.t_str); - el->el_term.t_str = NULL; - el_free((ptr_t) el->el_term.t_val); - el->el_term.t_val = NULL; - term_free_display(el); + + el_free((ptr_t) el->el_term.t_buf); + el->el_term.t_buf = NULL; + el_free((ptr_t) el->el_term.t_cap); + el->el_term.t_cap = NULL; + el->el_term.t_loc = 0; + el_free((ptr_t) el->el_term.t_str); + el->el_term.t_str = NULL; + el_free((ptr_t) el->el_term.t_val); + el->el_term.t_val = NULL; + term_free_display(el); } @@ -344,139 +378,143 @@ term_end(el) * Maintain a string pool for termcap strings */ private void -term_alloc(el, t, cap) - EditLine *el; - struct termcapstr *t; - char *cap; +term_alloc(EditLine *el, const struct termcapstr *t, const char *cap) { - char termbuf[TC_BUFSIZE]; - int tlen, clen; - char **tlist = el->el_term.t_str; - char **tmp, **str = &tlist[t - tstr]; - - if (cap == NULL || *cap == '\0') { - *str = NULL; - return; - } - else - clen = strlen(cap); - - tlen = *str == NULL ? 0 : strlen(*str); - - /* - * New string is shorter; no need to allocate space - */ - if (clen <= tlen) { - (void)strlcpy(*str, cap, tlen + 1); - return; - } - - /* - * New string is longer; see if we have enough space to append - */ - if (el->el_term.t_loc + 3 < TC_BUFSIZE) { + char termbuf[TC_BUFSIZE]; + int tlen, clen; + char **tlist = el->el_term.t_str; + char **tmp, **str = &tlist[t - tstr]; + + if (cap == NULL || *cap == '\0') { + *str = NULL; + return; + } else + clen = strlen(cap); + + tlen = *str == NULL ? 0 : strlen(*str); + + /* + * New string is shorter; no need to allocate space + */ + if (clen <= tlen) { + (void) strlcpy(*str, cap, tlen + 1); + return; + } + /* + * New string is longer; see if we have enough space to append + */ + if (el->el_term.t_loc + 3 < TC_BUFSIZE) { + tlen = TC_BUFSIZE - el->el_term.t_loc; + (void) strlcpy(*str = &el->el_term.t_buf[el->el_term.t_loc], + cap, tlen); + el->el_term.t_loc += clen + 1; /* one for \0 */ + return; + } + /* + * Compact our buffer; no need to check compaction, cause we know it + * fits... + */ + tlen = 0; + for (tmp = tlist; tmp < &tlist[T_str]; tmp++) + if (*tmp != NULL && *tmp != '\0' && *tmp != *str) { + char *ptr; + + for (ptr = *tmp; *ptr != '\0'; termbuf[tlen++] = *ptr++) + continue; + termbuf[tlen++] = '\0'; + } + memcpy(el->el_term.t_buf, termbuf, TC_BUFSIZE); + el->el_term.t_loc = tlen; + if (el->el_term.t_loc + 3 >= TC_BUFSIZE) { + (void) fprintf(el->el_errfile, + "Out of termcap string space.\n"); + return; + } tlen = TC_BUFSIZE - el->el_term.t_loc; - (void)strlcpy(*str = &el->el_term.t_buf[el->el_term.t_loc], cap, tlen); + (void) strlcpy(*str = &el->el_term.t_buf[el->el_term.t_loc], cap, tlen); el->el_term.t_loc += clen + 1; /* one for \0 */ return; - } - - /* - * Compact our buffer; no need to check compaction, cause we know it - * fits... - */ - tlen = 0; - for (tmp = tlist; tmp < &tlist[T_str]; tmp++) - if (*tmp != NULL && *tmp != '\0' && *tmp != *str) { - char *ptr; - - for (ptr = *tmp; *ptr != '\0'; termbuf[tlen++] = *ptr++) - continue; - termbuf[tlen++] = '\0'; - } - memcpy(el->el_term.t_buf, termbuf, TC_BUFSIZE); - el->el_term.t_loc = tlen; - if (el->el_term.t_loc + 3 >= TC_BUFSIZE) { - (void)fprintf(el->el_errfile, "Out of termcap string space.\n"); - return; - } - tlen = TC_BUFSIZE - el->el_term.t_loc; - (void)strlcpy(*str = &el->el_term.t_buf[el->el_term.t_loc], cap, tlen); - el->el_term.t_loc += clen + 1; /* one for \0 */ - return; -} /* end term_alloc */ +} /* term_rebuffer_display(): * Rebuffer the display after the screen changed size */ -private void -term_rebuffer_display(el) - EditLine *el; +private int +term_rebuffer_display(EditLine *el) { - coord_t *c = &el->el_term.t_size; + coord_t *c = &el->el_term.t_size; - term_free_display(el); + term_free_display(el); - /* make this public, -1 to avoid wraps */ - c->h = Val(T_co) - 1; - c->v = (EL_BUFSIZ * 4) / c->h + 1; + c->h = Val(T_co); + c->v = Val(T_li); - term_alloc_display(el); -} /* end term_rebuffer_display */ + if (term_alloc_display(el) == -1) + return (-1); + return (0); +} /* term_alloc_display(): * Allocate a new display. */ -private void -term_alloc_display(el) - EditLine *el; +private int +term_alloc_display(EditLine *el) { - int i; - char **b; - coord_t *c = &el->el_term.t_size; - - b = (char **) el_malloc((size_t) (sizeof(char *) * (c->v + 1))); - for (i = 0; i < c->v; i++) - b[i] = (char *) el_malloc((size_t) (sizeof(char) * (c->h + 1))); - b[c->v] = NULL; - el->el_display = b; - - b = (char **) el_malloc((size_t) (sizeof(char *) * (c->v + 1))); - for (i = 0; i < c->v; i++) - b[i] = (char *) el_malloc((size_t) (sizeof(char) * (c->h + 1))); - b[c->v] = NULL; - el->el_vdisplay = b; - -} /* end term_alloc_display */ + int i; + char **b; + coord_t *c = &el->el_term.t_size; + + b = (char **) el_malloc((size_t) (sizeof(char *) * (c->v + 1))); + if (b == NULL) + return (-1); + for (i = 0; i < c->v; i++) { + b[i] = (char *) el_malloc((size_t) (sizeof(char) * (c->h + 1))); + if (b[i] == NULL) + return (-1); + } + b[c->v] = NULL; + el->el_display = b; + + b = (char **) el_malloc((size_t) (sizeof(char *) * (c->v + 1))); + if (b == NULL) + return (-1); + for (i = 0; i < c->v; i++) { + b[i] = (char *) el_malloc((size_t) (sizeof(char) * (c->h + 1))); + if (b[i] == NULL) + return (-1); + } + b[c->v] = NULL; + el->el_vdisplay = b; + return (0); +} /* term_free_display(): * Free the display buffers */ private void -term_free_display(el) - EditLine *el; +term_free_display(EditLine *el) { - char **b; - char **bufp; - - b = el->el_display; - el->el_display = NULL; - if (b != NULL) { - for (bufp = b; *bufp != NULL; bufp++) - el_free((ptr_t) *bufp); - el_free((ptr_t) b); - } - b = el->el_vdisplay; - el->el_vdisplay = NULL; - if (b != NULL) { - for (bufp = b; *bufp != NULL; bufp++) - el_free((ptr_t) * bufp); - el_free((ptr_t) b); - } -} /* end term_free_display */ + char **b; + char **bufp; + + b = el->el_display; + el->el_display = NULL; + if (b != NULL) { + for (bufp = b; *bufp != NULL; bufp++) + el_free((ptr_t) * bufp); + el_free((ptr_t) b); + } + b = el->el_vdisplay; + el->el_vdisplay = NULL; + if (b != NULL) { + for (bufp = b; *bufp != NULL; bufp++) + el_free((ptr_t) * bufp); + el_free((ptr_t) b); + } +} /* term_move_to_line(): @@ -484,311 +522,343 @@ term_free_display(el) * as efficiently as possible */ protected void -term_move_to_line(el, where) - EditLine *el; - int where; +term_move_to_line(EditLine *el, int where) { - int del, i; + int del; - if (where == el->el_cursor.v) - return; + if (where == el->el_cursor.v) + return; - if (where > el->el_term.t_size.v) { + if (where > el->el_term.t_size.v) { #ifdef DEBUG_SCREEN - (void)fprintf(el->el_errfile, - "term_move_to_line: where is ridiculous: %d\r\n", where); + (void) fprintf(el->el_errfile, + "term_move_to_line: where is ridiculous: %d\r\n", where); #endif /* DEBUG_SCREEN */ - return; - } - - if ((del = where - el->el_cursor.v) > 0) { - if ((del > 1) && GoodStr(T_DO)) - (void)tputs(tgoto(Str(T_DO), del, del), del, term__putc); - else { - for (i = 0; i < del; i++) - term__putc('\n'); - el->el_cursor.h = 0; /* because the \n will become \r\n */ + return; } - } - else { /* del < 0 */ - if (GoodStr(T_UP) && (-del > 1 || !GoodStr(T_up))) - (void)tputs(tgoto(Str(T_UP), -del, -del), -del, term__putc); - else { - if (GoodStr(T_up)) - for (i = 0; i < -del; i++) - (void)tputs(Str(T_up), 1, term__putc); + if ((del = where - el->el_cursor.v) > 0) { + while (del > 0) { + if (EL_HAS_AUTO_MARGINS && + el->el_display[el->el_cursor.v][0] != '\0') { + /* move without newline */ + term_move_to_char(el, el->el_term.t_size.h - 1); + term_overwrite(el, + &el->el_display[el->el_cursor.v][el->el_cursor.h], + 1); + /* updates Cursor */ + del--; + } else { + if ((del > 1) && GoodStr(T_DO)) { + (void) tputs(tgoto(Str(T_DO), del, del), + del, term__putc); + del = 0; + } else { + for (; del > 0; del--) + term__putc('\n'); + /* because the \n will become \r\n */ + el->el_cursor.h = 0; + } + } + } + } else { /* del < 0 */ + if (GoodStr(T_UP) && (-del > 1 || !GoodStr(T_up))) + (void) tputs(tgoto(Str(T_UP), -del, -del), -del, + term__putc); + else { + if (GoodStr(T_up)) + for (; del < 0; del++) + (void) tputs(Str(T_up), 1, term__putc); + } } - } - el->el_cursor.v = where; /* now where is here */ -} /* end term_move_to_line */ + el->el_cursor.v = where;/* now where is here */ +} /* term_move_to_char(): * Move to the character position specified */ protected void -term_move_to_char(el, where) - EditLine *el; - int where; +term_move_to_char(EditLine *el, int where) { - int del, i; + int del, i; mc_again: - if (where == el->el_cursor.h) - return; + if (where == el->el_cursor.h) + return; - if (where > (el->el_term.t_size.h + 1)) { + if (where > el->el_term.t_size.h) { #ifdef DEBUG_SCREEN - (void)fprintf(el->el_errfile, - "term_move_to_char: where is ridiculous: %d\r\n", where); + (void) fprintf(el->el_errfile, + "term_move_to_char: where is riduculous: %d\r\n", where); #endif /* DEBUG_SCREEN */ - return; - } - - if (!where) { /* if where is first column */ - term__putc('\r'); /* do a CR */ - el->el_cursor.h = 0; - return; - } - - del = where - el->el_cursor.h; - - if ((del < -4 || del > 4) && GoodStr(T_ch)) - /* go there directly */ - (void)tputs(tgoto(Str(T_ch), where, where), where, term__putc); - else { - if (del > 0) { /* moving forward */ - if ((del > 4) && GoodStr(T_RI)) - (void)tputs(tgoto(Str(T_RI), del, del), del, term__putc); - else { - if (EL_CAN_TAB) { /* if I can do tabs, use them */ - if ((el->el_cursor.h & 0370) != (where & 0370)) { - /* if not within tab stop */ - for (i = (el->el_cursor.h & 0370); - i < (where & 0370); i += 8) - term__putc('\t'); /* then tab over */ - el->el_cursor.h = where & 0370; - } - } - /* it's usually cheaper to just write the chars, so we do. */ - - /* NOTE THAT term_overwrite() WILL CHANGE el->el_cursor.h!!! */ - term_overwrite(el, - &el->el_display[el->el_cursor.v][el->el_cursor.h], - where - el->el_cursor.h); - - } + return; } - else { /* del < 0 := moving backward */ - if ((-del > 4) && GoodStr(T_LE)) - (void)tputs(tgoto(Str(T_LE), -del, -del), -del, term__putc); - else { /* can't go directly there */ - /* if the "cost" is greater than the "cost" from col 0 */ - if (EL_CAN_TAB ? (-del > ((where >> 3) + (where & 07))) - : (-del > where)) { - term__putc('\r'); /* do a CR */ - el->el_cursor.h = 0; - goto mc_again; /* and try again */ + if (!where) { /* if where is first column */ + term__putc('\r'); /* do a CR */ + el->el_cursor.h = 0; + return; + } + del = where - el->el_cursor.h; + + if ((del < -4 || del > 4) && GoodStr(T_ch)) + /* go there directly */ + (void) tputs(tgoto(Str(T_ch), where, where), where, term__putc); + else { + if (del > 0) { /* moving forward */ + if ((del > 4) && GoodStr(T_RI)) + (void) tputs(tgoto(Str(T_RI), del, del), + del, term__putc); + else { + /* if I can do tabs, use them */ + if (EL_CAN_TAB) { + if ((el->el_cursor.h & 0370) != + (where & 0370)) { + /* if not within tab stop */ + for (i = + (el->el_cursor.h & 0370); + i < (where & 0370); + i += 8) + term__putc('\t'); + /* then tab over */ + el->el_cursor.h = where & 0370; + } + } + /* + * it's usually cheaper to just write the + * chars, so we do. + */ + /* + * NOTE THAT term_overwrite() WILL CHANGE + * el->el_cursor.h!!! + */ + term_overwrite(el, + &el->el_display[el->el_cursor.v][el->el_cursor.h], + where - el->el_cursor.h); + + } + } else { /* del < 0 := moving backward */ + if ((-del > 4) && GoodStr(T_LE)) + (void) tputs(tgoto(Str(T_LE), -del, -del), + -del, term__putc); + else { /* can't go directly there */ + /* + * if the "cost" is greater than the "cost" + * from col 0 + */ + if (EL_CAN_TAB ? + ((unsigned int)-del > + (((unsigned int) where >> 3) + + (where & 07))) + : (-del > where)) { + term__putc('\r'); /* do a CR */ + el->el_cursor.h = 0; + goto mc_again; /* and try again */ + } + for (i = 0; i < -del; i++) + term__putc('\b'); + } } - for (i = 0; i < -del; i++) - term__putc('\b'); - } } - } - el->el_cursor.h = where; /* now where is here */ -} /* end term_move_to_char */ + el->el_cursor.h = where; /* now where is here */ +} /* term_overwrite(): * Overstrike num characters */ protected void -term_overwrite(el, cp, n) - EditLine *el; - char *cp; - int n; +term_overwrite(EditLine *el, const char *cp, int n) { - if (n <= 0) - return; /* catch bugs */ + if (n <= 0) + return; /* catch bugs */ - if (n > (el->el_term.t_size.h + 1)) { + if (n > el->el_term.t_size.h) { #ifdef DEBUG_SCREEN - (void)fprintf(el->el_errfile, "term_overwrite: n is ridiculous: %d\r\n", n); + (void) fprintf(el->el_errfile, + "term_overwrite: n is riduculous: %d\r\n", n); #endif /* DEBUG_SCREEN */ - return; - } - - do { - term__putc(*cp++); - el->el_cursor.h++; - } while (--n); -} /* end term_overwrite */ + return; + } + do { + term__putc(*cp++); + el->el_cursor.h++; + } while (--n); + + if (el->el_cursor.h >= el->el_term.t_size.h) { /* wrap? */ + if (EL_HAS_AUTO_MARGINS) { /* yes */ + el->el_cursor.h = 0; + el->el_cursor.v++; + if (EL_HAS_MAGIC_MARGINS) { + /* force the wrap to avoid the "magic" + * situation */ + char c; + if ((c = el->el_display[el->el_cursor.v][el->el_cursor.h]) + != '\0') + term_overwrite(el, &c, 1); + else + term__putc(' '); + el->el_cursor.h = 1; + } + } else /* no wrap, but cursor stays on screen */ + el->el_cursor.h = el->el_term.t_size.h; + } +} /* term_deletechars(): * Delete num characters */ protected void -term_deletechars(el, num) - EditLine *el; - int num; +term_deletechars(EditLine *el, int num) { - if (num <= 0) - return; + if (num <= 0) + return; - if (!EL_CAN_DELETE) { + if (!EL_CAN_DELETE) { #ifdef DEBUG_EDIT - (void)fprintf(el->el_errfile, " ERROR: cannot delete \n"); + (void) fprintf(el->el_errfile, " ERROR: cannot delete \n"); #endif /* DEBUG_EDIT */ - return; - } - - if (num > el->el_term.t_size.h) { + return; + } + if (num > el->el_term.t_size.h) { #ifdef DEBUG_SCREEN - (void)fprintf(el->el_errfile, - "term_deletechars: num is ridiculous: %d\r\n", num); + (void) fprintf(el->el_errfile, + "term_deletechars: num is riduculous: %d\r\n", num); #endif /* DEBUG_SCREEN */ - return; - } - - if (GoodStr(T_DC)) /* if I have multiple delete */ - if ((num > 1) || !GoodStr(T_dc)) { /* if dc would be more expen. */ - (void)tputs(tgoto(Str(T_DC), num, num), num, term__putc); - return; + return; } + if (GoodStr(T_DC)) /* if I have multiple delete */ + if ((num > 1) || !GoodStr(T_dc)) { /* if dc would be more + * expen. */ + (void) tputs(tgoto(Str(T_DC), num, num), + num, term__putc); + return; + } + if (GoodStr(T_dm)) /* if I have delete mode */ + (void) tputs(Str(T_dm), 1, term__putc); - if (GoodStr(T_dm)) /* if I have delete mode */ - (void)tputs(Str(T_dm), 1, term__putc); - - if (GoodStr(T_dc)) /* else do one at a time */ - while (num--) - (void)tputs(Str(T_dc), 1, term__putc); + if (GoodStr(T_dc)) /* else do one at a time */ + while (num--) + (void) tputs(Str(T_dc), 1, term__putc); - if (GoodStr(T_ed)) /* if I have delete mode */ - (void)tputs(Str(T_ed), 1, term__putc); -} /* end term_deletechars */ + if (GoodStr(T_ed)) /* if I have delete mode */ + (void) tputs(Str(T_ed), 1, term__putc); +} /* term_insertwrite(): - * Puts terminal in insert character mode or inserts num - * characters in the line + * Puts terminal in insert character mode or inserts num + * characters in the line */ protected void -term_insertwrite(el, cp, num) - EditLine *el; - char *cp; - int num; +term_insertwrite(EditLine *el, char *cp, int num) { - if (num <= 0) - return; - if (!EL_CAN_INSERT) { + if (num <= 0) + return; + if (!EL_CAN_INSERT) { #ifdef DEBUG_EDIT - (void)fprintf(el->el_errfile, " ERROR: cannot insert \n"); + (void) fprintf(el->el_errfile, " ERROR: cannot insert \n"); #endif /* DEBUG_EDIT */ - return; - } - - if (num > el->el_term.t_size.h) { + return; + } + if (num > el->el_term.t_size.h) { #ifdef DEBUG_SCREEN - (void)fprintf(el->el_errfile, "StartInsert: num is ridiculous: %d\r\n", num); + (void) fprintf(el->el_errfile, + "StartInsert: num is riduculous: %d\r\n", num); #endif /* DEBUG_SCREEN */ - return; - } - - if (GoodStr(T_IC)) /* if I have multiple insert */ - if ((num > 1) || !GoodStr(T_ic)) { /* if ic would be more expen. */ - (void)tputs(tgoto(Str(T_IC), num, num), num, term__putc); - term_overwrite(el, cp, num); /* this updates el_cursor.h */ - return; + return; } + if (GoodStr(T_IC)) /* if I have multiple insert */ + if ((num > 1) || !GoodStr(T_ic)) { + /* if ic would be more expensive */ + (void) tputs(tgoto(Str(T_IC), num, num), + num, term__putc); + term_overwrite(el, cp, num); + /* this updates el_cursor.h */ + return; + } + if (GoodStr(T_im) && GoodStr(T_ei)) { /* if I have insert mode */ + (void) tputs(Str(T_im), 1, term__putc); - if (GoodStr(T_im) && GoodStr(T_ei)) { /* if I have insert mode */ - (void)tputs(Str(T_im), 1, term__putc); - - el->el_cursor.h += num; - do - term__putc(*cp++); - while (--num); - - if (GoodStr(T_ip)) /* have to make num chars insert */ - (void)tputs(Str(T_ip), 1, term__putc); + el->el_cursor.h += num; + do + term__putc(*cp++); + while (--num); - (void)tputs(Str(T_ei), 1, term__putc); - return; - } + if (GoodStr(T_ip)) /* have to make num chars insert */ + (void) tputs(Str(T_ip), 1, term__putc); - do { - if (GoodStr(T_ic)) /* have to make num chars insert */ - (void)tputs(Str(T_ic), 1, term__putc); /* insert a char */ + (void) tputs(Str(T_ei), 1, term__putc); + return; + } + do { + if (GoodStr(T_ic)) /* have to make num chars insert */ + (void) tputs(Str(T_ic), 1, term__putc); + /* insert a char */ - term__putc(*cp++); + term__putc(*cp++); - el->el_cursor.h++; + el->el_cursor.h++; - if (GoodStr(T_ip)) /* have to make num chars insert */ - (void)tputs(Str(T_ip), 1, term__putc);/* pad the inserted char */ + if (GoodStr(T_ip)) /* have to make num chars insert */ + (void) tputs(Str(T_ip), 1, term__putc); + /* pad the inserted char */ - } while (--num); -} /* end term_insertwrite */ + } while (--num); +} /* term_clear_EOL(): - * clear to end of line. There are num characters to clear + * clear to end of line. There are num characters to clear */ protected void -term_clear_EOL(el, num) - EditLine *el; - int num; +term_clear_EOL(EditLine *el, int num) { - int i; + int i; - if (EL_CAN_CEOL && GoodStr(T_ce)) - (void)tputs(Str(T_ce), 1, term__putc); - else { - for (i = 0; i < num; i++) - term__putc(' '); - el->el_cursor.h += num; /* have written num spaces */ - } -} /* end term_clear_EOL */ + if (EL_CAN_CEOL && GoodStr(T_ce)) + (void) tputs(Str(T_ce), 1, term__putc); + else { + for (i = 0; i < num; i++) + term__putc(' '); + el->el_cursor.h += num; /* have written num spaces */ + } +} /* term_clear_screen(): - * Clear the screen + * Clear the screen */ protected void -term_clear_screen(el) - EditLine *el; +term_clear_screen(EditLine *el) { /* clear the whole screen and home */ - if (GoodStr(T_cl)) - /* send the clear screen code */ - (void)tputs(Str(T_cl), Val(T_li), term__putc); - else if (GoodStr(T_ho) && GoodStr(T_cd)) { - (void)tputs(Str(T_ho), Val(T_li), term__putc); /* home */ - /* clear to bottom of screen */ - (void)tputs(Str(T_cd), Val(T_li), term__putc); - } - else { - term__putc('\r'); - term__putc('\n'); - } -} /* end term_clear_screen */ + + if (GoodStr(T_cl)) + /* send the clear screen code */ + (void) tputs(Str(T_cl), Val(T_li), term__putc); + else if (GoodStr(T_ho) && GoodStr(T_cd)) { + (void) tputs(Str(T_ho), Val(T_li), term__putc); /* home */ + /* clear to bottom of screen */ + (void) tputs(Str(T_cd), Val(T_li), term__putc); + } else { + term__putc('\r'); + term__putc('\n'); + } +} /* term_beep(): * Beep the way the terminal wants us */ protected void -term_beep(el) - EditLine *el; +term_beep(EditLine *el) { - if (GoodStr(T_vb)) - (void)tputs(Str(T_vb), 1, term__putc); /* visible bell */ - else if (GoodStr(T_bl)) - /* what termcap says we should use */ - (void)tputs(Str(T_bl), 1, term__putc); - else - term__putc('\007'); /* an ASCII bell; ^G */ -} /* end term_beep */ + if (GoodStr(T_bl)) + /* what termcap says we should use */ + (void) tputs(Str(T_bl), 1, term__putc); + else + term__putc('\007'); /* an ASCII bell; ^G */ +} #ifdef notdef @@ -796,181 +866,201 @@ term_beep(el) * Clear to the bottom of the screen */ protected void -term_clear_to_bottom(el) - EditLine *el; +term_clear_to_bottom(EditLine *el) { - if (GoodStr(T_cd)) - (void)tputs(Str(T_cd), Val(T_li), term__putc); - else if (GoodStr(T_ce)) - (void)tputs(Str(T_ce), Val(T_li), term__putc); -} /* end term_clear_to_bottom */ + if (GoodStr(T_cd)) + (void) tputs(Str(T_cd), Val(T_li), term__putc); + else if (GoodStr(T_ce)) + (void) tputs(Str(T_ce), Val(T_li), term__putc); +} #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(el, term) - EditLine *el; - char *term; +term_set(EditLine *el, const char *term) { - int i; - char buf[TC_BUFSIZE]; - char *area; - struct termcapstr *t; - sigset_t oset, nset; - int lins, cols; - - (void)sigemptyset(&nset); - (void)sigaddset(&nset, SIGWINCH); - (void)sigprocmask(SIG_BLOCK, &nset, &oset); - - area = buf; - - - if (term == NULL) - term = getenv("TERM"); - - if (!term || !term[0]) - term = "dumb"; - - memset(el->el_term.t_cap, 0, TC_BUFSIZE); - - i = tgetent(el->el_term.t_cap, term); - - if (i <= 0) { - if (i == -1) - (void)fprintf(el->el_errfile, "Cannot read termcap database;\n"); - else if (i == 0) - (void)fprintf(el->el_errfile, - "No entry for terminal type \"%s\";\n", term); - (void)fprintf(el->el_errfile, "using dumb terminal settings.\n"); - Val(T_co) = 80; /* do a dumb terminal */ - Val(T_pt) = Val(T_km) = Val(T_li) = 0; - Val(T_xt) = Val(T_MT); - for (t = tstr; t->name != NULL; t++) - term_alloc(el, t, NULL); - } - else { - /* Can we tab */ - Val(T_pt) = tgetflag("pt"); - Val(T_xt) = tgetflag("xt"); - /* do we have a meta? */ - Val(T_km) = tgetflag("km"); - Val(T_MT) = tgetflag("MT"); - /* 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)); - } + int i; + char buf[TC_BUFSIZE]; + char *area; + const struct termcapstr *t; + sigset_t oset, nset; + int lins, cols; + + (void) sigemptyset(&nset); + (void) sigaddset(&nset, SIGWINCH); + (void) sigprocmask(SIG_BLOCK, &nset, &oset); + + area = buf; + + + if (term == NULL) + term = getenv("TERM"); + + if (!term || !term[0]) + term = "dumb"; + + if (strcmp(term, "emacs") == 0) + el->el_flags |= EDIT_DISABLED; + + memset(el->el_term.t_cap, 0, TC_BUFSIZE); + + i = tgetent(el->el_term.t_cap, term); + + if (i <= 0) { + if (i == -1) + (void) fprintf(el->el_errfile, + "Cannot read termcap database;\n"); + else if (i == 0) + (void) fprintf(el->el_errfile, + "No entry for terminal type \"%s\";\n", term); + (void) fprintf(el->el_errfile, + "using dumb terminal settings.\n"); + Val(T_co) = 80; /* do a dumb terminal */ + Val(T_pt) = Val(T_km) = Val(T_li) = 0; + Val(T_xt) = Val(T_MT); + for (t = tstr; t->name != NULL; t++) + term_alloc(el, t, NULL); + } else { + /* auto/magic margins */ + Val(T_am) = tgetflag("am"); + Val(T_xn) = tgetflag("xn"); + /* Can we tab */ + Val(T_pt) = tgetflag("pt"); + Val(T_xt) = tgetflag("xt"); + /* do we have a meta? */ + Val(T_km) = tgetflag("km"); + Val(T_MT) = tgetflag("MT"); + /* 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((char *)t->name, &area)); + } - if (Val(T_co) < 2) - Val(T_co) = 80; /* just in case */ - if (Val(T_li) < 1) - Val(T_li) = 24; + if (Val(T_co) < 2) + Val(T_co) = 80; /* just in case */ + if (Val(T_li) < 1) + Val(T_li) = 24; - el->el_term.t_size.v = Val(T_co); - el->el_term.t_size.h = Val(T_li); + el->el_term.t_size.v = Val(T_co); + el->el_term.t_size.h = Val(T_li); - term_setflags(el); + term_setflags(el); - (void)term_get_size(el, &lins, &cols);/* get the correct window size */ - term_change_size(el, lins, cols); - (void)sigprocmask(SIG_SETMASK, &oset, NULL); - term_bind_arrow(el); - return 0; -} /* end term_set */ + /* get the correct window size */ + (void) term_get_size(el, &lins, &cols); + if (term_change_size(el, lins, cols) == -1) + return (-1); + (void) sigprocmask(SIG_SETMASK, &oset, NULL); + term_bind_arrow(el); + el->el_term.t_name = term; + return (i <= 0 ? -1 : 0); +} /* term_get_size(): * Return the new window size in lines and cols, and - * true if the size was changed. + * true if the size was changed. */ protected int -term_get_size(el, lins, cols) - EditLine *el; - int *lins, *cols; +term_get_size(EditLine *el, int *lins, int *cols) { - *cols = Val(T_co); - *lins = Val(T_li); + *cols = Val(T_co); + *lins = Val(T_li); #ifdef TIOCGWINSZ - { - struct winsize ws; - if (ioctl(el->el_infd, TIOCGWINSZ, (ioctl_t) &ws) != -1) { - if (ws.ws_col) - *cols = ws.ws_col; - if (ws.ws_row) - *lins = ws.ws_row; + { + struct winsize ws; + if (ioctl(el->el_infd, TIOCGWINSZ, (ioctl_t) & ws) != -1) { + if (ws.ws_col) + *cols = ws.ws_col; + if (ws.ws_row) + *lins = ws.ws_row; + } } - } #endif #ifdef TIOCGSIZE - { - struct ttysize ts; - if (ioctl(el->el_infd, TIOCGSIZE, (ioctl_t) &ts) != -1) { - if (ts.ts_cols) - *cols = ts.ts_cols; - if (ts.ts_lines) - *lins = ts.ts_lines; + { + struct ttysize ts; + if (ioctl(el->el_infd, TIOCGSIZE, (ioctl_t) & ts) != -1) { + if (ts.ts_cols) + *cols = ts.ts_cols; + if (ts.ts_lines) + *lins = ts.ts_lines; + } } - } #endif - return (Val(T_co) != *cols || Val(T_li) != *lins); -} /* end term_get_size */ + return (Val(T_co) != *cols || Val(T_li) != *lins); +} /* term_change_size(): * Change the size of the terminal */ -protected void -term_change_size(el, lins, cols) - EditLine *el; - int lins, cols; +protected int +term_change_size(EditLine *el, int lins, int cols) { - /* - * Just in case - */ - Val(T_co) = (cols < 2) ? 80 : cols; - Val(T_li) = (lins < 1) ? 24 : lins; - - term_rebuffer_display(el); /* re-make display buffers */ - re_clear_display(el); -} /* end term_change_size */ + /* + * Just in case + */ + Val(T_co) = (cols < 2) ? 80 : cols; + Val(T_li) = (lins < 1) ? 24 : lins; + + /* re-make display buffers */ + if (term_rebuffer_display(el) == -1) + return (-1); + re_clear_display(el); + return (0); +} /* term_init_arrow(): * Initialize the arrow key bindings from termcap */ private void -term_init_arrow(el) - EditLine *el; +term_init_arrow(EditLine *el) { - fkey_t *arrow = el->el_term.t_fkey; - - arrow[A_K_DN].name = "down"; - arrow[A_K_DN].key = T_kd; - arrow[A_K_DN].fun.cmd = ED_NEXT_HISTORY; - arrow[A_K_DN].type = XK_CMD; - - arrow[A_K_UP].name = "up"; - arrow[A_K_UP].key = T_ku; - arrow[A_K_UP].fun.cmd = ED_PREV_HISTORY; - arrow[A_K_UP].type = XK_CMD; - - arrow[A_K_LT].name = "left"; - arrow[A_K_LT].key = T_kl; - arrow[A_K_LT].fun.cmd = ED_PREV_CHAR; - arrow[A_K_LT].type = XK_CMD; - - arrow[A_K_RT].name = "right"; - arrow[A_K_RT].key = T_kr; - arrow[A_K_RT].fun.cmd = ED_NEXT_CHAR; - arrow[A_K_RT].type = XK_CMD; - + fkey_t *arrow = el->el_term.t_fkey; + + arrow[A_K_DN].name = "down"; + arrow[A_K_DN].key = T_kd; + arrow[A_K_DN].fun.cmd = ED_NEXT_HISTORY; + arrow[A_K_DN].type = XK_CMD; + + arrow[A_K_UP].name = "up"; + arrow[A_K_UP].key = T_ku; + arrow[A_K_UP].fun.cmd = ED_PREV_HISTORY; + arrow[A_K_UP].type = XK_CMD; + + arrow[A_K_LT].name = "left"; + arrow[A_K_LT].key = T_kl; + arrow[A_K_LT].fun.cmd = ED_PREV_CHAR; + arrow[A_K_LT].type = XK_CMD; + + arrow[A_K_RT].name = "right"; + arrow[A_K_RT].key = T_kr; + arrow[A_K_RT].fun.cmd = ED_NEXT_CHAR; + arrow[A_K_RT].type = XK_CMD; + + arrow[A_K_HO].name = "home"; + arrow[A_K_HO].key = T_kh; + arrow[A_K_HO].fun.cmd = ED_MOVE_TO_BEG; + arrow[A_K_HO].type = XK_CMD; + + arrow[A_K_EN].name = "end"; + arrow[A_K_EN].key = T_at7; + arrow[A_K_EN].fun.cmd = ED_MOVE_TO_END; + arrow[A_K_EN].type = XK_CMD; } @@ -978,38 +1068,49 @@ term_init_arrow(el) * Reset arrow key bindings */ private void -term_reset_arrow(el) - EditLine *el; +term_reset_arrow(EditLine *el) { - fkey_t *arrow = el->el_term.t_fkey; - static char strA[] = {033, '[', 'A', '\0'}; - static char strB[] = {033, '[', 'B', '\0'}; - static char strC[] = {033, '[', 'C', '\0'}; - static char strD[] = {033, '[', 'D', '\0'}; - static char stOA[] = {033, 'O', 'A', '\0'}; - static char stOB[] = {033, 'O', 'B', '\0'}; - static char stOC[] = {033, 'O', 'C', '\0'}; - static char stOD[] = {033, 'O', 'D', '\0'}; - - key_add(el, strA, &arrow[A_K_UP].fun, arrow[A_K_UP].type); - key_add(el, strB, &arrow[A_K_DN].fun, arrow[A_K_DN].type); - key_add(el, strC, &arrow[A_K_RT].fun, arrow[A_K_RT].type); - key_add(el, strD, &arrow[A_K_LT].fun, arrow[A_K_LT].type); - key_add(el, stOA, &arrow[A_K_UP].fun, arrow[A_K_UP].type); - key_add(el, stOB, &arrow[A_K_DN].fun, arrow[A_K_DN].type); - key_add(el, stOC, &arrow[A_K_RT].fun, arrow[A_K_RT].type); - key_add(el, stOD, &arrow[A_K_LT].fun, arrow[A_K_LT].type); - - if (el->el_map.type == MAP_VI) { - key_add(el, &strA[1], &arrow[A_K_UP].fun, arrow[A_K_UP].type); - key_add(el, &strB[1], &arrow[A_K_DN].fun, arrow[A_K_DN].type); - key_add(el, &strC[1], &arrow[A_K_RT].fun, arrow[A_K_RT].type); - key_add(el, &strD[1], &arrow[A_K_LT].fun, arrow[A_K_LT].type); - key_add(el, &stOA[1], &arrow[A_K_UP].fun, arrow[A_K_UP].type); - key_add(el, &stOB[1], &arrow[A_K_DN].fun, arrow[A_K_DN].type); - key_add(el, &stOC[1], &arrow[A_K_RT].fun, arrow[A_K_RT].type); - key_add(el, &stOD[1], &arrow[A_K_LT].fun, arrow[A_K_LT].type); - } + fkey_t *arrow = el->el_term.t_fkey; + static const char strA[] = {033, '[', 'A', '\0'}; + static const char strB[] = {033, '[', 'B', '\0'}; + static const char strC[] = {033, '[', 'C', '\0'}; + static const char strD[] = {033, '[', 'D', '\0'}; + static const char strH[] = {033, '[', 'H', '\0'}; + static const char strF[] = {033, '[', 'F', '\0'}; + static const char stOA[] = {033, 'O', 'A', '\0'}; + static const char stOB[] = {033, 'O', 'B', '\0'}; + static const char stOC[] = {033, 'O', 'C', '\0'}; + static const char stOD[] = {033, 'O', 'D', '\0'}; + static const char stOH[] = {033, 'O', 'H', '\0'}; + static const char stOF[] = {033, 'O', 'F', '\0'}; + + key_add(el, strA, &arrow[A_K_UP].fun, arrow[A_K_UP].type); + key_add(el, strB, &arrow[A_K_DN].fun, arrow[A_K_DN].type); + key_add(el, strC, &arrow[A_K_RT].fun, arrow[A_K_RT].type); + key_add(el, strD, &arrow[A_K_LT].fun, arrow[A_K_LT].type); + key_add(el, strH, &arrow[A_K_HO].fun, arrow[A_K_HO].type); + key_add(el, strF, &arrow[A_K_EN].fun, arrow[A_K_EN].type); + key_add(el, stOA, &arrow[A_K_UP].fun, arrow[A_K_UP].type); + key_add(el, stOB, &arrow[A_K_DN].fun, arrow[A_K_DN].type); + key_add(el, stOC, &arrow[A_K_RT].fun, arrow[A_K_RT].type); + key_add(el, stOD, &arrow[A_K_LT].fun, arrow[A_K_LT].type); + key_add(el, stOH, &arrow[A_K_HO].fun, arrow[A_K_HO].type); + key_add(el, stOF, &arrow[A_K_EN].fun, arrow[A_K_EN].type); + + if (el->el_map.type == MAP_VI) { + key_add(el, &strA[1], &arrow[A_K_UP].fun, arrow[A_K_UP].type); + key_add(el, &strB[1], &arrow[A_K_DN].fun, arrow[A_K_DN].type); + key_add(el, &strC[1], &arrow[A_K_RT].fun, arrow[A_K_RT].type); + key_add(el, &strD[1], &arrow[A_K_LT].fun, arrow[A_K_LT].type); + key_add(el, &strH[1], &arrow[A_K_HO].fun, arrow[A_K_HO].type); + key_add(el, &strF[1], &arrow[A_K_EN].fun, arrow[A_K_EN].type); + key_add(el, &stOA[1], &arrow[A_K_UP].fun, arrow[A_K_UP].type); + key_add(el, &stOB[1], &arrow[A_K_DN].fun, arrow[A_K_DN].type); + key_add(el, &stOC[1], &arrow[A_K_RT].fun, arrow[A_K_RT].type); + key_add(el, &stOD[1], &arrow[A_K_LT].fun, arrow[A_K_LT].type); + key_add(el, &stOH[1], &arrow[A_K_HO].fun, arrow[A_K_HO].type); + key_add(el, &stOF[1], &arrow[A_K_EN].fun, arrow[A_K_EN].type); + } } @@ -1017,22 +1118,18 @@ term_reset_arrow(el) * Set an arrow key binding */ protected int -term_set_arrow(el, name, fun, type) - 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; - - for (i = 0; i < A_K_NKEYS; i++) - if (strcmp(name, arrow[i].name) == 0) { - arrow[i].fun = *fun; - arrow[i].type = type; - return 0; - } - return -1; + fkey_t *arrow = el->el_term.t_fkey; + int i; + + for (i = 0; i < A_K_NKEYS; i++) + if (strcmp(name, arrow[i].name) == 0) { + arrow[i].fun = *fun; + arrow[i].type = type; + return (0); + } + return (-1); } @@ -1040,19 +1137,17 @@ term_set_arrow(el, name, fun, type) * Clear an arrow key binding */ protected int -term_clear_arrow(el, name) - EditLine *el; - char *name; +term_clear_arrow(EditLine *el, const char *name) { - fkey_t *arrow = el->el_term.t_fkey; - int i; + fkey_t *arrow = el->el_term.t_fkey; + int i; - for (i = 0; i < A_K_NKEYS; i++) - if (strcmp(name, arrow[i].name) == 0) { - arrow[i].type = XK_NOD; - return 0; - } - return -1; + for (i = 0; i < A_K_NKEYS; i++) + if (strcmp(name, arrow[i].name) == 0) { + arrow[i].type = XK_NOD; + return (0); + } + return (-1); } @@ -1060,17 +1155,16 @@ term_clear_arrow(el, name) * Print the arrow key bindings */ protected void -term_print_arrow(el, name) - EditLine *el; - char *name; +term_print_arrow(EditLine *el, const char *name) { - int i; - fkey_t *arrow = el->el_term.t_fkey; - - for (i = 0; i < A_K_NKEYS; i++) - if (*name == '\0' || strcmp(name, arrow[i].name) == 0) - if (arrow[i].type != XK_NOD) - key_kprint(el, arrow[i].name, &arrow[i].fun, arrow[i].type); + int i; + fkey_t *arrow = el->el_term.t_fkey; + + for (i = 0; i < A_K_NKEYS; i++) + if (*name == '\0' || strcmp(name, arrow[i].name) == 0) + if (arrow[i].type != XK_NOD) + key_kprint(el, arrow[i].name, &arrow[i].fun, + arrow[i].type); } @@ -1078,76 +1172,79 @@ term_print_arrow(el, name) * Bind the arrow keys */ protected void -term_bind_arrow(el) - EditLine *el; +term_bind_arrow(EditLine *el) { - el_action_t *map, *dmap; - int i, j; - char *p; - fkey_t *arrow = el->el_term.t_fkey; - - /* Check if the components needed are initialized */ - if (el->el_term.t_buf == NULL || el->el_map.key == NULL) - return; - - map = el->el_map.type == MAP_VI ? el->el_map.alt : el->el_map.key; - dmap = el->el_map.type == MAP_VI ? el->el_map.vic : el->el_map.emacs; - - term_reset_arrow(el); - - for (i = 0; i < 4; i++) { - p = el->el_term.t_str[arrow[i].key]; - if (p && *p) { - j = (unsigned char) *p; - /* - * Assign the arrow keys only if: - * - * 1. They are multi-character arrow keys and the user - * has not re-assigned the leading character, or - * has re-assigned the leading character to be - * ED_SEQUENCE_LEAD_IN - * 2. They are single arrow keys pointing to an unassigned key. - */ - if (arrow[i].type == XK_NOD) - key_clear(el, map, p); - else { - if (p[1] && (dmap[j] == map[j] || - map[j] == ED_SEQUENCE_LEAD_IN)) { - key_add(el, p, &arrow[i].fun, arrow[i].type); - map[j] = ED_SEQUENCE_LEAD_IN; - } - else if (map[j] == ED_UNASSIGNED) { - key_clear(el, map, p); - if (arrow[i].type == XK_CMD) - map[j] = arrow[i].fun.cmd; - else - key_add(el, p, &arrow[i].fun, arrow[i].type); + el_action_t *map; + const el_action_t *dmap; + int i, j; + char *p; + fkey_t *arrow = el->el_term.t_fkey; + + /* Check if the components needed are initialized */ + if (el->el_term.t_buf == NULL || el->el_map.key == NULL) + return; + + map = el->el_map.type == MAP_VI ? el->el_map.alt : el->el_map.key; + dmap = el->el_map.type == MAP_VI ? el->el_map.vic : el->el_map.emacs; + + term_reset_arrow(el); + + for (i = 0; i < A_K_NKEYS; i++) { + p = el->el_term.t_str[arrow[i].key]; + if (p && *p) { + j = (unsigned char) *p; + /* + * Assign the arrow keys only if: + * + * 1. They are multi-character arrow keys and the user + * has not re-assigned the leading character, or + * has re-assigned the leading character to be + * ED_SEQUENCE_LEAD_IN + * 2. They are single arrow keys pointing to an + * unassigned key. + */ + if (arrow[i].type == XK_NOD) + key_clear(el, map, p); + else { + if (p[1] && (dmap[j] == map[j] || + map[j] == ED_SEQUENCE_LEAD_IN)) { + key_add(el, p, &arrow[i].fun, + arrow[i].type); + map[j] = ED_SEQUENCE_LEAD_IN; + } else if (map[j] == ED_UNASSIGNED) { + key_clear(el, map, p); + if (arrow[i].type == XK_CMD) + map[j] = arrow[i].fun.cmd; + else + key_add(el, p, &arrow[i].fun, + arrow[i].type); + } + } } - } } - } } /* term__putc(): * Add a character */ -protected void -term__putc(c) - int c; +protected int +term__putc(int c) { - (void)fputc(c, term_outfile); -} /* end term__putc */ + + return (fputc(c, term_outfile)); +} /* term__flush(): * Flush output */ protected void -term__flush() +term__flush(void) { - (void)fflush(term_outfile); -} /* end term__flush */ + + (void) fflush(term_outfile); +} /* term_telltc(): @@ -1155,37 +1252,34 @@ term__flush() */ protected int /*ARGSUSED*/ -term_telltc(el, argc, argv) - EditLine *el; - int argc; - char **argv; +term_telltc(EditLine *el, int argc __attribute__((__unused__)), + const char **argv __attribute__((__unused__))) { - struct termcapstr *t; - char **ts; - char upbuf[EL_BUFSIZ]; + const struct termcapstr *t; + char **ts; + char upbuf[EL_BUFSIZ]; - (void)fprintf(el->el_outfile, "\n\tYour terminal has the\n"); - (void)fprintf(el->el_outfile, "\tfollowing characteristics:\n\n"); - (void)fprintf(el->el_outfile, "\tIt has %d columns and %d lines\n", + (void) fprintf(el->el_outfile, "\n\tYour terminal has the\n"); + (void) fprintf(el->el_outfile, "\tfollowing characteristics:\n\n"); + (void) fprintf(el->el_outfile, "\tIt has %d columns and %d lines\n", Val(T_co), Val(T_li)); - (void)fprintf(el->el_outfile, - "\tIt has %s meta key\n", EL_HAS_META ? "a" : "no"); - (void)fprintf(el->el_outfile, - "\tIt can%suse tabs\n", EL_CAN_TAB ? " " : "not "); -#ifdef notyet - (void)fprintf(el->el_outfile, "\tIt %s automatic margins\n", - (T_Margin&MARGIN_AUTO)? "has": "does not have"); - if (T_Margin & MARGIN_AUTO) - (void)fprintf(el->el_outfile, "\tIt %s magic margins\n", - (T_Margin&MARGIN_MAGIC)?"has":"does not have"); -#endif - - for (t = tstr, ts = el->el_term.t_str; t->name != NULL; t++, ts++) - (void)fprintf(el->el_outfile, "\t%25s (%s) == %s\n", t->long_name, - t->name, *ts && **ts ? - key__decode_str(*ts, upbuf, "") : "(empty)"); - (void)fputc('\n', el->el_outfile); - return 0; + (void) fprintf(el->el_outfile, + "\tIt has %s meta key\n", EL_HAS_META ? "a" : "no"); + (void) fprintf(el->el_outfile, + "\tIt can%suse tabs\n", EL_CAN_TAB ? " " : "not "); + (void) fprintf(el->el_outfile, "\tIt %s automatic margins\n", + EL_HAS_AUTO_MARGINS ? "has" : "does not have"); + if (EL_HAS_AUTO_MARGINS) + (void) fprintf(el->el_outfile, "\tIt %s magic margins\n", + EL_HAS_MAGIC_MARGINS ? "has" : "does not have"); + + for (t = tstr, ts = el->el_term.t_str; t->name != NULL; t++, ts++) + (void) fprintf(el->el_outfile, "\t%25s (%s) == %s\n", + t->long_name, + t->name, *ts && **ts ? + key__decode_str(*ts, upbuf, "") : "(empty)"); + (void) fputc('\n', el->el_outfile); + return (0); } @@ -1194,69 +1288,75 @@ term_telltc(el, argc, argv) */ protected int /*ARGSUSED*/ -term_settc(el, argc, argv) - EditLine *el; - int argc; - char **argv; +term_settc(EditLine *el, int argc __attribute__((__unused__)), + const char **argv) { - struct termcapstr *ts; - struct termcapval *tv; - char *what, *how; - - if (argv == NULL || argv[1] == NULL || argv[2] == NULL) - return -1; - - what = argv[1]; - how = argv[2]; - - /* - * Do the strings first - */ - for (ts = tstr; ts->name != NULL; ts++) - if (strcmp(ts->name, what) == 0) - break; - - if (ts->name != NULL) { - term_alloc(el, ts, how); - term_setflags(el); - return 0; - } - - /* - * Do the numeric ones second - */ - for (tv = tval; tv->name != NULL; tv++) - if (strcmp(tv->name, what) == 0) - break; - - if (tv->name != NULL) { - if (tv == &tval[T_pt] || tv == &tval[T_km] -#ifdef notyet - || tv == &tval[T_am] || tv == &tval[T_xn] -#endif - ) { - if (strcmp(how, "yes") == 0) - el->el_term.t_val[tv - tval] = 1; - else if (strcmp(how, "no") == 0) - el->el_term.t_val[tv - tval] = 0; - else { - (void)fprintf(el->el_errfile, "settc: Bad value `%s'.\n", how); - return -1; - } - term_setflags(el); - term_change_size(el, Val(T_li), Val(T_co)); - return 0; + const struct termcapstr *ts; + const struct termcapval *tv; + const char *what, *how; + + if (argv == NULL || argv[1] == NULL || argv[2] == NULL) + return (-1); + + what = argv[1]; + how = argv[2]; + + /* + * Do the strings first + */ + for (ts = tstr; ts->name != NULL; ts++) + if (strcmp(ts->name, what) == 0) + break; + + if (ts->name != NULL) { + term_alloc(el, ts, how); + term_setflags(el); + return (0); } - else { - el->el_term.t_val[tv - tval] = atoi(how); - el->el_term.t_size.v = Val(T_co); - el->el_term.t_size.h = Val(T_li); - if (tv == &tval[T_co] || tv == &tval[T_li]) - term_change_size(el, Val(T_li), Val(T_co)); - return 0; + /* + * Do the numeric ones second + */ + for (tv = tval; tv->name != NULL; tv++) + if (strcmp(tv->name, what) == 0) + break; + + if (tv->name != NULL) { + if (tv == &tval[T_pt] || tv == &tval[T_km] || + tv == &tval[T_am] || tv == &tval[T_xn]) { + if (strcmp(how, "yes") == 0) + el->el_term.t_val[tv - tval] = 1; + else if (strcmp(how, "no") == 0) + el->el_term.t_val[tv - tval] = 0; + else { + (void) fprintf(el->el_errfile, + "settc: Bad value `%s'.\n", how); + return (-1); + } + term_setflags(el); + if (term_change_size(el, Val(T_li), Val(T_co)) == -1) + return (-1); + return (0); + } else { + long i; + char *ep; + + i = strtol(how, &ep, 10); + if (*ep != '\0') { + (void) fprintf(el->el_errfile, + "settc: Bad value `%s'.\n", how); + return (-1); + } + el->el_term.t_val[tv - tval] = (int) i; + el->el_term.t_size.v = Val(T_co); + el->el_term.t_size.h = Val(T_li); + if (tv == &tval[T_co] || tv == &tval[T_li]) + if (term_change_size(el, Val(T_li), Val(T_co)) + == -1) + return (-1); + return (0); + } } - } - return -1; + return (-1); } @@ -1265,198 +1365,224 @@ term_settc(el, argc, argv) */ protected int /*ARGSUSED*/ -term_echotc(el, argc, argv) - EditLine *el; - int argc; - char **argv; +term_echotc(EditLine *el, int argc __attribute__((__unused__)), + const char **argv) { - char *cap, *scap; - int arg_need, arg_cols, arg_rows; - int verbose = 0, silent = 0; - char *area; - static char *fmts = "%s\n", *fmtd = "%d\n"; - struct termcapstr *t; - char buf[TC_BUFSIZE]; - - area = buf; - - if (argv == NULL || argv[1] == NULL) - return -1; - argv++; - - if (argv[0][0] == '-') { - switch (argv[0][1]) { - case 'v': - verbose = 1; - break; - case 's': - silent = 1; - break; - default: - /* stderror(ERR_NAME | ERR_TCUSAGE); */ - break; - } + char *cap, *scap, *ep; + int arg_need, arg_cols, arg_rows; + int verbose = 0, silent = 0; + char *area; + static const char fmts[] = "%s\n", fmtd[] = "%d\n"; + const struct termcapstr *t; + char buf[TC_BUFSIZE]; + long i; + + area = buf; + + if (argv == NULL || argv[1] == NULL) + return (-1); argv++; - } - if (!*argv || *argv[0] == '\0') - return 0; - if (strcmp(*argv, "tabs") == 0) { - (void)fprintf(el->el_outfile, fmts, EL_CAN_TAB ? "yes" : "no"); - return 0; - } - else if (strcmp(*argv, "meta") == 0) { - (void)fprintf(el->el_outfile, fmts, Val(T_km) ? "yes" : "no"); - return 0; - } -#ifdef notyet - else if (strcmp(*argv, "xn") == 0) { - (void)fprintf(el->el_outfile, fmts, T_Margin & MARGIN_MAGIC ? - "yes" : "no"); - return 0; - } - else if (strcmp(*argv, "am") == 0) { - (void)fprintf(el->el_outfile, fmts, T_Margin & MARGIN_AUTO ? - "yes" : "no"); - return 0; - } -#endif - else if (strcmp(*argv, "baud") == 0) { + + if (argv[0][0] == '-') { + switch (argv[0][1]) { + case 'v': + verbose = 1; + break; + case 's': + silent = 1; + break; + default: + /* stderror(ERR_NAME | ERR_TCUSAGE); */ + break; + } + argv++; + } + if (!*argv || *argv[0] == '\0') + return (0); + if (strcmp(*argv, "tabs") == 0) { + (void) fprintf(el->el_outfile, fmts, EL_CAN_TAB ? "yes" : "no"); + return (0); + } else if (strcmp(*argv, "meta") == 0) { + (void) fprintf(el->el_outfile, fmts, Val(T_km) ? "yes" : "no"); + return (0); + } else if (strcmp(*argv, "xn") == 0) { + (void) fprintf(el->el_outfile, fmts, EL_HAS_MAGIC_MARGINS ? + "yes" : "no"); + return (0); + } else if (strcmp(*argv, "am") == 0) { + (void) fprintf(el->el_outfile, fmts, EL_HAS_AUTO_MARGINS ? + "yes" : "no"); + return (0); + } else if (strcmp(*argv, "baud") == 0) { #ifdef notdef - int i; - - for (i = 0; baud_rate[i].b_name != NULL; i++) - if (el->el_tty.t_speed == baud_rate[i].b_rate) { - (void)fprintf(el->el_outfile, fmts, baud_rate[i].b_name); - return 0; - } - (void)fprintf(el->el_outfile, fmtd, 0); + int i; + + for (i = 0; baud_rate[i].b_name != NULL; i++) + if (el->el_tty.t_speed == baud_rate[i].b_rate) { + (void) fprintf(el->el_outfile, fmts, + baud_rate[i].b_name); + return (0); + } + (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, el->el_tty.t_speed); #endif - return 0; - } - else if (strcmp(*argv, "rows") == 0 || strcmp(*argv, "lines") == 0) { - (void)fprintf(el->el_outfile, fmtd, Val(T_li)); - return 0; - } - else if (strcmp(*argv, "cols") == 0) { - (void)fprintf(el->el_outfile, fmtd, Val(T_co)); - return 0; - } - - /* - * Try to use our local definition first - */ - scap = NULL; - for (t = tstr; t->name != NULL; t++) - if (strcmp(t->name, *argv) == 0) { - scap = el->el_term.t_str[t - tstr]; - break; + return (0); + } else if (strcmp(*argv, "rows") == 0 || strcmp(*argv, "lines") == 0) { + (void) fprintf(el->el_outfile, fmtd, Val(T_li)); + return (0); + } else if (strcmp(*argv, "cols") == 0) { + (void) fprintf(el->el_outfile, fmtd, Val(T_co)); + return (0); } - if (t->name == NULL) - scap = tgetstr(*argv, &area); - if (!scap || scap[0] == '\0') { - if (!silent) - (void)fprintf(el->el_errfile, - "echotc: Termcap parameter `%s' not found.\n", *argv); - return -1; - } - - /* - * Count home many values we need for this capability. - */ - for (cap = scap, arg_need = 0; *cap; cap++) - if (*cap == '%') - switch (*++cap) { - case 'd': - case '2': - case '3': - case '.': - case '+': - arg_need++; + /* + * Try to use our local definition first + */ + scap = NULL; + for (t = tstr; t->name != NULL; t++) + if (strcmp(t->name, *argv) == 0) { + scap = el->el_term.t_str[t - tstr]; + break; + } + if (t->name == NULL) + scap = tgetstr((char *)*argv, &area); + if (!scap || scap[0] == '\0') { + if (!silent) + (void) fprintf(el->el_errfile, + "echotc: Termcap parameter `%s' not found.\n", + *argv); + return (-1); + } + /* + * Count home many values we need for this capability. + */ + for (cap = scap, arg_need = 0; *cap; cap++) + if (*cap == '%') + switch (*++cap) { + case 'd': + case '2': + case '3': + case '.': + case '+': + arg_need++; + break; + case '%': + case '>': + case 'i': + case 'r': + case 'n': + case 'B': + case 'D': + break; + default: + /* + * hpux has lot's of them... + */ + if (verbose) + (void) fprintf(el->el_errfile, + "echotc: Warning: unknown termcap %% `%c'.\n", + *cap); + /* This is bad, but I won't complain */ + break; + } + + switch (arg_need) { + case 0: + argv++; + if (*argv && *argv[0]) { + if (!silent) + (void) fprintf(el->el_errfile, + "echotc: Warning: Extra argument `%s'.\n", + *argv); + return (-1); + } + (void) tputs(scap, 1, term__putc); break; - case '%': - case '>': - case 'i': - case 'r': - case 'n': - case 'B': - case 'D': + case 1: + argv++; + if (!*argv || *argv[0] == '\0') { + if (!silent) + (void) fprintf(el->el_errfile, + "echotc: Warning: Missing argument.\n"); + return (-1); + } + arg_cols = 0; + i = strtol(*argv, &ep, 10); + if (*ep != '\0' || i < 0) { + if (!silent) + (void) fprintf(el->el_errfile, + "echotc: Bad value `%s' for rows.\n", + *argv); + return (-1); + } + arg_rows = (int) i; + argv++; + if (*argv && *argv[0]) { + if (!silent) + (void) fprintf(el->el_errfile, + "echotc: Warning: Extra argument `%s'.\n", + *argv); + return (-1); + } + (void) tputs(tgoto(scap, arg_cols, arg_rows), 1, term__putc); break; - default: - /* - * hpux has lot's of them... - */ + default: + /* This is wrong, but I will ignore it... */ if (verbose) - (void)fprintf(el->el_errfile, - "echotc: Warning: unknown termcap %% `%c'.\n", *cap); - /* This is bad, but I won't complain */ + (void) fprintf(el->el_errfile, + "echotc: Warning: Too many required arguments (%d).\n", + arg_need); + /* FALLTHROUGH */ + case 2: + argv++; + if (!*argv || *argv[0] == '\0') { + if (!silent) + (void) fprintf(el->el_errfile, + "echotc: Warning: Missing argument.\n"); + return (-1); + } + i = strtol(*argv, &ep, 10); + if (*ep != '\0' || i < 0) { + if (!silent) + (void) fprintf(el->el_errfile, + "echotc: Bad value `%s' for cols.\n", + *argv); + return (-1); + } + arg_cols = (int) i; + argv++; + if (!*argv || *argv[0] == '\0') { + if (!silent) + (void) fprintf(el->el_errfile, + "echotc: Warning: Missing argument.\n"); + return (-1); + } + i = strtol(*argv, &ep, 10); + if (*ep != '\0' || i < 0) { + if (!silent) + (void) fprintf(el->el_errfile, + "echotc: Bad value `%s' for rows.\n", + *argv); + return (-1); + } + arg_rows = (int) i; + if (*ep != '\0') { + if (!silent) + (void) fprintf(el->el_errfile, + "echotc: Bad value `%s'.\n", *argv); + return (-1); + } + argv++; + if (*argv && *argv[0]) { + if (!silent) + (void) fprintf(el->el_errfile, + "echotc: Warning: Extra argument `%s'.\n", + *argv); + return (-1); + } + (void) tputs(tgoto(scap, arg_cols, arg_rows), arg_rows, + term__putc); break; - } - - switch (arg_need) { - case 0: - argv++; - if (*argv && *argv[0]) { - if (!silent) - (void)fprintf(el->el_errfile, - "echotc: Warning: Extra argument `%s'.\n", *argv); - return -1; - } - (void)tputs(scap, 1, term__putc); - break; - case 1: - argv++; - if (!*argv || *argv[0] == '\0') { - if (!silent) - (void)fprintf(el->el_errfile, - "echotc: Warning: Missing argument.\n"); - return -1; - } - arg_cols = 0; - arg_rows = atoi(*argv); - argv++; - if (*argv && *argv[0]) { - if (!silent) - (void)fprintf(el->el_errfile, - "echotc: Warning: Extra argument `%s'.\n", *argv); - return -1; - } - (void)tputs(tgoto(scap, arg_cols, arg_rows), 1, term__putc); - break; - default: - /* This is wrong, but I will ignore it... */ - if (verbose) - (void)fprintf(el->el_errfile, - "echotc: Warning: Too many required arguments (%d).\n", - arg_need); - /*FALLTHROUGH*/ - case 2: - argv++; - if (!*argv || *argv[0] == '\0') { - if (!silent) - (void)fprintf(el->el_errfile, - "echotc: Warning: Missing argument.\n"); - return -1; - } - arg_cols = atoi(*argv); - argv++; - if (!*argv || *argv[0] == '\0') { - if (!silent) - (void)fprintf(el->el_errfile, - "echotc: Warning: Missing argument.\n"); - return -1; - } - arg_rows = atoi(*argv); - argv++; - if (*argv && *argv[0]) { - if (!silent) - (void)fprintf(el->el_errfile, - "echotc: Warning: Extra argument `%s'.\n", *argv); - return -1; } - (void)tputs(tgoto(scap, arg_cols, arg_rows), arg_rows, term__putc); - break; - } - return 0; + return (0); } diff --git a/lib/libedit/term.h b/lib/libedit/term.h index cc09739b791..794cba094a6 100644 --- a/lib/libedit/term.h +++ b/lib/libedit/term.h @@ -1,5 +1,5 @@ -/* $OpenBSD: term.h,v 1.6 2003/06/02 20:18:40 millert Exp $ */ -/* $NetBSD: term.h,v 1.4 1997/01/11 06:48:14 lukem Exp $ */ +/* $OpenBSD: term.h,v 1.7 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: term.h,v 1.15 2003/09/14 21:48:55 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -39,78 +39,85 @@ * el.term.h: Termcap header */ #ifndef _h_el_term -#define _h_el_term +#define _h_el_term #include "histedit.h" -typedef struct { /* Symbolic function key bindings */ - 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 */ +typedef struct { /* Symbolic function key bindings */ + 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 { - coord_t t_size; /* # lines and cols */ - bool_t t_flags; -#define TERM_CAN_INSERT 0x01 /* Has insert cap */ -#define TERM_CAN_DELETE 0x02 /* Has delete cap */ -#define TERM_CAN_CEOL 0x04 /* Has CEOL cap */ -#define TERM_CAN_TAB 0x08 /* Can use tabs */ -#define TERM_CAN_ME 0x10 /* Can turn all attrs. */ -#define TERM_CAN_UP 0x20 /* Can move up */ -#define TERM_HAS_META 0x40 /* Has a meta key */ - char *t_buf; /* Termcap buffer */ - int t_loc; /* location used */ - char **t_str; /* termcap strings */ - int *t_val; /* termcap values */ - char *t_cap; /* Termcap buffer */ - fkey_t *t_fkey; /* Array of keys */ + 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 */ +#define TERM_CAN_DELETE 0x002 /* Has delete cap */ +#define TERM_CAN_CEOL 0x004 /* Has CEOL cap */ +#define TERM_CAN_TAB 0x008 /* Can use tabs */ +#define TERM_CAN_ME 0x010 /* Can turn all attrs. */ +#define TERM_CAN_UP 0x020 /* Can move up */ +#define TERM_HAS_META 0x040 /* Has a meta key */ +#define TERM_HAS_AUTO_MARGINS 0x080 /* Has auto margins */ +#define TERM_HAS_MAGIC_MARGINS 0x100 /* Has magic margins */ + char *t_buf; /* Termcap buffer */ + int t_loc; /* location used */ + char **t_str; /* termcap strings */ + int *t_val; /* termcap values */ + char *t_cap; /* Termcap buffer */ + fkey_t *t_fkey; /* Array of keys */ } el_term_t; /* * fKey indexes */ -#define A_K_DN 0 -#define A_K_UP 1 -#define A_K_LT 2 -#define A_K_RT 3 -#define A_K_NKEYS 4 +#define A_K_DN 0 +#define A_K_UP 1 +#define A_K_LT 2 +#define A_K_RT 3 +#define A_K_HO 4 +#define A_K_EN 5 +#define A_K_NKEYS 6 -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_insertwrite(EditLine *, char *, int); -protected void term_deletechars(EditLine *, int); -protected void term_clear_screen(EditLine *); -protected void term_beep(EditLine *); -protected void 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_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__putc(int); -protected void term__flush(void); +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 *, const char *, int); +protected void term_insertwrite(EditLine *, char *, int); +protected void term_deletechars(EditLine *, int); +protected void term_clear_screen(EditLine *); +protected void term_beep(EditLine *); +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 *, 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 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); /* * Easy access macros */ -#define EL_FLAGS (el)->el_term.t_flags +#define EL_FLAGS (el)->el_term.t_flags -#define EL_CAN_INSERT (EL_FLAGS & TERM_CAN_INSERT) -#define EL_CAN_DELETE (EL_FLAGS & TERM_CAN_DELETE) -#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_HAS_META (EL_FLAGS & TERM_HAS_META) +#define EL_CAN_INSERT (EL_FLAGS & TERM_CAN_INSERT) +#define EL_CAN_DELETE (EL_FLAGS & TERM_CAN_DELETE) +#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_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) #endif /* _h_el_term */ diff --git a/lib/libedit/termcap.h b/lib/libedit/termcap.h deleted file mode 100644 index fabbe4884df..00000000000 --- a/lib/libedit/termcap.h +++ /dev/null @@ -1,51 +0,0 @@ -/* $OpenBSD: termcap.h,v 1.6 2003/06/02 20:18:40 millert Exp $ */ -/* $NetBSD: termcap.h,v 1.2 1997/01/11 06:48:14 lukem Exp $ */ - -/*- - * 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. 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. - * - * @(#)termcap.h 8.1 (Berkeley) 6/4/93 - */ - -/* - * termcap.h: I cannot find those in any include files... - */ -#ifndef _h_termcap -#define _h_termcap - -int tgetent(char *, char *); -char *tgetstr(char *, char **); -int tgetflag(char *); -int tgetnum(char *); -char *tgoto(char *, int, int); -char *tputs(char *, int, void (*)(int)); - -#endif /* _h_termcap */ diff --git a/lib/libedit/tokenizer.c b/lib/libedit/tokenizer.c index 6f152838803..da1c64fdcb0 100644 --- a/lib/libedit/tokenizer.c +++ b/lib/libedit/tokenizer.c @@ -1,5 +1,5 @@ -/* $OpenBSD: tokenizer.c,v 1.8 2003/08/11 18:21:40 deraadt Exp $ */ -/* $NetBSD: tokenizer.c,v 1.2 1997/01/11 06:48:15 lukem Exp $ */ +/* $OpenBSD: tokenizer.c,v 1.9 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: tokenizer.c,v 1.12 2003/08/07 16:44:34 agc Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -33,46 +33,48 @@ * SUCH DAMAGE. */ +#include "config.h" #if !defined(lint) && !defined(SCCSID) #if 0 static char sccsid[] = "@(#)tokenizer.c 8.1 (Berkeley) 6/4/93"; #else -static const char rcsid[] = "$OpenBSD: tokenizer.c,v 1.8 2003/08/11 18:21:40 deraadt Exp $"; +static const char rcsid[] = "$OpenBSD: tokenizer.c,v 1.9 2003/10/31 08:42:24 otto Exp $"; #endif #endif /* not lint && not SCCSID */ /* * tokenize.c: Bourne shell like tokenizer */ -#include "sys.h" #include <string.h> #include <stdlib.h> #include "tokenizer.h" -typedef enum { Q_none, Q_single, Q_double, Q_one, Q_doubleone } quote_t; +typedef enum { + Q_none, Q_single, Q_double, Q_one, Q_doubleone +} quote_t; -#define IFS "\t \n" +#define IFS "\t \n" -#define TOK_KEEP 1 -#define TOK_EAT 2 +#define TOK_KEEP 1 +#define TOK_EAT 2 -#define WINCR 20 -#define AINCR 10 +#define WINCR 20 +#define AINCR 10 -#define tok_malloc(a) malloc(a) -#define tok_free(a) free(a) -#define tok_realloc(a, b) realloc(a, b) +#define tok_malloc(a) malloc(a) +#define tok_free(a) free(a) +#define tok_realloc(a, b) realloc(a, b) struct tokenizer { - char *ifs; /* In field separator */ - int argc, amax; /* Current and maximum number of args */ - char **argv; /* Argument list */ - char *wptr, *wmax; /* Space and limit on the word buffer */ - char *wstart; /* Beginning of next word */ - char *wspace; /* Space of word buffer */ - quote_t quote; /* Quoting state */ - int flags; /* flags; */ + char *ifs; /* In field separator */ + int argc, amax; /* Current and maximum number of args */ + char **argv; /* Argument list */ + char *wptr, *wmax; /* Space and limit on the word buffer */ + char *wstart; /* Beginning of next word */ + char *wspace; /* Space of word buffer */ + quote_t quote; /* Quoting state */ + int flags; /* flags; */ }; @@ -83,16 +85,16 @@ private void tok_finish(Tokenizer *); * Finish a word in the tokenizer. */ private void -tok_finish(tok) - Tokenizer *tok; +tok_finish(Tokenizer *tok) { - *tok->wptr = '\0'; - if ((tok->flags & TOK_KEEP) || tok->wptr != tok->wstart) { - tok->argv[tok->argc++] = tok->wstart; - tok->argv[tok->argc] = NULL; - tok->wstart = ++tok->wptr; - } - tok->flags &= ~TOK_KEEP; + + *tok->wptr = '\0'; + if ((tok->flags & TOK_KEEP) || tok->wptr != tok->wstart) { + tok->argv[tok->argc++] = tok->wstart; + tok->argv[tok->argc] = NULL; + tok->wstart = ++tok->wptr; + } + tok->flags &= ~TOK_KEEP; } @@ -100,24 +102,40 @@ tok_finish(tok) * Initialize the tokenizer */ public Tokenizer * -tok_init(ifs) - const char *ifs; +tok_init(const char *ifs) { - Tokenizer* tok = (Tokenizer*) tok_malloc(sizeof(Tokenizer)); - - tok->ifs = strdup(ifs ? ifs : IFS); - tok->argc = 0; - tok->amax = AINCR; - tok->argv = (char **) tok_malloc(sizeof(char *) * tok->amax); - tok->argv[0] = NULL; - tok->wspace = (char *) tok_malloc(WINCR); - tok->wmax = tok->wspace + WINCR; - tok->wstart = tok->wspace; - tok->wptr = tok->wspace; - tok->flags = 0; - tok->quote = Q_none; - - return tok; + Tokenizer *tok = (Tokenizer *) tok_malloc(sizeof(Tokenizer)); + + if (tok == NULL) + return NULL; + tok->ifs = 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) { + 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) { + 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; + tok->flags = 0; + tok->quote = Q_none; + + return (tok); } @@ -125,14 +143,14 @@ tok_init(ifs) * Reset the tokenizer */ public void -tok_reset(tok) - Tokenizer *tok; +tok_reset(Tokenizer *tok) { - tok->argc = 0; - tok->wstart = tok->wspace; - tok->wptr = tok->wspace; - tok->flags = 0; - tok->quote = Q_none; + + tok->argc = 0; + tok->wstart = tok->wspace; + tok->wptr = tok->wspace; + tok->flags = 0; + tok->quote = Q_none; } @@ -140,13 +158,13 @@ tok_reset(tok) * Clean up */ public void -tok_end(tok) - Tokenizer *tok; +tok_end(Tokenizer *tok) { - tok_free((ptr_t) tok->ifs); - tok_free((ptr_t) tok->wspace); - tok_free((ptr_t) tok->argv); - tok_free((ptr_t) tok); + + tok_free((ptr_t) tok->ifs); + tok_free((ptr_t) tok->wspace); + tok_free((ptr_t) tok->argv); + tok_free((ptr_t) tok); } @@ -158,235 +176,232 @@ tok_end(tok) * 3: Quoted return * 2: Unmatched double quote * 1: Unmatched single quote - * 0: Ok + * 0: Ok */ public int -tok_line(tok, line, argc, argv) - Tokenizer *tok; - const char* line; - int *argc; - char ***argv; +tok_line(Tokenizer *tok, const char *line, int *argc, const char ***argv) { - const char *ptr; - - while (1) { - switch (*(ptr = line++)) { - case '\'': - tok->flags |= TOK_KEEP; - tok->flags &= ~TOK_EAT; - switch (tok->quote) { - case Q_none: - tok->quote = Q_single; /* Enter single quote mode */ - break; - - case Q_single: /* Exit single quote mode */ - tok->quote = Q_none; - break; - - case Q_one: /* Quote this ' */ - tok->quote = Q_none; - *tok->wptr++ = *ptr; - break; - - case Q_double: /* Stay in double quote mode */ - *tok->wptr++ = *ptr; - break; - - case Q_doubleone: /* Quote this ' */ - tok->quote = Q_double; - *tok->wptr++ = *ptr; - break; - - default: - return(-1); - } - break; - - case '"': - tok->flags &= ~TOK_EAT; - tok->flags |= TOK_KEEP; - switch (tok->quote) { - case Q_none: /* Enter double quote mode */ - tok->quote = Q_double; - break; - - case Q_double: - tok->quote = Q_none; /* Exit double quote mode */ - break; - - case Q_one: /* Quote this " */ - tok->quote = Q_none; - *tok->wptr++ = *ptr; - break; - - case Q_single: /* Stay in single quote mode */ - *tok->wptr++ = *ptr; - break; - - case Q_doubleone: /* Quote this " */ - tok->quote = Q_double; - *tok->wptr++ = *ptr; - break; - - default: - return(-1); - } - break; - - case '\\': - tok->flags |= TOK_KEEP; - tok->flags &= ~TOK_EAT; - switch (tok->quote) { - case Q_none: /* Quote next character */ - tok->quote = Q_one; - break; - - case Q_double: - tok->quote = Q_doubleone;/* Quote next character */ - break; - - case Q_one: - *tok->wptr++ = *ptr; - tok->quote = Q_none; /* Quote this, restore state */ - break; - - case Q_single: /* Stay in single quote mode */ - *tok->wptr++ = *ptr; - break; - - case Q_doubleone: /* Quote this \ */ - tok->quote = Q_double; - *tok->wptr++ = *ptr; - break; - - default: - return(-1); - } - break; - - case '\n': - tok->flags &= ~TOK_EAT; - switch (tok->quote) { - case Q_none: - tok_finish(tok); - *argv = tok->argv; - *argc = tok->argc; - return(0); - - case Q_single: - case Q_double: - *tok->wptr++ = *ptr; /* Add the return */ - break; - - case Q_doubleone: - tok->flags |= TOK_EAT; - tok->quote = Q_double; /* Back to double, eat the '\n' */ - break; - - case Q_one: - tok->flags |= TOK_EAT; - tok->quote = Q_none; /* No quote, more eat the '\n' */ - break; - - default: - return(0); - } - break; - - case '\0': - switch (tok->quote) { - case Q_none: - /* Finish word and return */ - if (tok->flags & TOK_EAT) { - tok->flags &= ~TOK_EAT; - return 3; + const char *ptr; + + for (;;) { + switch (*(ptr = line++)) { + case '\'': + tok->flags |= TOK_KEEP; + tok->flags &= ~TOK_EAT; + switch (tok->quote) { + case Q_none: + tok->quote = Q_single; /* Enter single quote + * mode */ + break; + + case Q_single: /* Exit single quote mode */ + tok->quote = Q_none; + break; + + case Q_one: /* Quote this ' */ + tok->quote = Q_none; + *tok->wptr++ = *ptr; + break; + + case Q_double: /* Stay in double quote mode */ + *tok->wptr++ = *ptr; + break; + + case Q_doubleone: /* Quote this ' */ + tok->quote = Q_double; + *tok->wptr++ = *ptr; + break; + + default: + return (-1); + } + break; + + case '"': + tok->flags &= ~TOK_EAT; + tok->flags |= TOK_KEEP; + switch (tok->quote) { + case Q_none: /* Enter double quote mode */ + tok->quote = Q_double; + break; + + case Q_double: /* Exit double quote mode */ + tok->quote = Q_none; + break; + + case Q_one: /* Quote this " */ + tok->quote = Q_none; + *tok->wptr++ = *ptr; + break; + + case Q_single: /* Stay in single quote mode */ + *tok->wptr++ = *ptr; + break; + + case Q_doubleone: /* Quote this " */ + tok->quote = Q_double; + *tok->wptr++ = *ptr; + break; + + default: + return (-1); + } + break; + + case '\\': + tok->flags |= TOK_KEEP; + tok->flags &= ~TOK_EAT; + switch (tok->quote) { + case Q_none: /* Quote next character */ + tok->quote = Q_one; + break; + + case Q_double: /* Quote next character */ + tok->quote = Q_doubleone; + break; + + case Q_one: /* Quote this, restore state */ + *tok->wptr++ = *ptr; + tok->quote = Q_none; + break; + + case Q_single: /* Stay in single quote mode */ + *tok->wptr++ = *ptr; + break; + + case Q_doubleone: /* Quote this \ */ + tok->quote = Q_double; + *tok->wptr++ = *ptr; + break; + + default: + return (-1); + } + break; + + case '\n': + tok->flags &= ~TOK_EAT; + switch (tok->quote) { + case Q_none: + tok_finish(tok); + *argv = (const char **)tok->argv; + *argc = tok->argc; + return (0); + + case Q_single: + case Q_double: + *tok->wptr++ = *ptr; /* Add the return */ + break; + + case Q_doubleone: /* Back to double, eat the '\n' */ + tok->flags |= TOK_EAT; + tok->quote = Q_double; + break; + + case Q_one: /* No quote, more eat the '\n' */ + tok->flags |= TOK_EAT; + tok->quote = Q_none; + break; + + default: + return (0); + } + break; + + case '\0': + switch (tok->quote) { + case Q_none: + /* Finish word and return */ + if (tok->flags & TOK_EAT) { + tok->flags &= ~TOK_EAT; + return (3); + } + tok_finish(tok); + *argv = (const char **)tok->argv; + *argc = tok->argc; + return (0); + + case Q_single: + return (1); + + case Q_double: + return (2); + + case Q_doubleone: + tok->quote = Q_double; + *tok->wptr++ = *ptr; + break; + + case Q_one: + tok->quote = Q_none; + *tok->wptr++ = *ptr; + break; + + default: + return (-1); + } + break; + + default: + tok->flags &= ~TOK_EAT; + switch (tok->quote) { + case Q_none: + if (strchr(tok->ifs, *ptr) != NULL) + tok_finish(tok); + else + *tok->wptr++ = *ptr; + break; + + case Q_single: + case Q_double: + *tok->wptr++ = *ptr; + break; + + + case Q_doubleone: + *tok->wptr++ = '\\'; + tok->quote = Q_double; + *tok->wptr++ = *ptr; + break; + + case Q_one: + tok->quote = Q_none; + *tok->wptr++ = *ptr; + break; + + default: + return (-1); + + } + break; } - tok_finish(tok); - *argv = tok->argv; - *argc = tok->argc; - return(0); - - case Q_single: - return(1); - - case Q_double: - return(2); - - case Q_doubleone: - tok->quote = Q_double; - *tok->wptr++ = *ptr; - break; - - case Q_one: - tok->quote = Q_none; - *tok->wptr++ = *ptr; - break; - - default: - return(-1); - } - break; - - default: - tok->flags &= ~TOK_EAT; - switch (tok->quote) { - case Q_none: - if (strchr(tok->ifs, *ptr) != NULL) - tok_finish(tok); - else - *tok->wptr++ = *ptr; - break; - - case Q_single: - case Q_double: - *tok->wptr++ = *ptr; - break; - - - case Q_doubleone: - *tok->wptr++ = '\\'; - tok->quote = Q_double; - *tok->wptr++ = *ptr; - break; - - case Q_one: - tok->quote = Q_none; - *tok->wptr++ = *ptr; - break; - - default: - return(-1); - - } - break; - } - - if (tok->wptr >= tok->wmax - 4) { - size_t size = tok->wmax - tok->wspace + WINCR; - char *s; - int offs; - - if ((s = tok_realloc(tok->wspace, size)) == NULL) - return -1; - - if ((offs = s - tok->wspace) != 0) { - 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->wspace = s; - } - tok->wmax = s + size; - } - if (tok->argc >= tok->amax - 4) { - char **nargv = (char **) tok_realloc(tok->argv, (tok->amax + AINCR) - * sizeof(char*)); - if (nargv == NULL) - return -1; - tok->amax += AINCR; - tok->argv = nargv; + if (tok->wptr >= tok->wmax - 4) { + size_t size = tok->wmax - tok->wspace + WINCR; + char *s = (char *) tok_realloc(tok->wspace, size); + if (s == NULL) + return (-1); + + if (s != tok->wspace) { + int i; + 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; + tok->amax += AINCR; + p = (char **) tok_realloc(tok->argv, + tok->amax * sizeof(char *)); + if (p == NULL) + return (-1); + tok->argv = p; + } } - } } diff --git a/lib/libedit/tokenizer.h b/lib/libedit/tokenizer.h index 1a43a0c8977..1d20a256fe3 100644 --- a/lib/libedit/tokenizer.h +++ b/lib/libedit/tokenizer.h @@ -1,5 +1,5 @@ -/* $OpenBSD: tokenizer.h,v 1.6 2003/06/02 20:18:40 millert Exp $ */ -/* $NetBSD: tokenizer.h,v 1.2 1997/01/11 06:48:16 lukem Exp $ */ +/* $OpenBSD: tokenizer.h,v 1.7 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: tokenizer.h,v 1.6 2003/08/07 16:44:34 agc Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -39,13 +39,13 @@ * tokenizer.h: Header file for tokenizer routines */ #ifndef _h_tokenizer -#define _h_tokenizer +#define _h_tokenizer typedef struct tokenizer Tokenizer; -Tokenizer *tok_init(const char *); +Tokenizer *tok_init(const char *); void tok_reset(Tokenizer *); void tok_end(Tokenizer *); -int tok_line(Tokenizer *, const char *, int *, char ***); +int tok_line(Tokenizer *, const char *, int *, const char ***); #endif /* _h_tokenizer */ diff --git a/lib/libedit/tty.c b/lib/libedit/tty.c index 98184fae78f..b9910427472 100644 --- a/lib/libedit/tty.c +++ b/lib/libedit/tty.c @@ -1,5 +1,5 @@ -/* $OpenBSD: tty.c,v 1.8 2003/06/02 20:18:40 millert Exp $ */ -/* $NetBSD: tty.c,v 1.3 1997/04/11 17:52:49 christos Exp $ */ +/* $OpenBSD: tty.c,v 1.9 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: tty.c,v 1.18 2003/08/07 16:44:34 agc Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -33,520 +33,531 @@ * SUCH DAMAGE. */ +#include "config.h" #if !defined(lint) && !defined(SCCSID) #if 0 static char sccsid[] = "@(#)tty.c 8.1 (Berkeley) 6/4/93"; #else -static const char rcsid[] = "$OpenBSD: tty.c,v 1.8 2003/06/02 20:18:40 millert Exp $"; +static const char rcsid[] = "$OpenBSD: tty.c,v 1.9 2003/10/31 08:42:24 otto Exp $"; #endif #endif /* not lint && not SCCSID */ -/* +/* * tty.c: tty interface stuff */ -#include "sys.h" #include "tty.h" #include "el.h" typedef struct ttymodes_t { - char *m_name; - u_int m_value; - int m_type; -} ttymodes_t; + const char *m_name; + u_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 */ + int nch, och; /* Internal and termio rep of chars */ + el_action_t bind[3]; /* emacs, vi, and vi-cmd */ } ttymap_t; -private ttyperm_t ttyperm = { - { - { "iflag:", ICRNL, (INLCR|IGNCR) }, - { "oflag:", (OPOST|ONLCR), ONLRET }, - { "cflag:", 0, 0 }, - { "lflag:", (ISIG|ICANON|ECHO|ECHOE|ECHOCTL|IEXTEN), - (NOFLSH|ECHONL|EXTPROC|FLUSHO) }, - { "chars:", 0, 0 }, - }, - { - { "iflag:", (INLCR|ICRNL), IGNCR }, - { "oflag:", (OPOST|ONLCR), ONLRET }, - { "cflag:", 0, 0 }, - { "lflag:", ISIG, - (NOFLSH|ICANON|ECHO|ECHOK|ECHONL|EXTPROC|IEXTEN|FLUSHO) }, - { "chars:", (C_SH(C_MIN)|C_SH(C_TIME)|C_SH(C_SWTCH)|C_SH(C_DSWTCH)| - C_SH(C_SUSP)|C_SH(C_DSUSP)|C_SH(C_EOL)|C_SH(C_DISCARD)| - C_SH(C_PGOFF)|C_SH(C_PAGE)|C_SH(C_STATUS)), 0 } - }, - { - { "iflag:", 0, IXON | IXOFF }, - { "oflag:", 0, 0 }, - { "cflag:", 0, 0 }, - { "lflag:", 0, ISIG | IEXTEN }, - { "chars:", 0, 0 }, - } +private const ttyperm_t ttyperm = { + { + {"iflag:", ICRNL, (INLCR | IGNCR)}, + {"oflag:", (OPOST | ONLCR), ONLRET}, + {"cflag:", 0, 0}, + {"lflag:", (ISIG | ICANON | ECHO | ECHOE | ECHOCTL | IEXTEN), + (NOFLSH | ECHONL | EXTPROC | FLUSHO)}, + {"chars:", 0, 0}, + }, + { + {"iflag:", (INLCR | ICRNL), IGNCR}, + {"oflag:", (OPOST | ONLCR), ONLRET}, + {"cflag:", 0, 0}, + {"lflag:", ISIG, + (NOFLSH | ICANON | ECHO | ECHOK | ECHONL | EXTPROC | IEXTEN | FLUSHO)}, + {"chars:", (C_SH(C_MIN) | C_SH(C_TIME) | C_SH(C_SWTCH) | C_SH(C_DSWTCH) | + C_SH(C_SUSP) | C_SH(C_DSUSP) | C_SH(C_EOL) | C_SH(C_DISCARD) | + C_SH(C_PGOFF) | C_SH(C_PAGE) | C_SH(C_STATUS)), 0} + }, + { + {"iflag:", 0, IXON | IXOFF | INLCR | ICRNL}, + {"oflag:", 0, 0}, + {"cflag:", 0, 0}, + {"lflag:", 0, ISIG | IEXTEN}, + {"chars:", 0, 0}, + } }; -private ttychar_t ttychar = { - { - CINTR, CQUIT, CERASE, CKILL, - CEOF, CEOL, CEOL2, CSWTCH, - CDSWTCH, CERASE2, CSTART, CSTOP, - CWERASE, CSUSP, CDSUSP, CREPRINT, - CDISCARD, CLNEXT, CSTATUS, CPAGE, - CPGOFF, CKILL2, CBRK, CMIN, - CTIME - }, - { - CINTR, CQUIT, CERASE, CKILL, - _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, - _POSIX_VDISABLE, CERASE2, CSTART, CSTOP, - _POSIX_VDISABLE, CSUSP, _POSIX_VDISABLE, _POSIX_VDISABLE, - CDISCARD, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, - _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, 1, - 0 - }, - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0 - } +private const ttychar_t ttychar = { + { + CINTR, CQUIT, CERASE, CKILL, + CEOF, CEOL, CEOL2, CSWTCH, + CDSWTCH, CERASE2, CSTART, CSTOP, + CWERASE, CSUSP, CDSUSP, CREPRINT, + CDISCARD, CLNEXT, CSTATUS, CPAGE, + CPGOFF, CKILL2, CBRK, CMIN, + CTIME + }, + { + CINTR, CQUIT, CERASE, CKILL, + _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, + _POSIX_VDISABLE, CERASE2, CSTART, CSTOP, + _POSIX_VDISABLE, CSUSP, _POSIX_VDISABLE, _POSIX_VDISABLE, + CDISCARD, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, + _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, 1, + 0 + }, + { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0 + } }; -private ttymap_t tty_map[] = { +private const ttymap_t tty_map[] = { #ifdef VERASE - { C_ERASE, VERASE, - { ED_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR } }, + {C_ERASE, VERASE, + {ED_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 } }, + {C_ERASE2, VERASE2, + {ED_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}}, #endif /* VERASE2 */ #ifdef VKILL - { C_KILL, VKILL, - { EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED } }, + {C_KILL, VKILL, + {EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}}, #endif /* VKILL */ #ifdef VKILL2 - { C_KILL2, VKILL2, - { EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED } }, + {C_KILL2, VKILL2, + {EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}}, #endif /* VKILL2 */ #ifdef VEOF - { C_EOF, VEOF, - { EM_DELETE_OR_LIST, VI_LIST_OR_EOF, ED_UNASSIGNED } }, + {C_EOF, VEOF, + {EM_DELETE_OR_LIST, VI_LIST_OR_EOF, ED_UNASSIGNED}}, #endif /* VEOF */ #ifdef VWERASE - { C_WERASE, VWERASE, - { ED_DELETE_PREV_WORD, ED_DELETE_PREV_WORD, ED_PREV_WORD } }, + {C_WERASE, VWERASE, + {ED_DELETE_PREV_WORD, ED_DELETE_PREV_WORD, ED_PREV_WORD}}, #endif /* VWERASE */ #ifdef VREPRINT - { C_REPRINT, VREPRINT, - { ED_REDISPLAY, ED_INSERT, ED_REDISPLAY } }, + {C_REPRINT, VREPRINT, + {ED_REDISPLAY, ED_INSERT, ED_REDISPLAY}}, #endif /* VREPRINT */ #ifdef VLNEXT - { C_LNEXT, VLNEXT, - { ED_QUOTED_INSERT, ED_QUOTED_INSERT, ED_UNASSIGNED } }, + {C_LNEXT, VLNEXT, + {ED_QUOTED_INSERT, ED_QUOTED_INSERT, ED_UNASSIGNED}}, +#endif /* VLNEXT */ + {-1, -1, + {ED_UNASSIGNED, ED_UNASSIGNED, ED_UNASSIGNED}} +}; + +private const ttymodes_t ttymodes[] = { +#ifdef IGNBRK + {"ignbrk", IGNBRK, MD_INP}, +#endif /* IGNBRK */ +#ifdef BRKINT + {"brkint", BRKINT, MD_INP}, +#endif /* BRKINT */ +#ifdef IGNPAR + {"ignpar", IGNPAR, MD_INP}, +#endif /* IGNPAR */ +#ifdef PARMRK + {"parmrk", PARMRK, MD_INP}, +#endif /* PARMRK */ +#ifdef INPCK + {"inpck", INPCK, MD_INP}, +#endif /* INPCK */ +#ifdef ISTRIP + {"istrip", ISTRIP, MD_INP}, +#endif /* ISTRIP */ +#ifdef INLCR + {"inlcr", INLCR, MD_INP}, +#endif /* INLCR */ +#ifdef IGNCR + {"igncr", IGNCR, MD_INP}, +#endif /* IGNCR */ +#ifdef ICRNL + {"icrnl", ICRNL, MD_INP}, +#endif /* ICRNL */ +#ifdef IUCLC + {"iuclc", IUCLC, MD_INP}, +#endif /* IUCLC */ +#ifdef IXON + {"ixon", IXON, MD_INP}, +#endif /* IXON */ +#ifdef IXANY + {"ixany", IXANY, MD_INP}, +#endif /* IXANY */ +#ifdef IXOFF + {"ixoff", IXOFF, MD_INP}, +#endif /* IXOFF */ +#ifdef IMAXBEL + {"imaxbel", IMAXBEL, MD_INP}, +#endif /* IMAXBEL */ + +#ifdef OPOST + {"opost", OPOST, MD_OUT}, +#endif /* OPOST */ +#ifdef OLCUC + {"olcuc", OLCUC, MD_OUT}, +#endif /* OLCUC */ +#ifdef ONLCR + {"onlcr", ONLCR, MD_OUT}, +#endif /* ONLCR */ +#ifdef OCRNL + {"ocrnl", OCRNL, MD_OUT}, +#endif /* OCRNL */ +#ifdef ONOCR + {"onocr", ONOCR, MD_OUT}, +#endif /* ONOCR */ +#ifdef ONOEOT + {"onoeot", ONOEOT, MD_OUT}, +#endif /* ONOEOT */ +#ifdef ONLRET + {"onlret", ONLRET, MD_OUT}, +#endif /* ONLRET */ +#ifdef OFILL + {"ofill", OFILL, MD_OUT}, +#endif /* OFILL */ +#ifdef OFDEL + {"ofdel", OFDEL, MD_OUT}, +#endif /* OFDEL */ +#ifdef NLDLY + {"nldly", NLDLY, MD_OUT}, +#endif /* NLDLY */ +#ifdef CRDLY + {"crdly", CRDLY, MD_OUT}, +#endif /* CRDLY */ +#ifdef TABDLY + {"tabdly", TABDLY, MD_OUT}, +#endif /* TABDLY */ +#ifdef XTABS + {"xtabs", XTABS, MD_OUT}, +#endif /* XTABS */ +#ifdef BSDLY + {"bsdly", BSDLY, MD_OUT}, +#endif /* BSDLY */ +#ifdef VTDLY + {"vtdly", VTDLY, MD_OUT}, +#endif /* VTDLY */ +#ifdef FFDLY + {"ffdly", FFDLY, MD_OUT}, +#endif /* FFDLY */ +#ifdef PAGEOUT + {"pageout", PAGEOUT, MD_OUT}, +#endif /* PAGEOUT */ +#ifdef WRAP + {"wrap", WRAP, MD_OUT}, +#endif /* WRAP */ + +#ifdef CIGNORE + {"cignore", CIGNORE, MD_CTL}, +#endif /* CBAUD */ +#ifdef CBAUD + {"cbaud", CBAUD, MD_CTL}, +#endif /* CBAUD */ +#ifdef CSTOPB + {"cstopb", CSTOPB, MD_CTL}, +#endif /* CSTOPB */ +#ifdef CREAD + {"cread", CREAD, MD_CTL}, +#endif /* CREAD */ +#ifdef PARENB + {"parenb", PARENB, MD_CTL}, +#endif /* PARENB */ +#ifdef PARODD + {"parodd", PARODD, MD_CTL}, +#endif /* PARODD */ +#ifdef HUPCL + {"hupcl", HUPCL, MD_CTL}, +#endif /* HUPCL */ +#ifdef CLOCAL + {"clocal", CLOCAL, MD_CTL}, +#endif /* CLOCAL */ +#ifdef LOBLK + {"loblk", LOBLK, MD_CTL}, +#endif /* LOBLK */ +#ifdef CIBAUD + {"cibaud", CIBAUD, MD_CTL}, +#endif /* CIBAUD */ +#ifdef CRTSCTS +#ifdef CCTS_OFLOW + {"ccts_oflow", CCTS_OFLOW, MD_CTL}, +#else + {"crtscts", CRTSCTS, MD_CTL}, +#endif /* CCTS_OFLOW */ +#endif /* CRTSCTS */ +#ifdef CRTS_IFLOW + {"crts_iflow", CRTS_IFLOW, MD_CTL}, +#endif /* CRTS_IFLOW */ +#ifdef CDTRCTS + {"cdtrcts", CDTRCTS, MD_CTL}, +#endif /* CDTRCTS */ +#ifdef MDMBUF + {"mdmbuf", MDMBUF, MD_CTL}, +#endif /* MDMBUF */ +#ifdef RCV1EN + {"rcv1en", RCV1EN, MD_CTL}, +#endif /* RCV1EN */ +#ifdef XMT1EN + {"xmt1en", XMT1EN, MD_CTL}, +#endif /* XMT1EN */ + +#ifdef ISIG + {"isig", ISIG, MD_LIN}, +#endif /* ISIG */ +#ifdef ICANON + {"icanon", ICANON, MD_LIN}, +#endif /* ICANON */ +#ifdef XCASE + {"xcase", XCASE, MD_LIN}, +#endif /* XCASE */ +#ifdef ECHO + {"echo", ECHO, MD_LIN}, +#endif /* ECHO */ +#ifdef ECHOE + {"echoe", ECHOE, MD_LIN}, +#endif /* ECHOE */ +#ifdef ECHOK + {"echok", ECHOK, MD_LIN}, +#endif /* ECHOK */ +#ifdef ECHONL + {"echonl", ECHONL, MD_LIN}, +#endif /* ECHONL */ +#ifdef NOFLSH + {"noflsh", NOFLSH, MD_LIN}, +#endif /* NOFLSH */ +#ifdef TOSTOP + {"tostop", TOSTOP, MD_LIN}, +#endif /* TOSTOP */ +#ifdef ECHOCTL + {"echoctl", ECHOCTL, MD_LIN}, +#endif /* ECHOCTL */ +#ifdef ECHOPRT + {"echoprt", ECHOPRT, MD_LIN}, +#endif /* ECHOPRT */ +#ifdef ECHOKE + {"echoke", ECHOKE, MD_LIN}, +#endif /* ECHOKE */ +#ifdef DEFECHO + {"defecho", DEFECHO, MD_LIN}, +#endif /* DEFECHO */ +#ifdef FLUSHO + {"flusho", FLUSHO, MD_LIN}, +#endif /* FLUSHO */ +#ifdef PENDIN + {"pendin", PENDIN, MD_LIN}, +#endif /* PENDIN */ +#ifdef IEXTEN + {"iexten", IEXTEN, MD_LIN}, +#endif /* IEXTEN */ +#ifdef NOKERNINFO + {"nokerninfo", NOKERNINFO, MD_LIN}, +#endif /* NOKERNINFO */ +#ifdef ALTWERASE + {"altwerase", ALTWERASE, MD_LIN}, +#endif /* ALTWERASE */ +#ifdef EXTPROC + {"extproc", EXTPROC, MD_LIN}, +#endif /* EXTPROC */ + +#if defined(VINTR) + {"intr", C_SH(C_INTR), MD_CHAR}, +#endif /* VINTR */ +#if defined(VQUIT) + {"quit", C_SH(C_QUIT), MD_CHAR}, +#endif /* VQUIT */ +#if defined(VERASE) + {"erase", C_SH(C_ERASE), MD_CHAR}, +#endif /* VERASE */ +#if defined(VKILL) + {"kill", C_SH(C_KILL), MD_CHAR}, +#endif /* VKILL */ +#if defined(VEOF) + {"eof", C_SH(C_EOF), MD_CHAR}, +#endif /* VEOF */ +#if defined(VEOL) + {"eol", C_SH(C_EOL), MD_CHAR}, +#endif /* VEOL */ +#if defined(VEOL2) + {"eol2", C_SH(C_EOL2), MD_CHAR}, +#endif /* VEOL2 */ +#if defined(VSWTCH) + {"swtch", C_SH(C_SWTCH), MD_CHAR}, +#endif /* VSWTCH */ +#if defined(VDSWTCH) + {"dswtch", C_SH(C_DSWTCH), MD_CHAR}, +#endif /* VDSWTCH */ +#if defined(VERASE2) + {"erase2", C_SH(C_ERASE2), MD_CHAR}, +#endif /* VERASE2 */ +#if defined(VSTART) + {"start", C_SH(C_START), MD_CHAR}, +#endif /* VSTART */ +#if defined(VSTOP) + {"stop", C_SH(C_STOP), MD_CHAR}, +#endif /* VSTOP */ +#if defined(VWERASE) + {"werase", C_SH(C_WERASE), MD_CHAR}, +#endif /* VWERASE */ +#if defined(VSUSP) + {"susp", C_SH(C_SUSP), MD_CHAR}, +#endif /* VSUSP */ +#if defined(VDSUSP) + {"dsusp", C_SH(C_DSUSP), MD_CHAR}, +#endif /* VDSUSP */ +#if defined(VREPRINT) + {"reprint", C_SH(C_REPRINT), MD_CHAR}, +#endif /* VREPRINT */ +#if defined(VDISCARD) + {"discard", C_SH(C_DISCARD), MD_CHAR}, +#endif /* VDISCARD */ +#if defined(VLNEXT) + {"lnext", C_SH(C_LNEXT), MD_CHAR}, #endif /* VLNEXT */ - { -1, -1, - { ED_UNASSIGNED, ED_UNASSIGNED, ED_UNASSIGNED } } - }; - -private ttymodes_t ttymodes[] = { -# ifdef IGNBRK - { "ignbrk", IGNBRK, M_INP }, -# endif /* IGNBRK */ -# ifdef BRKINT - { "brkint", BRKINT, M_INP }, -# endif /* BRKINT */ -# ifdef IGNPAR - { "ignpar", IGNPAR, M_INP }, -# endif /* IGNPAR */ -# ifdef PARMRK - { "parmrk", PARMRK, M_INP }, -# endif /* PARMRK */ -# ifdef INPCK - { "inpck", INPCK, M_INP }, -# endif /* INPCK */ -# ifdef ISTRIP - { "istrip", ISTRIP, M_INP }, -# endif /* ISTRIP */ -# ifdef INLCR - { "inlcr", INLCR, M_INP }, -# endif /* INLCR */ -# ifdef IGNCR - { "igncr", IGNCR, M_INP }, -# endif /* IGNCR */ -# ifdef ICRNL - { "icrnl", ICRNL, M_INP }, -# endif /* ICRNL */ -# ifdef IUCLC - { "iuclc", IUCLC, M_INP }, -# endif /* IUCLC */ -# ifdef IXON - { "ixon", IXON, M_INP }, -# endif /* IXON */ -# ifdef IXANY - { "ixany", IXANY, M_INP }, -# endif /* IXANY */ -# ifdef IXOFF - { "ixoff", IXOFF, M_INP }, -# endif /* IXOFF */ -# ifdef IMAXBEL - { "imaxbel",IMAXBEL,M_INP }, -# endif /* IMAXBEL */ - -# ifdef OPOST - { "opost", OPOST, M_OUT }, -# endif /* OPOST */ -# ifdef OLCUC - { "olcuc", OLCUC, M_OUT }, -# endif /* OLCUC */ -# ifdef ONLCR - { "onlcr", ONLCR, M_OUT }, -# endif /* ONLCR */ -# ifdef OCRNL - { "ocrnl", OCRNL, M_OUT }, -# endif /* OCRNL */ -# ifdef ONOCR - { "onocr", ONOCR, M_OUT }, -# endif /* ONOCR */ -# ifdef ONOEOT - { "onoeot", ONOEOT, M_OUT }, -# endif /* ONOEOT */ -# ifdef ONLRET - { "onlret", ONLRET, M_OUT }, -# endif /* ONLRET */ -# ifdef OFILL - { "ofill", OFILL, M_OUT }, -# endif /* OFILL */ -# ifdef OFDEL - { "ofdel", OFDEL, M_OUT }, -# endif /* OFDEL */ -# ifdef NLDLY - { "nldly", NLDLY, M_OUT }, -# endif /* NLDLY */ -# ifdef CRDLY - { "crdly", CRDLY, M_OUT }, -# endif /* CRDLY */ -# ifdef TABDLY - { "tabdly", TABDLY, M_OUT }, -# endif /* TABDLY */ -# ifdef XTABS - { "xtabs", XTABS, M_OUT }, -# endif /* XTABS */ -# ifdef BSDLY - { "bsdly", BSDLY, M_OUT }, -# endif /* BSDLY */ -# ifdef VTDLY - { "vtdly", VTDLY, M_OUT }, -# endif /* VTDLY */ -# ifdef FFDLY - { "ffdly", FFDLY, M_OUT }, -# endif /* FFDLY */ -# ifdef PAGEOUT - { "pageout",PAGEOUT,M_OUT }, -# endif /* PAGEOUT */ -# ifdef WRAP - { "wrap", WRAP, M_OUT }, -# endif /* WRAP */ - -# ifdef CIGNORE - { "cignore",CIGNORE,M_CTL }, -# endif /* CBAUD */ -# ifdef CBAUD - { "cbaud", CBAUD, M_CTL }, -# endif /* CBAUD */ -# ifdef CSTOPB - { "cstopb", CSTOPB, M_CTL }, -# endif /* CSTOPB */ -# ifdef CREAD - { "cread", CREAD, M_CTL }, -# endif /* CREAD */ -# ifdef PARENB - { "parenb", PARENB, M_CTL }, -# endif /* PARENB */ -# ifdef PARODD - { "parodd", PARODD, M_CTL }, -# endif /* PARODD */ -# ifdef HUPCL - { "hupcl", HUPCL, M_CTL }, -# endif /* HUPCL */ -# ifdef CLOCAL - { "clocal", CLOCAL, M_CTL }, -# endif /* CLOCAL */ -# ifdef LOBLK - { "loblk", LOBLK, M_CTL }, -# endif /* LOBLK */ -# ifdef CIBAUD - { "cibaud", CIBAUD, M_CTL }, -# endif /* CIBAUD */ -# ifdef CRTSCTS -# ifdef CCTS_OFLOW - { "ccts_oflow",CCTS_OFLOW,M_CTL }, -# else - { "crtscts",CRTSCTS,M_CTL }, -# endif /* CCTS_OFLOW */ -# endif /* CRTSCTS */ -# ifdef CRTS_IFLOW - { "crts_iflow",CRTS_IFLOW,M_CTL }, -# endif /* CRTS_IFLOW */ -# ifdef MDMBUF - { "mdmbuf", MDMBUF, M_CTL }, -# endif /* MDMBUF */ -# ifdef RCV1EN - { "rcv1en", RCV1EN, M_CTL }, -# endif /* RCV1EN */ -# ifdef XMT1EN - { "xmt1en", XMT1EN, M_CTL }, -# endif /* XMT1EN */ - -# ifdef ISIG - { "isig", ISIG, M_LIN }, -# endif /* ISIG */ -# ifdef ICANON - { "icanon", ICANON, M_LIN }, -# endif /* ICANON */ -# ifdef XCASE - { "xcase", XCASE, M_LIN }, -# endif /* XCASE */ -# ifdef ECHO - { "echo", ECHO, M_LIN }, -# endif /* ECHO */ -# ifdef ECHOE - { "echoe", ECHOE, M_LIN }, -# endif /* ECHOE */ -# ifdef ECHOK - { "echok", ECHOK, M_LIN }, -# endif /* ECHOK */ -# ifdef ECHONL - { "echonl", ECHONL, M_LIN }, -# endif /* ECHONL */ -# ifdef NOFLSH - { "noflsh", NOFLSH, M_LIN }, -# endif /* NOFLSH */ -# ifdef TOSTOP - { "tostop", TOSTOP, M_LIN }, -# endif /* TOSTOP */ -# ifdef ECHOCTL - { "echoctl",ECHOCTL,M_LIN }, -# endif /* ECHOCTL */ -# ifdef ECHOPRT - { "echoprt",ECHOPRT,M_LIN }, -# endif /* ECHOPRT */ -# ifdef ECHOKE - { "echoke", ECHOKE, M_LIN }, -# endif /* ECHOKE */ -# ifdef DEFECHO - { "defecho",DEFECHO,M_LIN }, -# endif /* DEFECHO */ -# ifdef FLUSHO - { "flusho", FLUSHO, M_LIN }, -# endif /* FLUSHO */ -# ifdef PENDIN - { "pendin", PENDIN, M_LIN }, -# endif /* PENDIN */ -# ifdef IEXTEN - { "iexten", IEXTEN, M_LIN }, -# endif /* IEXTEN */ -# ifdef NOKERNINFO - { "nokerninfo",NOKERNINFO,M_LIN }, -# endif /* NOKERNINFO */ -# ifdef ALTWERASE - { "altwerase",ALTWERASE,M_LIN }, -# endif /* ALTWERASE */ -# ifdef EXTPROC - { "extproc",EXTPROC, M_LIN }, -# endif /* EXTPROC */ - -# if defined(VINTR) - { "intr", C_SH(C_INTR), M_CHAR }, -# endif /* VINTR */ -# if defined(VQUIT) - { "quit", C_SH(C_QUIT), M_CHAR }, -# endif /* VQUIT */ -# if defined(VERASE) - { "erase", C_SH(C_ERASE), M_CHAR }, -# endif /* VERASE */ -# if defined(VKILL) - { "kill", C_SH(C_KILL), M_CHAR }, -# endif /* VKILL */ -# if defined(VEOF) - { "eof", C_SH(C_EOF), M_CHAR }, -# endif /* VEOF */ -# if defined(VEOL) - { "eol", C_SH(C_EOL), M_CHAR }, -# endif /* VEOL */ -# if defined(VEOL2) - { "eol2", C_SH(C_EOL2), M_CHAR }, -# endif /* VEOL2 */ -# if defined(VSWTCH) - { "swtch", C_SH(C_SWTCH), M_CHAR }, -# endif /* VSWTCH */ -# if defined(VDSWTCH) - { "dswtch", C_SH(C_DSWTCH), M_CHAR }, -# endif /* VDSWTCH */ -# if defined(VERASE2) - { "erase2", C_SH(C_ERASE2), M_CHAR }, -# endif /* VERASE2 */ -# if defined(VSTART) - { "start", C_SH(C_START), M_CHAR }, -# endif /* VSTART */ -# if defined(VSTOP) - { "stop", C_SH(C_STOP), M_CHAR }, -# endif /* VSTOP */ -# if defined(VWERASE) - { "werase", C_SH(C_WERASE), M_CHAR }, -# endif /* VWERASE */ -# if defined(VSUSP) - { "susp", C_SH(C_SUSP), M_CHAR }, -# endif /* VSUSP */ -# if defined(VDSUSP) - { "dsusp", C_SH(C_DSUSP), M_CHAR }, -# endif /* VDSUSP */ -# if defined(VREPRINT) - { "reprint", C_SH(C_REPRINT),M_CHAR }, -# endif /* VREPRINT */ -# if defined(VDISCARD) - { "discard", C_SH(C_DISCARD),M_CHAR }, -# endif /* VDISCARD */ -# if defined(VLNEXT) - { "lnext", C_SH(C_LNEXT), M_CHAR }, -# endif /* VLNEXT */ -# if defined(VSTATUS) - { "status", C_SH(C_STATUS), M_CHAR }, -# endif /* VSTATUS */ -# if defined(VPAGE) - { "page", C_SH(C_PAGE), M_CHAR }, -# endif /* VPAGE */ -# if defined(VPGOFF) - { "pgoff", C_SH(C_PGOFF), M_CHAR }, -# endif /* VPGOFF */ -# if defined(VKILL2) - { "kill2", C_SH(C_KILL2), M_CHAR }, -# endif /* VKILL2 */ -# if defined(VBRK) - { "brk", C_SH(C_BRK), M_CHAR }, -# endif /* VBRK */ -# if defined(VMIN) - { "min", C_SH(C_MIN), M_CHAR }, -# endif /* VMIN */ -# if defined(VTIME) - { "time", C_SH(C_TIME), M_CHAR }, -# endif /* VTIME */ - { NULL, 0, -1 }, +#if defined(VSTATUS) + {"status", C_SH(C_STATUS), MD_CHAR}, +#endif /* VSTATUS */ +#if defined(VPAGE) + {"page", C_SH(C_PAGE), MD_CHAR}, +#endif /* VPAGE */ +#if defined(VPGOFF) + {"pgoff", C_SH(C_PGOFF), MD_CHAR}, +#endif /* VPGOFF */ +#if defined(VKILL2) + {"kill2", C_SH(C_KILL2), MD_CHAR}, +#endif /* VKILL2 */ +#if defined(VBRK) + {"brk", C_SH(C_BRK), MD_CHAR}, +#endif /* VBRK */ +#if defined(VMIN) + {"min", C_SH(C_MIN), MD_CHAR}, +#endif /* VMIN */ +#if defined(VTIME) + {"time", C_SH(C_TIME), MD_CHAR}, +#endif /* VTIME */ + {NULL, 0, -1}, }; -#define tty_getty(el, td) tcgetattr((el)->el_infd, (td)) -#define tty_setty(el, td) tcsetattr((el)->el_infd, TCSADRAIN, (td)) +#define tty_getty(el, td) tcgetattr((el)->el_infd, (td)) +#define tty_setty(el, td) tcsetattr((el)->el_infd, TCSADRAIN, (td)) -#define tty__gettabs(td) ((((td)->c_oflag & TAB3) == TAB3) ? 0 : 1) -#define tty__geteightbit(td) (((td)->c_cflag & CSIZE) == CS8) -#define tty__cooked_mode(td) ((td)->c_lflag & ICANON) +#define tty__gettabs(td) ((((td)->c_oflag & TAB3) == TAB3) ? 0 : 1) +#define tty__geteightbit(td) (((td)->c_cflag & CSIZE) == CS8) +#define tty__cooked_mode(td) ((td)->c_lflag & ICANON) -private void tty__getchar(struct termios *, unsigned char *); -private void tty__setchar(struct termios *, unsigned char *); -private speed_t tty__getspeed(struct termios *); -private int tty_setup(EditLine *); +private void tty__getchar(struct termios *, unsigned char *); +private void tty__setchar(struct termios *, unsigned char *); +private speed_t tty__getspeed(struct termios *); +private int tty_setup(EditLine *); -#define t_qu t_ts +#define t_qu t_ts /* tty_setup(): * Get the tty parameters and initialize the editing state */ -private int -tty_setup(el) - EditLine *el; +private int +tty_setup(EditLine *el) { - int rst = 1; - if (tty_getty(el, &el->el_tty.t_ed) == -1) { + int rst = 1; + + if (el->el_flags & EDIT_DISABLED) + return (0); + + if (tty_getty(el, &el->el_tty.t_ed) == -1) { #ifdef DEBUG_TTY - (void)fprintf(el->el_errfile, - "tty_setup: tty_getty: %s\n", strerror(errno)); + (void) fprintf(el->el_errfile, + "tty_setup: tty_getty: %s\n", strerror(errno)); #endif /* DEBUG_TTY */ - return(-1); - } - el->el_tty.t_ts = el->el_tty.t_ex = el->el_tty.t_ed; - - el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ex); - el->el_tty.t_tabs = tty__gettabs(&el->el_tty.t_ex); - el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ex); - - el->el_tty.t_ex.c_iflag &= ~el->el_tty.t_t[EX_IO][M_INP].t_clrmask; - el->el_tty.t_ex.c_iflag |= el->el_tty.t_t[EX_IO][M_INP].t_setmask; - - el->el_tty.t_ex.c_oflag &= ~el->el_tty.t_t[EX_IO][M_OUT].t_clrmask; - el->el_tty.t_ex.c_oflag |= el->el_tty.t_t[EX_IO][M_OUT].t_setmask; - - el->el_tty.t_ex.c_cflag &= ~el->el_tty.t_t[EX_IO][M_CTL].t_clrmask; - el->el_tty.t_ex.c_cflag |= el->el_tty.t_t[EX_IO][M_CTL].t_setmask; - - el->el_tty.t_ex.c_lflag &= ~el->el_tty.t_t[EX_IO][M_LIN].t_clrmask; - el->el_tty.t_ex.c_lflag |= el->el_tty.t_t[EX_IO][M_LIN].t_setmask; - - /* - * Reset the tty chars to reasonable defaults - * If they are disabled, then enable them. - */ - if (rst) { - if (tty__cooked_mode(&el->el_tty.t_ts)) { - tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]); - /* - * Don't affect CMIN and CTIME for the editor mode - */ - for (rst = 0; rst < C_NCC - 2; rst++) - if (el->el_tty.t_c[TS_IO][rst] != el->el_tty.t_vdisable && - el->el_tty.t_c[ED_IO][rst] != el->el_tty.t_vdisable) - el->el_tty.t_c[ED_IO][rst] = el->el_tty.t_c[TS_IO][rst]; - for (rst = 0; rst < C_NCC; rst++) - if (el->el_tty.t_c[TS_IO][rst] != el->el_tty.t_vdisable && - el->el_tty.t_c[EX_IO][rst] != el->el_tty.t_vdisable) - el->el_tty.t_c[EX_IO][rst] = el->el_tty.t_c[TS_IO][rst]; - } - tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]); - if (tty_setty(el, &el->el_tty.t_ex) == -1) { + return (-1); + } + el->el_tty.t_ts = el->el_tty.t_ex = el->el_tty.t_ed; + + el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ex); + el->el_tty.t_tabs = tty__gettabs(&el->el_tty.t_ex); + el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ex); + + el->el_tty.t_ex.c_iflag &= ~el->el_tty.t_t[EX_IO][MD_INP].t_clrmask; + el->el_tty.t_ex.c_iflag |= el->el_tty.t_t[EX_IO][MD_INP].t_setmask; + + el->el_tty.t_ex.c_oflag &= ~el->el_tty.t_t[EX_IO][MD_OUT].t_clrmask; + el->el_tty.t_ex.c_oflag |= el->el_tty.t_t[EX_IO][MD_OUT].t_setmask; + + el->el_tty.t_ex.c_cflag &= ~el->el_tty.t_t[EX_IO][MD_CTL].t_clrmask; + el->el_tty.t_ex.c_cflag |= el->el_tty.t_t[EX_IO][MD_CTL].t_setmask; + + el->el_tty.t_ex.c_lflag &= ~el->el_tty.t_t[EX_IO][MD_LIN].t_clrmask; + el->el_tty.t_ex.c_lflag |= el->el_tty.t_t[EX_IO][MD_LIN].t_setmask; + + /* + * Reset the tty chars to reasonable defaults + * If they are disabled, then enable them. + */ + if (rst) { + if (tty__cooked_mode(&el->el_tty.t_ts)) { + tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]); + /* + * Don't affect CMIN and CTIME for the editor mode + */ + for (rst = 0; rst < C_NCC - 2; rst++) + if (el->el_tty.t_c[TS_IO][rst] != + el->el_tty.t_vdisable + && el->el_tty.t_c[ED_IO][rst] != + el->el_tty.t_vdisable) + el->el_tty.t_c[ED_IO][rst] = + el->el_tty.t_c[TS_IO][rst]; + for (rst = 0; rst < C_NCC; rst++) + if (el->el_tty.t_c[TS_IO][rst] != + el->el_tty.t_vdisable) + el->el_tty.t_c[EX_IO][rst] = + el->el_tty.t_c[TS_IO][rst]; + } + tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]); + if (tty_setty(el, &el->el_tty.t_ex) == -1) { #ifdef DEBUG_TTY - (void)fprintf(el->el_errfile, "tty_setup: tty_setty: %s\n", - strerror(errno)); + (void) fprintf(el->el_errfile, + "tty_setup: tty_setty: %s\n", + strerror(errno)); #endif /* DEBUG_TTY */ - return(-1); - } - } - else - tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]); + return (-1); + } + } else + tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]); - el->el_tty.t_ed.c_iflag &= ~el->el_tty.t_t[ED_IO][M_INP].t_clrmask; - el->el_tty.t_ed.c_iflag |= el->el_tty.t_t[ED_IO][M_INP].t_setmask; + el->el_tty.t_ed.c_iflag &= ~el->el_tty.t_t[ED_IO][MD_INP].t_clrmask; + el->el_tty.t_ed.c_iflag |= el->el_tty.t_t[ED_IO][MD_INP].t_setmask; - el->el_tty.t_ed.c_oflag &= ~el->el_tty.t_t[ED_IO][M_OUT].t_clrmask; - el->el_tty.t_ed.c_oflag |= el->el_tty.t_t[ED_IO][M_OUT].t_setmask; + el->el_tty.t_ed.c_oflag &= ~el->el_tty.t_t[ED_IO][MD_OUT].t_clrmask; + el->el_tty.t_ed.c_oflag |= el->el_tty.t_t[ED_IO][MD_OUT].t_setmask; - el->el_tty.t_ed.c_cflag &= ~el->el_tty.t_t[ED_IO][M_CTL].t_clrmask; - el->el_tty.t_ed.c_cflag |= el->el_tty.t_t[ED_IO][M_CTL].t_setmask; + el->el_tty.t_ed.c_cflag &= ~el->el_tty.t_t[ED_IO][MD_CTL].t_clrmask; + el->el_tty.t_ed.c_cflag |= el->el_tty.t_t[ED_IO][MD_CTL].t_setmask; - el->el_tty.t_ed.c_lflag &= ~el->el_tty.t_t[ED_IO][M_LIN].t_clrmask; - el->el_tty.t_ed.c_lflag |= el->el_tty.t_t[ED_IO][M_LIN].t_setmask; + el->el_tty.t_ed.c_lflag &= ~el->el_tty.t_t[ED_IO][MD_LIN].t_clrmask; + el->el_tty.t_ed.c_lflag |= el->el_tty.t_t[ED_IO][MD_LIN].t_setmask; - tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]); - return 0; + tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]); + tty_bind_char(el, 1); + return (0); } protected int -tty_init(el) - EditLine *el; +tty_init(EditLine *el) { - el->el_tty.t_mode = EX_IO; - el->el_tty.t_vdisable = _POSIX_VDISABLE; - (void)memcpy(el->el_tty.t_t, ttyperm, sizeof(ttyperm_t)); - (void)memcpy(el->el_tty.t_c, ttychar, sizeof(ttychar_t)); - return tty_setup(el); -} /* end tty_init */ + + el->el_tty.t_mode = EX_IO; + el->el_tty.t_vdisable = _POSIX_VDISABLE; + (void) memcpy(el->el_tty.t_t, ttyperm, sizeof(ttyperm_t)); + (void) memcpy(el->el_tty.t_c, ttychar, sizeof(ttychar_t)); + return (tty_setup(el)); +} /* tty_end(): @@ -554,10 +565,10 @@ tty_init(el) */ protected void /*ARGSUSED*/ -tty_end(el) - EditLine *el; +tty_end(EditLine *el __attribute__((__unused__))) { - /* XXX: Maybe reset to an initial state? */ + + /* XXX: Maybe reset to an initial state? */ } @@ -565,560 +576,582 @@ tty_end(el) * Get the tty speed */ private speed_t -tty__getspeed(td) - struct termios *td; +tty__getspeed(struct termios *td) { - speed_t spd; + speed_t spd; - if ((spd = cfgetispeed(td)) == 0) - spd = cfgetospeed(td); - return spd; -} /* end tty__getspeed */ + if ((spd = cfgetispeed(td)) == 0) + spd = cfgetospeed(td); + return (spd); +} /* tty__getchar(): * Get the tty characters */ private void -tty__getchar(td, s) - struct termios *td; - unsigned char *s; -{ -# ifdef VINTR - s[C_INTR] = td->c_cc[VINTR]; -# endif /* VINTR */ -# ifdef VQUIT - s[C_QUIT] = td->c_cc[VQUIT]; -# endif /* VQUIT */ -# ifdef VERASE - s[C_ERASE] = td->c_cc[VERASE]; -# endif /* VERASE */ -# ifdef VKILL - s[C_KILL] = td->c_cc[VKILL]; -# endif /* VKILL */ -# ifdef VEOF - s[C_EOF] = td->c_cc[VEOF]; -# endif /* VEOF */ -# ifdef VEOL - s[C_EOL] = td->c_cc[VEOL]; -# endif /* VEOL */ -# ifdef VEOL2 - s[C_EOL2] = td->c_cc[VEOL2]; -# endif /* VEOL2 */ -# ifdef VSWTCH - s[C_SWTCH] = td->c_cc[VSWTCH]; -# endif /* VSWTCH */ -# ifdef VDSWTCH - s[C_DSWTCH] = td->c_cc[VDSWTCH]; -# endif /* VDSWTCH */ -# ifdef VERASE2 - s[C_ERASE2] = td->c_cc[VERASE2]; -# endif /* VERASE2 */ -# ifdef VSTART - s[C_START] = td->c_cc[VSTART]; -# endif /* VSTART */ -# ifdef VSTOP - s[C_STOP] = td->c_cc[VSTOP]; -# endif /* VSTOP */ -# ifdef VWERASE - s[C_WERASE] = td->c_cc[VWERASE]; -# endif /* VWERASE */ -# ifdef VSUSP - s[C_SUSP] = td->c_cc[VSUSP]; -# endif /* VSUSP */ -# ifdef VDSUSP - s[C_DSUSP] = td->c_cc[VDSUSP]; -# endif /* VDSUSP */ -# ifdef VREPRINT - s[C_REPRINT]= td->c_cc[VREPRINT]; -# endif /* VREPRINT */ -# ifdef VDISCARD - s[C_DISCARD]= td->c_cc[VDISCARD]; -# endif /* VDISCARD */ -# ifdef VLNEXT - s[C_LNEXT] = td->c_cc[VLNEXT]; -# endif /* VLNEXT */ -# ifdef VSTATUS - s[C_STATUS] = td->c_cc[VSTATUS]; -# endif /* VSTATUS */ -# ifdef VPAGE - s[C_PAGE] = td->c_cc[VPAGE]; -# endif /* VPAGE */ -# ifdef VPGOFF - s[C_PGOFF] = td->c_cc[VPGOFF]; -# endif /* VPGOFF */ -# ifdef VKILL2 - s[C_KILL2] = td->c_cc[VKILL2]; -# endif /* KILL2 */ -# ifdef VMIN - s[C_MIN] = td->c_cc[VMIN]; -# endif /* VMIN */ -# ifdef VTIME - s[C_TIME] = td->c_cc[VTIME]; -# endif /* VTIME */ -} /* tty__getchar */ +tty__getchar(struct termios *td, unsigned char *s) +{ + +#ifdef VINTR + s[C_INTR] = td->c_cc[VINTR]; +#endif /* VINTR */ +#ifdef VQUIT + s[C_QUIT] = td->c_cc[VQUIT]; +#endif /* VQUIT */ +#ifdef VERASE + s[C_ERASE] = td->c_cc[VERASE]; +#endif /* VERASE */ +#ifdef VKILL + s[C_KILL] = td->c_cc[VKILL]; +#endif /* VKILL */ +#ifdef VEOF + s[C_EOF] = td->c_cc[VEOF]; +#endif /* VEOF */ +#ifdef VEOL + s[C_EOL] = td->c_cc[VEOL]; +#endif /* VEOL */ +#ifdef VEOL2 + s[C_EOL2] = td->c_cc[VEOL2]; +#endif /* VEOL2 */ +#ifdef VSWTCH + s[C_SWTCH] = td->c_cc[VSWTCH]; +#endif /* VSWTCH */ +#ifdef VDSWTCH + s[C_DSWTCH] = td->c_cc[VDSWTCH]; +#endif /* VDSWTCH */ +#ifdef VERASE2 + s[C_ERASE2] = td->c_cc[VERASE2]; +#endif /* VERASE2 */ +#ifdef VSTART + s[C_START] = td->c_cc[VSTART]; +#endif /* VSTART */ +#ifdef VSTOP + s[C_STOP] = td->c_cc[VSTOP]; +#endif /* VSTOP */ +#ifdef VWERASE + s[C_WERASE] = td->c_cc[VWERASE]; +#endif /* VWERASE */ +#ifdef VSUSP + s[C_SUSP] = td->c_cc[VSUSP]; +#endif /* VSUSP */ +#ifdef VDSUSP + s[C_DSUSP] = td->c_cc[VDSUSP]; +#endif /* VDSUSP */ +#ifdef VREPRINT + s[C_REPRINT] = td->c_cc[VREPRINT]; +#endif /* VREPRINT */ +#ifdef VDISCARD + s[C_DISCARD] = td->c_cc[VDISCARD]; +#endif /* VDISCARD */ +#ifdef VLNEXT + s[C_LNEXT] = td->c_cc[VLNEXT]; +#endif /* VLNEXT */ +#ifdef VSTATUS + s[C_STATUS] = td->c_cc[VSTATUS]; +#endif /* VSTATUS */ +#ifdef VPAGE + s[C_PAGE] = td->c_cc[VPAGE]; +#endif /* VPAGE */ +#ifdef VPGOFF + s[C_PGOFF] = td->c_cc[VPGOFF]; +#endif /* VPGOFF */ +#ifdef VKILL2 + s[C_KILL2] = td->c_cc[VKILL2]; +#endif /* KILL2 */ +#ifdef VMIN + s[C_MIN] = td->c_cc[VMIN]; +#endif /* VMIN */ +#ifdef VTIME + s[C_TIME] = td->c_cc[VTIME]; +#endif /* VTIME */ +} /* tty__getchar */ /* tty__setchar(): * Set the tty characters */ private void -tty__setchar(td, s) - struct termios *td; - unsigned char *s; -{ -# ifdef VINTR - td->c_cc[VINTR] = s[C_INTR]; -# endif /* VINTR */ -# ifdef VQUIT - td->c_cc[VQUIT] = s[C_QUIT]; -# endif /* VQUIT */ -# ifdef VERASE - td->c_cc[VERASE] = s[C_ERASE]; -# endif /* VERASE */ -# ifdef VKILL - td->c_cc[VKILL] = s[C_KILL]; -# endif /* VKILL */ -# ifdef VEOF - td->c_cc[VEOF] = s[C_EOF]; -# endif /* VEOF */ -# ifdef VEOL - td->c_cc[VEOL] = s[C_EOL]; -# endif /* VEOL */ -# ifdef VEOL2 - td->c_cc[VEOL2] = s[C_EOL2]; -# endif /* VEOL2 */ -# ifdef VSWTCH - td->c_cc[VSWTCH] = s[C_SWTCH]; -# endif /* VSWTCH */ -# ifdef VDSWTCH - td->c_cc[VDSWTCH] = s[C_DSWTCH]; -# endif /* VDSWTCH */ -# ifdef VERASE2 - td->c_cc[VERASE2] = s[C_ERASE2]; -# endif /* VERASE2 */ -# ifdef VSTART - td->c_cc[VSTART] = s[C_START]; -# endif /* VSTART */ -# ifdef VSTOP - td->c_cc[VSTOP] = s[C_STOP]; -# endif /* VSTOP */ -# ifdef VWERASE - td->c_cc[VWERASE] = s[C_WERASE]; -# endif /* VWERASE */ -# ifdef VSUSP - td->c_cc[VSUSP] = s[C_SUSP]; -# endif /* VSUSP */ -# ifdef VDSUSP - td->c_cc[VDSUSP] = s[C_DSUSP]; -# endif /* VDSUSP */ -# ifdef VREPRINT - td->c_cc[VREPRINT] = s[C_REPRINT]; -# endif /* VREPRINT */ -# ifdef VDISCARD - td->c_cc[VDISCARD] = s[C_DISCARD]; -# endif /* VDISCARD */ -# ifdef VLNEXT - td->c_cc[VLNEXT] = s[C_LNEXT]; -# endif /* VLNEXT */ -# ifdef VSTATUS - td->c_cc[VSTATUS] = s[C_STATUS]; -# endif /* VSTATUS */ -# ifdef VPAGE - td->c_cc[VPAGE] = s[C_PAGE]; -# endif /* VPAGE */ -# ifdef VPGOFF - td->c_cc[VPGOFF] = s[C_PGOFF]; -# endif /* VPGOFF */ -# ifdef VKILL2 - td->c_cc[VKILL2] = s[C_KILL2]; -# endif /* VKILL2 */ -# ifdef VMIN - td->c_cc[VMIN] = s[C_MIN]; -# endif /* VMIN */ -# ifdef VTIME - td->c_cc[VTIME] = s[C_TIME]; -# endif /* VTIME */ -} /* tty__setchar */ +tty__setchar(struct termios *td, unsigned char *s) +{ + +#ifdef VINTR + td->c_cc[VINTR] = s[C_INTR]; +#endif /* VINTR */ +#ifdef VQUIT + td->c_cc[VQUIT] = s[C_QUIT]; +#endif /* VQUIT */ +#ifdef VERASE + td->c_cc[VERASE] = s[C_ERASE]; +#endif /* VERASE */ +#ifdef VKILL + td->c_cc[VKILL] = s[C_KILL]; +#endif /* VKILL */ +#ifdef VEOF + td->c_cc[VEOF] = s[C_EOF]; +#endif /* VEOF */ +#ifdef VEOL + td->c_cc[VEOL] = s[C_EOL]; +#endif /* VEOL */ +#ifdef VEOL2 + td->c_cc[VEOL2] = s[C_EOL2]; +#endif /* VEOL2 */ +#ifdef VSWTCH + td->c_cc[VSWTCH] = s[C_SWTCH]; +#endif /* VSWTCH */ +#ifdef VDSWTCH + td->c_cc[VDSWTCH] = s[C_DSWTCH]; +#endif /* VDSWTCH */ +#ifdef VERASE2 + td->c_cc[VERASE2] = s[C_ERASE2]; +#endif /* VERASE2 */ +#ifdef VSTART + td->c_cc[VSTART] = s[C_START]; +#endif /* VSTART */ +#ifdef VSTOP + td->c_cc[VSTOP] = s[C_STOP]; +#endif /* VSTOP */ +#ifdef VWERASE + td->c_cc[VWERASE] = s[C_WERASE]; +#endif /* VWERASE */ +#ifdef VSUSP + td->c_cc[VSUSP] = s[C_SUSP]; +#endif /* VSUSP */ +#ifdef VDSUSP + td->c_cc[VDSUSP] = s[C_DSUSP]; +#endif /* VDSUSP */ +#ifdef VREPRINT + td->c_cc[VREPRINT] = s[C_REPRINT]; +#endif /* VREPRINT */ +#ifdef VDISCARD + td->c_cc[VDISCARD] = s[C_DISCARD]; +#endif /* VDISCARD */ +#ifdef VLNEXT + td->c_cc[VLNEXT] = s[C_LNEXT]; +#endif /* VLNEXT */ +#ifdef VSTATUS + td->c_cc[VSTATUS] = s[C_STATUS]; +#endif /* VSTATUS */ +#ifdef VPAGE + td->c_cc[VPAGE] = s[C_PAGE]; +#endif /* VPAGE */ +#ifdef VPGOFF + td->c_cc[VPGOFF] = s[C_PGOFF]; +#endif /* VPGOFF */ +#ifdef VKILL2 + td->c_cc[VKILL2] = s[C_KILL2]; +#endif /* VKILL2 */ +#ifdef VMIN + td->c_cc[VMIN] = s[C_MIN]; +#endif /* VMIN */ +#ifdef VTIME + td->c_cc[VTIME] = s[C_TIME]; +#endif /* VTIME */ +} /* tty__setchar */ /* tty_bind_char(): * Rebind the editline functions */ protected void -tty_bind_char(el, force) - EditLine *el; - int force; +tty_bind_char(EditLine *el, int force) { - unsigned char *t_n = el->el_tty.t_c[ED_IO]; - unsigned char *t_o = el->el_tty.t_ed.c_cc; - unsigned char new[2], old[2]; - ttymap_t *tp; - el_action_t *dmap, *dalt, *map, *alt; - new[1] = old[1] = '\0'; - - - map = el->el_map.key; - alt = el->el_map.alt; - if (el->el_map.type == MAP_VI) { - dmap = el->el_map.vii; - dalt = el->el_map.vic; - } - else { - dmap = el->el_map.emacs; - dalt = NULL; - } - - for (tp = tty_map; tp->nch != -1; tp++) { - new[0] = t_n[tp->nch]; - old[0] = t_o[tp->och]; - if (new[0] == old[0] && !force) - continue; - /* Put the old default binding back, and set the new binding */ - key_clear(el, map, old); - map[old[0]] = dmap[old[0]]; - key_clear(el, map, new); - /* MAP_VI == 1, MAP_EMACS == 0... */ - map[new[0]] = tp->bind[el->el_map.type]; - if (dalt) { - key_clear(el, alt, old); - alt[old[0]] = dalt[old[0]]; - key_clear(el, alt, new); - alt[new[0]] = tp->bind[el->el_map.type+1]; + + unsigned char *t_n = el->el_tty.t_c[ED_IO]; + unsigned char *t_o = el->el_tty.t_ed.c_cc; + unsigned char new[2], old[2]; + const ttymap_t *tp; + el_action_t *map, *alt; + const el_action_t *dmap, *dalt; + new[1] = old[1] = '\0'; + + map = el->el_map.key; + alt = el->el_map.alt; + if (el->el_map.type == MAP_VI) { + dmap = el->el_map.vii; + dalt = el->el_map.vic; + } else { + dmap = el->el_map.emacs; + dalt = NULL; + } + + for (tp = tty_map; tp->nch != -1; tp++) { + new[0] = t_n[tp->nch]; + old[0] = t_o[tp->och]; + if (new[0] == old[0] && !force) + continue; + /* Put the old default binding back, and set the new binding */ + key_clear(el, map, (char *)old); + map[old[0]] = dmap[old[0]]; + key_clear(el, map, (char *)new); + /* MAP_VI == 1, MAP_EMACS == 0... */ + map[new[0]] = tp->bind[el->el_map.type]; + if (dalt) { + key_clear(el, alt, (char *)old); + alt[old[0]] = dalt[old[0]]; + key_clear(el, alt, (char *)new); + alt[new[0]] = tp->bind[el->el_map.type + 1]; + } } - } } + /* tty_rawmode(): * Set terminal into 1 character at a time mode. */ protected int -tty_rawmode(el) - EditLine *el; +tty_rawmode(EditLine *el) { - if (el->el_tty.t_mode == ED_IO) - return (0); - - if (tty_getty(el, &el->el_tty.t_ts) == -1) { -#ifdef DEBUG_TTY - (void)fprintf(el->el_errfile, "tty_rawmode: tty_getty: %s\n", strerror(errno)); -#endif /* DEBUG_TTY */ - return(-1); - } - - /* - * We always keep up with the eight bit setting and the speed of the - * tty. But only we only believe changes that are made to cooked mode! - */ - el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ts); - el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ts); - - if (tty__getspeed(&el->el_tty.t_ex) != el->el_tty.t_speed || - tty__getspeed(&el->el_tty.t_ed) != el->el_tty.t_speed) { - (void)cfsetispeed(&el->el_tty.t_ex, el->el_tty.t_speed); - (void)cfsetospeed(&el->el_tty.t_ex, el->el_tty.t_speed); - (void)cfsetispeed(&el->el_tty.t_ed, el->el_tty.t_speed); - (void)cfsetospeed(&el->el_tty.t_ed, el->el_tty.t_speed); - } - - if (tty__cooked_mode(&el->el_tty.t_ts)) { - if (el->el_tty.t_ts.c_cflag != el->el_tty.t_ex.c_cflag) { - el->el_tty.t_ex.c_cflag = el->el_tty.t_ts.c_cflag; - el->el_tty.t_ex.c_cflag &= ~el->el_tty.t_t[EX_IO][M_CTL].t_clrmask; - el->el_tty.t_ex.c_cflag |= el->el_tty.t_t[EX_IO][M_CTL].t_setmask; - - el->el_tty.t_ed.c_cflag = el->el_tty.t_ts.c_cflag; - el->el_tty.t_ed.c_cflag &= ~el->el_tty.t_t[ED_IO][M_CTL].t_clrmask; - el->el_tty.t_ed.c_cflag |= el->el_tty.t_t[ED_IO][M_CTL].t_setmask; - } - - if ((el->el_tty.t_ts.c_lflag != el->el_tty.t_ex.c_lflag) && - (el->el_tty.t_ts.c_lflag != el->el_tty.t_ed.c_lflag)) { - el->el_tty.t_ex.c_lflag = el->el_tty.t_ts.c_lflag; - el->el_tty.t_ex.c_lflag &= ~el->el_tty.t_t[EX_IO][M_LIN].t_clrmask; - el->el_tty.t_ex.c_lflag |= el->el_tty.t_t[EX_IO][M_LIN].t_setmask; - el->el_tty.t_ed.c_lflag = el->el_tty.t_ts.c_lflag; - el->el_tty.t_ed.c_lflag &= ~el->el_tty.t_t[ED_IO][M_LIN].t_clrmask; - el->el_tty.t_ed.c_lflag |= el->el_tty.t_t[ED_IO][M_LIN].t_setmask; - } + if (el->el_tty.t_mode == ED_IO || el->el_tty.t_mode == QU_IO) + return (0); - if ((el->el_tty.t_ts.c_iflag != el->el_tty.t_ex.c_iflag) && - (el->el_tty.t_ts.c_iflag != el->el_tty.t_ed.c_iflag)) { - el->el_tty.t_ex.c_iflag = el->el_tty.t_ts.c_iflag; - el->el_tty.t_ex.c_iflag &= ~el->el_tty.t_t[EX_IO][M_INP].t_clrmask; - el->el_tty.t_ex.c_iflag |= el->el_tty.t_t[EX_IO][M_INP].t_setmask; + if (el->el_flags & EDIT_DISABLED) + return (0); - el->el_tty.t_ed.c_iflag = el->el_tty.t_ts.c_iflag; - el->el_tty.t_ed.c_iflag &= ~el->el_tty.t_t[ED_IO][M_INP].t_clrmask; - el->el_tty.t_ed.c_iflag |= el->el_tty.t_t[ED_IO][M_INP].t_setmask; + if (tty_getty(el, &el->el_tty.t_ts) == -1) { +#ifdef DEBUG_TTY + (void) fprintf(el->el_errfile, "tty_rawmode: tty_getty: %s\n", + strerror(errno)); +#endif /* DEBUG_TTY */ + return (-1); } - - if ((el->el_tty.t_ts.c_oflag != el->el_tty.t_ex.c_oflag) && - (el->el_tty.t_ts.c_oflag != el->el_tty.t_ed.c_oflag)) { - el->el_tty.t_ex.c_oflag = el->el_tty.t_ts.c_oflag; - el->el_tty.t_ex.c_oflag &= ~el->el_tty.t_t[EX_IO][M_OUT].t_clrmask; - el->el_tty.t_ex.c_oflag |= el->el_tty.t_t[EX_IO][M_OUT].t_setmask; - - el->el_tty.t_ed.c_oflag = el->el_tty.t_ts.c_oflag; - el->el_tty.t_ed.c_oflag &= ~el->el_tty.t_t[ED_IO][M_OUT].t_clrmask; - el->el_tty.t_ed.c_oflag |= el->el_tty.t_t[ED_IO][M_OUT].t_setmask; + /* + * We always keep up with the eight bit setting and the speed of the + * tty. But only we only believe changes that are made to cooked mode! + */ + el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ts); + el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ts); + + if (tty__getspeed(&el->el_tty.t_ex) != el->el_tty.t_speed || + tty__getspeed(&el->el_tty.t_ed) != el->el_tty.t_speed) { + (void) cfsetispeed(&el->el_tty.t_ex, el->el_tty.t_speed); + (void) cfsetospeed(&el->el_tty.t_ex, el->el_tty.t_speed); + (void) cfsetispeed(&el->el_tty.t_ed, el->el_tty.t_speed); + (void) cfsetospeed(&el->el_tty.t_ed, el->el_tty.t_speed); } - - if (tty__gettabs(&el->el_tty.t_ex) == 0) - el->el_tty.t_tabs = 0; - else - el->el_tty.t_tabs = EL_CAN_TAB ? 1 : 0; - - { - int i; - - tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]); - /* - * Check if the user made any changes. - * If he did, then propagate the changes to the - * edit and execute data structures. - */ - for (i = 0; i < C_NCC; i++) - if (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i]) - break; - - if (i != C_NCC) { - /* - * Propagate changes only to the unprotected chars - * that have been modified just now. - */ - for (i = 0; i < C_NCC; i++) { - if (!((el->el_tty.t_t[ED_IO][M_CHAR].t_setmask & C_SH(i))) - && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i])) - el->el_tty.t_c[ED_IO][i] = el->el_tty.t_c[TS_IO][i]; - if (el->el_tty.t_t[ED_IO][M_CHAR].t_clrmask & C_SH(i)) - el->el_tty.t_c[ED_IO][i] = el->el_tty.t_vdisable; + if (tty__cooked_mode(&el->el_tty.t_ts)) { + if (el->el_tty.t_ts.c_cflag != el->el_tty.t_ex.c_cflag) { + el->el_tty.t_ex.c_cflag = + el->el_tty.t_ts.c_cflag; + el->el_tty.t_ex.c_cflag &= + ~el->el_tty.t_t[EX_IO][MD_CTL].t_clrmask; + el->el_tty.t_ex.c_cflag |= + el->el_tty.t_t[EX_IO][MD_CTL].t_setmask; + + el->el_tty.t_ed.c_cflag = + el->el_tty.t_ts.c_cflag; + el->el_tty.t_ed.c_cflag &= + ~el->el_tty.t_t[ED_IO][MD_CTL].t_clrmask; + el->el_tty.t_ed.c_cflag |= + el->el_tty.t_t[ED_IO][MD_CTL].t_setmask; } - tty_bind_char(el, 0); - tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]); - - for (i = 0; i < C_NCC; i++) { - if (!((el->el_tty.t_t[EX_IO][M_CHAR].t_setmask & C_SH(i))) - && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i])) - el->el_tty.t_c[EX_IO][i] = el->el_tty.t_c[TS_IO][i]; - if (el->el_tty.t_t[EX_IO][M_CHAR].t_clrmask & C_SH(i)) - el->el_tty.t_c[EX_IO][i] = el->el_tty.t_vdisable; + if ((el->el_tty.t_ts.c_lflag != el->el_tty.t_ex.c_lflag) && + (el->el_tty.t_ts.c_lflag != el->el_tty.t_ed.c_lflag)) { + el->el_tty.t_ex.c_lflag = + el->el_tty.t_ts.c_lflag; + el->el_tty.t_ex.c_lflag &= + ~el->el_tty.t_t[EX_IO][MD_LIN].t_clrmask; + el->el_tty.t_ex.c_lflag |= + el->el_tty.t_t[EX_IO][MD_LIN].t_setmask; + + el->el_tty.t_ed.c_lflag = + el->el_tty.t_ts.c_lflag; + el->el_tty.t_ed.c_lflag &= + ~el->el_tty.t_t[ED_IO][MD_LIN].t_clrmask; + el->el_tty.t_ed.c_lflag |= + el->el_tty.t_t[ED_IO][MD_LIN].t_setmask; + } + if ((el->el_tty.t_ts.c_iflag != el->el_tty.t_ex.c_iflag) && + (el->el_tty.t_ts.c_iflag != el->el_tty.t_ed.c_iflag)) { + el->el_tty.t_ex.c_iflag = + el->el_tty.t_ts.c_iflag; + el->el_tty.t_ex.c_iflag &= + ~el->el_tty.t_t[EX_IO][MD_INP].t_clrmask; + el->el_tty.t_ex.c_iflag |= + el->el_tty.t_t[EX_IO][MD_INP].t_setmask; + + el->el_tty.t_ed.c_iflag = + el->el_tty.t_ts.c_iflag; + el->el_tty.t_ed.c_iflag &= + ~el->el_tty.t_t[ED_IO][MD_INP].t_clrmask; + el->el_tty.t_ed.c_iflag |= + el->el_tty.t_t[ED_IO][MD_INP].t_setmask; + } + if ((el->el_tty.t_ts.c_oflag != el->el_tty.t_ex.c_oflag) && + (el->el_tty.t_ts.c_oflag != el->el_tty.t_ed.c_oflag)) { + el->el_tty.t_ex.c_oflag = + el->el_tty.t_ts.c_oflag; + el->el_tty.t_ex.c_oflag &= + ~el->el_tty.t_t[EX_IO][MD_OUT].t_clrmask; + el->el_tty.t_ex.c_oflag |= + el->el_tty.t_t[EX_IO][MD_OUT].t_setmask; + + el->el_tty.t_ed.c_oflag = + el->el_tty.t_ts.c_oflag; + el->el_tty.t_ed.c_oflag &= + ~el->el_tty.t_t[ED_IO][MD_OUT].t_clrmask; + el->el_tty.t_ed.c_oflag |= + el->el_tty.t_t[ED_IO][MD_OUT].t_setmask; + } + if (tty__gettabs(&el->el_tty.t_ex) == 0) + el->el_tty.t_tabs = 0; + else + el->el_tty.t_tabs = EL_CAN_TAB ? 1 : 0; + + { + int i; + + tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]); + /* + * Check if the user made any changes. + * If he did, then propagate the changes to the + * edit and execute data structures. + */ + for (i = 0; i < C_NCC; i++) + if (el->el_tty.t_c[TS_IO][i] != + el->el_tty.t_c[EX_IO][i]) + break; + + if (i != C_NCC) { + /* + * Propagate changes only to the unprotected + * chars that have been modified just now. + */ + for (i = 0; i < C_NCC; i++) { + if (!((el->el_tty.t_t[ED_IO][MD_CHAR].t_setmask & C_SH(i))) + && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i])) + el->el_tty.t_c[ED_IO][i] = el->el_tty.t_c[TS_IO][i]; + if (el->el_tty.t_t[ED_IO][MD_CHAR].t_clrmask & C_SH(i)) + el->el_tty.t_c[ED_IO][i] = el->el_tty.t_vdisable; + } + tty_bind_char(el, 0); + tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]); + + for (i = 0; i < C_NCC; i++) { + if (!((el->el_tty.t_t[EX_IO][MD_CHAR].t_setmask & C_SH(i))) + && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i])) + el->el_tty.t_c[EX_IO][i] = el->el_tty.t_c[TS_IO][i]; + if (el->el_tty.t_t[EX_IO][MD_CHAR].t_clrmask & C_SH(i)) + el->el_tty.t_c[EX_IO][i] = el->el_tty.t_vdisable; + } + tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]); + } } - tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]); - } - } - } - - if (tty_setty(el, &el->el_tty.t_ed) == -1) { + if (tty_setty(el, &el->el_tty.t_ed) == -1) { #ifdef DEBUG_TTY - (void)fprintf(el->el_errfile, "tty_rawmode: tty_setty: %s\n", - strerror(errno)); + (void) fprintf(el->el_errfile, "tty_rawmode: tty_setty: %s\n", + strerror(errno)); #endif /* DEBUG_TTY */ - return -1; - } - el->el_tty.t_mode = ED_IO; - return (0); -} /* end tty_rawmode */ + return (-1); + } + el->el_tty.t_mode = ED_IO; + return (0); +} /* tty_cookedmode(): * Set the tty back to normal mode */ protected int -tty_cookedmode(el) - EditLine *el; +tty_cookedmode(EditLine *el) { /* set tty in normal setup */ - if (el->el_tty.t_mode == EX_IO) - return (0); - if (tty_setty(el, &el->el_tty.t_ex) == -1) { + if (el->el_tty.t_mode == EX_IO) + return (0); + + if (el->el_flags & EDIT_DISABLED) + return (0); + + if (tty_setty(el, &el->el_tty.t_ex) == -1) { #ifdef DEBUG_TTY - (void)fprintf(el->el_errfile, "tty_cookedmode: tty_setty: %s\n", - strerror(errno)); + (void) fprintf(el->el_errfile, + "tty_cookedmode: tty_setty: %s\n", + strerror(errno)); #endif /* DEBUG_TTY */ - return -1; - } - el->el_tty.t_mode = EX_IO; - return (0); -} /* end tty_cookedmode */ + return (-1); + } + el->el_tty.t_mode = EX_IO; + return (0); +} /* tty_quotemode(): * Turn on quote mode */ protected int -tty_quotemode(el) - EditLine *el; +tty_quotemode(EditLine *el) { - if (el->el_tty.t_mode == QU_IO) - return 0; + if (el->el_tty.t_mode == QU_IO) + return (0); - el->el_tty.t_qu = el->el_tty.t_ed; + el->el_tty.t_qu = el->el_tty.t_ed; - el->el_tty.t_qu.c_iflag &= ~el->el_tty.t_t[QU_IO][M_INP].t_clrmask; - el->el_tty.t_qu.c_iflag |= el->el_tty.t_t[QU_IO][M_INP].t_setmask; + el->el_tty.t_qu.c_iflag &= ~el->el_tty.t_t[QU_IO][MD_INP].t_clrmask; + el->el_tty.t_qu.c_iflag |= el->el_tty.t_t[QU_IO][MD_INP].t_setmask; - el->el_tty.t_qu.c_oflag &= ~el->el_tty.t_t[QU_IO][M_OUT].t_clrmask; - el->el_tty.t_qu.c_oflag |= el->el_tty.t_t[QU_IO][M_OUT].t_setmask; + el->el_tty.t_qu.c_oflag &= ~el->el_tty.t_t[QU_IO][MD_OUT].t_clrmask; + el->el_tty.t_qu.c_oflag |= el->el_tty.t_t[QU_IO][MD_OUT].t_setmask; - el->el_tty.t_qu.c_cflag &= ~el->el_tty.t_t[QU_IO][M_CTL].t_clrmask; - el->el_tty.t_qu.c_cflag |= el->el_tty.t_t[QU_IO][M_CTL].t_setmask; + el->el_tty.t_qu.c_cflag &= ~el->el_tty.t_t[QU_IO][MD_CTL].t_clrmask; + el->el_tty.t_qu.c_cflag |= el->el_tty.t_t[QU_IO][MD_CTL].t_setmask; - el->el_tty.t_qu.c_lflag &= ~el->el_tty.t_t[QU_IO][M_LIN].t_clrmask; - el->el_tty.t_qu.c_lflag |= el->el_tty.t_t[QU_IO][M_LIN].t_setmask; + el->el_tty.t_qu.c_lflag &= ~el->el_tty.t_t[QU_IO][MD_LIN].t_clrmask; + el->el_tty.t_qu.c_lflag |= el->el_tty.t_t[QU_IO][MD_LIN].t_setmask; - if (tty_setty(el, &el->el_tty.t_qu) == -1) { + if (tty_setty(el, &el->el_tty.t_qu) == -1) { #ifdef DEBUG_TTY - (void)fprintf(el->el_errfile, "QuoteModeOn: tty_setty: %s\n", - strerror(errno)); + (void) fprintf(el->el_errfile, "QuoteModeOn: tty_setty: %s\n", + strerror(errno)); #endif /* DEBUG_TTY */ - return -1; - } - el->el_tty.t_mode = QU_IO; - return 0; -} /* end tty_quotemode */ + return (-1); + } + el->el_tty.t_mode = QU_IO; + return (0); +} /* tty_noquotemode(): * Turn off quote mode */ protected int -tty_noquotemode(el) - EditLine *el; +tty_noquotemode(EditLine *el) { - if (el->el_tty.t_mode != QU_IO) - return 0; - if (tty_setty(el, &el->el_tty.t_ed) == -1) { + + if (el->el_tty.t_mode != QU_IO) + return (0); + if (tty_setty(el, &el->el_tty.t_ed) == -1) { #ifdef DEBUG_TTY - (void)fprintf(el->el_errfile, "QuoteModeOff: tty_setty: %s\n", - strerror(errno)); + (void) fprintf(el->el_errfile, "QuoteModeOff: tty_setty: %s\n", + strerror(errno)); #endif /* DEBUG_TTY */ - return -1; - } - el->el_tty.t_mode = ED_IO; - return 0; + return (-1); + } + el->el_tty.t_mode = ED_IO; + return (0); } + /* tty_stty(): * Stty builtin */ protected int /*ARGSUSED*/ -tty_stty(el, argc, argv) - EditLine *el; - int argc; - char **argv; +tty_stty(EditLine *el, int argc __attribute__((__unused__)), const char **argv) { - ttymodes_t *m; - char x, *d; - int aflag = 0; - char *s; - char *name; - int z = EX_IO; - - if (argv == NULL) - return -1; - name = *argv++; - - while (argv && *argv && argv[0][0] == '-' && argv[0][2] == '\0') - switch (argv[0][1]) { - case 'a': - aflag++; - argv++; - break; - case 'd': - argv++; - z = ED_IO; - break; - case 'x': - argv++; - z = EX_IO; - break; - case 'q': - argv++; - z = QU_IO; - break; - default: - (void)fprintf(el->el_errfile, "%s: Unknown switch `%c'.\n", - name, argv[0][1]); - return -1; - } - - if (!argv || !*argv) { - int i = -1; - int len = 0, st = 0, cu; - for (m = ttymodes; m->m_name; m++) { - if (m->m_type != i) { - (void)fprintf(el->el_outfile, "%s%s", i != -1 ? "\n" : "", - el->el_tty.t_t[z][m->m_type].t_name); - i = m->m_type; - st = len = strlen(el->el_tty.t_t[z][m->m_type].t_name); - } - - x = (el->el_tty.t_t[z][i].t_setmask & m->m_value) ? '+' : '\0'; - x = (el->el_tty.t_t[z][i].t_clrmask & m->m_value) ? '-' : x; - - if (x != '\0' || aflag) { - - cu = strlen(m->m_name) + (x != '\0') + 1; - - if (len + cu >= el->el_term.t_size.h) { - (void)fprintf(el->el_outfile, "\n%*s", st, ""); - len = st + cu; + const ttymodes_t *m; + char x; + int aflag = 0; + const char *s, *d; + const char *name; + int z = EX_IO; + + if (argv == NULL) + return (-1); + name = *argv++; + + while (argv && *argv && argv[0][0] == '-' && argv[0][2] == '\0') + switch (argv[0][1]) { + case 'a': + aflag++; + argv++; + break; + case 'd': + argv++; + z = ED_IO; + break; + case 'x': + argv++; + z = EX_IO; + break; + case 'q': + argv++; + z = QU_IO; + break; + default: + (void) fprintf(el->el_errfile, + "%s: Unknown switch `%c'.\n", + name, argv[0][1]); + return (-1); } - else - len += cu; - if (x != '\0') - (void)fprintf(el->el_outfile, "%c%s ", x, m->m_name); - else - (void)fprintf(el->el_outfile, "%s ", m->m_name); - } - } - (void)fprintf(el->el_outfile, "\n"); - return 0; - } - - while (argv && (s = *argv++)) { - switch (*s) { - case '+': - case '-': - x = *s++; - break; - default: - x = '\0'; - break; - } - d = s; - for (m = ttymodes; m->m_name; m++) - if (strcmp(m->m_name, d) == 0) - break; - - if (!m->m_name) { - (void)fprintf(el->el_errfile, "%s: Invalid argument `%s'.\n", - name, d); - return -1; + if (!argv || !*argv) { + int i = -1; + int len = 0, st = 0, cu; + for (m = ttymodes; m->m_name; m++) { + if (m->m_type != i) { + (void) fprintf(el->el_outfile, "%s%s", + i != -1 ? "\n" : "", + el->el_tty.t_t[z][m->m_type].t_name); + i = m->m_type; + st = len = + strlen(el->el_tty.t_t[z][m->m_type].t_name); + } + x = (el->el_tty.t_t[z][i].t_setmask & m->m_value) + ? '+' : '\0'; + x = (el->el_tty.t_t[z][i].t_clrmask & m->m_value) + ? '-' : x; + + if (x != '\0' || aflag) { + + cu = strlen(m->m_name) + (x != '\0') + 1; + + if (len + cu >= el->el_term.t_size.h) { + (void) fprintf(el->el_outfile, "\n%*s", + st, ""); + len = st + cu; + } else + len += cu; + + if (x != '\0') + (void) fprintf(el->el_outfile, "%c%s ", + x, m->m_name); + else + (void) fprintf(el->el_outfile, "%s ", + m->m_name); + } + } + (void) fprintf(el->el_outfile, "\n"); + return (0); } - - switch (x) { - case '+': - el->el_tty.t_t[z][m->m_type].t_setmask |= m->m_value; - el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value; - break; - case '-': - el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value; - el->el_tty.t_t[z][m->m_type].t_clrmask |= m->m_value; - break; - default: - el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value; - el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value; - break; + while (argv && (s = *argv++)) { + switch (*s) { + case '+': + case '-': + x = *s++; + break; + default: + x = '\0'; + break; + } + d = s; + for (m = ttymodes; m->m_name; m++) + if (strcmp(m->m_name, d) == 0) + break; + + if (!m->m_name) { + (void) fprintf(el->el_errfile, + "%s: Invalid argument `%s'.\n", name, d); + return (-1); + } + switch (x) { + case '+': + el->el_tty.t_t[z][m->m_type].t_setmask |= m->m_value; + el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value; + break; + case '-': + el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value; + el->el_tty.t_t[z][m->m_type].t_clrmask |= m->m_value; + break; + default: + el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value; + el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value; + break; + } } - } - return 0; -} /* end tty_stty */ + return (0); +} #ifdef notyet @@ -1126,22 +1159,21 @@ tty_stty(el, argc, argv) * DEbugging routine to print the tty characters */ private void -tty_printchar(el, s) - EditLine *el; - unsigned char *s; +tty_printchar(EditLine *el, unsigned char *s) { - ttyperm_t *m; - int i; - - for (i = 0; i < C_NCC; i++) { - for (m = el->el_tty.t_t; m->m_name; m++) - if (m->m_type == M_CHAR && C_SH(i) == m->m_value) - break; - if (m->m_name) - (void)fprintf(el->el_errfile, "%s ^%c ", m->m_name, s[i] + 'A'-1); - if (i % 5 == 0) - (void)fprintf(el->el_errfile, "\n"); - } - (void)fprintf(el->el_errfile, "\n"); + ttyperm_t *m; + int i; + + for (i = 0; i < C_NCC; i++) { + for (m = el->el_tty.t_t; m->m_name; m++) + if (m->m_type == MD_CHAR && C_SH(i) == m->m_value) + break; + if (m->m_name) + (void) fprintf(el->el_errfile, "%s ^%c ", + m->m_name, s[i] + 'A' - 1); + if (i % 5 == 0) + (void) fprintf(el->el_errfile, "\n"); + } + (void) fprintf(el->el_errfile, "\n"); } #endif /* notyet */ diff --git a/lib/libedit/tty.h b/lib/libedit/tty.h index b9783cd1653..0ab2dd1c9a8 100644 --- a/lib/libedit/tty.h +++ b/lib/libedit/tty.h @@ -1,5 +1,5 @@ -/* $OpenBSD: tty.h,v 1.6 2003/06/02 20:18:40 millert Exp $ */ -/* $NetBSD: tty.h,v 1.4 1997/04/11 21:38:02 christos Exp $ */ +/* $OpenBSD: tty.h,v 1.7 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: tty.h,v 1.10 2003/08/07 16:44:34 agc Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -39,13 +39,14 @@ * el.tty.h: Local terminal header */ #ifndef _h_el_tty -#define _h_el_tty +#define _h_el_tty #include "histedit.h" #include <termios.h> +#include <unistd.h> /* Define our own since everyone gets it wrong! */ -#define CONTROL(A) ((A) & 037) +#define CONTROL(A) ((A) & 037) /* * Aix compatible names @@ -404,61 +405,61 @@ # endif /* NUMCC */ #endif /* !POSIX */ -#define C_INTR 0 -#define C_QUIT 1 -#define C_ERASE 2 -#define C_KILL 3 -#define C_EOF 4 -#define C_EOL 5 -#define C_EOL2 6 -#define C_SWTCH 7 -#define C_DSWTCH 8 -#define C_ERASE2 9 -#define C_START 10 -#define C_STOP 11 -#define C_WERASE 12 -#define C_SUSP 13 -#define C_DSUSP 14 -#define C_REPRINT 15 -#define C_DISCARD 16 -#define C_LNEXT 17 -#define C_STATUS 18 -#define C_PAGE 19 -#define C_PGOFF 20 -#define C_KILL2 21 -#define C_BRK 22 -#define C_MIN 23 -#define C_TIME 24 -#define C_NCC 25 -#define C_SH(A) (1 << (A)) +#define C_INTR 0 +#define C_QUIT 1 +#define C_ERASE 2 +#define C_KILL 3 +#define C_EOF 4 +#define C_EOL 5 +#define C_EOL2 6 +#define C_SWTCH 7 +#define C_DSWTCH 8 +#define C_ERASE2 9 +#define C_START 10 +#define C_STOP 11 +#define C_WERASE 12 +#define C_SUSP 13 +#define C_DSUSP 14 +#define C_REPRINT 15 +#define C_DISCARD 16 +#define C_LNEXT 17 +#define C_STATUS 18 +#define C_PAGE 19 +#define C_PGOFF 20 +#define C_KILL2 21 +#define C_BRK 22 +#define C_MIN 23 +#define C_TIME 24 +#define C_NCC 25 +#define C_SH(A) (1 << (A)) /* * Terminal dependend data structures */ -#define EX_IO 0 /* while we are executing */ -#define ED_IO 1 /* while we are editing */ -#define TS_IO 2 /* new mode from terminal */ -#define QU_IO 2 /* used only for quoted chars */ -#define NN_IO 3 /* The number of entries */ - -#define M_INP 0 -#define M_OUT 1 -#define M_CTL 2 -#define M_LIN 3 -#define M_CHAR 4 -#define M_NN 5 - -typedef struct { - char *t_name; - u_int t_setmask; - u_int t_clrmask; -} ttyperm_t[NN_IO][M_NN]; +#define EX_IO 0 /* while we are executing */ +#define ED_IO 1 /* while we are editing */ +#define TS_IO 2 /* new mode from terminal */ +#define QU_IO 2 /* used only for quoted chars */ +#define NN_IO 3 /* The number of entries */ + +#define MD_INP 0 +#define MD_OUT 1 +#define MD_CTL 2 +#define MD_LIN 3 +#define MD_CHAR 4 +#define MD_NN 5 + +typedef struct { + const char *t_name; + u_int t_setmask; + u_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 d0d289f20e4..888c1469381 100644 --- a/lib/libedit/vi.c +++ b/lib/libedit/vi.c @@ -1,5 +1,5 @@ -/* $OpenBSD: vi.c,v 1.6 2003/06/02 20:18:40 millert Exp $ */ -/* $NetBSD: vi.c,v 1.2 1997/01/11 06:48:19 lukem Exp $ */ +/* $OpenBSD: vi.c,v 1.7 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: vi.c,v 1.19 2003/08/07 16:44:35 agc Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -33,391 +33,358 @@ * SUCH DAMAGE. */ +#include "config.h" +#include <stdlib.h> +#include <unistd.h> +#include <sys/wait.h> + #if !defined(lint) && !defined(SCCSID) #if 0 static char sccsid[] = "@(#)vi.c 8.1 (Berkeley) 6/4/93"; #else -static const char rcsid[] = "$OpenBSD: vi.c,v 1.6 2003/06/02 20:18:40 millert Exp $"; +static const char rcsid[] = "$OpenBSD: vi.c,v 1.7 2003/10/31 08:42:24 otto Exp $"; #endif #endif /* not lint && not SCCSID */ /* * vi.c: Vi mode commands. */ -#include "sys.h" #include "el.h" -private el_action_t cv_action(EditLine *, int); +private el_action_t cv_action(EditLine *, int); +private el_action_t cv_paste(EditLine *, int); /* cv_action(): * Handle vi actions. */ private el_action_t -cv_action(el, c) - EditLine *el; - int c; +cv_action(EditLine *el, int c) { - register char *cp, *kp; - if (el->el_chared.c_vcmd.action & DELETE) { - el->el_chared.c_vcmd.action = NOP; - el->el_chared.c_vcmd.pos = 0; - - el->el_chared.c_undo.isize = 0; - el->el_chared.c_undo.dsize = 0; - kp = el->el_chared.c_undo.buf; - for (cp = el->el_line.buffer; cp < el->el_line.lastchar; cp++) { - *kp++ = *cp; - el->el_chared.c_undo.dsize++; + if (el->el_chared.c_vcmd.action != NOP) { + /* 'cc', 'dd' and (possibly) friends */ + if (c != el->el_chared.c_vcmd.action) + return CC_ERROR; + + if (!(c & YANK)) + cv_undo(el); + cv_yank(el, el->el_line.buffer, + el->el_line.lastchar - el->el_line.buffer); + el->el_chared.c_vcmd.action = NOP; + el->el_chared.c_vcmd.pos = 0; + el->el_line.lastchar = el->el_line.buffer; + el->el_line.cursor = el->el_line.buffer; + if (c & INSERT) + el->el_map.current = el->el_map.key; + + return (CC_REFRESH); } - - el->el_chared.c_undo.action = INSERT; - el->el_chared.c_undo.ptr = el->el_line.buffer; - el->el_line.lastchar = el->el_line.buffer; - el->el_line.cursor = el->el_line.buffer; - if (c & INSERT) - el->el_map.current = el->el_map.key; - - return CC_REFRESH; - } - - el->el_chared.c_vcmd.pos = el->el_line.cursor; - el->el_chared.c_vcmd.action = c; - return CC_ARGHACK; - -#ifdef notdef - /* - * I don't think that this is needed. But we keep it for now - */ - else if (el_chared.c_vcmd.action == NOP) { el->el_chared.c_vcmd.pos = el->el_line.cursor; el->el_chared.c_vcmd.action = c; - return CC_ARGHACK; - } - else { - el->el_chared.c_vcmd.action = 0; - el->el_chared.c_vcmd.pos = 0; - return CC_ERROR; - } -#endif + return (CC_ARGHACK); } - /* cv_paste(): * Paste previous deletion before or after the cursor */ -protected el_action_t -cv_paste(el, c) - EditLine *el; - int c; +private el_action_t +cv_paste(EditLine *el, int c) { - char *ptr; - c_undo_t *un = &el->el_chared.c_undo; + char *ptr; + c_kill_t *k = &el->el_chared.c_kill; + int len = k->last - k->buf; + + if (k->buf == NULL || len == 0) + return (CC_ERROR); #ifdef DEBUG_PASTE - (void)fprintf(el->el_errfile, "Paste: %x \"%s\" +%d -%d\n", - un->action, un->buf, un->isize, un->dsize); + (void) fprintf(el->el_errfile, "Paste: \"%.*s\"\n", len, k->buf); #endif - if (un->isize == 0) - return CC_ERROR; - if (!c && el->el_line.cursor < el->el_line.lastchar) - el->el_line.cursor++; - ptr = el->el_line.cursor; - - c_insert(el, un->isize); - if (el->el_line.cursor + un->isize > el->el_line.lastchar) - return CC_ERROR; - (void)memcpy(ptr, un->buf, un->isize); - return CC_REFRESH; + cv_undo(el); + + if (!c && el->el_line.cursor < el->el_line.lastchar) + el->el_line.cursor++; + ptr = el->el_line.cursor; + + c_insert(el, len); + if (el->el_line.cursor + len > el->el_line.lastchar) + return (CC_ERROR); + (void) memcpy(ptr, k->buf, len +0u); + return (CC_REFRESH); } -/* vi_paste_next(): +/* vi_paste_next(): * Vi paste previous deletion to the right of the cursor * [p] */ protected el_action_t /*ARGSUSED*/ -vi_paste_next(el, c) - EditLine *el; - int c; +vi_paste_next(EditLine *el, int c __attribute__((__unused__))) { - return cv_paste(el, 0); + + return (cv_paste(el, 0)); } -/* vi_paste_prev(): +/* vi_paste_prev(): * Vi paste previous deletion to the left of the cursor * [P] */ protected el_action_t /*ARGSUSED*/ -vi_paste_prev(el, c) - EditLine *el; - int c; +vi_paste_prev(EditLine *el, int c __attribute__((__unused__))) { - return cv_paste(el, 1); + + return (cv_paste(el, 1)); } -/* vi_prev_space_word(): +/* vi_prev_big_word(): * Vi move to the previous space delimited word * [B] */ protected el_action_t /*ARGSUSED*/ -vi_prev_space_word(el, c) - EditLine *el; - int c; +vi_prev_big_word(EditLine *el, int c) { - if (el->el_line.cursor == el->el_line.buffer) - return CC_ERROR; - el->el_line.cursor = cv_prev_word(el, el->el_line.cursor, - el->el_line.buffer, - el->el_state.argument, - cv__isword); + if (el->el_line.cursor == el->el_line.buffer) + return (CC_ERROR); - if (el->el_chared.c_vcmd.action & DELETE) { - cv_delfini(el); - return CC_REFRESH; - } + el->el_line.cursor = cv_prev_word(el->el_line.cursor, + el->el_line.buffer, + el->el_state.argument, + cv__isWord); - return CC_CURSOR; + if (el->el_chared.c_vcmd.action != NOP) { + cv_delfini(el); + return (CC_REFRESH); + } + return (CC_CURSOR); } -/* vi_prev_word(): +/* vi_prev_word(): * Vi move to the previous word - * [B] + * [b] */ protected el_action_t /*ARGSUSED*/ -vi_prev_word(el, c) - EditLine *el; - int c; +vi_prev_word(EditLine *el, int c __attribute__((__unused__))) { - if (el->el_line.cursor == el->el_line.buffer) - return CC_ERROR; - el->el_line.cursor = cv_prev_word(el, el->el_line.cursor, - el->el_line.buffer, - el->el_state.argument, - ce__isword); + if (el->el_line.cursor == el->el_line.buffer) + return (CC_ERROR); - if (el->el_chared.c_vcmd.action & DELETE) { - cv_delfini(el); - return CC_REFRESH; - } + el->el_line.cursor = cv_prev_word(el->el_line.cursor, + el->el_line.buffer, + el->el_state.argument, + cv__isword); - return CC_CURSOR; + if (el->el_chared.c_vcmd.action != NOP) { + cv_delfini(el); + return (CC_REFRESH); + } + return (CC_CURSOR); } -/* vi_next_space_word(): +/* vi_next_big_word(): * Vi move to the next space delimited word * [W] */ protected el_action_t /*ARGSUSED*/ -vi_next_space_word(el, c) - EditLine *el; - int c; +vi_next_big_word(EditLine *el, int c) { - if (el->el_line.cursor == el->el_line.lastchar) - return CC_ERROR; - el->el_line.cursor = cv_next_word(el, el->el_line.cursor, - el->el_line.lastchar, - el->el_state.argument, - cv__isword); + if (el->el_line.cursor >= el->el_line.lastchar - 1) + return (CC_ERROR); - if (el->el_map.type == MAP_VI) - if (el->el_chared.c_vcmd.action & DELETE) { - cv_delfini(el); - return CC_REFRESH; - } + el->el_line.cursor = cv_next_word(el, el->el_line.cursor, + el->el_line.lastchar, el->el_state.argument, cv__isWord); - return CC_CURSOR; + if (el->el_map.type == MAP_VI) + if (el->el_chared.c_vcmd.action != NOP) { + cv_delfini(el); + return (CC_REFRESH); + } + return (CC_CURSOR); } -/* vi_next_word(): + +/* vi_next_word(): * Vi move to the next word * [w] */ protected el_action_t /*ARGSUSED*/ -vi_next_word(el, c) - EditLine *el; - int c; +vi_next_word(EditLine *el, int c __attribute__((__unused__))) { - if (el->el_line.cursor == el->el_line.lastchar) - return CC_ERROR; - el->el_line.cursor = cv_next_word(el, el->el_line.cursor, - el->el_line.lastchar, - el->el_state.argument, - ce__isword); + if (el->el_line.cursor >= el->el_line.lastchar - 1) + return (CC_ERROR); - if (el->el_map.type == MAP_VI) - if (el->el_chared.c_vcmd.action & DELETE) { - cv_delfini(el); - return CC_REFRESH; - } + el->el_line.cursor = cv_next_word(el, el->el_line.cursor, + el->el_line.lastchar, el->el_state.argument, cv__isword); - return CC_CURSOR; + if (el->el_map.type == MAP_VI) + if (el->el_chared.c_vcmd.action != NOP) { + cv_delfini(el); + return (CC_REFRESH); + } + return (CC_CURSOR); } - -/* vi_change_case(): +/* vi_change_case(): * Vi change case of character under the cursor and advance one character * [~] */ protected el_action_t -vi_change_case(el, c) - EditLine *el; - int c; +vi_change_case(EditLine *el, int c) { - if (el->el_line.cursor < el->el_line.lastchar) { - c = *el->el_line.cursor; - if (isupper(c)) - *el->el_line.cursor++ = tolower(c); - else if (islower(c)) - *el->el_line.cursor++ = toupper(c); - else - el->el_line.cursor++; - re_fastaddc(el); + int i; + + if (el->el_line.cursor >= el->el_line.lastchar) + return (CC_ERROR); + cv_undo(el); + for (i = 0; i < el->el_state.argument; i++) { + + c = *(unsigned char *)el->el_line.cursor; + if (isupper(c)) + *el->el_line.cursor = tolower(c); + else if (islower(c)) + *el->el_line.cursor = toupper(c); + + if (++el->el_line.cursor >= el->el_line.lastchar) { + el->el_line.cursor--; + re_fastaddc(el); + break; + } + re_fastaddc(el); + } return CC_NORM; - } - return CC_ERROR; } -/* vi_change_meta(): +/* vi_change_meta(): * Vi change prefix command * [c] */ protected el_action_t /*ARGSUSED*/ -vi_change_meta(el, c) - EditLine *el; - int c; +vi_change_meta(EditLine *el, int c __attribute__((__unused__))) { - /* - * Delete with insert == change: first we delete and then we leave in - * insert mode. - */ - return cv_action(el, DELETE|INSERT); + + /* + * Delete with insert == change: first we delete and then we leave in + * insert mode. + */ + return (cv_action(el, DELETE | INSERT)); } -/* vi_insert_at_bol(): +/* vi_insert_at_bol(): * Vi enter insert mode at the beginning of line * [I] */ protected el_action_t /*ARGSUSED*/ -vi_insert_at_bol(el, c) - EditLine *el; - int c; +vi_insert_at_bol(EditLine *el, int c __attribute__((__unused__))) { - el->el_line.cursor = el->el_line.buffer; - el->el_chared.c_vcmd.ins = el->el_line.cursor; - el->el_chared.c_undo.ptr = el->el_line.cursor; - el->el_chared.c_undo.action = DELETE; - - el->el_map.current = el->el_map.key; - return CC_CURSOR; + el->el_line.cursor = el->el_line.buffer; + cv_undo(el); + el->el_map.current = el->el_map.key; + return (CC_CURSOR); } -/* vi_replace_char(): +/* vi_replace_char(): * Vi replace character under the cursor with the next character typed * [r] */ protected el_action_t /*ARGSUSED*/ -vi_replace_char(el, c) - EditLine *el; - int c; +vi_replace_char(EditLine *el, int c __attribute__((__unused__))) { - el->el_map.current = el->el_map.key; - el->el_state.inputmode = MODE_REPLACE_1; - el->el_chared.c_undo.action = CHANGE; - el->el_chared.c_undo.ptr = el->el_line.cursor; - el->el_chared.c_undo.isize = 0; - el->el_chared.c_undo.dsize = 0; - return CC_NORM; + + if (el->el_line.cursor >= el->el_line.lastchar) + return CC_ERROR; + + el->el_map.current = el->el_map.key; + el->el_state.inputmode = MODE_REPLACE_1; + cv_undo(el); + return (CC_ARGHACK); } -/* vi_replace_mode(): +/* vi_replace_mode(): * Vi enter replace mode * [R] */ protected el_action_t /*ARGSUSED*/ -vi_replace_mode(el, c) - EditLine *el; - int c; +vi_replace_mode(EditLine *el, int c __attribute__((__unused__))) { - el->el_map.current = el->el_map.key; - el->el_state.inputmode = MODE_REPLACE; - el->el_chared.c_undo.action = CHANGE; - el->el_chared.c_undo.ptr = el->el_line.cursor; - el->el_chared.c_undo.isize = 0; - el->el_chared.c_undo.dsize = 0; - return CC_NORM; + + el->el_map.current = el->el_map.key; + el->el_state.inputmode = MODE_REPLACE; + cv_undo(el); + return (CC_NORM); } -/* vi_substitute_char(): +/* vi_substitute_char(): * Vi replace character under the cursor and enter insert mode - * [r] + * [s] */ protected el_action_t /*ARGSUSED*/ -vi_substitute_char(el, c) - EditLine *el; - int c; +vi_substitute_char(EditLine *el, int c __attribute__((__unused__))) { - c_delafter(el, el->el_state.argument); - el->el_map.current = el->el_map.key; - return CC_REFRESH; + + c_delafter(el, el->el_state.argument); + el->el_map.current = el->el_map.key; + return (CC_REFRESH); } -/* vi_substitute_line(): +/* vi_substitute_line(): * Vi substitute entire line * [S] */ protected el_action_t /*ARGSUSED*/ -vi_substitute_line(el, c) - EditLine *el; - int c; +vi_substitute_line(EditLine *el, int c __attribute__((__unused__))) { - (void)em_kill_line(el, 0); - el->el_map.current = el->el_map.key; - return CC_REFRESH; + + cv_undo(el); + cv_yank(el, el->el_line.buffer, + el->el_line.lastchar - el->el_line.buffer); + (void) em_kill_line(el, 0); + el->el_map.current = el->el_map.key; + return (CC_REFRESH); } -/* vi_change_to_eol(): +/* vi_change_to_eol(): * Vi change to end of line * [C] */ protected el_action_t /*ARGSUSED*/ -vi_change_to_eol(el, c) - EditLine *el; - int c; +vi_change_to_eol(EditLine *el, int c __attribute__((__unused__))) { - (void)ed_kill_line(el, 0); - el->el_map.current = el->el_map.key; - return CC_REFRESH; + + cv_undo(el); + cv_yank(el, el->el_line.cursor, + el->el_line.lastchar - el->el_line.cursor); + (void) ed_kill_line(el, 0); + el->el_map.current = el->el_map.key; + return (CC_REFRESH); } @@ -427,46 +394,37 @@ vi_change_to_eol(el, c) */ protected el_action_t /*ARGSUSED*/ -vi_insert(el, c) - EditLine *el; - int c; +vi_insert(EditLine *el, int c __attribute__((__unused__))) { - el->el_map.current = el->el_map.key; - el->el_chared.c_vcmd.ins = el->el_line.cursor; - el->el_chared.c_undo.ptr = el->el_line.cursor; - el->el_chared.c_undo.action = DELETE; - - return CC_NORM; + el->el_map.current = el->el_map.key; + cv_undo(el); + return (CC_NORM); } /* vi_add(): - * Vi enter insert mode after the cursor + * Vi enter insert mode after the cursor * [a] */ protected el_action_t /*ARGSUSED*/ -vi_add(el, c) - EditLine *el; - int c; +vi_add(EditLine *el, int c __attribute__((__unused__))) { - int ret; - el->el_map.current = el->el_map.key; - if (el->el_line.cursor < el->el_line.lastchar) { - el->el_line.cursor++; - if (el->el_line.cursor > el->el_line.lastchar) - el->el_line.cursor = el->el_line.lastchar; - ret = CC_CURSOR; - } - else - ret = CC_NORM; + int ret; + + el->el_map.current = el->el_map.key; + if (el->el_line.cursor < el->el_line.lastchar) { + el->el_line.cursor++; + if (el->el_line.cursor > el->el_line.lastchar) + el->el_line.cursor = el->el_line.lastchar; + ret = CC_CURSOR; + } else + ret = CC_NORM; - el->el_chared.c_vcmd.ins = el->el_line.cursor; - el->el_chared.c_undo.ptr = el->el_line.cursor; - el->el_chared.c_undo.action = DELETE; + cv_undo(el); - return ret; + return (ret); } @@ -476,84 +434,74 @@ vi_add(el, c) */ protected el_action_t /*ARGSUSED*/ -vi_add_at_eol(el, c) - EditLine *el; - int c; +vi_add_at_eol(EditLine *el, int c __attribute__((__unused__))) { - el->el_map.current = el->el_map.key; - el->el_line.cursor = el->el_line.lastchar; - /* Mark where insertion begins */ - el->el_chared.c_vcmd.ins = el->el_line.lastchar; - el->el_chared.c_undo.ptr = el->el_line.lastchar; - el->el_chared.c_undo.action = DELETE; - return CC_CURSOR; + el->el_map.current = el->el_map.key; + el->el_line.cursor = el->el_line.lastchar; + cv_undo(el); + return (CC_CURSOR); } /* vi_delete_meta(): - * Vi delete prefix command + * Vi delete prefix command * [d] */ protected el_action_t /*ARGSUSED*/ -vi_delete_meta(el, c) - EditLine *el; - int c; +vi_delete_meta(EditLine *el, int c __attribute__((__unused__))) { - return cv_action(el, DELETE); + + return (cv_action(el, DELETE)); } -/* vi_end_word(): - * Vi move to the end of the current space delimited word - * [E] +/* vi_end_big_word(): + * Vi move to the end of the current space delimited word + * [E] */ protected el_action_t /*ARGSUSED*/ -vi_end_word(el, c) - EditLine *el; - int c; +vi_end_big_word(EditLine *el, int c) { - if (el->el_line.cursor == el->el_line.lastchar) - return CC_ERROR; - el->el_line.cursor = cv__endword(el->el_line.cursor, el->el_line.lastchar, - el->el_state.argument); + if (el->el_line.cursor == el->el_line.lastchar) + return (CC_ERROR); - if (el->el_chared.c_vcmd.action & DELETE) { - el->el_line.cursor++; - cv_delfini(el); - return CC_REFRESH; - } + el->el_line.cursor = cv__endword(el->el_line.cursor, + el->el_line.lastchar, el->el_state.argument, cv__isWord); - return CC_CURSOR; + if (el->el_chared.c_vcmd.action != NOP) { + el->el_line.cursor++; + cv_delfini(el); + return (CC_REFRESH); + } + return (CC_CURSOR); } -/* vi_to_end_word(): +/* vi_end_word(): * Vi move to the end of the current word * [e] */ protected el_action_t /*ARGSUSED*/ -vi_to_end_word(el, c) - EditLine *el; - int c; +vi_end_word(EditLine *el, int c __attribute__((__unused__))) { - if (el->el_line.cursor == el->el_line.lastchar) - return CC_ERROR; - el->el_line.cursor = cv__endword(el->el_line.cursor, el->el_line.lastchar, - el->el_state.argument); + if (el->el_line.cursor == el->el_line.lastchar) + return (CC_ERROR); - if (el->el_chared.c_vcmd.action & DELETE) { - el->el_line.cursor++; - cv_delfini(el); - return CC_REFRESH; - } + el->el_line.cursor = cv__endword(el->el_line.cursor, + el->el_line.lastchar, el->el_state.argument, cv__isword); - return CC_CURSOR; + if (el->el_chared.c_vcmd.action != NOP) { + el->el_line.cursor++; + cv_delfini(el); + return (CC_REFRESH); + } + return (CC_CURSOR); } @@ -563,107 +511,23 @@ vi_to_end_word(el, c) */ protected el_action_t /*ARGSUSED*/ -vi_undo(el, c) - EditLine *el; - int c; +vi_undo(EditLine *el, int c __attribute__((__unused__))) { - char *cp, *kp; - char temp; - int i, size; - c_undo_t *un = &el->el_chared.c_undo; + c_undo_t un = el->el_chared.c_undo; -#ifdef DEBUG_UNDO - (void)fprintf(el->el_errfile, "Undo: %x \"%s\" +%d -%d\n", - un->action, un->buf, un->isize, un->dsize); -#endif - switch (un->action) { - case DELETE: - if (un->dsize == 0) - return CC_NORM; - - (void)memcpy(un->buf, un->ptr, un->dsize); - for (cp = un->ptr; cp <= el->el_line.lastchar; cp++) - *cp = cp[un->dsize]; - - el->el_line.lastchar -= un->dsize; - el->el_line.cursor = un->ptr; - - un->action = INSERT; - un->isize = un->dsize; - un->dsize = 0; - break; - - case DELETE|INSERT: - size = un->isize - un->dsize; - if (size > 0) - i = un->dsize; - else - i = un->isize; - cp = un->ptr; - kp = un->buf; - while (i-- > 0) { - temp = *kp; - *kp++ = *cp; - *cp++ = temp; - } - if (size > 0) { - el->el_line.cursor = cp; - c_insert(el, size); - while (size-- > 0 && cp < el->el_line.lastchar) { - temp = *kp; - *kp++ = *cp; - *cp++ = temp; - } - } - else if (size < 0) { - size = -size; - for (; cp <= el->el_line.lastchar; cp++) { - *kp++ = *cp; - *cp = cp[size]; - } - el->el_line.lastchar -= size; - } - el->el_line.cursor = un->ptr; - i = un->dsize; - un->dsize = un->isize; - un->isize = i; - break; - - case INSERT: - if (un->isize == 0) - return CC_NORM; - - el->el_line.cursor = un->ptr; - c_insert(el, un->isize); - memcpy(un->ptr, un->buf, un->isize); - un->action = DELETE; - un->dsize = un->isize; - un->isize = 0; - break; - - case CHANGE: - if (un->isize == 0) - return CC_NORM; - - el->el_line.cursor = un->ptr; - size = (int) (el->el_line.cursor - el->el_line.lastchar); - if (size < un->isize) - size = un->isize; - cp = un->ptr; - kp = un->buf; - for(i = 0; i < size; i++) { - temp = *kp; - *kp++ = *cp; - *cp++ = temp; - } - un->dsize = 0; - break; + if (un.len == -1) + return CC_ERROR; - default: - return CC_ERROR; - } + /* switch line buffer and undo buffer */ + el->el_chared.c_undo.buf = el->el_line.buffer; + el->el_chared.c_undo.len = el->el_line.lastchar - el->el_line.buffer; + el->el_chared.c_undo.cursor = el->el_line.cursor - el->el_line.buffer; + el->el_line.limit = un.buf + (el->el_line.limit - el->el_line.buffer); + el->el_line.buffer = un.buf; + el->el_line.cursor = un.buf + un.cursor; + el->el_line.lastchar = un.buf + un.len; - return CC_REFRESH; + return (CC_REFRESH); } @@ -673,84 +537,67 @@ vi_undo(el, c) */ protected el_action_t /*ARGSUSED*/ -vi_command_mode(el, c) - EditLine *el; - int c; +vi_command_mode(EditLine *el, int c __attribute__((__unused__))) { - int size; - /* [Esc] cancels pending action */ - el->el_chared.c_vcmd.ins = 0; - el->el_chared.c_vcmd.action = NOP; - el->el_chared.c_vcmd.pos = 0; - el->el_state.doingarg = 0; - size = el->el_chared.c_undo.ptr - el->el_line.cursor; - if (size < 0) - size = -size; - if (el->el_chared.c_undo.action == (INSERT|DELETE) || - el->el_chared.c_undo.action == DELETE) - el->el_chared.c_undo.dsize = size; - else - el->el_chared.c_undo.isize = size; + /* [Esc] cancels pending action */ + el->el_chared.c_vcmd.action = NOP; + el->el_chared.c_vcmd.pos = 0; - el->el_state.inputmode = MODE_INSERT; - el->el_map.current = el->el_map.alt; + el->el_state.doingarg = 0; + + el->el_state.inputmode = MODE_INSERT; + el->el_map.current = el->el_map.alt; #ifdef VI_MOVE - if (el->el_line.cursor > el->el_line.buffer) - el->el_line.cursor--; + if (el->el_line.cursor > el->el_line.buffer) + el->el_line.cursor--; #endif - return CC_CURSOR; + return (CC_CURSOR); } + /* vi_zero(): - * Vi move to the beginning of line + * Vi move to the beginning of line * [0] */ protected el_action_t -vi_zero(el, c) - EditLine *el; - int c; +vi_zero(EditLine *el, int c) { - if (el->el_state.doingarg) { - if (el->el_state.argument > 1000000) - return CC_ERROR; - el->el_state.argument = - (el->el_state.argument * 10) + (c - '0'); - return CC_ARGHACK; - } - else { + + if (el->el_state.doingarg) + return ed_argument_digit(el, c); + el->el_line.cursor = el->el_line.buffer; - if (el->el_chared.c_vcmd.action & DELETE) { - cv_delfini(el); - return CC_REFRESH; - } - return CC_CURSOR; - } + if (el->el_chared.c_vcmd.action != NOP) { + cv_delfini(el); + return (CC_REFRESH); + } + return (CC_CURSOR); } /* vi_delete_prev_char(): - * Vi move to previous character (backspace) - * [^H] - */ + * Vi move to previous character (backspace) + * [^H] in insert mode only + */ protected el_action_t /*ARGSUSED*/ -vi_delete_prev_char(el, c) - EditLine *el; - int c; +vi_delete_prev_char(EditLine *el, int c __attribute__((__unused__))) { - if (el->el_chared.c_vcmd.ins == 0) - return CC_ERROR; + char *cp; - if (el->el_chared.c_vcmd.ins > - el->el_line.cursor - el->el_state.argument) - return CC_ERROR; + cp = el->el_line.cursor; + if (cp <= el->el_line.buffer) + return (CC_ERROR); - c_delbefore(el, el->el_state.argument); - el->el_line.cursor -= el->el_state.argument; + /* do the delete here so we dont mess up the undo and paste buffers */ + el->el_line.cursor = --cp; + for (; cp < el->el_line.lastchar; cp++) + cp[0] = cp[1]; + el->el_line.lastchar = cp - 1; - return CC_REFRESH; -} /* end v_del_char_prev */ + return (CC_REFRESH); +} /* vi_list_or_eof(): @@ -759,48 +606,56 @@ vi_delete_prev_char(el, c) */ protected el_action_t /*ARGSUSED*/ -vi_list_or_eof(el, c) - EditLine *el; - int c; +vi_list_or_eof(EditLine *el, int c __attribute__((__unused__))) { + + if (el->el_line.cursor == el->el_line.lastchar) { + if (el->el_line.cursor == el->el_line.buffer) { + term_overwrite(el, STReof, 4); /* then do a EOF */ + term__flush(); + return (CC_EOF); + } else { + /* + * Here we could list completions, but it is an + * error right now + */ + term_beep(el); + return (CC_ERROR); + } + } else { #ifdef notyet - if (el->el_line.cursor == el->el_line.lastchar && - el->el_line.cursor == el->el_line.buffer) { -#endif - term_overwrite(el, STReof, 4); /* then do a EOF */ - term__flush(); - return CC_EOF; -#ifdef notyet - } - else { - re_goto_bottom(el); - *el->el_line.lastchar = '\0'; /* just in case */ - return CC_LIST_CHOICES; - } + re_goto_bottom(el); + *el->el_line.lastchar = '\0'; /* just in case */ + return (CC_LIST_CHOICES); +#else + /* + * Just complain for now. + */ + term_beep(el); + return (CC_ERROR); #endif + } } /* vi_kill_line_prev(): - * Vi cut from beginning of line to cursor + * Vi cut from beginning of line to cursor * [^U] */ protected el_action_t /*ARGSUSED*/ -vi_kill_line_prev(el, c) - EditLine *el; - int c; +vi_kill_line_prev(EditLine *el, int c __attribute__((__unused__))) { - char *kp, *cp; - - cp = el->el_line.buffer; - kp = el->el_chared.c_kill.buf; - while (cp < el->el_line.cursor) - *kp++ = *cp++; /* copy it */ - el->el_chared.c_kill.last = kp; - c_delbefore(el, el->el_line.cursor - el->el_line.buffer); - el->el_line.cursor = el->el_line.buffer; /* zap! */ - return CC_REFRESH; + char *kp, *cp; + + cp = el->el_line.buffer; + kp = el->el_chared.c_kill.buf; + while (cp < el->el_line.cursor) + *kp++ = *cp++; /* copy it */ + el->el_chared.c_kill.last = kp; + c_delbefore(el, el->el_line.cursor - el->el_line.buffer); + el->el_line.cursor = el->el_line.buffer; /* zap! */ + return (CC_REFRESH); } @@ -810,11 +665,10 @@ vi_kill_line_prev(el, c) */ protected el_action_t /*ARGSUSED*/ -vi_search_prev(el, c) - EditLine *el; - int c; +vi_search_prev(EditLine *el, int c __attribute__((__unused__))) { - return cv_search(el, ED_SEARCH_PREV_HISTORY); + + return (cv_search(el, ED_SEARCH_PREV_HISTORY)); } @@ -824,11 +678,10 @@ vi_search_prev(el, c) */ protected el_action_t /*ARGSUSED*/ -vi_search_next(el, c) - EditLine *el; - int c; +vi_search_next(EditLine *el, int c __attribute__((__unused__))) { - return cv_search(el, ED_SEARCH_NEXT_HISTORY); + + return (cv_search(el, ED_SEARCH_NEXT_HISTORY)); } @@ -838,14 +691,13 @@ vi_search_next(el, c) */ protected el_action_t /*ARGSUSED*/ -vi_repeat_search_next(el, c) - EditLine *el; - int c; +vi_repeat_search_next(EditLine *el, int c __attribute__((__unused__))) { - if (el->el_search.patlen == 0) - return CC_ERROR; - else - return cv_repeat_srch(el, el->el_search.patdir); + + if (el->el_search.patlen == 0) + return (CC_ERROR); + else + return (cv_repeat_srch(el, el->el_search.patdir)); } @@ -855,16 +707,15 @@ vi_repeat_search_next(el, c) */ /*ARGSUSED*/ protected el_action_t -vi_repeat_search_prev(el, c) - EditLine *el; - int c; +vi_repeat_search_prev(EditLine *el, int c __attribute__((__unused__))) { - if (el->el_search.patlen == 0) - return CC_ERROR; - else - return cv_repeat_srch(el, - el->el_search.patdir == ED_SEARCH_PREV_HISTORY ? - ED_SEARCH_NEXT_HISTORY : ED_SEARCH_PREV_HISTORY); + + if (el->el_search.patlen == 0) + return (CC_ERROR); + else + return (cv_repeat_srch(el, + el->el_search.patdir == ED_SEARCH_PREV_HISTORY ? + ED_SEARCH_NEXT_HISTORY : ED_SEARCH_PREV_HISTORY)); } @@ -874,20 +725,9 @@ vi_repeat_search_prev(el, c) */ protected el_action_t /*ARGSUSED*/ -vi_next_char(el, c) - EditLine *el; - int c; +vi_next_char(EditLine *el, int c __attribute__((__unused__))) { - char ch; - - if (el_getc(el, &ch) != 1) - return ed_end_of_file(el, 0); - - el->el_search.chadir = CHAR_FWD; - el->el_search.chacha = ch; - - return cv_csearch_fwd(el, ch, el->el_state.argument, 0); - + return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 0); } @@ -897,19 +737,9 @@ vi_next_char(el, c) */ protected el_action_t /*ARGSUSED*/ -vi_prev_char(el, c) - EditLine *el; - int c; +vi_prev_char(EditLine *el, int c __attribute__((__unused__))) { - char ch; - - if (el_getc(el, &ch) != 1) - return ed_end_of_file(el, 0); - - el->el_search.chadir = CHAR_BACK; - el->el_search.chacha = ch; - - return cv_csearch_back(el, ch, el->el_state.argument, 0); + return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 0); } @@ -919,17 +749,9 @@ vi_prev_char(el, c) */ protected el_action_t /*ARGSUSED*/ -vi_to_next_char(el, c) - EditLine *el; - int c; +vi_to_next_char(EditLine *el, int c __attribute__((__unused__))) { - char ch; - - if (el_getc(el, &ch) != 1) - return ed_end_of_file(el, 0); - - return cv_csearch_fwd(el, ch, el->el_state.argument, 1); - + return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 1); } @@ -939,15 +761,9 @@ vi_to_next_char(el, c) */ protected el_action_t /*ARGSUSED*/ -vi_to_prev_char(el, c) - EditLine *el; - int c; +vi_to_prev_char(EditLine *el, int c __attribute__((__unused__))) { - char ch; - if (el_getc(el, &ch) != 1) - return ed_end_of_file(el, 0); - - return cv_csearch_back(el, ch, el->el_state.argument, 1); + return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 1); } @@ -957,16 +773,11 @@ vi_to_prev_char(el, c) */ protected el_action_t /*ARGSUSED*/ -vi_repeat_next_char(el, c) - EditLine *el; - int c; +vi_repeat_next_char(EditLine *el, int c __attribute__((__unused__))) { - if (el->el_search.chacha == 0) - return CC_ERROR; - return el->el_search.chadir == CHAR_FWD ? - cv_csearch_fwd(el, el->el_search.chacha, el->el_state.argument, 0) : - cv_csearch_back(el, el->el_search.chacha, el->el_state.argument, 0); + return cv_csearch(el, el->el_search.chadir, el->el_search.chacha, + el->el_state.argument, el->el_search.chatflg); } @@ -976,14 +787,345 @@ vi_repeat_next_char(el, c) */ protected el_action_t /*ARGSUSED*/ -vi_repeat_prev_char(el, c) - EditLine *el; - int c; +vi_repeat_prev_char(EditLine *el, int c __attribute__((__unused__))) +{ + el_action_t r; + int dir = el->el_search.chadir; + + r = cv_csearch(el, -dir, el->el_search.chacha, + el->el_state.argument, el->el_search.chatflg); + el->el_search.chadir = dir; + return r; +} + + +/* vi_match(): + * Vi go to matching () {} or [] + * [%] + */ +protected el_action_t +/*ARGSUSED*/ +vi_match(EditLine *el, int c) +{ + const char match_chars[] = "()[]{}"; + char *cp; + int delta, i, count; + char o_ch, c_ch; + + *el->el_line.lastchar = '\0'; /* just in case */ + + i = strcspn(el->el_line.cursor, match_chars); + o_ch = el->el_line.cursor[i]; + if (o_ch == 0) + return CC_ERROR; + delta = strchr(match_chars, o_ch) - match_chars; + c_ch = match_chars[delta ^ 1]; + count = 1; + delta = 1 - (delta & 1) * 2; + + for (cp = &el->el_line.cursor[i]; count; ) { + cp += delta; + if (cp < el->el_line.buffer || cp >= el->el_line.lastchar) + return CC_ERROR; + if (*cp == o_ch) + count++; + else if (*cp == c_ch) + count--; + } + + el->el_line.cursor = cp; + + if (el->el_chared.c_vcmd.action != NOP) { + /* NB posix says char under cursor should NOT be deleted + for -ve delta - this is different to netbsd vi. */ + if (delta > 0) + el->el_line.cursor++; + cv_delfini(el); + return (CC_REFRESH); + } + return (CC_CURSOR); +} + +/* vi_undo_line(): + * Vi undo all changes to line + * [U] + */ +protected el_action_t +/*ARGSUSED*/ +vi_undo_line(EditLine *el, int c) +{ + + cv_undo(el); + return hist_get(el); +} + +/* vi_to_column(): + * Vi go to specified column + * [|] + * NB netbsd vi goes to screen column 'n', posix says nth character + */ +protected el_action_t +/*ARGSUSED*/ +vi_to_column(EditLine *el, int c) +{ + + el->el_line.cursor = el->el_line.buffer; + el->el_state.argument--; + return ed_next_char(el, 0); +} + +/* vi_yank_end(): + * Vi yank to end of line + * [Y] + */ +protected el_action_t +/*ARGSUSED*/ +vi_yank_end(EditLine *el, int c) +{ + + cv_yank(el, el->el_line.cursor, + el->el_line.lastchar - el->el_line.cursor); + return CC_REFRESH; +} + +/* vi_yank(): + * Vi yank + * [y] + */ +protected el_action_t +/*ARGSUSED*/ +vi_yank(EditLine *el, int c) +{ + + return cv_action(el, YANK); +} + +/* vi_comment_out(): + * Vi comment out current command + * [c] + */ +protected el_action_t +/*ARGSUSED*/ +vi_comment_out(EditLine *el, int c) +{ + + el->el_line.cursor = el->el_line.buffer; + c_insert(el, 1); + *el->el_line.cursor = '#'; + re_refresh(el); + return ed_newline(el, 0); +} + +/* vi_alias(): + * Vi include shell alias + * [@] + * NB: posix impiles that we should enter insert mode, however + * this is against historical precedent... + */ +protected el_action_t +/*ARGSUSED*/ +vi_alias(EditLine *el, int c) { - if (el->el_search.chacha == 0) +#ifdef __weak_extern + char alias_name[3]; + char *alias_text; + extern char *get_alias_text(const char *); + __weak_extern(get_alias_text); + + if (get_alias_text == 0) { + return CC_ERROR; + } + + alias_name[0] = '_'; + alias_name[2] = 0; + if (el_getc(el, &alias_name[1]) != 1) + return CC_ERROR; + + alias_text = get_alias_text(alias_name); + if (alias_text != NULL) + el_push(el, alias_text); + return CC_NORM; +#else return CC_ERROR; +#endif +} + +/* vi_to_history_line(): + * Vi go to specified history file line. + * [G] + */ +protected el_action_t +/*ARGSUSED*/ +vi_to_history_line(EditLine *el, int c) +{ + int sv_event_no = el->el_history.eventno; + el_action_t rval; + + + if (el->el_history.eventno == 0) { + (void) strncpy(el->el_history.buf, el->el_line.buffer, + EL_BUFSIZ); + el->el_history.last = el->el_history.buf + + (el->el_line.lastchar - el->el_line.buffer); + } + + /* Lack of a 'count' means oldest, not 1 */ + if (!el->el_state.doingarg) { + el->el_history.eventno = 0x7fffffff; + hist_get(el); + } else { + /* This is brain dead, all the rest of this code counts + * upwards going into the past. Here we need count in the + * other direction (to match the output of fc -l). + * I could change the world, but this seems to suffice. + */ + el->el_history.eventno = 1; + if (hist_get(el) == CC_ERROR) + return CC_ERROR; + el->el_history.eventno = 1 + el->el_history.ev.num + - el->el_state.argument; + if (el->el_history.eventno < 0) { + el->el_history.eventno = sv_event_no; + return CC_ERROR; + } + } + rval = hist_get(el); + if (rval == CC_ERROR) + el->el_history.eventno = sv_event_no; + return rval; +} + +/* vi_histedit(): + * Vi edit history line with vi + * [v] + */ +protected el_action_t +/*ARGSUSED*/ +vi_histedit(EditLine *el, int c) +{ + int fd; + pid_t pid; + int st; + char tempfile[] = "/tmp/histedit.XXXXXXXXXX"; + char *cp; + + if (el->el_state.doingarg) { + if (vi_to_history_line(el, 0) == CC_ERROR) + return CC_ERROR; + } + + fd = mkstemp(tempfile); + if (fd < 0) + return CC_ERROR; + cp = el->el_line.buffer; + write(fd, cp, el->el_line.lastchar - cp +0u); + write(fd, "\n", 1); + pid = fork(); + switch (pid) { + case -1: + close(fd); + unlink(tempfile); + return CC_ERROR; + case 0: + close(fd); + execlp("vi", "vi", tempfile, (char*)NULL); + exit(0); + /*NOTREACHED*/ + default: + while (waitpid(pid, &st, 0) != pid) + continue; + lseek(fd, 0ll, SEEK_SET); + st = read(fd, cp, el->el_line.limit - cp +0u); + if (st > 0 && cp[st - 1] == '\n') + st--; + el->el_line.cursor = cp; + el->el_line.lastchar = cp + st; + break; + } + + close(fd); + unlink(tempfile); + /* return CC_REFRESH; */ + return ed_newline(el, 0); +} + +/* vi_history_word(): + * Vi append word from previous input line + * [_] + * Who knows where this one came from! + * '_' in vi means 'entire current line', so 'cc' is a synonym for 'c_' + */ +protected el_action_t +/*ARGSUSED*/ +vi_history_word(EditLine *el, int c) +{ + const char *wp = HIST_FIRST(el); + const char *wep, *wsp; + int len; + char *cp; + const char *lim; + + if (wp == NULL) + return CC_ERROR; + + wep = wsp = 0; + do { + while (isspace((unsigned char)*wp)) + wp++; + if (*wp == 0) + break; + wsp = wp; + while (*wp && !isspace((unsigned char)*wp)) + wp++; + wep = wp; + } while ((!el->el_state.doingarg || --el->el_state.argument > 0) && *wp != 0); + + if (wsp == 0 || (el->el_state.doingarg && el->el_state.argument != 0)) + return CC_ERROR; + + cv_undo(el); + len = wep - wsp; + if (el->el_line.cursor < el->el_line.lastchar) + el->el_line.cursor++; + c_insert(el, len + 1); + cp = el->el_line.cursor; + lim = el->el_line.limit; + if (cp < lim) + *cp++ = ' '; + while (wsp < wep && cp < lim) + *cp++ = *wsp++; + el->el_line.cursor = cp; + + el->el_map.current = el->el_map.key; + return CC_REFRESH; +} + +/* vi_redo(): + * Vi redo last non-motion command + * [.] + */ +protected el_action_t +/*ARGSUSED*/ +vi_redo(EditLine *el, int c) +{ + c_redo_t *r = &el->el_chared.c_redo; + + if (!el->el_state.doingarg && r->count) { + el->el_state.doingarg = 1; + el->el_state.argument = r->count; + } + + el->el_chared.c_vcmd.pos = el->el_line.cursor; + el->el_chared.c_vcmd.action = r->action; + if (r->pos != r->buf) { + if (r->pos + 1 > r->lim) + /* sanity */ + r->pos = r->lim - 1; + r->pos[0] = 0; + el_push(el, r->buf); + } - return el->el_search.chadir == CHAR_BACK ? - cv_csearch_fwd(el, el->el_search.chacha, el->el_state.argument, 0) : - cv_csearch_back(el, el->el_search.chacha, el->el_state.argument, 0); + el->el_state.thiscmd = r->cmd; + el->el_state.thisch = r->ch; + return (*el->el_map.func[r->cmd])(el, r->ch); } |