aboutsummaryrefslogtreecommitdiff
path: root/lib/libedit
diff options
context:
space:
mode:
authorRodney W. Grimes <rgrimes@FreeBSD.org>1994-05-27 05:00:24 +0000
committerRodney W. Grimes <rgrimes@FreeBSD.org>1994-05-27 05:00:24 +0000
commit58f0484fa251c266ede97b591b499fe3dd4f578e (patch)
tree41932a7161f4cd72005330a9c69747e7bab2ee5b /lib/libedit
parentfb49e767ba942f74b1cee8814e085e5f2615ac53 (diff)
downloadsrc-58f0484fa251c266ede97b591b499fe3dd4f578e.tar.gz
src-58f0484fa251c266ede97b591b499fe3dd4f578e.zip
Notes
Diffstat (limited to 'lib/libedit')
-rw-r--r--lib/libedit/Makefile58
-rw-r--r--lib/libedit/TEST/test.c213
-rw-r--r--lib/libedit/chared.c639
-rw-r--r--lib/libedit/chared.h158
-rw-r--r--lib/libedit/common.c994
-rw-r--r--lib/libedit/el.c335
-rw-r--r--lib/libedit/el.h129
-rw-r--r--lib/libedit/emacs.c508
-rw-r--r--lib/libedit/hist.c170
-rw-r--r--lib/libedit/hist.h75
-rw-r--r--lib/libedit/histedit.h172
-rw-r--r--lib/libedit/history.c602
-rw-r--r--lib/libedit/key.c726
-rw-r--r--lib/libedit/key.h80
-rw-r--r--lib/libedit/makelist187
-rw-r--r--lib/libedit/map.c1397
-rw-r--r--lib/libedit/map.h77
-rw-r--r--lib/libedit/parse.c247
-rw-r--r--lib/libedit/parse.h50
-rw-r--r--lib/libedit/prompt.c123
-rw-r--r--lib/libedit/prompt.h59
-rw-r--r--lib/libedit/read.c437
-rw-r--r--lib/libedit/refresh.c1013
-rw-r--r--lib/libedit/refresh.h60
-rw-r--r--lib/libedit/search.c619
-rw-r--r--lib/libedit/search.h68
-rw-r--r--lib/libedit/sig.c193
-rw-r--r--lib/libedit/sig.h70
-rw-r--r--lib/libedit/sys.h113
-rw-r--r--lib/libedit/term.c1447
-rw-r--r--lib/libedit/term.h118
-rw-r--r--lib/libedit/termcap.h52
-rw-r--r--lib/libedit/tokenizer.c385
-rw-r--r--lib/libedit/tokenizer.h53
-rw-r--r--lib/libedit/tty.c1144
-rw-r--r--lib/libedit/tty.h476
-rw-r--r--lib/libedit/vi.c986
37 files changed, 14233 insertions, 0 deletions
diff --git a/lib/libedit/Makefile b/lib/libedit/Makefile
new file mode 100644
index 000000000000..9dc0471b02cd
--- /dev/null
+++ b/lib/libedit/Makefile
@@ -0,0 +1,58 @@
+# @(#)Makefile 8.1 (Berkeley) 6/4/93
+
+LIB= edit
+
+OSRCS= chared.c common.c el.c emacs.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 fcns.c
+
+# For speed and debugging
+#SRCS= ${OSRCS} tokenizer.c history.c
+# For protection
+SRCS= editline.c tokenizer.c history.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
+
+AHDR=vi.h emacs.h common.h
+ASRC=${.CURDIR}/vi.c ${.CURDIR}/emacs.c ${.CURDIR}/common.c
+
+vi.h: vi.c makelist
+ sh ${.CURDIR}/makelist -h ${.CURDIR}/vi.c > ${.TARGET}
+
+emacs.h: emacs.c makelist
+ sh ${.CURDIR}/makelist -h ${.CURDIR}/emacs.c > ${.TARGET}
+
+common.h: common.c makelist
+ sh ${.CURDIR}/makelist -h ${.CURDIR}/common.c > ${.TARGET}
+
+fcns.h: ${AHDR} makelist
+ sh ${.CURDIR}/makelist -fh ${AHDR} > ${.TARGET}
+
+fcns.c: ${AHDR} fcns.h makelist
+ sh ${.CURDIR}/makelist -fc ${AHDR} > ${.TARGET}
+
+help.c: ${ASRC} makelist
+ sh ${.CURDIR}/makelist -bc ${ASRC} > ${.TARGET}
+
+help.h: ${ASRC} makelist
+ sh ${.CURDIR}/makelist -bh ${ASRC} > ${.TARGET}
+
+editline.c: ${OSRCS}
+ sh ${.CURDIR}/makelist -e ${.ALLSRC:T} > ${.TARGET}
+
+.depend: vi.h emacs.h common.h fcns.h help.h help.c
+
+
+test: libedit.a test.o
+ ${CC} ${CFLAGS} ${.ALLSRC} -o ${.TARGET} libedit.a ${LDADD} -ltermcap
+
+beforeinstall:
+ -cd ${.CURDIR}; cmp -s histedit.h ${DESTDIR}/usr/include/histedit.h > \
+ /dev/null 2>&1 || \
+ install -c -o ${BINOWN} -g ${BINGRP} -m 444 histedit.h \
+ ${DESTDIR}/usr/include
+
+.include <bsd.lib.mk>
diff --git a/lib/libedit/TEST/test.c b/lib/libedit/TEST/test.c
new file mode 100644
index 000000000000..f456f51277c9
--- /dev/null
+++ b/lib/libedit/TEST/test.c
@@ -0,0 +1,213 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char 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)
+static char sccsid[] = "@(#)test.c 8.1 (Berkeley) 6/4/93";
+#endif /* not lint && not SCCSID */
+
+/*
+ * test.c: A little test program
+ */
+#include "sys.h"
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <dirent.h>
+
+#include "histedit.h"
+#include "tokenizer.h"
+
+static int continuation = 0;
+static EditLine *el = NULL;
+
+static char *
+/*ARGSUSED*/
+prompt(el)
+ EditLine *el;
+{
+ static char a[] = "Edit$";
+ static char b[] = "Edit>";
+ return continuation ? b : a;
+}
+
+static void
+sig(i)
+ int i;
+{
+ (void) fprintf(stderr, "Got signal %d.\n", i);
+ el_reset(el);
+}
+
+static unsigned char
+/*ARGSUSED*/
+complete(el, ch)
+ 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;
+ }
+ }
+
+ closedir(dd);
+ return CC_ERROR;
+}
+
+int
+/*ARGSUSED*/
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ int num;
+ const char *buf;
+ Tokenizer *tok;
+ History *hist;
+
+ (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 */
+
+ tok = tok_init(NULL); /* Initialize the tokenizer */
+
+ el = el_init(*argv, stdin, stdout); /* Initialize editline */
+
+ 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);
+
+ /* 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 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);
+
+ while ((buf = el_gets(el, &num)) != NULL && num != 0) {
+ int ac;
+ char **av;
+#ifdef DEBUG
+ (void) fprintf(stderr, "got %d %s", num, buf);
+#endif
+ if (!continuation && num == 1)
+ continue;
+ if (tok_line(tok, buf, &ac, &av) > 0) {
+ history(hist, continuation ? H_ADD : H_ENTER, buf);
+ continuation = 1;
+ continue;
+ }
+ history(hist, continuation ? H_ADD : H_ENTER, buf);
+
+ continuation = 0;
+ if (el_parse(el, ac, av) != -1) {
+ tok_reset(tok);
+ continue;
+ }
+
+ 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);
+
+ return 0;
+}
diff --git a/lib/libedit/chared.c b/lib/libedit/chared.c
new file mode 100644
index 000000000000..5a393a762484
--- /dev/null
+++ b/lib/libedit/chared.c
@@ -0,0 +1,639 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if !defined(lint) && !defined(SCCSID)
+static char sccsid[] = "@(#)chared.c 8.1 (Berkeley) 6/4/93";
+#endif /* not lint && not SCCSID */
+
+/*
+ * chared.c: Character editor utilities
+ */
+#include "sys.h"
+
+#include <stdlib.h>
+#include "el.h"
+
+/* cv_undo():
+ * Handle state for the vi undo command
+ */
+protected void
+cv_undo(el, action, size, ptr)
+ EditLine *el;
+ int action, size;
+ char *ptr;
+{
+ 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_insert():
+ * Insert num characters
+ */
+protected void
+c_insert(el, num)
+ EditLine *el;
+ int num;
+{
+ char *cp;
+
+ if (el->el_line.lastchar + num >= el->el_line.limit)
+ return; /* can't go past end of buffer */
+
+ if (el->el_line.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 */
+
+
+/* c_delafter():
+ * Delete num characters after the cursor
+ */
+protected void
+c_delafter(el, num)
+ EditLine *el;
+ int num;
+{
+
+ 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, INSERT, num, el->el_line.cursor);
+
+ for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++)
+ *cp = cp[num];
+
+ el->el_line.lastchar -= num;
+ }
+}
+
+
+/* c_delbefore():
+ * Delete num characters before the cursor
+ */
+protected void
+c_delbefore(el, num)
+ EditLine *el;
+ int num;
+{
+
+ 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, INSERT, num, el->el_line.cursor - num);
+
+ for (cp = el->el_line.cursor - num; cp <= el->el_line.lastchar; cp++)
+ *cp = cp[num];
+
+ el->el_line.lastchar -= num;
+ }
+}
+
+
+/* ce__isword():
+ * Return if p is part of a word according to emacs
+ */
+protected int
+ce__isword(p)
+ int p;
+{
+ return isalpha(p) || isdigit(p) || strchr("*?_-.[]~=", p) != NULL;
+}
+
+
+/* cv__isword():
+ * Return if p is part of a word according to vi
+ */
+protected int
+cv__isword(p)
+ int p;
+{
+ return !isspace(p);
+}
+
+
+/* c__prev_word():
+ * Find the previous word
+ */
+protected char *
+c__prev_word(p, low, n, wtest)
+ register char *p, *low;
+ register int n;
+ int (*wtest) __P((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;
+}
+
+
+/* c__next_word():
+ * Find the next word
+ */
+protected char *
+c__next_word(p, high, n, wtest)
+ register char *p, *high;
+ register int n;
+ int (*wtest) __P((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;
+}
+
+/* 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) __P((int));
+{
+ 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 (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;
+}
+
+
+/* cv_prev_word():
+ * 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) __P((int));
+{
+ 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--;
+ p++;
+ while (isspace((unsigned char) *p))
+ p++;
+ }
+
+ /* p now points where we want it */
+ if (p < low)
+ return low;
+ else
+ return p;
+}
+
+
+#ifdef notdef
+/* c__number():
+ * Ignore character p points to, return number appearing after that.
+ * A '$' by itself means a big number; "$-" is for negative; '^' means 1.
+ * 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 */
+{
+ register int i;
+ register int sign = 1;
+
+ if (*++p == '^') {
+ *num = 1;
+ return p;
+ }
+ if (*p == '$') {
+ if (*++p != '-') {
+ *num = 0x7fffffff; /* Handle $ */
+ return --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;
+}
+#endif
+
+/* cv_delfini():
+ * Finish vi delete action
+ */
+protected void
+cv_delfini(el)
+ EditLine *el;
+{
+ register int size;
+ int oaction;
+
+ if (el->el_chared.c_vcmd.action & INSERT)
+ el->el_map.current = el->el_map.key;
+
+ oaction = el->el_chared.c_vcmd.action;
+ el->el_chared.c_vcmd.action = NOP;
+
+ if (el->el_chared.c_vcmd.pos == 0)
+ return;
+
+
+ if (el->el_line.cursor > el->el_chared.c_vcmd.pos) {
+ size = (int) (el->el_line.cursor - el->el_chared.c_vcmd.pos);
+ c_delbefore(el, size);
+ el->el_line.cursor = el->el_chared.c_vcmd.pos;
+ re_refresh_cursor(el);
+ }
+ else if (el->el_line.cursor < el->el_chared.c_vcmd.pos) {
+ size = (int)(el->el_chared.c_vcmd.pos - el->el_line.cursor);
+ c_delafter(el, size);
+ }
+ else {
+ size = 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;
+}
+
+
+#ifdef notdef
+/* ce__endword():
+ * Go to the end of this word according to emacs
+ */
+protected char *
+ce__endword(p, high, n)
+ char *p, *high;
+ int n;
+{
+ p++;
+
+ while (n--) {
+ while ((p < high) && isspace((unsigned char) *p))
+ p++;
+ while ((p < high) && !isspace((unsigned char) *p))
+ p++;
+ }
+
+ p--;
+ return p;
+}
+#endif
+
+
+/* cv__endword():
+ * Go to the end of this word according to vi
+ */
+protected char *
+cv__endword(p, high, n)
+ char *p, *high;
+ int n;
+{
+ 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;
+}
+
+/* ch_init():
+ * Initialize the character editor
+ */
+protected int
+ch_init(el)
+ 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;
+}
+
+/* ch_reset():
+ * Reset the character editor
+ */
+protected void
+ch_reset(el)
+ EditLine *el;
+{
+ 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_vcmd.action = NOP;
+ el->el_chared.c_vcmd.pos = el->el_line.buffer;
+ el->el_chared.c_vcmd.ins = el->el_line.buffer;
+
+ el->el_chared.c_kill.mark = el->el_line.buffer;
+
+ 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.level = -1;
+
+ el->el_history.eventno = 0;
+}
+
+
+/* ch_end():
+ * Free the data structures used by the editor
+ */
+protected void
+ch_end(el)
+ 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_insertstr():
+ * Insert string at cursorI
+ */
+public int
+el_insertstr(el, s)
+ EditLine *el;
+ char *s;
+{
+ int len;
+
+ if ((len = strlen(s)) == 0)
+ return -1;
+ if (el->el_line.lastchar + len >= el->el_line.limit)
+ return -1;
+
+ c_insert(el, len);
+ while (*s)
+ *el->el_line.cursor++ = *s++;
+ return 0;
+}
+
+
+/* el_deletestr():
+ * Delete num characters before the cursor
+ */
+public void
+el_deletestr(el, n)
+ EditLine *el;
+ int n;
+{
+ if (n <= 0)
+ 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_gets():
+ * Get a string
+ */
+protected int
+c_gets(el, buf)
+ EditLine *el;
+ char *buf;
+{
+ 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;
+ }
+ }
+ buf[len] = ch;
+ return len;
+}
+
+
+/* c_hpos():
+ * Return the current horizontal position of the cursor
+ */
+protected int
+c_hpos(el)
+ EditLine *el;
+{
+ 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;
+ }
+}
diff --git a/lib/libedit/chared.h b/lib/libedit/chared.h
new file mode 100644
index 000000000000..20da6c87a6db
--- /dev/null
+++ b/lib/libedit/chared.h
@@ -0,0 +1,158 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)chared.h 8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.chared.h: Character editor interface
+ */
+#ifndef _h_el_chared
+#define _h_el_chared
+
+#include <ctype.h>
+#include <string.h>
+
+#include "histedit.h"
+
+#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
+ * 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
+
+
+typedef struct c_macro_t {
+ int level;
+ char **macro;
+ char *nline;
+} c_macro_t;
+
+/*
+ * Undo information for both vi and emacs
+ */
+typedef struct c_undo_t {
+ int action;
+ int isize;
+ int dsize;
+ char *ptr;
+ char *buf;
+} c_undo_t;
+
+/*
+ * Current action information for vi
+ */
+typedef struct c_vcmd_t {
+ int action;
+ char *pos;
+ char *ins;
+} c_vcmd_t;
+
+/*
+ * Kill buffer for emacs
+ */
+typedef struct c_kill_t {
+ char *buf;
+ char *last;
+ char *mark;
+} c_kill_t;
+
+/*
+ * Note that we use both data structures because the user can bind
+ * 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;
+} el_chared_t;
+
+
+#define STReof "^D\b\b"
+#define STRQQ "\"\""
+
+#define isglob(a) (strchr("*[]?", (a)) != NULL)
+#define isword(a) (isprint(a))
+
+#define NOP 0x00
+#define DELETE 0x01
+#define INSERT 0x02
+#define CHANGE 0x04
+
+#define CHAR_FWD 0
+#define CHAR_BACK 1
+
+#define MODE_INSERT 0
+#define MODE_REPLACE 1
+#define MODE_REPLACE_1 2
+
+#include "common.h"
+#include "vi.h"
+#include "emacs.h"
+#include "search.h"
+#include "fcns.h"
+
+
+protected int cv__isword __P((int));
+protected void cv_delfini __P((EditLine *));
+protected char *cv__endword __P((char *, char *, int));
+protected int ce__isword __P((int));
+protected void cv_undo __P((EditLine *, int, int, char *));
+protected char *cv_next_word __P((EditLine*, char *, char *, int,
+ int (*)(int)));
+protected char *cv_prev_word __P((EditLine*, char *, char *, int,
+ int (*)(int)));
+protected char *c__next_word __P((char *, char *, int, int (*)(int)));
+protected char *c__prev_word __P((char *, char *, int, int (*)(int)));
+protected void c_insert __P((EditLine *, int));
+protected void c_delbefore __P((EditLine *, int));
+protected void c_delafter __P((EditLine *, int));
+protected int c_gets __P((EditLine *, char *));
+protected int c_hpos __P((EditLine *));
+
+protected int ch_init __P((EditLine *));
+protected void ch_reset __P((EditLine *));
+protected void ch_end __P((EditLine *));
+
+#endif /* _h_el_chared */
diff --git a/lib/libedit/common.c b/lib/libedit/common.c
new file mode 100644
index 000000000000..696da528e510
--- /dev/null
+++ b/lib/libedit/common.c
@@ -0,0 +1,994 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if !defined(lint) && !defined(SCCSID)
+static char sccsid[] = "@(#)common.c 8.1 (Berkeley) 6/4/93";
+#endif /* not lint && not SCCSID */
+
+/*
+ * common.c: Common Editor functions
+ */
+#include "sys.h"
+#include "el.h"
+
+/* ed_end_of_file():
+ * Indicate end of file
+ * [^D]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_end_of_file(el, c)
+ EditLine *el;
+ int c;
+{
+ re_goto_bottom(el);
+ *el->el_line.lastchar = '\0';
+ return CC_EOF;
+}
+
+
+/* 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;
+{
+ 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 */
+
+ if (el->el_state.argument == 1) {
+ if (el->el_state.inputmode != MODE_INSERT) {
+ el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
+ *el->el_line.cursor;
+ el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] = '\0';
+ c_delafter(el, 1);
+ }
+
+ c_insert(el, 1);
+
+ *el->el_line.cursor++ = c;
+ el->el_state.doingarg = 0; /* just in case */
+ re_fastaddc(el); /* fast refresh for one char. */
+ }
+ else {
+ if (el->el_state.inputmode != MODE_INSERT) {
+
+ for(i = 0;i < el->el_state.argument; i++)
+ el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
+ el->el_line.cursor[i];
+
+ el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] = '\0';
+ c_delafter(el, el->el_state.argument);
+ }
+
+ c_insert(el, el->el_state.argument);
+
+ while (el->el_state.argument--)
+ *el->el_line.cursor++ = c;
+ re_refresh(el);
+ }
+
+ if (el->el_state.inputmode == MODE_REPLACE_1)
+ (void) vi_command_mode(el, 0);
+
+ return CC_NORM;
+}
+
+
+/* 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;
+{
+ char *cp, *p, *kp;
+
+ 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);
+
+ 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;
+}
+
+
+/* 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);
+#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 */
+#ifdef KSHVI
+ return CC_ERROR;
+#else
+ term_overwrite(el, STReof, 4);/* then do a EOF */
+ term__flush();
+ return CC_EOF;
+#endif
+ }
+ else {
+#ifdef KSHVI
+ el->el_line.cursor--;
+#else
+ return CC_ERROR;
+#endif
+ }
+ }
+ 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;
+}
+
+
+/* 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;
+{
+ 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;
+}
+
+
+/* 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;
+{
+ el->el_line.cursor = el->el_line.lastchar;
+ if (el->el_map.type == MAP_VI) {
+#ifdef VI_MOVE
+ el->el_line.cursor--;
+#endif
+ if (el->el_chared.c_vcmd.action & DELETE) {
+ cv_delfini(el);
+ return CC_REFRESH;
+ }
+ }
+ return CC_CURSOR;
+}
+
+
+/* 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;
+ }
+ }
+
+ return CC_CURSOR;
+}
+
+
+/* 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_next_char():
+ * Move to the right one character
+ * [^F] [^F]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_next_char(el, c)
+ EditLine *el;
+ int c;
+{
+ if (el->el_line.cursor >= el->el_line.lastchar)
+ return CC_ERROR;
+
+ el->el_line.cursor += el->el_state.argument;
+ if (el->el_line.cursor > el->el_line.lastchar)
+ el->el_line.cursor = el->el_line.lastchar;
+
+ if (el->el_map.type == MAP_VI)
+ if (el->el_chared.c_vcmd.action & DELETE) {
+ cv_delfini(el);
+ return CC_REFRESH;
+ }
+
+ return CC_CURSOR;
+}
+
+
+/* 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;
+{
+ 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_map.type == MAP_VI)
+ if (el->el_chared.c_vcmd.action & DELETE) {
+ cv_delfini(el);
+ return CC_REFRESH;
+ }
+
+ return CC_CURSOR;
+}
+
+
+/* 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;
+{
+ 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;
+ }
+
+ return CC_CURSOR;
+ }
+ else
+ return CC_ERROR;
+}
+
+
+/* ed_quoted_insert():
+ * Add the next character typed verbatim
+ * [^V] [^V]
+ */
+protected el_action_t
+ed_quoted_insert(el, c)
+ EditLine *el;
+ int c;
+{
+ 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);
+}
+
+
+/* ed_digit():
+ * Adds to argument or enters a digit
+ */
+protected el_action_t
+ed_digit(el, c)
+ 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');
+ }
+ 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():
+ * Digit that starts argument
+ * For ESC-n
+ */
+protected el_action_t
+ed_argument_digit(el, c)
+ EditLine *el;
+ register 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;
+}
+
+
+/* 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;
+{
+ term_beep(el);
+ term__flush();
+ return CC_NORM;
+}
+
+
+/**
+ ** TTY key handling.
+ **/
+
+/* 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_dsusp():
+ * Tty delayed suspend character
+ * [^Y]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_tty_dsusp(el, c)
+ EditLine *el;
+ int c;
+{
+ return CC_NORM;
+}
+
+
+/* ed_tty_flush_output():
+ * Tty flush output characters
+ * [^O]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_tty_flush_output(el, c)
+ EditLine *el;
+ int c;
+{
+ return CC_NORM;
+}
+
+
+/* ed_tty_sigquit():
+ * Tty quit character
+ * [^\]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_tty_sigquit(el, c)
+ EditLine *el;
+ int c;
+{
+ return CC_NORM;
+}
+
+
+/* ed_tty_sigtstp():
+ * Tty suspend character
+ * [^Z]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_tty_sigtstp(el, c)
+ EditLine *el;
+ int c;
+{
+ return CC_NORM;
+}
+
+
+/* ed_tty_stop_output():
+ * Tty disallow output characters
+ * [^S]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_tty_stop_output(el, c)
+ EditLine *el;
+ int c;
+{
+ return CC_NORM;
+}
+
+
+/* ed_tty_start_output():
+ * Tty allow output characters
+ * [^Q]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_tty_start_output(el, c)
+ EditLine *el;
+ int c;
+{
+ return CC_NORM;
+}
+
+
+/* ed_newline():
+ * Execute command
+ * [^J]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_newline(el, c)
+ EditLine *el;
+ int c;
+{
+ 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;
+}
+
+
+/* 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;
+{
+ 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():
+ * Clear screen leaving current line at the top
+ * [^L]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_clear_screen(el, c)
+ EditLine *el;
+ int c;
+{
+ term_clear_screen(el); /* clear the whole real screen */
+ re_clear_display(el); /* reset everything */
+ return CC_REFRESH;
+}
+
+
+/* ed_redisplay():
+ * Redisplay everything
+ * ^R
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_redisplay(el, c)
+ EditLine *el;
+ int c;
+{
+ re_clear_lines(el);
+ re_clear_display(el);
+ return CC_REFRESH;
+}
+
+
+/* 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;
+{
+ ch_reset(el);
+ return CC_REFRESH;
+}
+
+
+/* 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;
+{
+ return CC_NORM;
+}
+
+
+/* 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;
+{
+ 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);
+ 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) {
+ beep = 1;
+ /* el->el_history.eventno was fixed by first call */
+ (void) hist_get(el);
+ }
+
+ re_refresh(el);
+ if (beep)
+ return CC_ERROR;
+ else
+ return CC_NORM; /* was CC_UP_HIST */
+}
+
+
+/* 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;
+{
+ el->el_chared.c_undo.action = NOP;
+ *el->el_line.lastchar = '\0'; /* just in case */
+
+ el->el_history.eventno -= el->el_state.argument;
+
+ if (el->el_history.eventno < 0) {
+ el->el_history.eventno = 0;
+ return CC_ERROR; /* make it beep */
+ }
+
+ return hist_get(el);
+}
+
+
+/* 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) {
+#ifdef DEBUG_EDIT
+ (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);
+ 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;
+
+ c_setpat(el); /* Set search pattern !! */
+
+ for (h = 1; h <= el->el_history.eventno; h++)
+ hp = HIST_NEXT(el);
+
+ while (hp != NULL) {
+#ifdef SDEBUG
+ (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;
+ }
+ h++;
+ hp = HIST_NEXT(el);
+ }
+
+ if (!found) {
+#ifdef SDEBUG
+ (void) fprintf(el->el_errfile, "not found\n");
+#endif
+ return CC_ERROR;
+ }
+
+ el->el_history.eventno = h;
+
+ return hist_get(el);
+}
+
+
+/* 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;
+{
+ 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)
+ return CC_ERROR;
+
+ if (el->el_history.ref == NULL)
+ return CC_ERROR;
+
+ hp = HIST_FIRST(el);
+ if (hp == NULL)
+ return CC_ERROR;
+
+ c_setpat(el); /* Set search pattern !! */
+
+ for (h = 1; h < el->el_history.eventno && hp; h++) {
+#ifdef SDEBUG
+ (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)) {
+#ifdef SDEBUG
+ (void) fprintf(el->el_errfile, "not found\n");
+#endif
+ return CC_ERROR;
+ }
+ }
+
+ el->el_history.eventno = found;
+
+ return hist_get(el);
+}
+
+
+/* ed_prev_line():
+ * Move up one line
+ * Could be [k] [^p]
+ */
+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_next_line():
+ * Move down one line
+ * Could be [j] [^n]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_next_line(el, c)
+ EditLine *el;
+ int c;
+{
+ 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;
+
+ 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;
+
+ el->el_line.cursor = ptr;
+ return CC_CURSOR;
+}
+
+
+/* ed_command():
+ * Editline extended command
+ * [M-X] [:]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_command(el, c)
+ EditLine *el;
+ int c;
+{
+ char tmpbuf[EL_BUFSIZ];
+ int tmplen;
+
+ el->el_line.buffer[0] = '\0';
+ el->el_line.lastchar = el->el_line.buffer;
+ el->el_line.cursor = el->el_line.buffer;
+
+ c_insert(el, 3); /* prompt + ": " */
+ *el->el_line.cursor++ = '\n';
+ *el->el_line.cursor++ = ':';
+ *el->el_line.cursor++ = ' ';
+ re_refresh(el);
+
+ tmplen = c_gets(el, tmpbuf);
+ tmpbuf[tmplen] = '\0';
+
+ el->el_line.buffer[0] = '\0';
+ el->el_line.lastchar = el->el_line.buffer;
+ el->el_line.cursor = el->el_line.buffer;
+
+ if (parse_line(el, tmpbuf) == -1)
+ return CC_ERROR;
+ else
+ return CC_REFRESH;
+}
diff --git a/lib/libedit/el.c b/lib/libedit/el.c
new file mode 100644
index 000000000000..7314477a69ac
--- /dev/null
+++ b/lib/libedit/el.c
@@ -0,0 +1,335 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if !defined(lint) && !defined(SCCSID)
+static char sccsid[] = "@(#)el.c 8.2 (Berkeley) 1/3/94";
+#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>
+#if __STDC__
+# include <stdarg.h>
+#else
+# include <varargs.h>
+#endif
+#include "el.h"
+
+/* el_init():
+ * Initialize editline and set default parameters.
+ */
+public EditLine *
+el_init(prog, fin, fout)
+ const char *prog;
+ FILE *fin, *fout;
+{
+ EditLine *el = (EditLine *) el_malloc(sizeof(EditLine));
+#ifdef DEBUG
+ char *tty;
+#endif
+
+ if (el == NULL)
+ return NULL;
+
+ memset(el, 0, sizeof(EditLine));
+
+ el->el_infd = fileno(fin);
+ el->el_outfile = fout;
+ el->el_prog = strdup(prog);
+
+#ifdef DEBUG
+ if ((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));
+ 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 */
+
+
+/* el_end():
+ * Clean up.
+ */
+public void
+el_end(el)
+ EditLine *el;
+{
+ if (el == NULL)
+ return;
+
+ el_reset(el);
+
+ 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_free((ptr_t) el->el_prog);
+ el_free((ptr_t) el);
+} /* end el_end */
+
+
+/* el_reset():
+ * Reset the tty and the parser
+ */
+public void
+el_reset(el)
+ EditLine *el;
+{
+ tty_cookedmode(el);
+ ch_reset(el); /* XXX: Do we want that? */
+}
+
+
+/* el_set():
+ * set the editline parameters
+ */
+public int
+#if __STDC__
+el_set(EditLine *el, int op, ...)
+#else
+el_set(va_alist)
+ va_dcl
+#endif
+{
+ va_list va;
+ int rv;
+#if __STDC__
+ va_start(va, op);
+#else
+ EditLine *el;
+ int op;
+
+ va_start(va);
+ el = va_arg(va, EditLine *);
+ op = va_arg(va, int);
+#endif
+
+ 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:
+ {
+ 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;
+ abort();
+ break;
+ }
+ }
+ break;
+
+ 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;
+
+ default:
+ rv = -1;
+ }
+
+ va_end(va);
+ return rv;
+} /* end el_set */
+
+
+/* el_line():
+ * Return editing info
+ */
+public const LineInfo *
+el_line(el)
+ EditLine *el;
+{
+ return (const LineInfo *) &el->el_line;
+}
+
+static const char elpath[] = "/.editrc";
+
+/* el_source():
+ * Source a file
+ */
+public int
+el_source(el, fname)
+ EditLine *el;
+ const char *fname;
+{
+ FILE *fp;
+ size_t len;
+ char *ptr, path[MAXPATHLEN];
+
+ if (fname == NULL) {
+ fname = &elpath[1];
+ if ((fp = fopen(fname, "r")) == NULL) {
+ if ((ptr = getenv("HOME")) == NULL)
+ return -1;
+ fname = strncpy(path, ptr, MAXPATHLEN);
+ (void) strncat(path, elpath, MAXPATHLEN);
+ path[MAXPATHLEN-1] = '\0';
+ }
+ }
+
+ if ((fp = fopen(fname, "r")) == NULL)
+ return -1;
+
+ while ((ptr = fgetln(fp, &len)) != NULL)
+ ptr[len - 1] = '\0';
+ if (parse_line(el, ptr) == -1) {
+ (void) fclose(fp);
+ return -1;
+ }
+
+ (void) fclose(fp);
+ return 0;
+}
+
+
+/* el_resize():
+ * Called from program when terminal is resized
+ */
+public void
+el_resize(el)
+ 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);
+}
diff --git a/lib/libedit/el.h b/lib/libedit/el.h
new file mode 100644
index 000000000000..77cce15a3d45
--- /dev/null
+++ b/lib/libedit/el.h
@@ -0,0 +1,129 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)el.h 8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.h: Internal structures.
+ */
+#ifndef _h_el
+#define _h_el
+/*
+ * Local defaults
+ */
+#define KSHVI
+#define VIDEFAULT
+#define ANCHOR
+
+#include <stdio.h>
+#include <sys/types.h>
+
+#define EL_BUFSIZ 1024 /* Maximum line size */
+
+#define HANDLE_SIGNALS 1
+
+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;
+} coord_t;
+
+typedef struct el_line_t {
+ char *buffer, /* Input line */
+ *cursor, /* Cursor position */
+ *lastchar, /* Last character */
+ *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 */
+} 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)
+
+#include "tty.h"
+#include "prompt.h"
+#include "key.h"
+#include "term.h"
+#include "refresh.h"
+#include "chared.h"
+#include "common.h"
+#include "search.h"
+#include "hist.h"
+#include "map.h"
+#include "parse.h"
+#include "sig.h"
+#include "help.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 */
+};
+
+#endif /* _h_el */
diff --git a/lib/libedit/emacs.c b/lib/libedit/emacs.c
new file mode 100644
index 000000000000..f960a544a434
--- /dev/null
+++ b/lib/libedit/emacs.c
@@ -0,0 +1,508 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if !defined(lint) && !defined(SCCSID)
+static char sccsid[] = "@(#)emacs.c 8.1 (Berkeley) 6/4/93";
+#endif /* not lint && not SCCSID */
+
+/*
+ * emacs.c: Emacs functions
+ */
+#include "sys.h"
+#include "el.h"
+
+/* em_delete_or_list():
+ * Delete character under cursor or list completions if at end of line
+ * [^D]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_delete_or_list(el, c)
+ EditLine *el;
+ int c;
+{
+ if (el->el_line.cursor == el->el_line.lastchar) { /* if I'm at the end */
+#ifdef notyet
+ if (el->el_line.cursor == el->el_line.buffer) { /* and the beginning */
+#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;
+ }
+#endif
+ }
+ 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;
+ }
+}
+
+
+/* em_delete_next_word():
+ * Cut from cursor to end of current word
+ * [M-d]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_delete_next_word(el, c)
+ EditLine *el;
+ int c;
+{
+ char *cp, *p, *kp;
+
+ 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);
+
+ 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;
+}
+
+
+/* em_yank():
+ * Paste cut buffer at cursor position
+ * [^Y]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_yank(el, c)
+ EditLine *el;
+ int c;
+{
+ char *kp, *cp;
+
+ if (el->el_chared.c_kill.last == el->el_chared.c_kill.buf)
+ 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;
+
+ /* 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;
+
+ return CC_REFRESH;
+}
+
+
+/* em_kill_line():
+ * Cut the entire line and save in cut buffer
+ * [^U]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_kill_line(el, c)
+ EditLine *el;
+ int c;
+{
+ 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;
+}
+
+
+/* em_kill_region():
+ * Cut area between mark and cursor and save in cut buffer
+ * [^W]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_kill_region(el, c)
+ EditLine *el;
+ int c;
+{
+ 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;
+}
+
+
+/* em_copy_region():
+ * Copy area between mark and cursor to cut buffer
+ * [M-W]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_copy_region(el, c)
+ EditLine *el;
+ int c;
+{
+ 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():
+ * 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;
+{
+
+ 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;
+}
+
+
+/* em_next_word():
+ * Move next to end of current word
+ * [M-f]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_next_word(el, c)
+ EditLine *el;
+ int c;
+{
+ 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;
+}
+
+/* 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;
+{
+ 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 (islower(*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;
+}
+
+
+/* em_capitol_case():
+ * Capitalize the characters from cursor to end of current word
+ * [M-c]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_capitol_case(el, c)
+ EditLine *el;
+ int c;
+{
+ 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;
+ }
+ }
+ 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;
+}
+
+/* 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;
+{
+ 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 (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;
+}
+
+
+/* em_set_mark():
+ * Set the mark at cursor
+ * [^@]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_set_mark(el, c)
+ EditLine *el;
+ int c;
+{
+ el->el_chared.c_kill.mark = el->el_line.cursor;
+ return CC_NORM;
+}
+
+
+/* em_exchange_mark():
+ * Exchange the cursor and mark
+ * [^X^X]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_exchange_mark(el, c)
+ EditLine *el;
+ int c;
+{
+ register 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;
+}
+
+/* em_universal_argument():
+ * Universal argument (argument times 4)
+ * [^U]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_universal_argument(el, c)
+ EditLine *el;
+ int c;
+{ /* 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;
+}
+
+/* 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;
+{
+ el->el_state.metanext = 1;
+ return CC_ARGHACK;
+}
+
+
+/* em_toggle_overwrite():
+ * Switch from insert to overwrite mode or vice versa
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_toggle_overwrite(el, c)
+ EditLine *el;
+ int c;
+{
+ el->el_state.inputmode =
+ (el->el_state.inputmode == MODE_INSERT) ? MODE_REPLACE : MODE_INSERT;
+ return CC_NORM;
+}
+
+
+/* em_copy_prev_word():
+ * Copy current word to cursor
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_copy_prev_word(el, c)
+ EditLine *el;
+ int c;
+{
+ char *cp, *oldc, *dp;
+
+ 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);
+
+ 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 */
+
+ return CC_REFRESH;
+}
+
+
+/* em_inc_search_next():
+ * Emacs incremental next search
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_inc_search_next(el, c)
+ EditLine *el;
+ int c;
+{
+ el->el_search.patlen = 0;
+ return ce_inc_search(el, ED_SEARCH_NEXT_HISTORY);
+}
+
+
+/* em_inc_search_prev():
+ * Emacs incremental reverse search
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_inc_search_prev(el, c)
+ EditLine *el;
+ int c;
+{
+ 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
new file mode 100644
index 000000000000..394df63e9d3e
--- /dev/null
+++ b/lib/libedit/hist.c
@@ -0,0 +1,170 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if !defined(lint) && !defined(SCCSID)
+static char sccsid[] = "@(#)hist.c 8.1 (Berkeley) 6/4/93";
+#endif /* not lint && not SCCSID */
+
+/*
+ * hist.c: History access functions
+ */
+#include "sys.h"
+#include <stdlib.h>
+#include "el.h"
+
+/* hist_init():
+ * Initialization function.
+ */
+protected int
+hist_init(el)
+ 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;
+}
+
+
+/* hist_end():
+ * clean up history;
+ */
+protected void
+hist_end(el)
+ EditLine *el;
+{
+ el_free((ptr_t) el->el_history.buf);
+ el->el_history.buf = NULL;
+}
+
+
+/* hist_set():
+ * Set new history interface
+ */
+protected int
+hist_set(el, fun, ptr)
+ EditLine *el;
+ hist_fun_t fun;
+ ptr_t ptr;
+
+{
+ el->el_history.ref = ptr;
+ el->el_history.fun = fun;
+ return 0;
+}
+
+
+/* hist_get():
+ * Get a history line and update it in the buffer.
+ * eventno tells us the event to get.
+ */
+protected el_action_t
+hist_get(el)
+ EditLine *el;
+{
+ 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);
+ 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
+#endif /* KSHVI */
+ el->el_line.cursor = el->el_line.lastchar;
+
+ 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) strncpy(el->el_line.buffer, hp, EL_BUFSIZ);
+ el->el_line.lastchar = el->el_line.buffer + strlen(el->el_line.buffer);
+
+ if (el->el_line.lastchar > el->el_line.buffer) {
+ if (el->el_line.lastchar[-1] == '\n')
+ el->el_line.lastchar--;
+ if (el->el_line.lastchar[-1] == ' ')
+ el->el_line.lastchar--;
+ if (el->el_line.lastchar < el->el_line.buffer)
+ el->el_line.lastchar = el->el_line.buffer;
+ }
+
+#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;
+
+ return CC_REFRESH;
+}
+
+/* hist_list()
+ * List history entries
+ */
+protected int
+/*ARGSUSED*/
+hist_list(el, argc, argv)
+ EditLine *el;
+ int argc;
+ char **argv;
+{
+ const char *str;
+
+ 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;
+}
diff --git a/lib/libedit/hist.h b/lib/libedit/hist.h
new file mode 100644
index 000000000000..90c05698b489
--- /dev/null
+++ b/lib/libedit/hist.h
@@ -0,0 +1,75 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)hist.h 8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.hist.c: History functions
+ */
+#ifndef _h_el_hist
+#define _h_el_hist
+
+#include "histedit.h"
+
+typedef const HistEvent * (*hist_fun_t) __P((ptr_t, 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 */
+} 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_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)
+
+protected int hist_init __P((EditLine *));
+protected void hist_end __P((EditLine *));
+protected el_action_t hist_get __P((EditLine *));
+protected int hist_set __P((EditLine *, hist_fun_t, ptr_t));
+protected int hist_list __P((EditLine *, int, char **));
+
+#endif /* _h_el_hist */
diff --git a/lib/libedit/histedit.h b/lib/libedit/histedit.h
new file mode 100644
index 000000000000..95423c6482f5
--- /dev/null
+++ b/lib/libedit/histedit.h
@@ -0,0 +1,172 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)histedit.h 8.2 (Berkeley) 1/3/94
+ */
+
+/*
+ * histedit.h: Line editor and history interface.
+ */
+#ifndef _h_editline
+#define _h_editline
+
+#include <sys/types.h>
+#include <stdio.h>
+
+/*
+ * ==== Editing ====
+ */
+typedef struct editline EditLine;
+
+/*
+ * For user-defined function interface
+ */
+typedef struct lineinfo {
+ __const char *buffer;
+ __const char *cursor;
+ __const char *lastchar;
+} LineInfo;
+
+
+/*
+ * EditLine editor function return codes.
+ * For user-defined function interface
+ */
+#define CC_NORM 0
+#define CC_NEWLINE 1
+#define CC_EOF 2
+#define CC_ARGHACK 3
+#define CC_REFRESH 4
+#define CC_CURSOR 5
+#define CC_ERROR 6
+#define CC_FATAL 7
+
+/*
+ * Initialization, cleanup, and resetting
+ */
+EditLine *el_init __P((const char *, FILE *, FILE *));
+void el_reset __P((EditLine *));
+void el_end __P((EditLine *));
+
+
+/*
+ * Get a line, a character or push a string back in the input queue
+ */
+__const char *el_gets __P((EditLine *, int *));
+int el_getc __P((EditLine *, char *));
+void el_push __P((EditLine *, const char *));
+
+/*
+ * High level function internals control
+ * Parses argc, argv array and executes builtin editline commands
+ */
+int el_parse __P((EditLine *, int, char **));
+
+/*
+ * Low level editline access function
+ */
+int el_set __P((EditLine *, int, ...));
+
+/*
+ * 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_BIND 4 /* , const char *, ..., NULL); */
+#define EL_TELLTC 5 /* , const char *, ..., NULL); */
+#define EL_SETTC 6 /* , const char *, ..., NULL); */
+#define EL_ECHOTC 7 /* , const char *, ..., NULL); */
+#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 *); */
+
+/*
+ * Source named file or $PWD/.editrc or $HOME/.editrc
+ */
+int el_source __P((EditLine *, const char *));
+
+/*
+ * Must be called when the terminal changes size; If EL_SIGNAL
+ * is set this is done automatically otherwise it is the responsibility
+ * of the application
+ */
+void el_resize __P((EditLine *));
+
+
+/*
+ * User-defined function interface.
+ */
+__const LineInfo *el_line __P((EditLine *));
+int el_insertstr __P((EditLine *, char *));
+void el_deletestr __P((EditLine *, int));
+
+/*
+ * ==== History ====
+ */
+
+typedef struct history History;
+
+typedef struct HistEvent {
+ int num;
+ __const char *str;
+} HistEvent;
+
+/*
+ * History access functions.
+ */
+History * history_init __P((void));
+void history_end __P((History *));
+
+__const HistEvent * history __P((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); */
+
+#endif /* _h_editline */
diff --git a/lib/libedit/history.c b/lib/libedit/history.c
new file mode 100644
index 000000000000..e8665481977c
--- /dev/null
+++ b/lib/libedit/history.c
@@ -0,0 +1,602 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if !defined(lint) && !defined(SCCSID)
+static char sccsid[] = "@(#)history.c 8.1 (Berkeley) 6/4/93";
+#endif /* not lint && not SCCSID */
+
+/*
+ * hist.c: History access functions
+ */
+#include "sys.h"
+
+#include <string.h>
+#include <stdlib.h>
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#include "histedit.h"
+
+typedef const HistEvent * (*history_gfun_t) __P((ptr_t));
+typedef const HistEvent * (*history_efun_t) __P((ptr_t, const char *));
+
+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_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 HENTER(h, str) (*(h)->h_enter)((h)->h_ref, str)
+#define HADD(h, str) (*(h)->h_add)((h)->h_ref, str)
+
+#define h_malloc(a) malloc(a)
+#define h_free(a) free(a)
+
+
+private int history_set_num __P((History *, int));
+private int history_set_fun __P((History *, history_gfun_t,
+ history_gfun_t,
+ history_gfun_t,
+ history_gfun_t,
+ history_gfun_t,
+ history_efun_t,
+ history_efun_t, ptr_t));
+private const HistEvent *history_prev_event __P((History *, int));
+private const HistEvent *history_next_event __P((History *, int));
+private const HistEvent *history_next_string __P((History *, const char *));
+private const HistEvent *history_prev_string __P((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 */
+} 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 */
+} history_t;
+
+private const HistEvent *history_def_first __P((ptr_t));
+private const HistEvent *history_def_last __P((ptr_t));
+private const HistEvent *history_def_next __P((ptr_t));
+private const HistEvent *history_def_prev __P((ptr_t));
+private const HistEvent *history_def_curr __P((ptr_t));
+private const HistEvent *history_def_enter __P((ptr_t, const char *));
+private const HistEvent *history_def_add __P((ptr_t, const char *));
+private void history_def_init __P((ptr_t *, int));
+private void history_def_end __P((ptr_t));
+private const HistEvent *history_def_insert __P((history_t *, const char *));
+private void history_def_delete __P((history_t *, hentry_t *));
+
+#define history_def_set(p, num) (void) (((history_t *) p)->max = (num))
+
+
+/* history_def_first():
+ * Default function to return the first event in the history.
+ */
+private const HistEvent *
+history_def_first(p)
+ ptr_t p;
+{
+ history_t *h = (history_t *) p;
+ h->cursor = h->list.next;
+ if (h->cursor != &h->list)
+ return &h->cursor->ev;
+ else
+ return NULL;
+}
+
+/* history_def_last():
+ * Default function to return the last event in the history.
+ */
+private const HistEvent *
+history_def_last(p)
+ ptr_t p;
+{
+ history_t *h = (history_t *) p;
+ h->cursor = h->list.prev;
+ if (h->cursor != &h->list)
+ return &h->cursor->ev;
+ else
+ return NULL;
+}
+
+/* history_def_next():
+ * Default function to return the next event in the history.
+ */
+private const HistEvent *
+history_def_next(p)
+ ptr_t p;
+{
+ history_t *h = (history_t *) p;
+
+ if (h->cursor != &h->list)
+ h->cursor = h->cursor->next;
+ else
+ return NULL;
+
+ if (h->cursor != &h->list)
+ return &h->cursor->ev;
+ else
+ return NULL;
+}
+
+
+/* history_def_prev():
+ * Default function to return the previous event in the history.
+ */
+private const HistEvent *
+history_def_prev(p)
+ ptr_t p;
+{
+ history_t *h = (history_t *) p;
+
+ if (h->cursor != &h->list)
+ h->cursor = h->cursor->prev;
+ else
+ return NULL;
+
+ if (h->cursor != &h->list)
+ return &h->cursor->ev;
+ else
+ return NULL;
+}
+
+
+/* history_def_curr():
+ * Default function to return the current event in the history.
+ */
+private const HistEvent *
+history_def_curr(p)
+ ptr_t p;
+{
+ history_t *h = (history_t *) p;
+
+ if (h->cursor != &h->list)
+ return &h->cursor->ev;
+ else
+ return NULL;
+}
+
+
+/* history_def_add():
+ * Append string to element
+ */
+private const HistEvent *
+history_def_add(p, str)
+ ptr_t p;
+ 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) strcpy(s, h->cursor->ev.str);
+ (void) strcat(s, str);
+ h_free((ptr_t) h->cursor->ev.str);
+ h->cursor->ev.str = s;
+ return &h->cursor->ev;
+}
+
+
+/* history_def_delete():
+ * Delete element hp of the h list
+ */
+private void
+history_def_delete(h, hp)
+ history_t *h;
+ 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--;
+}
+
+
+/* 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;
+{
+ 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;
+}
+
+
+/* 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;
+{
+ history_t *h = (history_t *) p;
+ const HistEvent *ev;
+
+
+ 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 + 1)
+ history_def_delete(h, h->list.prev);
+ return ev;
+}
+
+
+/* history_def_init():
+ * Default history initialization function
+ */
+private void
+history_def_init(p, n)
+ ptr_t *p;
+ 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_def_end():
+ * Default history cleanup function
+ */
+private void
+history_def_end(p)
+ ptr_t p;
+{
+ history_t *h = (history_t *) p;
+
+ while (h->list.prev != &h->list)
+ history_def_delete(h, h->list.prev);
+}
+
+/************************************************************************/
+
+/* history_init():
+ * Initialization function.
+ */
+public History *
+history_init()
+{
+ 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_enter = history_def_enter;
+ h->h_add = history_def_add;
+
+ return h;
+}
+
+
+/* history_end():
+ * clean up history;
+ */
+public void
+history_end(h)
+ History *h;
+{
+ if (h->h_next == history_def_next)
+ history_def_end(h->h_ref);
+}
+
+
+
+/* history_set_num():
+ * Set history number of events
+ */
+private int
+history_set_num(h, num)
+ History *h;
+ int num;
+{
+ if (h->h_next != history_def_next || num < 0)
+ return -1;
+ history_def_set(h->h_ref, num);
+ return 0;
+}
+
+
+/* history_set_fun():
+ * Set history functions
+ */
+private int
+history_set_fun(h, first, next, last, prev, curr, enter, add, ptr)
+ History *h;
+ history_gfun_t first, next, last, prev, curr;
+ history_efun_t enter, add;
+ ptr_t ptr;
+{
+ if (first == NULL || next == NULL ||
+ last == NULL || prev == NULL || curr == NULL ||
+ enter == NULL || add == NULL ||
+ ptr == 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_enter = history_def_enter;
+ h->h_add = history_def_add;
+ }
+ return -1;
+ }
+
+ if (h->h_next == history_def_next)
+ history_def_end(h->h_ref);
+
+ h->h_next = next;
+ h->h_first = first;
+ h->h_enter = enter;
+ h->h_add = add;
+ return 0;
+}
+
+
+/* history_prev_event():
+ * Find the previous event, with number given
+ */
+private const HistEvent *
+history_prev_event(h, num)
+ History *h;
+ int num;
+{
+ const HistEvent *ev;
+ for (ev = HCURR(h); ev != NULL; ev = HPREV(h))
+ if (ev->num == num)
+ return ev;
+ return NULL;
+}
+
+
+/* history_next_event():
+ * Find the next event, with number given
+ */
+private const HistEvent *
+history_next_event(h, num)
+ History *h;
+ int num;
+{
+ const HistEvent *ev;
+ for (ev = HCURR(h); ev != NULL; ev = HNEXT(h))
+ if (ev->num == num)
+ return ev;
+ return NULL;
+}
+
+
+/* history_prev_string():
+ * Find the previous event beginning with string
+ */
+private const HistEvent *
+history_prev_string(h, str)
+ History *h;
+ 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;
+}
+
+
+/* history_next_string():
+ * Find the next event beginning with string
+ */
+private const HistEvent *
+history_next_string(h, str)
+ History *h;
+ const char* str;
+{
+ const HistEvent *ev;
+ size_t len = strlen(str);
+
+ for (ev = HCURR(h); ev != NULL; ev = HPREV(h))
+ if (strncmp(str, ev->str, len) == 0)
+ return ev;
+ return NULL;
+}
+
+
+/* history():
+ * User interface to history functions.
+ */
+const HistEvent *
+#if __STDC__
+history(History *h, int fun, ...)
+#else
+history(va_alist)
+ va_dcl
+#endif
+{
+ va_list va;
+ const HistEvent *ev = NULL;
+ const char *str;
+ static const HistEvent sev = { 0, "" };
+
+#if __STDC__
+ va_start(va, fun);
+#else
+ History *h;
+ int fun;
+ va_start(va);
+ h = va_arg(va, History *);
+ fun = va_arg(va, int);
+#endif
+
+ 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_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)
+ ev = &sev;
+ break;
+
+ case H_FUNC:
+ {
+ history_gfun_t first = va_arg(va, history_gfun_t);
+ history_gfun_t next = va_arg(va, history_gfun_t);
+ history_gfun_t last = va_arg(va, history_gfun_t);
+ history_gfun_t prev = va_arg(va, history_gfun_t);
+ history_gfun_t curr = va_arg(va, history_gfun_t);
+ history_efun_t enter = va_arg(va, history_efun_t);
+ history_efun_t add = va_arg(va, history_efun_t);
+ ptr_t ptr = va_arg(va, ptr_t);
+
+ if (history_set_fun(h, first, next, last, prev,
+ curr, enter, add, ptr) == 0)
+ ev = &sev;
+ }
+ break;
+
+ case H_END:
+ history_end(h);
+ break;
+
+ default:
+ break;
+ }
+ va_end(va);
+ return ev;
+}
diff --git a/lib/libedit/key.c b/lib/libedit/key.c
new file mode 100644
index 000000000000..058da0e7f435
--- /dev/null
+++ b/lib/libedit/key.c
@@ -0,0 +1,726 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if !defined(lint) && !defined(SCCSID)
+static char sccsid[] = "@(#)key.c 8.1 (Berkeley) 6/4/93";
+#endif /* not lint && not SCCSID */
+
+/*
+ * 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
+ * (XK_STR), editor functions (XK_CMD), or unix commands (XK_EXE).
+ *
+ * Warning:
+ * If key is a substr of some other keys, then the longer
+ * keys are lost!! That is, if the keys "abcd" and "abcef"
+ * are in el->el_key.map, adding the key "abc" will cause the first two
+ * definitions to be lost.
+ *
+ * Restrictions:
+ * -------------
+ * 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
+ * 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 */
+};
+
+private int node_trav __P((EditLine *, key_node_t *, char *,
+ key_value_t *));
+private int node__try __P((key_node_t *, char *,
+ key_value_t *, int));
+private key_node_t *node__get __P((int));
+private void node__put __P((key_node_t *));
+private int node__delete __P((key_node_t **, char *));
+private int node_lookup __P((EditLine *, char *, key_node_t *,
+ int));
+private int node_enum __P((EditLine *, key_node_t *, int));
+private int key__decode_char __P((char *, int, int));
+
+#define KEY_BUFSIZ EL_BUFSIZ
+
+
+/* key_init():
+ * Initialize the key maps
+ */
+protected int
+key_init(el)
+ EditLine *el;
+{
+ el->el_key.buf = (char *) el_malloc(KEY_BUFSIZ);
+ el->el_key.map = NULL;
+ key_reset(el);
+ return 0;
+}
+
+
+/* key_end():
+ * Free the key maps
+ */
+protected void
+key_end(el)
+ 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;
+}
+
+
+/* key_map_cmd():
+ * Associate cmd with a key value
+ */
+protected key_value_t *
+key_map_cmd(el, cmd)
+ EditLine *el;
+ int cmd;
+{
+ el->el_key.val.cmd = (el_action_t) cmd;
+ return &el->el_key.val;
+}
+
+
+/* key_map_str():
+ * Associate str with a key value
+ */
+protected key_value_t *
+key_map_str(el, str)
+ EditLine *el;
+ char *str;
+{
+ el->el_key.val.str = str;
+ return &el->el_key.val;
+}
+
+
+/* key_reset():
+ * Takes all nodes on el->el_key.map and puts them on free list. Then
+ * initializes el->el_key.map with arrow keys
+ * [Always bind the ansi arrow keys?]
+ */
+protected void
+key_reset(el)
+ EditLine *el;
+{
+ node__put(el->el_key.map);
+ el->el_key.map = NULL;
+ return;
+}
+
+
+/* key_get():
+ * Calls the recursive function with entry point el->el_key.map
+ * 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.
+ * The last character read is returned in *ch.
+ */
+protected int
+key_get(el, ch, val)
+ EditLine *el;
+ char *ch;
+ key_value_t *val;
+{
+ return node_trav(el, el->el_key.map, ch, val);
+}
+
+
+
+/* key_add():
+ * Adds key to the el->el_key.map and associates the value in val with it.
+ * If key is already is in el->el_key.map, the new code is applied to the
+ * existing key. Ntype specifies if code is a command, an
+ * out str or a unix command.
+ */
+protected void
+key_add(el, key, val, ntype)
+ EditLine *el;
+ 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 */
+
+ /* Now recurse through el->el_key.map */
+ (void) node__try(el->el_key.map, key, val, ntype);
+ return;
+}
+
+
+/* key_clear():
+ *
+ */
+protected void
+key_clear(el, map, in)
+ EditLine *el;
+ el_action_t *map;
+ 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);
+}
+
+
+/* key_delete():
+ * Delete the key and all longer keys staring with key, if
+ * they exists.
+ */
+protected int
+key_delete(el, key)
+ EditLine *el;
+ 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;
+
+ (void) node__delete(&el->el_key.map, key);
+ return 0;
+}
+
+
+/* key_print():
+ * Print the binding associated with key key.
+ * Print entire el->el_key.map if null
+ */
+protected void
+key_print(el, key)
+ EditLine *el;
+ 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;
+}
+
+
+/* node_trav():
+ * recursively traverses node in tree until match or mismatch is
+ * 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;
+{
+ 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;
+ }
+ }
+}
+
+
+/* node__try():
+ * 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;
+{
+ 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 (*++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;
+ }
+
+ 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;
+ }
+ }
+ 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;
+}
+
+
+/* node__delete():
+ * Delete node that matches str
+ */
+private int
+node__delete(inptr, str)
+ key_node_t **inptr;
+ char *str;
+{
+ key_node_t *ptr;
+ key_node_t *prev_ptr = NULL;
+
+ ptr = *inptr;
+
+ 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;
+ }
+}
+
+/* node__put():
+ * Puts a tree of nodes onto free list using free(3).
+ */
+private void
+node__put(ptr)
+ key_node_t *ptr;
+{
+ 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);
+}
+
+
+/* node__get():
+ * Returns pointer to an key_node_t for ch.
+ */
+private key_node_t *
+node__get(ch)
+ 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;
+}
+
+
+
+/* node_lookup():
+ * look for the str starting at node ptr.
+ * Print if last node
+ */
+private int
+node_lookup(el, str, ptr, cnt)
+ EditLine *el;
+ 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;
+ }
+ 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;
+ }
+ }
+}
+
+
+/* node_enum():
+ * 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;
+{
+ 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,
+ "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) {
+#ifdef DEBUG_EDIT
+ (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;
+}
+
+
+/* key_kprint():
+ * Print the specified key and its associated
+ * function specified by val
+ */
+protected void
+key_kprint(el, key, val, ntype)
+ EditLine *el;
+ 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;
+ }
+#ifdef DEBUG_KEY
+ if (fp->name == NULL)
+ (void) fprintf(el->el_errfile, "BUG! Command not found.\n");
+#endif
+
+ break;
+ default:
+ abort();
+ break;
+ }
+ else
+ (void) fprintf(el->el_errfile, fmt, key, "no input");
+}
+
+
+/* key__decode_char():
+ * Put a printable form of char in buf.
+ */
+private int
+key__decode_char(buf, cnt, ch)
+ char *buf;
+ int cnt, 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;
+}
+
+/* key__decode_str():
+ * Make a printable version of the ey
+ */
+protected char *
+key__decode_str(str, buf, sep)
+ char *str;
+ char *buf;
+ 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;
+ }
+ else {
+ *b++ = '\\';
+ *b++ = ((*p >> 6) & 7) + '0';
+ *b++ = ((*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 */
+}
diff --git a/lib/libedit/key.h b/lib/libedit/key.h
new file mode 100644
index 000000000000..2ed3afc8fe08
--- /dev/null
+++ b/lib/libedit/key.h
@@ -0,0 +1,80 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)key.h 8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.key.h: Key macro header
+ */
+#ifndef _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... */
+} 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 */
+} el_key_t;
+
+#define XK_CMD 0
+#define XK_STR 1
+#define XK_NOD 2
+#define XK_EXE 3
+
+protected int key_init __P((EditLine *));
+protected void key_end __P((EditLine *));
+protected key_value_t * key_map_cmd __P((EditLine *, int));
+protected key_value_t * key_map_str __P((EditLine *, char *));
+protected void key_reset __P((EditLine *));
+protected int key_get __P((EditLine *, char *,
+ key_value_t *));
+protected void key_add __P((EditLine *, char *, key_value_t *,
+ int));
+protected void key_clear __P((EditLine *, el_action_t *,
+ char *));
+protected int key_delete __P((EditLine *, char *));
+protected void key_print __P((EditLine *, char *));
+protected void key_kprint __P((EditLine *, char *,
+ key_value_t *, int));
+protected char *key__decode_str __P((char *, char *, char *));
+
+#endif /* _h_el_key */
diff --git a/lib/libedit/makelist b/lib/libedit/makelist
new file mode 100644
index 000000000000..0b2e7a01ee10
--- /dev/null
+++ b/lib/libedit/makelist
@@ -0,0 +1,187 @@
+#!/bin/sh -
+#
+# Copyright (c) 1992, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Christos Zoulas of Cornell University.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# @(#)makelist 5.3 (Berkeley) 6/4/93
+
+# makelist.sh: Automatically generate header files...
+
+AWK=/usr/bin/awk
+USAGE="Usage: $0 -h|-e|-fc|-fh|-bc|-bh <filenames>"
+
+if [ "x$1" = "x" ]
+then
+ echo $USAGE 1>&2
+ exit 1
+fi
+
+FLAG="$1"
+shift
+
+FILES="$@"
+
+case $FLAG in
+-h)
+ OIFS="$IFS"
+ IFS=".$IFS"
+ set - $FILES
+ IFS="$OIFS"
+ hdr="_h_`basename $1`_$2"
+ cat $FILES | $AWK '
+ BEGIN {
+ printf("/* Automatically generated file, do not edit */\n");
+ printf("#ifndef %s\n#define %s\n", "'$hdr'", "'$hdr'");
+ }
+ /\(\):/ {
+ 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 __P((EditLine *, int));\n", name);
+ }
+ }
+ END {
+ printf("#endif /* %s */\n", "'$hdr'");
+ }';;
+-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");
+ low = "abcdefghijklmnopqrstuvwxyz_";
+ high = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_";
+ for (i = 1; i <= length(low); i++)
+ tr[substr(low, i, 1)] = substr(high, i, 1);
+ }
+ /\(\):/ {
+ pr = substr($2, 1, 2);
+ if (pr == "vi" || pr == "em" || pr == "ed") {
+ name = substr($2, 1, length($2) - 3);
+ uname = "";
+ fname = "";
+ for (i = 1; i <= length(name); i++) {
+ s = substr(name, i, 1);
+ uname = uname tr[s];
+ if (s == "_")
+ s = "-";
+ fname = fname s;
+ }
+
+ printf(" { %-30.30s %-30.30s\n","\"" fname "\",", uname ",");
+ ok = 1;
+ }
+ }
+ /^ \*/ {
+ if (ok) {
+ printf(" \"");
+ for (i = 2; i < NF; i++)
+ printf("%s ", $i);
+ printf("%s\" },\n", $i);
+ ok = 0;
+ }
+ }
+ END {
+ printf(" { NULL, 0, NULL }\n");
+ printf("};\n");
+ printf("\nprotected el_bindings_t* help__get()");
+ printf("{ return el_func_help; }\n");
+ }';;
+-bh)
+ $AWK '
+ 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__P((void));\n");
+ printf("#endif /* _h_help_c */\n");
+ }' /dev/null;;
+-fh)
+ cat $FILES | $AWK '/el_action_t/ { print $3 }' | \
+ sort | tr '[a-z]' '[A-Z]' | $AWK '
+ BEGIN {
+ printf("/* Automatically generated file, do not edit */\n");
+ printf("#ifndef _h_fcns_c\n#define _h_fcns_c\n");
+ 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) __P((EditLine *, int));");
+ printf("\nprotected el_func_t* func__get __P((void));\n");
+ printf("#endif /* _h_fcns_c */\n");
+ }';;
+-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[] = {");
+ maxlen = 80;
+ needn = 1;
+ len = 0;
+ }
+ {
+ clen = 25 + 2;
+ len += clen;
+ if (len >= maxlen)
+ needn = 1;
+ if (needn) {
+ printf("\n ");
+ needn = 0;
+ len = 4 + clen;
+ }
+ s = $1 ",";
+ printf("%-26.26s ", s);
+ }
+ END {
+ printf("\n};\n");
+ printf("\nprotected el_func_t* func__get() { return el_func; }\n");
+ }';;
+-e)
+ echo "$FILES" | tr ' ' '\012' | $AWK '
+ BEGIN {
+ printf("/* Automatically generated file, do not edit */\n");
+ printf("#define protected static\n");
+ printf("#define SCCSID\n");
+ }
+ {
+ printf("#include \"%s\"\n", $1);
+ }';;
+*)
+ echo $USAGE 1>&2
+ exit 1;;
+esac
diff --git a/lib/libedit/map.c b/lib/libedit/map.c
new file mode 100644
index 000000000000..3378217ff851
--- /dev/null
+++ b/lib/libedit/map.c
@@ -0,0 +1,1397 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if !defined(lint) && !defined(SCCSID)
+static char sccsid[] = "@(#)map.c 8.1 (Berkeley) 6/4/93";
+#endif /* not lint && not SCCSID */
+
+/*
+ * map.c: Editor function definitions
+ */
+#include "sys.h"
+#include <stdlib.h>
+#include "el.h"
+
+#define N_KEYS 256
+
+private void map_print_key __P((EditLine *, el_action_t *, char *));
+private void map_print_some_keys __P((EditLine *, el_action_t *, int, int));
+private void map_print_all_keys __P((EditLine *));
+private void map_init_nls __P((EditLine *));
+private void map_init_meta __P((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 */
+};
+
+/*
+ * 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[] = {
+#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, /* ^_ */
+#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, /* ^_ */
+#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-^? */
+};
+
+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-^? */
+};
+
+
+/* map_init():
+ * Initialize and allocate the maps
+ */
+protected int
+map_init(el)
+ EditLine *el;
+{
+
+ /*
+ * 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();
+#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;
+
+#ifdef VIDEFAULT
+ map_init_vi(el);
+#else
+ map_init_emacs(el);
+#endif /* VIDEFAULT */
+ return 0;
+}
+
+
+/* map_end():
+ * Free the space taken by the editor maps
+ */
+protected void
+map_end(el)
+ 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;
+}
+
+
+/* map_init_nls():
+ * Find all the printable keys and bind them to self insert
+ */
+private void
+map_init_nls(el)
+ EditLine *el;
+{
+ int i;
+ el_action_t *map = el->el_map.key;
+
+ for (i = 0200; i <= 0377; i++)
+ if (isprint(i))
+ map[i] = ED_INSERT;
+}
+
+
+/* map_init_meta():
+ * Bind all the meta keys to the appropriate ESC-<key> sequence
+ */
+private void
+map_init_meta(el)
+ EditLine *el;
+{
+ char buf[3];
+ register 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;
+
+ 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;
+ }
+ else
+ map = alt;
+ }
+ 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[buf[0]] = ED_SEQUENCE_LEAD_IN;
+}
+
+
+/* map_init_vi():
+ * Initialize the vi bindings
+ */
+protected void
+map_init_vi(el)
+ 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;
+
+ el->el_map.type = MAP_VI;
+ el->el_map.current = el->el_map.key;
+
+ key_reset(el);
+
+ 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_nls(el);
+#endif
+
+ tty_bind_char(el, 1);
+ term_bind_arrow(el);
+}
+
+
+/* map_init_emacs():
+ * Initialize the emacs bindings
+ */
+protected void
+map_init_emacs(el)
+ 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 */)
+ map_init_nls(el);
+#endif
+ map_init_nls(el);
+
+ buf[0] = CONTROL('X');
+ buf[2] = 0;
+ buf[1] = CONTROL('X');
+ 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
+ */
+protected int
+map_set_editor(el, 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;
+}
+
+
+/* map_print_key():
+ * Print the function description for 1 key
+ */
+private void
+map_print_key(el, map, in)
+ EditLine *el;
+ el_action_t *map;
+ 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);
+}
+
+
+/* map_print_some_keys():
+ * 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;
+{
+ 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]);
+ }
+#endif
+ abort();
+}
+
+
+/* map_print_all_keys():
+ * Print the function description for all keys.
+ */
+private void
+map_print_all_keys(el)
+ 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;
+ 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;
+ 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, "");
+}
+
+
+/* map_bind():
+ * Add/remove/change bindings
+ */
+protected int
+map_bind(el, argc, argv)
+ EditLine *el;
+ int argc;
+ 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;
+#ifdef notyet
+ 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;
+ }
+ 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;
+ }
+#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);
+ map[(unsigned char) *in] = ED_SEQUENCE_LEAD_IN;
+ }
+ else {
+ key_clear(el, map, in);
+ map[(unsigned char) *in] = cmd;
+ }
+ }
+ break;
+
+ default:
+ abort();
+ break;
+ }
+ return 0;
+}
+
+
+/* map_addfunc():
+ * 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;
+{
+ int nf = el->el_map.nfunc + 2;
+ if (name == NULL || help == NULL || func == NULL)
+ return -1;
+
+ el->el_map.func = (el_func_t *)
+ el_realloc(el->el_map.func, nf * sizeof(el_func_t));
+ el->el_map.help = (el_bindings_t *)
+ el_realloc(el->el_map.help, nf * sizeof(el_bindings_t));
+
+ 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
new file mode 100644
index 000000000000..71c93b4a21e2
--- /dev/null
+++ b/lib/libedit/map.h
@@ -0,0 +1,77 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)map.h 8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.map.h: Editor maps
+ */
+#ifndef _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 */
+} 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_map_t;
+
+#define MAP_EMACS 0
+#define MAP_VI 1
+
+protected int map_bind __P((EditLine *, int, char **));
+protected int map_init __P((EditLine *));
+protected void map_end __P((EditLine *));
+protected void map_init_vi __P((EditLine *));
+protected void map_init_emacs __P((EditLine *));
+protected int map_set_editor __P((EditLine *, char *));
+protected int map_addfunc __P((EditLine *, const char *,
+ const char *, el_func_t));
+
+#endif /* _h_el_map */
diff --git a/lib/libedit/parse.c b/lib/libedit/parse.c
new file mode 100644
index 000000000000..2fe746f370bc
--- /dev/null
+++ b/lib/libedit/parse.c
@@ -0,0 +1,247 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if !defined(lint) && !defined(SCCSID)
+static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/4/93";
+#endif /* not lint && not SCCSID */
+
+/*
+ * parse.c: parse an editline extended command
+ *
+ * commands are:
+ *
+ * bind
+ * echotc
+ * settc
+ * gettc
+ */
+#include "sys.h"
+#include "el.h"
+#include "tokenizer.h"
+
+private struct {
+ char *name;
+ int (*func) __P((EditLine *, int, char **));
+} cmds[] = {
+ { "bind", map_bind },
+ { "echotc", term_echotc },
+ { "history", hist_list },
+ { "telltc", term_telltc },
+ { "settc", term_settc },
+ { "setty", tty_stty },
+ { NULL, NULL }
+};
+
+
+/* parse_line():
+ * Parse a line and dispatch it
+ */
+protected int
+parse_line(el, 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;
+}
+
+/* el_parse():
+ * Command dispatcher
+ */
+public int
+el_parse(el, argc, argv)
+ EditLine *el;
+ int argc;
+ char *argv[];
+{
+ char *ptr;
+ int i;
+
+ for (ptr = argv[0]; *ptr && *ptr != ':'; ptr++)
+ continue;
+
+ if (*ptr == ':') {
+ *ptr = '\0';
+ if (el_match(el->el_prog, ptr))
+ 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;
+}
+
+
+/* parse__escape():
+ * Parse a string of the form ^<char> \<odigit> \<char> and return
+ * the appropriate character or -1 if the escape is not valid
+ */
+protected int
+parse__escape(ptr)
+ 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--;
+ 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)) {
+ 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;
+{
+ 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;
+{
+ 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;
+}
diff --git a/lib/libedit/parse.h b/lib/libedit/parse.h
new file mode 100644
index 000000000000..263076b30a5a
--- /dev/null
+++ b/lib/libedit/parse.h
@@ -0,0 +1,50 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)parse.h 8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.parse.h: Parser functions
+ */
+#ifndef _h_el_parse
+#define _h_el_parse
+
+protected int parse_line __P((EditLine *, const char *));
+protected int parse__escape __P((const char ** const));
+protected char * parse__string __P((char *, const char *));
+protected int parse_cmd __P((EditLine *, const char *));
+
+#endif /* _h_el_parse */
diff --git a/lib/libedit/prompt.c b/lib/libedit/prompt.c
new file mode 100644
index 000000000000..cea7ad7d1334
--- /dev/null
+++ b/lib/libedit/prompt.c
@@ -0,0 +1,123 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if !defined(lint) && !defined(SCCSID)
+static char sccsid[] = "@(#)prompt.c 8.1 (Berkeley) 6/4/93";
+#endif /* not lint && not SCCSID */
+
+/*
+ * prompt.c: Prompt printing functions
+ */
+#include "sys.h"
+#include <stdio.h>
+#include "el.h"
+
+private char *prompt_default __P((EditLine *));
+
+/* prompt_default():
+ * Just a default prompt, in case the user did not provide one
+ */
+private char *
+/*ARGSUSED*/
+prompt_default(el)
+ EditLine *el;
+{
+ static char a[3] = { '?', ' ', '\0' };
+ return a;
+}
+
+
+/* prompt_print():
+ * Print the prompt and update the prompt position.
+ * We use an array of integers in case we want to pass
+ * literal escape sequences in the prompt and we want a
+ * bit to flag them
+ */
+protected void
+prompt_print(el)
+ EditLine *el;
+{
+ char *p = (*el->el_prompt.p_func)(el);
+ while (*p)
+ re_putc(el, *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;
+
+} /* end prompt_print */
+
+
+/* prompt_init():
+ * Initialize the prompt stuff
+ */
+protected int
+prompt_init(el)
+ 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 */
+
+
+/* prompt_end():
+ * Clean up the prompt stuff
+ */
+protected void
+/*ARGSUSED*/
+prompt_end(el)
+ EditLine *el;
+{
+} /* end prompt_end */
+
+
+/* prompt_set():
+ * Install a prompt printing function
+ */
+protected int
+prompt_set(el, prf)
+ EditLine *el;
+ el_pfunc_t prf;
+{
+ 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 */
diff --git a/lib/libedit/prompt.h b/lib/libedit/prompt.h
new file mode 100644
index 000000000000..a624fc053e25
--- /dev/null
+++ b/lib/libedit/prompt.h
@@ -0,0 +1,59 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)prompt.h 8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.prompt.h: Prompt printing stuff
+ */
+#ifndef _h_el_prompt
+#define _h_el_prompt
+
+#include "histedit.h"
+
+typedef char * (*el_pfunc_t) __P((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_prompt_t;
+
+protected void prompt_print __P((EditLine *));
+protected int prompt_set __P((EditLine *, el_pfunc_t));
+protected int prompt_init __P((EditLine *));
+protected void prompt_end __P((EditLine *));
+
+#endif /* _h_el_prompt */
diff --git a/lib/libedit/read.c b/lib/libedit/read.c
new file mode 100644
index 000000000000..ccfc88b8f59d
--- /dev/null
+++ b/lib/libedit/read.c
@@ -0,0 +1,437 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if !defined(lint) && !defined(SCCSID)
+static char sccsid[] = "@(#)read.c 8.1 (Berkeley) 6/4/93";
+
+#endif /* not lint && not SCCSID */
+/*
+ * read.c: Clean this junk up! This is horrible code.
+ * Terminal read functions
+ */
+#include "sys.h"
+#include <sys/errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+extern int errno;
+#include "el.h"
+
+#define OKCMD -1
+
+private int read__fixio __P((int, int));
+private int read_preread __P((EditLine *));
+private int read_getcmd __P((EditLine *, el_action_t *, char *));
+
+#ifdef DEBUG_EDIT
+private void
+read_debug(el)
+ 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");
+}
+#endif /* DEBUG_EDIT */
+
+/* read__fixio():
+ * Try to recover from a read error
+ */
+private int
+read__fixio(fd, e)
+ int fd, e;
+{
+ switch (e) {
+ case -1: /* Make sure that the code is reachable */
+
+#ifdef EWOULDBLOCK
+ case EWOULDBLOCK:
+# define TRY_AGAIN
+#endif /* EWOULDBLOCK */
+
+#if defined(POSIX) && defined(EAGAIN)
+# if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
+ case EAGAIN:
+# define TRY_AGAIN
+# endif /* EWOULDBLOCK && EWOULDBLOCK != EAGAIN */
+#endif /* POSIX && EAGAIN */
+
+ 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 */
+
+#endif /* TRY_AGAIN */
+ return e ? 0 : -1;
+
+ case EINTR:
+ return 0;
+
+ default:
+ return -1;
+ }
+}
+
+
+/* read_preread():
+ * Try to read the stuff in the input queue;
+ */
+private int
+read_preread(el)
+ EditLine *el;
+{
+ int chrs = 0;
+
+ if (el->el_chared.c_macro.nline) {
+ el_free((ptr_t) el->el_chared.c_macro.nline);
+ el->el_chared.c_macro.nline = NULL;
+ }
+
+ if (el->el_tty.t_mode == ED_IO)
+ return 0;
+
+#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));
+ if (chrs > 0) {
+ buf[chrs] = '\0';
+ el->el_chared.c_macro.nline = strdup(buf);
+ el_push(el->el_chared.c_macro.nline);
+ }
+ }
+#endif /* FIONREAD */
+
+ return chrs > 0;
+}
+
+
+/* el_push():
+ * Push a macro
+ */
+public void
+el_push(el, str)
+ EditLine *el;
+ const 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();
+ }
+}
+
+
+/* read_getcmd():
+ * Return next command from the input stream.
+ */
+private int
+read_getcmd(el, cmdnum, ch)
+ EditLine *el;
+ el_action_t *cmdnum;
+ char *ch;
+{
+ el_action_t cmd = 0;
+ int num;
+
+ while (cmd == 0 || cmd == ED_SEQUENCE_LEAD_IN) {
+ 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
+#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;
+#ifdef notyet
+ 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;
+}
+
+
+/* el_getc():
+ * Read a character
+ */
+public int
+el_getc(el, cp)
+ EditLine *el;
+ char *cp;
+{
+ int num_read;
+ unsigned char tcp;
+ int tried = 0;
+
+ 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--;
+ }
+ return 1;
+ }
+
+#ifdef DEBUG_READ
+ (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;
+
+#ifdef DEBUG_READ
+ (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;
+ }
+#ifdef DEBUG_READ
+ (void) fprintf(el->el_errfile, "Got it %c\n", tcp);
+#endif /* DEBUG_READ */
+ *cp = tcp;
+ return num_read;
+}
+
+
+
+public const char *
+el_gets(el, nread)
+ EditLine *el;
+ int *nread;
+{
+ int retval;
+ el_action_t cmdnum = 0;
+ int num; /* how many chars we have read at NL */
+ char ch;
+
+ if (el->el_flags & HANDLE_SIGNALS)
+ sig_set(el);
+
+ re_clear_display(el); /* reset the display stuff */
+ ch_reset(el);
+
+#ifdef FIONREAD
+ 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 */
+
+ for (num = OKCMD; num == OKCMD;) { /* while still editing this line */
+#ifdef DEBUG_EDIT
+ read_debug(el);
+#endif /* DEBUG_EDIT */
+ /* 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);
+#endif /* DEBUG_READ */
+ break;
+ }
+
+ if (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);
+#endif /* DEBUG_EDIT */
+ 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);
+ }
+#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_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 */
+#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 */
+ el->el_state.argument = 1;
+ el->el_state.doingarg = 0;
+ break;
+
+ case CC_ERROR:
+ default: /* functions we don't know about */
+#ifdef DEBUG_READ
+ (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;
+ }
+ }
+
+ (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;
+}
diff --git a/lib/libedit/refresh.c b/lib/libedit/refresh.c
new file mode 100644
index 000000000000..b64d0119c6eb
--- /dev/null
+++ b/lib/libedit/refresh.c
@@ -0,0 +1,1013 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if !defined(lint) && !defined(SCCSID)
+static char sccsid[] = "@(#)refresh.c 8.1 (Berkeley) 6/4/93";
+#endif /* not lint && not SCCSID */
+
+/*
+ * refresh.c: Lower level screen refreshing functions
+ */
+#include "sys.h"
+#include <stdio.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "el.h"
+
+private void re_addc __P((EditLine *, int));
+private void re_update_line __P((EditLine *, char *, char *, int));
+private void re_insert __P((EditLine *, char *, int, int,
+ char *, int));
+private void re_delete __P((EditLine *, char *, int, int,
+ int));
+private void re_fastputc __P((EditLine *, int));
+
+private void re__strncopy __P((char *, char *, size_t));
+private void re__copy_and_pad __P((char *, char *, size_t));
+
+#ifdef DEBUG_REFRESH
+private void re_printstr __P((EditLine *, char *, char *,
+ char *));
+# define __F el->el_errfile
+# define RE_DEBUG(a, b, c) do \
+ if (a) { \
+ (void) fprintf b; \
+ c; \
+ } \
+ while (0)
+/* 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_DEBUG(1,(__F, "%s:\"", str),);
+ while (f < t)
+ RE_DEBUG(1,(__F, "%c", *f++ & 0177),);
+ RE_DEBUG(1,(__F, "\"\r\n"),);
+}
+#else
+# define RE_DEBUG(a, b, c)
+#endif
+
+
+/* re_addc():
+ * Draw c, expanding tabs, control chars etc.
+ */
+private void
+re_addc(el, c)
+ 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 */
+ }
+ }
+ 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_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 */
+
+
+/* re_refresh():
+ * draws the new virtual screen image from the current input
+ * line, then goes line-by-line changing the real image to the new
+ * virtual image. The routine to re-draw a line can be replaced
+ * easily in hopes of a smarter one being placed there.
+ */
+protected void
+re_refresh(el)
+ EditLine *el;
+{
+ int i;
+ char *cp;
+ coord_t cur;
+
+ RE_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;
+
+ cur.h = -1; /* set flag in case I'm not set */
+ cur.v = 0;
+
+ prompt_print(el);
+
+ /* 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;
+ }
+ 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]));
+#ifdef DEBUG_REFRESH
+ 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 */
+
+
+/* re_goto_bottom():
+ * used to go to last used screen line
+ */
+protected void
+re_goto_bottom(el)
+ 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 */
+
+
+/* re_insert():
+ * insert num characters of s into d (in front of the character)
+ * 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;
+{
+ 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,
+ "re_insert() after insert: %d at %d max %d, d == \"%s\"\n",
+ num, dat, dlen, d),);
+ RE_DEBUG(1,(__F, "s == \"%s\"n", 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 */
+
+
+/* re_delete():
+ * 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;
+{
+ 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 */
+
+
+/* re__strncopy():
+ * Like strncpy without padding.
+ */
+private void
+re__strncopy(a, b, n)
+ char *a, *b;
+ size_t n;
+{
+ while (n-- && *b)
+ *a++ = *b++;
+} /* end re__strncopy */
+
+
+/* ****************************************************************
+ re_update_line() is based on finding the middle difference of each line
+ on the screen; vis:
+
+ /old first difference
+ /beginning of line | /old last same /old EOL
+ v v v v
+old: eddie> Oh, my little gruntle-buggy is to me, as lurgid as
+new: eddie> Oh, my little buggy says to me, as lurgid as
+ ^ ^ ^ ^
+ \beginning of line | \new last same \new end of line
+ \new first difference
+
+ all are character pointers for the sake of speed. Special cases for
+ no differences, as well as for end of line additions must be handled.
+**************************************************************** */
+
+/* Minimum at which doing an insert it "worth it". This should be about
+ * half the "cost" of going into insert mode, inserting a character, and
+ * 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
+
+private void
+re_update_line(el, old, new, i)
+ EditLine *el;
+ char *old, *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;
+ }
+ if (sx < 0) {
+ ols = oe;
+ nls = ne;
+ }
+ if ((ols - ofd) > (nls - nfd)) {
+ ols = oe;
+ nls = ne;
+ }
+ }
+
+ /*
+ * 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);
+
+ 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 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);
+ }
+ 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;
+ }
+ }
+ 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);
+ /*
+ * 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));
+
+ }
+ 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;
+ }
+ }
+ else
+ fx = 0;
+
+ if (sx < 0) {
+ RE_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) {
+ 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 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),);
+
+ 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) {
+ /*
+ * insert fx chars of new starting at nfd
+ */
+ 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));
+ }
+ }
+
+ /*
+ * 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);
+ }
+ 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.
+ */
+ }
+ }
+ RE_DEBUG(1,(__F, "done.\r\n"),);
+} /* re_update_line */
+
+
+/* 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;
+{
+ int i;
+
+ for (i = 0; i < width; i++) {
+ if (*src == '\0')
+ break;
+ *dst++ = *src++;
+ }
+
+ while (i < width) {
+ *dst++ = ' ';
+ i++;
+ }
+ *dst = '\0';
+} /* end re__copy_and_pad */
+
+
+/* re_refresh_cursor():
+ * Move to the new cursor position
+ */
+protected void
+re_refresh_cursor(el)
+ 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++;
+ }
+ 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++;
+ }
+ }
+ }
+
+ 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 */
+
+
+/* re_fastputc():
+ * Add a character fast.
+ */
+private void
+re_fastputc(el, c)
+ 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 */
+
+
+/* re_fastaddc():
+ * we added just one char, handle it fast.
+ * Assumes that screen cursor == real cursor
+ */
+protected void
+re_fastaddc(el)
+ 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 */
+
+
+/* re_clear_display():
+ * clear the screen buffers so that new new prompt starts fresh.
+ */
+protected void
+re_clear_display(el)
+ EditLine *el;
+{
+ 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 */
+
+
+/* re_clear_lines():
+ * Make sure all lines are *really* blank
+ */
+protected void
+re_clear_lines(el)
+ 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);
+ }
+ 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
new file mode 100644
index 000000000000..4fe50bc9aa31
--- /dev/null
+++ b/lib/libedit/refresh.h
@@ -0,0 +1,60 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)refresh.h 8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.refresh.h: Screen refresh functions
+ */
+#ifndef _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 */
+} el_refresh_t;
+
+protected void re_putc __P((EditLine *, int));
+protected void re_clear_lines __P((EditLine *));
+protected void re_clear_display __P((EditLine *));
+protected void re_refresh __P((EditLine *));
+protected void re_refresh_cursor __P((EditLine *));
+protected void re_fastaddc __P((EditLine *));
+protected void re_goto_bottom __P((EditLine *));
+
+#endif /* _h_el_refresh */
diff --git a/lib/libedit/search.c b/lib/libedit/search.c
new file mode 100644
index 000000000000..4ff9c61a5103
--- /dev/null
+++ b/lib/libedit/search.c
@@ -0,0 +1,619 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if !defined(lint) && !defined(SCCSID)
+static char sccsid[] = "@(#)search.c 8.1 (Berkeley) 6/4/93";
+#endif /* not lint && not SCCSID */
+
+/*
+ * search.c: History and character search functions
+ */
+#include "sys.h"
+#include <stdlib.h>
+#ifdef REGEXP
+#include <regexp.h>
+#endif
+#include "el.h"
+
+/*
+ * Adjust cursor in vi mode to include the character under it
+ */
+#define EL_CURSOR(el) \
+ ((el)->el_line.cursor + (((el)->el_map.type == MAP_VI) && \
+ ((el)->el_map.current == (el)->el_map.alt)))
+
+/* search_init():
+ * Initialize the search stuff
+ */
+protected int
+search_init(el)
+ 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;
+}
+
+
+/* search_end():
+ * Initialize the search stuff
+ */
+protected void
+search_end(el)
+ EditLine *el;
+{
+ el_free((ptr_t) el->el_search.patbuf);
+ el->el_search.patbuf = NULL;
+}
+
+#ifdef REGEXP
+/* regerror():
+ * Handle regular expression errors
+ */
+public void
+/*ARGSUSED*/
+regerror(msg)
+ const char *msg;
+{
+}
+#endif
+
+/* el_match():
+ * Return if string matches pattern
+ */
+protected int
+el_match(str, pat)
+ const char *str;
+ const char *pat;
+{
+#ifndef REGEXP
+ extern char *re_comp __P((const char *));
+ extern int re_exec __P((const char *));
+#else
+ regexp *re;
+ int rv;
+#endif
+
+ if (strstr(str, pat) != NULL)
+ return 1;
+#ifndef REGEXP
+ if (re_comp(pat) != NULL)
+ return 0;
+ else
+ return re_exec(str) == 1;
+#else
+ if ((re = regcomp(pat)) != NULL) {
+ rv = regexec(re, str);
+ free((ptr_t) re);
+ }
+ else
+ rv = 0;
+ return rv;
+#endif
+
+}
+
+
+/* c_hmatch():
+ * return True if the pattern matches the prefix
+ */
+protected int
+c_hmatch(el, str)
+ EditLine *el;
+ const char *str;
+{
+#ifdef SDEBUG
+ (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);
+}
+
+
+/* c_setpat():
+ * Set the history seatch pattern
+ */
+protected void
+c_setpat(el)
+ 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';
+ }
+ 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);
+#endif
+}
+
+
+/* ce_inc_search():
+ * Emacs incremental search
+ */
+protected el_action_t
+ce_inc_search(el, dir)
+ 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;
+
+ el_action_t ret = CC_NORM;
+
+ int ohisteventno = el->el_history.eventno,
+ oldpatlen = el->el_search.patlen,
+ newdir = dir,
+ done, redo;
+
+ if (el->el_line.lastchar + sizeof(STRfwd) / sizeof(char) + 2 +
+ el->el_search.patlen >= el->el_line.limit)
+ return CC_ERROR;
+
+ for (;;) {
+
+ 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++] = '*';
+#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;
+ *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) {
+ 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;
+
+ 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';
+
+ 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.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 = ':';
+ }
+ }
+
+ 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 (done || ret != CC_NORM)
+ return ret;
+ }
+}
+
+
+/* cv_search():
+ * Vi search.
+ */
+protected el_action_t
+cv_search(el, dir)
+ EditLine *el;
+ int dir;
+{
+ char ch;
+ char tmpbuf[EL_BUFSIZ];
+ int tmplen;
+
+ tmplen = 0;
+#ifdef ANCHOR
+ tmpbuf[tmplen++] = '.';
+ tmpbuf[tmplen++] = '*';
+#endif
+
+ el->el_line.buffer[0] = '\0';
+ el->el_line.lastchar = el->el_line.buffer;
+ el->el_line.cursor = el->el_line.buffer;
+ el->el_search.patdir = dir;
+
+ c_insert(el, 2); /* prompt + '\n' */
+ *el->el_line.cursor++ = '\n';
+ *el->el_line.cursor++ = dir == ED_SEARCH_PREV_HISTORY ? '/' : '?';
+ re_refresh(el);
+
+#ifdef ANCHOR
+# define LEN 2
+#else
+# define LEN 0
+#endif
+
+ tmplen = c_gets(el, &tmpbuf[LEN]) + 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;
+ }
+#ifdef ANCHOR
+ if (el->el_search.patbuf[0] != '.' && el->el_search.patbuf[0] != '*') {
+ (void) strcpy(tmpbuf, el->el_search.patbuf);
+ el->el_search.patbuf[0] = '.';
+ el->el_search.patbuf[1] = '*';
+ (void) strcpy(&el->el_search.patbuf[2], tmpbuf);
+ 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 {
+#ifdef ANCHOR
+ tmpbuf[tmplen++] = '.';
+ tmpbuf[tmplen++] = '*';
+#endif
+ tmpbuf[tmplen] = '\0';
+ (void) strcpy(el->el_search.patbuf, tmpbuf);
+ 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;
+ }
+ else {
+ if (ch == 0033) {
+ re_refresh(el);
+ *el->el_line.lastchar++ = '\n';
+ *el->el_line.lastchar = '\0';
+ re_goto_bottom(el);
+ return CC_NEWLINE;
+ }
+ else
+ return CC_REFRESH;
+ }
+}
+
+
+/* ce_search_line():
+ * Look for a pattern inside a line
+ */
+protected el_action_t
+ce_search_line(el, pattern, dir)
+ 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;
+ }
+}
+
+
+/* cv_repeat_srch():
+ * Vi repeat search
+ */
+protected el_action_t
+cv_repeat_srch(el, c)
+ 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);
+#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;
+ }
+}
+
+
+/* cv_csearch_back():
+ * Vi character search reverse
+ */
+protected el_action_t
+cv_csearch_back(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.buffer && *cp != ch)
+ cp--;
+ }
+
+ if (cp < el->el_line.buffer || (cp == el->el_line.buffer && *cp != ch))
+ return CC_ERROR;
+
+ if (*cp == ch && tflag)
+ cp++;
+
+ el->el_line.cursor = cp;
+
+ if (el->el_chared.c_vcmd.action & DELETE) {
+ el->el_line.cursor++;
+ cv_delfini(el);
+ return CC_REFRESH;
+ }
+
+ re_refresh_cursor(el);
+ return CC_NORM;
+}
+
+
+/* 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;
+}
diff --git a/lib/libedit/search.h b/lib/libedit/search.h
new file mode 100644
index 000000000000..51c58b4ab5ee
--- /dev/null
+++ b/lib/libedit/search.h
@@ -0,0 +1,68 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)search.h 8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.search.h: Line and history searching utilities
+ */
+#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 */
+} el_search_t;
+
+
+protected int el_match __P((const char *, const char *));
+protected int search_init __P((EditLine *));
+protected void search_end __P((EditLine *));
+protected int c_hmatch __P((EditLine *, const char *));
+protected void c_setpat __P((EditLine *));
+protected el_action_t ce_inc_search __P((EditLine *, int));
+protected el_action_t cv_search __P((EditLine *, int));
+protected el_action_t ce_search_line __P((EditLine *, char *, int));
+protected el_action_t cv_repeat_srch __P((EditLine *, int));
+protected el_action_t cv_csearch_back __P((EditLine *, int, int, int));
+protected el_action_t cv_csearch_fwd __P((EditLine *, int, int, int));
+
+#endif /* _h_el_search */
diff --git a/lib/libedit/sig.c b/lib/libedit/sig.c
new file mode 100644
index 000000000000..94ab4bb8380b
--- /dev/null
+++ b/lib/libedit/sig.c
@@ -0,0 +1,193 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if !defined(lint) && !defined(SCCSID)
+static char sccsid[] = "@(#)sig.c 8.1 (Berkeley) 6/4/93";
+#endif /* not lint && not SCCSID */
+
+/*
+ * sig.c: Signal handling stuff.
+ * 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 void sig_handler __P((int));
+
+/* sig_handler():
+ * This is the handler called for all signals
+ * XXX: we cannot pass any data so we just store the old editline
+ * state in a private variable
+ */
+private void
+sig_handler(signo)
+ int signo;
+{
+ 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);
+}
+
+
+/* sig_init():
+ * Initialize all signal stuff
+ */
+protected int
+sig_init(el)
+ EditLine *el;
+{
+ int i;
+ sigset_t nset, oset;
+
+ (void) sigemptyset(&nset);
+#define _DO(a) (void) sigaddset(&nset, SIGWINCH);
+ ALLSIGS
+#undef _DO
+ (void) sigprocmask(SIG_BLOCK, &nset, &oset);
+
+#define SIGSIZE (sizeof(sighdl) / sizeof(sighdl[0]) * sizeof(sig_t))
+
+ el->el_signal = (sig_t *) el_malloc(SIGSIZE);
+ for (i = 0; sighdl[i] != -1; i++)
+ el->el_signal[i] = BADSIG;
+
+ (void) sigprocmask(SIG_SETMASK, &oset, NULL);
+
+ return 0;
+}
+
+
+/* sig_end():
+ * Clear all signal stuff
+ */
+protected void
+sig_end(el)
+ EditLine *el;
+{
+ el_free((ptr_t) el->el_signal);
+ el->el_signal = NULL;
+}
+
+
+/* sig_set():
+ * set all the signal handlers
+ */
+protected void
+sig_set(el)
+ EditLine *el;
+{
+ int i;
+ sigset_t nset, oset;
+
+ (void) sigemptyset(&nset);
+#define _DO(a) (void) sigaddset(&nset, SIGWINCH);
+ 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);
+}
+
+
+/* sig_clr():
+ * clear all the signal handlers
+ */
+protected void
+sig_clr(el)
+ EditLine *el;
+{
+ int i;
+ sigset_t nset, oset;
+
+ (void) sigemptyset(&nset);
+#define _DO(a) (void) sigaddset(&nset, SIGWINCH);
+ ALLSIGS
+#undef _DO
+ (void) sigprocmask(SIG_BLOCK, &nset, &oset);
+
+ for (i = 0; sighdl[i] != -1; i++)
+ if (el->el_signal[i] != BADSIG)
+ (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
new file mode 100644
index 000000000000..98da74f44c42
--- /dev/null
+++ b/lib/libedit/sig.h
@@ -0,0 +1,70 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)sig.h 8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.sig.h: Signal handling functions
+ */
+#ifndef _h_el_sig
+#define _h_el_sig
+
+#include <signal.h>
+
+#include "histedit.h"
+
+/*
+ * 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)
+
+typedef sig_t *el_signal_t;
+
+protected void sig_end __P((EditLine*));
+protected int sig_init __P((EditLine*));
+protected void sig_set __P((EditLine*));
+protected void sig_clr __P((EditLine*));
+
+#endif /* _h_el_sig */
diff --git a/lib/libedit/sys.h b/lib/libedit/sys.h
new file mode 100644
index 000000000000..cc260f5791a0
--- /dev/null
+++ b/lib/libedit/sys.h
@@ -0,0 +1,113 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)sys.h 8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * sys.h: Put all the stupid compiler and system dependencies here...
+ */
+#ifndef _h_sys
+#define _h_sys
+
+#ifndef public
+# define public /* Externally visible functions/variables */
+#endif
+
+#ifndef private
+# define private static /* Always hidden internals */
+#endif
+
+#ifndef protected
+# define protected /* Redefined from elsewhere to "static" */
+ /* When we want to hide everything */
+#endif
+
+#include <sys/cdefs.h>
+
+#ifndef _PTR_T
+# define _PTR_T
+# if __STDC__
+typedef void* ptr_t;
+# else
+typedef char* ptr_t;
+# endif
+#endif
+
+#ifndef _IOCTL_T
+# define _IOCTL_T
+# if __STDC__
+typedef void* ioctl_t;
+# else
+typedef char* ioctl_t;
+# endif
+#endif
+
+#include <stdio.h>
+#define REGEXP
+
+#ifdef SUNOS
+# undef REGEXP
+# include <malloc.h>
+typedef void (*sig_t)__P((int));
+# ifdef __GNUC__
+/*
+ * Broken hdrs.
+ */
+extern char *getenv __P((const char *));
+extern int fprintf __P((FILE *, const char *, ...));
+extern int sigsetmask __P((int));
+extern int sigblock __P((int));
+extern int ioctl __P((int, int, void *));
+extern int fputc __P((int, FILE *));
+extern int fgetc __P((FILE *));
+extern int fflush __P((FILE *));
+extern int tolower __P((int));
+extern int toupper __P((int));
+extern int errno, sys_nerr;
+extern char *sys_errlist[];
+extern void perror __P((const char *));
+extern int read __P((int, const char*, int));
+# include <string.h>
+# define strerror(e) sys_errlist[e]
+# endif
+# ifdef SABER
+extern ptr_t memcpy __P((ptr_t, const ptr_t, size_t));
+extern ptr_t memset __P((ptr_t, int, size_t));
+# endif
+extern char *fgetline __P((FILE *, int *));
+#endif
+
+#endif /* _h_sys */
diff --git a/lib/libedit/term.c b/lib/libedit/term.c
new file mode 100644
index 000000000000..4971ef1d8928
--- /dev/null
+++ b/lib/libedit/term.c
@@ -0,0 +1,1447 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if !defined(lint) && !defined(SCCSID)
+static char sccsid[] = "@(#)term.c 8.1 (Berkeley) 6/4/93";
+#endif /* not lint && not SCCSID */
+
+/*
+ * term.c: Editor/termcap-curses interface
+ * 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/types.h>
+
+#include "el.h"
+
+/*
+ * IMPORTANT NOTE: these routines are allowed to look at the current screen
+ * and the current possition assuming that it is correct. If this is not
+ * true, then the update will be WRONG! This is (should be) a valid
+ * assumption...
+ */
+
+#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]
+
+private struct {
+ char *b_name;
+ int b_rate;
+} baud_rate[] = {
+#ifdef B0
+ { "0", B0 },
+#endif
+#ifdef B50
+ { "50", B50 },
+#endif
+#ifdef B75
+ { "75", B75 },
+#endif
+#ifdef B110
+ { "110", B110 },
+#endif
+#ifdef B134
+ { "134", B134 },
+#endif
+#ifdef B150
+ { "150", B150 },
+#endif
+#ifdef B200
+ { "200", B200 },
+#endif
+#ifdef B300
+ { "300", B300 },
+#endif
+#ifdef B600
+ { "600", B600 },
+#endif
+#ifdef B900
+ { "900", B900 },
+#endif
+#ifdef B1200
+ { "1200", B1200 },
+#endif
+#ifdef B1800
+ { "1800", B1800 },
+#endif
+#ifdef B2400
+ { "2400", B2400 },
+#endif
+#ifdef B3600
+ { "3600", B3600 },
+#endif
+#ifdef B4800
+ { "4800", B4800 },
+#endif
+#ifdef B7200
+ { "7200", B7200 },
+#endif
+#ifdef B9600
+ { "9600", B9600 },
+#endif
+#ifdef EXTA
+ { "19200", EXTA },
+#endif
+#ifdef B19200
+ { "19200", B19200 },
+#endif
+#ifdef EXTB
+ { "38400", EXTB },
+#endif
+#ifdef B38400
+ { "38400", B38400 },
+#endif
+ { NULL, 0 }
+};
+
+private struct termcapstr {
+ char *name;
+ 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_dc 6
+ { "dc", "delete a character" },
+#define T_dl 7
+ { "dl", "delete a line" },
+#define T_dm 8
+ { "dm", "start delete mode" },
+#define T_ed 9
+ { "ed", "end delete mode" },
+#define T_ei 10
+ { "ei", "end insert mode" },
+#define T_fs 11
+ { "fs", "cursor from status line" },
+#define T_ho 12
+ { "ho", "home cursor" },
+#define T_ic 13
+ { "ic", "insert character" },
+#define T_im 14
+ { "im", "start insert mode" },
+#define T_ip 15
+ { "ip", "insert padding" },
+#define T_kd 16
+ { "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 }
+};
+
+private struct termcapval {
+ char *name;
+ 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, }
+};
+
+/* do two or more of the attributes use me */
+
+private void term_rebuffer_display __P((EditLine *));
+private void term_free_display __P((EditLine *));
+private void term_alloc_display __P((EditLine *));
+private void term_alloc __P((EditLine *,
+ struct termcapstr *, char *));
+private void term_init_arrow __P((EditLine *));
+private void term_reset_arrow __P((EditLine *));
+
+
+private FILE *term_outfile = NULL; /* XXX: How do we fix that? */
+
+
+/* term_setflags():
+ * Set the terminal capability flags
+ */
+private void
+term_setflags(el)
+ 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;
+
+
+#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");
+#endif /* DEBUG_SCREEN */
+}
+
+
+/* term_init():
+ * Initialize the terminal stuff
+ */
+protected int
+term_init(el)
+ 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(char*));
+ 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;
+{
+ 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);
+}
+
+
+/* term_alloc():
+ * Maintain a string pool for termcap strings
+ */
+private void
+term_alloc(el, t, cap)
+ EditLine *el;
+ struct termcapstr *t;
+ 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) strcpy(*str, cap);
+ return;
+ }
+
+ /*
+ * New string is longer; see if we have enough space to append
+ */
+ if (el->el_term.t_loc + 3 < TC_BUFSIZE) {
+ (void) strcpy(*str = &el->el_term.t_buf[el->el_term.t_loc], cap);
+ 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;
+ }
+ (void) strcpy(*str = &el->el_term.t_buf[el->el_term.t_loc], cap);
+ 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;
+{
+ coord_t *c = &el->el_term.t_size;
+
+ 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;
+
+ term_alloc_display(el);
+} /* end term_rebuffer_display */
+
+
+/* term_alloc_display():
+ * Allocate a new display.
+ */
+private void
+term_alloc_display(el)
+ 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 */
+
+
+/* term_free_display():
+ * Free the display buffers
+ */
+private void
+term_free_display(el)
+ 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 */
+
+
+/* term_move_to_line():
+ * move to line <where> (first line == 0)
+ * as efficiently as possible
+ */
+protected void
+term_move_to_line(el, where)
+ EditLine *el;
+ int where;
+{
+ int del, i;
+
+ if (where == el->el_cursor.v)
+ return;
+
+ 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);
+#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 */
+ }
+ }
+ 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);
+ }
+ }
+ el->el_cursor.v = where; /* now where is here */
+} /* end term_move_to_line */
+
+
+/* term_move_to_char():
+ * Move to the character position specified
+ */
+protected void
+term_move_to_char(el, where)
+ EditLine *el;
+ int where;
+{
+ int del, i;
+
+mc_again:
+ if (where == el->el_cursor.h)
+ return;
+
+ if (where > (el->el_term.t_size.h + 1)) {
+#ifdef DEBUG_SCREEN
+ (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);
+
+ }
+ }
+ 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 */
+ }
+ for (i = 0; i < -del; i++)
+ term__putc('\b');
+ }
+ }
+ }
+ el->el_cursor.h = where; /* now where is here */
+} /* end term_move_to_char */
+
+
+/* term_overwrite():
+ * Overstrike num characters
+ */
+protected void
+term_overwrite(el, cp, n)
+ EditLine *el;
+ char *cp;
+ int n;
+{
+ if (n <= 0)
+ return; /* catch bugs */
+
+ if (n > (el->el_term.t_size.h + 1)) {
+#ifdef DEBUG_SCREEN
+ (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 */
+
+
+/* term_deletechars():
+ * Delete num characters
+ */
+protected void
+term_deletechars(el, num)
+ EditLine *el;
+ int num;
+{
+ if (num <= 0)
+ return;
+
+ if (!EL_CAN_DELETE) {
+#ifdef DEBUG_EDIT
+ (void) fprintf(el->el_errfile, " ERROR: cannot delete \n");
+#endif /* DEBUG_EDIT */
+ return;
+ }
+
+ if (num > el->el_term.t_size.h) {
+#ifdef DEBUG_SCREEN
+ (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;
+ }
+
+ 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_ed)) /* if I have delete mode */
+ (void) tputs(Str(T_ed), 1, term__putc);
+} /* end term_deletechars */
+
+
+/* term_insertwrite():
+ * 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;
+{
+ if (num <= 0)
+ return;
+ if (!EL_CAN_INSERT) {
+#ifdef DEBUG_EDIT
+ (void) fprintf(el->el_errfile, " ERROR: cannot insert \n");
+#endif /* DEBUG_EDIT */
+ return;
+ }
+
+ if (num > el->el_term.t_size.h) {
+#ifdef DEBUG_SCREEN
+ (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;
+ }
+
+ 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);
+
+ (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++);
+
+ 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 */
+
+ } while (--num);
+} /* end term_insertwrite */
+
+
+/* term_clear_EOL():
+ * clear to end of line. There are num characters to clear
+ */
+protected void
+term_clear_EOL(el, num)
+ EditLine *el;
+ int num;
+{
+ 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 */
+
+
+/* term_clear_screen():
+ * Clear the screen
+ */
+protected void
+term_clear_screen(el)
+ 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 */
+
+
+/* term_beep():
+ * Beep the way the terminal wants us
+ */
+protected void
+term_beep(el)
+ 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 */
+
+
+#ifdef notdef
+/* term_clear_to_bottom():
+ * Clear to the bottom of the screen
+ */
+protected void
+term_clear_to_bottom(el)
+ 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 */
+#endif
+
+
+/* term_set():
+ * Read in the terminal capabilities from the requested terminal
+ */
+protected int
+term_set(el, term)
+ EditLine *el;
+ 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 open /etc/termcap.\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));
+ }
+
+ 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);
+
+ 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 */
+
+
+/* term_get_size():
+ * Return the new window size in lines and cols, and
+ * true if the size was changed.
+ */
+protected int
+term_get_size(el, lins, cols)
+ EditLine *el;
+ int *lins, *cols;
+{
+
+ *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;
+ }
+ }
+#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;
+ }
+ }
+#endif
+ return (Val(T_co) != *cols || Val(T_li) != *lins);
+} /* end term_get_size */
+
+
+/* term_change_size():
+ * Change the size of the terminal
+ */
+protected void
+term_change_size(el, lins, cols)
+ EditLine *el;
+ int lins, 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 */
+
+
+/* term_init_arrow():
+ * Initialize the arrow key bindings from termcap
+ */
+private void
+term_init_arrow(el)
+ EditLine *el;
+{
+ fkey_t *arrow = el->el_term.t_fkey;
+
+ arrow[A_K_DN].name = "down";
+ 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].fun.cmd = ED_PREV_HISTORY;
+ arrow[A_K_UP].type = XK_CMD;
+
+ arrow[A_K_LT].name = "left";
+ 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].fun.cmd = ED_NEXT_CHAR;
+ arrow[A_K_RT].type = XK_CMD;
+
+}
+
+
+/* term_reset_arrow():
+ * Reset arrow key bindings
+ */
+private void
+term_reset_arrow(el)
+ 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);
+ }
+}
+
+
+/* term_set_arrow():
+ * Set an arrow key binding
+ */
+protected int
+term_set_arrow(el, name, fun, type)
+ EditLine *el;
+ 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;
+}
+
+
+/* term_clear_arrow():
+ * Clear an arrow key binding
+ */
+protected int
+term_clear_arrow(el, name)
+ EditLine *el;
+ char *name;
+{
+ 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;
+}
+
+
+/* term_print_arrow():
+ * Print the arrow key bindings
+ */
+protected void
+term_print_arrow(el, name)
+ EditLine *el;
+ 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);
+}
+
+
+/* term_bind_arrow():
+ * Bind the arrow keys
+ */
+protected void
+term_bind_arrow(el)
+ 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);
+ }
+ }
+ }
+ }
+}
+
+
+/* term__putc():
+ * Add a character
+ */
+protected void
+term__putc(c)
+ int c;
+{
+ (void) fputc(c, term_outfile);
+} /* end term__putc */
+
+
+/* term__flush():
+ * Flush output
+ */
+protected void
+term__flush()
+{
+ (void) fflush(term_outfile);
+} /* end term__flush */
+
+
+/* term_telltc():
+ * Print the current termcap characteristics
+ */
+protected int
+/*ARGSUSED*/
+term_telltc(el, argc, argv)
+ EditLine *el;
+ int argc;
+ char **argv;
+{
+ 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",
+ 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;
+}
+
+
+/* term_settc():
+ * Change the current terminal characteristics
+ */
+protected int
+/*ARGSUSED*/
+term_settc(el, argc, argv)
+ EditLine *el;
+ int argc;
+ 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;
+ }
+ 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;
+ }
+ }
+ return -1;
+}
+
+
+/* term_echotc():
+ * Print the termcap string out with variable substitution
+ */
+protected int
+/*ARGSUSED*/
+term_echotc(el, argc, argv)
+ EditLine *el;
+ int argc;
+ 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;
+ }
+ 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) {
+ 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);
+ 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;
+ }
+ 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++;
+ 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 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;
+}
diff --git a/lib/libedit/term.h b/lib/libedit/term.h
new file mode 100644
index 000000000000..416e73ee8faa
--- /dev/null
+++ b/lib/libedit/term.h
@@ -0,0 +1,118 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)term.h 8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.term.h: Termcap header
+ */
+#ifndef _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 */
+} 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 */
+} 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
+
+protected void term_move_to_line __P((EditLine *, int));
+protected void term_move_to_char __P((EditLine *, int));
+protected void term_clear_EOL __P((EditLine *, int));
+protected void term_overwrite __P((EditLine *, char *, int));
+protected void term_insertwrite __P((EditLine *, char *, int));
+protected void term_deletechars __P((EditLine *, int));
+protected void term_clear_screen __P((EditLine *));
+protected void term_beep __P((EditLine *));
+protected void term_change_size __P((EditLine *, int, int));
+protected int term_get_size __P((EditLine *, int *, int *));
+protected int term_init __P((EditLine *));
+protected void term_bind_arrow __P((EditLine *));
+protected void term_print_arrow __P((EditLine *, char *));
+protected int term_clear_arrow __P((EditLine *, char *));
+protected int term_set_arrow __P((EditLine *, char *,
+ key_value_t *, int));
+protected void term_end __P((EditLine *));
+protected int term_set __P((EditLine *, char *));
+protected int term_settc __P((EditLine *, int, char **));
+protected int term_telltc __P((EditLine *, int, char **));
+protected int term_echotc __P((EditLine *, int, char **));
+
+protected void term__putc __P((int));
+protected void term__flush __P((void));
+
+/*
+ * Easy access macros
+ */
+#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)
+
+#endif /* _h_el_term */
diff --git a/lib/libedit/termcap.h b/lib/libedit/termcap.h
new file mode 100644
index 000000000000..4fd2cab0ec02
--- /dev/null
+++ b/lib/libedit/termcap.h
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)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 __P((char *, char *));
+char *tgetstr __P((char *, char **));
+int tgetflag __P((char *));
+int tgetnum __P((char *));
+char *tgoto __P((char *, int, int));
+char *tputs __P((char *, int, void (*)(int)));
+
+#endif /* _h_termcap */
diff --git a/lib/libedit/tokenizer.c b/lib/libedit/tokenizer.c
new file mode 100644
index 000000000000..41095fa980f6
--- /dev/null
+++ b/lib/libedit/tokenizer.c
@@ -0,0 +1,385 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if !defined(lint) && !defined(SCCSID)
+static char sccsid[] = "@(#)tokenizer.c 8.1 (Berkeley) 6/4/93";
+#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;
+
+#define IFS "\t \n"
+
+#define TOK_KEEP 1
+#define TOK_EAT 2
+
+#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)
+
+
+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; */
+};
+
+
+private void tok_finish __P((Tokenizer *));
+
+
+/* tok_finish():
+ * Finish a word in the tokenizer.
+ */
+private void
+tok_finish(tok)
+ 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_init():
+ * Initialize the tokenizer
+ */
+public Tokenizer *
+tok_init(ifs)
+ 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;
+}
+
+
+/* tok_reset():
+ * Reset the tokenizer
+ */
+public void
+tok_reset(tok)
+ Tokenizer *tok;
+{
+ tok->argc = 0;
+ tok->wstart = tok->wspace;
+ tok->wptr = tok->wspace;
+ tok->flags = 0;
+ tok->quote = Q_none;
+}
+
+
+/* tok_end():
+ * Clean up
+ */
+public void
+tok_end(tok)
+ 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_line():
+ * Bourne shell like tokenizing
+ * Return:
+ * -1: Internal error
+ * 3: Quoted return
+ * 2: Unmatched double quote
+ * 1: Unmatched single quote
+ * 0: Ok
+ */
+public int
+tok_line(tok, line, argc, argv)
+ Tokenizer *tok;
+ const char* line;
+ int *argc;
+ 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;
+ }
+ 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 = (char *) tok_realloc(tok->wspace, size);
+ /*SUPPRESS 22*/
+ int offs = s - tok->wspace;
+
+ if (offs != 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->wmax = s + size;
+ tok->wspace = s;
+ }
+ }
+
+ if (tok->argc >= tok->amax - 4) {
+ tok->amax += AINCR;
+ tok->argv = (char **) tok_realloc(tok->argv,
+ tok->amax * sizeof(char*));
+ }
+
+ }
+}
diff --git a/lib/libedit/tokenizer.h b/lib/libedit/tokenizer.h
new file mode 100644
index 000000000000..d495dc69ab02
--- /dev/null
+++ b/lib/libedit/tokenizer.h
@@ -0,0 +1,53 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)tokenizer.h 8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * tokenizer.h: Header file for tokenizer routines
+ */
+#ifndef _h_tokenizer
+#define _h_tokenizer
+
+typedef struct tokenizer Tokenizer;
+
+Tokenizer *tok_init __P((const char *));
+void tok_reset __P((Tokenizer *));
+void tok_end __P((Tokenizer *));
+int tok_line __P((Tokenizer *, const char *,
+ int *, char ***));
+
+#endif /* _h_tokenizer */
diff --git a/lib/libedit/tty.c b/lib/libedit/tty.c
new file mode 100644
index 000000000000..ac99843b7746
--- /dev/null
+++ b/lib/libedit/tty.c
@@ -0,0 +1,1144 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if !defined(lint) && !defined(SCCSID)
+static char sccsid[] = "@(#)tty.c 8.1 (Berkeley) 6/4/93";
+#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;
+ int m_value;
+ int m_type;
+} ttymodes_t;
+
+typedef struct ttymap_t {
+ int nch, och; /* Internal and termio rep of chars */
+ el_action_t bind[3]; /* emacs, vi, and vi-cmd */
+} ttymap_t;
+
+
+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 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[] = {
+#ifdef VERASE
+ { 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 } },
+#endif /* VERASE2 */
+#ifdef VKILL
+ { 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 } },
+#endif /* VKILL2 */
+#ifdef VEOF
+ { 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 } },
+#endif /* VWERASE */
+#ifdef VREPRINT
+ { C_REPRINT, VREPRINT,
+ { ED_REDISPLAY, ED_INSERT, ED_REDISPLAY } },
+#endif /* VREPRINT */
+#ifdef VLNEXT
+ { C_LNEXT, VLNEXT,
+ { ED_QUOTED_INSERT, ED_QUOTED_INSERT, ED_UNASSIGNED } },
+#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 },
+};
+
+
+
+#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)
+
+private void tty__getchar __P((struct termios *, unsigned char *));
+private void tty__setchar __P((struct termios *, unsigned char *));
+private speed_t tty__getspeed __P((struct termios *));
+private int tty_setup __P((EditLine *));
+
+#define t_qu t_ts
+
+
+/* tty_setup():
+ * Get the tty parameters and initialize the editing state
+ */
+private int
+tty_setup(el)
+ EditLine *el;
+{
+ int rst = 1;
+ 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));
+#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) {
+#ifdef DEBUG_TTY
+ (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]);
+
+ 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_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_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_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;
+
+ tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
+ return 0;
+}
+
+protected int
+tty_init(el)
+ 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 */
+
+
+/* tty_end():
+ * Restore the tty to its original settings
+ */
+protected void
+/*ARGSUSED*/
+tty_end(el)
+ EditLine *el;
+{
+ /* XXX: Maybe reset to an initial state? */
+}
+
+
+/* tty__getspeed():
+ * Get the tty speed
+ */
+private speed_t
+tty__getspeed(td)
+ struct termios *td;
+{
+ speed_t spd;
+
+ if ((spd = cfgetispeed(td)) == 0)
+ spd = cfgetospeed(td);
+ return spd;
+} /* end tty__getspeed */
+
+
+/* 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__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_bind_char():
+ * Rebind the editline functions
+ */
+protected void
+tty_bind_char(el, force)
+ 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;
+ 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];
+ }
+ }
+}
+
+/* tty_rawmode():
+ * Set terminal into 1 character at a time mode.
+ */
+protected int
+tty_rawmode(el)
+ 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_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;
+
+ 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 ((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;
+ }
+
+ 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;
+ }
+ 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;
+ }
+ tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
+ }
+
+ }
+ }
+
+ 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));
+#endif /* DEBUG_TTY */
+ return -1;
+ }
+ el->el_tty.t_mode = ED_IO;
+ return (0);
+} /* end tty_rawmode */
+
+
+/* tty_cookedmode():
+ * Set the tty back to normal mode
+ */
+protected int
+tty_cookedmode(el)
+ 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) {
+#ifdef DEBUG_TTY
+ (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 */
+
+
+/* tty_quotemode():
+ * Turn on quote mode
+ */
+protected int
+tty_quotemode(el)
+ EditLine *el;
+{
+ 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.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_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_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_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;
+
+ 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));
+#endif /* DEBUG_TTY */
+ return -1;
+ }
+ el->el_tty.t_mode = QU_IO;
+ return 0;
+} /* end tty_quotemode */
+
+
+/* tty_noquotemode():
+ * Turn off quote mode
+ */
+protected int
+tty_noquotemode(el)
+ EditLine *el;
+{
+ 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));
+#endif /* DEBUG_TTY */
+ 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;
+{
+ 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;
+ }
+ 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;
+ }
+
+ 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 */
+
+
+#ifdef notyet
+/* tty_printchar():
+ * DEbugging routine to print the tty characters
+ */
+private void
+tty_printchar(el, s)
+ 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");
+}
+#endif /* notyet */
diff --git a/lib/libedit/tty.h b/lib/libedit/tty.h
new file mode 100644
index 000000000000..12da50dcb5bd
--- /dev/null
+++ b/lib/libedit/tty.h
@@ -0,0 +1,476 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)tty.h 8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.tty.h: Local terminal header
+ */
+#ifndef _h_el_tty
+#define _h_el_tty
+
+#include "histedit.h"
+#include <termios.h>
+
+/* Define our own since everyone gets it wrong! */
+#define CONTROL(A) ((A) & 037)
+
+/*
+ * Aix compatible names
+ */
+# if defined(VWERSE) && !defined(VWERASE)
+# define VWERASE VWERSE
+# endif /* VWERSE && !VWERASE */
+
+# if defined(VDISCRD) && !defined(VDISCARD)
+# define VDISCARD VDISCRD
+# endif /* VDISCRD && !VDISCARD */
+
+# if defined(VFLUSHO) && !defined(VDISCARD)
+# define VDISCARD VFLUSHO
+# endif /* VFLUSHO && VDISCARD */
+
+# if defined(VSTRT) && !defined(VSTART)
+# define VSTART VSTRT
+# endif /* VSTRT && ! VSTART */
+
+# if defined(VSTAT) && !defined(VSTATUS)
+# define VSTATUS VSTAT
+# endif /* VSTAT && ! VSTATUS */
+
+# ifndef ONLRET
+# define ONLRET 0
+# endif /* ONLRET */
+
+# ifndef TAB3
+# ifdef OXTABS
+# define TAB3 OXTABS
+# else
+# define TAB3 0
+# endif /* OXTABS */
+# endif /* !TAB3 */
+
+# if defined(OXTABS) && !defined(XTABS)
+# define XTABS OXTABS
+# endif /* OXTABS && !XTABS */
+
+# ifndef ONLCR
+# define ONLCR 0
+# endif /* ONLCR */
+
+# ifndef IEXTEN
+# define IEXTEN 0
+# endif /* IEXTEN */
+
+# ifndef ECHOCTL
+# define ECHOCTL 0
+# endif /* ECHOCTL */
+
+# ifndef PARENB
+# define PARENB 0
+# endif /* PARENB */
+
+# ifndef EXTPROC
+# define EXTPROC 0
+# endif /* EXTPROC */
+
+# ifndef FLUSHO
+# define FLUSHO 0
+# endif /* FLUSHO */
+
+
+# if defined(VDISABLE) && !defined(_POSIX_VDISABLE)
+# define _POSIX_VDISABLE VDISABLE
+# endif /* VDISABLE && ! _POSIX_VDISABLE */
+
+/*
+ * Work around ISC's definition of IEXTEN which is
+ * XCASE!
+ */
+# ifdef ISC
+# if defined(IEXTEN) && defined(XCASE)
+# if IEXTEN == XCASE
+# undef IEXTEN
+# define IEXTEN 0
+# endif /* IEXTEN == XCASE */
+# endif /* IEXTEN && XCASE */
+# if defined(IEXTEN) && !defined(XCASE)
+# define XCASE IEXTEN
+# undef IEXTEN
+# define IEXTEN 0
+# endif /* IEXTEN && !XCASE */
+# endif /* ISC */
+
+/*
+ * Work around convex weirdness where turning off IEXTEN makes us
+ * lose all postprocessing!
+ */
+#if defined(convex) || defined(__convex__)
+# if defined(IEXTEN) && IEXTEN != 0
+# undef IEXTEN
+# define IEXTEN 0
+# endif /* IEXTEN != 0 */
+#endif /* convex || __convex__ */
+
+
+
+#ifndef _POSIX_VDISABLE
+# define _POSIX_VDISABLE ((unsigned char) -1)
+#endif /* _POSIX_VDISABLE */
+
+#if !defined(CREPRINT) && defined(CRPRNT)
+# define CREPRINT CRPRNT
+#endif /* !CREPRINT && CRPRNT */
+#if !defined(CDISCARD) && defined(CFLUSH)
+# define CDISCARD CFLUSH
+#endif /* !CDISCARD && CFLUSH */
+
+#ifndef CINTR
+# define CINTR CONTROL('c')
+#endif /* CINTR */
+#ifndef CQUIT
+# define CQUIT 034 /* ^\ */
+#endif /* CQUIT */
+#ifndef CERASE
+# define CERASE 0177 /* ^? */
+#endif /* CERASE */
+#ifndef CKILL
+# define CKILL CONTROL('u')
+#endif /* CKILL */
+#ifndef CEOF
+# define CEOF CONTROL('d')
+#endif /* CEOF */
+#ifndef CEOL
+# define CEOL _POSIX_VDISABLE
+#endif /* CEOL */
+#ifndef CEOL2
+# define CEOL2 _POSIX_VDISABLE
+#endif /* CEOL2 */
+#ifndef CSWTCH
+# define CSWTCH _POSIX_VDISABLE
+#endif /* CSWTCH */
+#ifndef CDSWTCH
+# define CDSWTCH _POSIX_VDISABLE
+#endif /* CDSWTCH */
+#ifndef CERASE2
+# define CERASE2 _POSIX_VDISABLE
+#endif /* CERASE2 */
+#ifndef CSTART
+# define CSTART CONTROL('q')
+#endif /* CSTART */
+#ifndef CSTOP
+# define CSTOP CONTROL('s')
+#endif /* CSTOP */
+#ifndef CSUSP
+# define CSUSP CONTROL('z')
+#endif /* CSUSP */
+#ifndef CDSUSP
+# define CDSUSP CONTROL('y')
+#endif /* CDSUSP */
+
+#ifdef hpux
+
+# ifndef CREPRINT
+# define CREPRINT _POSIX_VDISABLE
+# endif /* CREPRINT */
+# ifndef CDISCARD
+# define CDISCARD _POSIX_VDISABLE
+# endif /* CDISCARD */
+# ifndef CLNEXT
+# define CLNEXT _POSIX_VDISABLE
+# endif /* CLNEXT */
+# ifndef CWERASE
+# define CWERASE _POSIX_VDISABLE
+# endif /* CWERASE */
+
+#else /* !hpux */
+
+# ifndef CREPRINT
+# define CREPRINT CONTROL('r')
+# endif /* CREPRINT */
+# ifndef CDISCARD
+# define CDISCARD CONTROL('o')
+# endif /* CDISCARD */
+# ifndef CLNEXT
+# define CLNEXT CONTROL('v')
+# endif /* CLNEXT */
+# ifndef CWERASE
+# define CWERASE CONTROL('w')
+# endif /* CWERASE */
+
+#endif /* hpux */
+
+#ifndef CSTATUS
+# define CSTATUS CONTROL('t')
+#endif /* CSTATUS */
+#ifndef CPAGE
+# define CPAGE ' '
+#endif /* CPAGE */
+#ifndef CPGOFF
+# define CPGOFF CONTROL('m')
+#endif /* CPGOFF */
+#ifndef CKILL2
+# define CKILL2 _POSIX_VDISABLE
+#endif /* CKILL2 */
+#ifndef CBRK
+# ifndef masscomp
+# define CBRK 0377
+# else
+# define CBRK '\0'
+# endif /* masscomp */
+#endif /* CBRK */
+#ifndef CMIN
+# define CMIN CEOF
+#endif /* CMIN */
+#ifndef CTIME
+# define CTIME CEOL
+#endif /* CTIME */
+
+/*
+ * Fix for sun inconsistency. On termio VSUSP and the rest of the
+ * ttychars > NCC are defined. So we undefine them.
+ */
+#if defined(TERMIO) || defined(POSIX)
+# if defined(POSIX) && defined(NCCS)
+# define NUMCC NCCS
+# else
+# ifdef NCC
+# define NUMCC NCC
+# endif /* NCC */
+# endif /* POSIX && NCCS */
+# ifdef NUMCC
+# ifdef VINTR
+# if NUMCC <= VINTR
+# undef VINTR
+# endif /* NUMCC <= VINTR */
+# endif /* VINTR */
+# ifdef VQUIT
+# if NUMCC <= VQUIT
+# undef VQUIT
+# endif /* NUMCC <= VQUIT */
+# endif /* VQUIT */
+# ifdef VERASE
+# if NUMCC <= VERASE
+# undef VERASE
+# endif /* NUMCC <= VERASE */
+# endif /* VERASE */
+# ifdef VKILL
+# if NUMCC <= VKILL
+# undef VKILL
+# endif /* NUMCC <= VKILL */
+# endif /* VKILL */
+# ifdef VEOF
+# if NUMCC <= VEOF
+# undef VEOF
+# endif /* NUMCC <= VEOF */
+# endif /* VEOF */
+# ifdef VEOL
+# if NUMCC <= VEOL
+# undef VEOL
+# endif /* NUMCC <= VEOL */
+# endif /* VEOL */
+# ifdef VEOL2
+# if NUMCC <= VEOL2
+# undef VEOL2
+# endif /* NUMCC <= VEOL2 */
+# endif /* VEOL2 */
+# ifdef VSWTCH
+# if NUMCC <= VSWTCH
+# undef VSWTCH
+# endif /* NUMCC <= VSWTCH */
+# endif /* VSWTCH */
+# ifdef VDSWTCH
+# if NUMCC <= VDSWTCH
+# undef VDSWTCH
+# endif /* NUMCC <= VDSWTCH */
+# endif /* VDSWTCH */
+# ifdef VERASE2
+# if NUMCC <= VERASE2
+# undef VERASE2
+# endif /* NUMCC <= VERASE2 */
+# endif /* VERASE2 */
+# ifdef VSTART
+# if NUMCC <= VSTART
+# undef VSTART
+# endif /* NUMCC <= VSTART */
+# endif /* VSTART */
+# ifdef VSTOP
+# if NUMCC <= VSTOP
+# undef VSTOP
+# endif /* NUMCC <= VSTOP */
+# endif /* VSTOP */
+# ifdef VWERASE
+# if NUMCC <= VWERASE
+# undef VWERASE
+# endif /* NUMCC <= VWERASE */
+# endif /* VWERASE */
+# ifdef VSUSP
+# if NUMCC <= VSUSP
+# undef VSUSP
+# endif /* NUMCC <= VSUSP */
+# endif /* VSUSP */
+# ifdef VDSUSP
+# if NUMCC <= VDSUSP
+# undef VDSUSP
+# endif /* NUMCC <= VDSUSP */
+# endif /* VDSUSP */
+# ifdef VREPRINT
+# if NUMCC <= VREPRINT
+# undef VREPRINT
+# endif /* NUMCC <= VREPRINT */
+# endif /* VREPRINT */
+# ifdef VDISCARD
+# if NUMCC <= VDISCARD
+# undef VDISCARD
+# endif /* NUMCC <= VDISCARD */
+# endif /* VDISCARD */
+# ifdef VLNEXT
+# if NUMCC <= VLNEXT
+# undef VLNEXT
+# endif /* NUMCC <= VLNEXT */
+# endif /* VLNEXT */
+# ifdef VSTATUS
+# if NUMCC <= VSTATUS
+# undef VSTATUS
+# endif /* NUMCC <= VSTATUS */
+# endif /* VSTATUS */
+# ifdef VPAGE
+# if NUMCC <= VPAGE
+# undef VPAGE
+# endif /* NUMCC <= VPAGE */
+# endif /* VPAGE */
+# ifdef VPGOFF
+# if NUMCC <= VPGOFF
+# undef VPGOFF
+# endif /* NUMCC <= VPGOFF */
+# endif /* VPGOFF */
+# ifdef VKILL2
+# if NUMCC <= VKILL2
+# undef VKILL2
+# endif /* NUMCC <= VKILL2 */
+# endif /* VKILL2 */
+# ifdef VBRK
+# if NUMCC <= VBRK
+# undef VBRK
+# endif /* NUMCC <= VBRK */
+# endif /* VBRK */
+# ifdef VMIN
+# if NUMCC <= VMIN
+# undef VMIN
+# endif /* NUMCC <= VMIN */
+# endif /* VMIN */
+# ifdef VTIME
+# if NUMCC <= VTIME
+# undef VTIME
+# endif /* NUMCC <= VTIME */
+# endif /* VTIME */
+# 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))
+
+/*
+ * 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;
+ int t_setmask;
+ int t_clrmask;
+} ttyperm_t[NN_IO][M_NN];
+
+typedef unsigned char ttychar_t[NN_IO][C_NCC];
+
+protected int tty_init __P((EditLine *));
+protected void tty_end __P((EditLine *));
+protected int tty_stty __P((EditLine *, int, char**));
+protected int tty_rawmode __P((EditLine *));
+protected int tty_cookedmode __P((EditLine *));
+protected int tty_quotemode __P((EditLine *));
+protected int tty_noquotemode __P((EditLine *));
+protected void tty_bind_char __P((EditLine *, int));
+
+typedef struct {
+ ttyperm_t t_t;
+ ttychar_t t_c;
+ struct termios t_ex, t_ed, t_ts;
+ int t_tabs;
+ int t_eight;
+ speed_t t_speed;
+ int t_mode;
+ unsigned char t_vdisable;
+} el_tty_t;
+
+
+#endif /* _h_el_tty */
diff --git a/lib/libedit/vi.c b/lib/libedit/vi.c
new file mode 100644
index 000000000000..030ee2286b0d
--- /dev/null
+++ b/lib/libedit/vi.c
@@ -0,0 +1,986 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if !defined(lint) && !defined(SCCSID)
+static char sccsid[] = "@(#)vi.c 8.1 (Berkeley) 6/4/93";
+#endif /* not lint && not SCCSID */
+
+/*
+ * vi.c: Vi mode commands.
+ */
+#include "sys.h"
+#include "el.h"
+
+private el_action_t cv_action __P((EditLine *, int));
+
+/* cv_action():
+ * Handle vi actions.
+ */
+private el_action_t
+cv_action(el, c)
+ 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++;
+ }
+
+ 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
+}
+
+
+/* cv_paste():
+ * Paste previous deletion before or after the cursor
+ */
+protected el_action_t
+cv_paste(el, c)
+ EditLine *el;
+ int c;
+{
+ char *ptr;
+ c_undo_t *un = &el->el_chared.c_undo;
+#ifdef DEBUG_PASTE
+ (void) fprintf(el->el_errfile, "Paste: %x \"%s\" +%d -%d\n",
+ un->action, un->buf, un->isize, un->dsize);
+#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;
+}
+
+
+/* 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;
+{
+ return cv_paste(el, 0);
+}
+
+
+/* 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;
+{
+ return cv_paste(el, 1);
+}
+
+
+/* vi_prev_space_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;
+{
+ 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_chared.c_vcmd.action & DELETE) {
+ cv_delfini(el);
+ return CC_REFRESH;
+ }
+
+ return CC_CURSOR;
+}
+
+
+/* vi_prev_word():
+ * Vi move to the previous word
+ * [B]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_prev_word(el, c)
+ 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,
+ ce__isword);
+
+ if (el->el_chared.c_vcmd.action & DELETE) {
+ cv_delfini(el);
+ return CC_REFRESH;
+ }
+
+ return CC_CURSOR;
+}
+
+
+/* vi_next_space_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;
+{
+ 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_map.type == MAP_VI)
+ if (el->el_chared.c_vcmd.action & DELETE) {
+ cv_delfini(el);
+ return CC_REFRESH;
+ }
+
+ return CC_CURSOR;
+}
+
+/* vi_next_word():
+ * Vi move to the next word
+ * [w]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_next_word(el, c)
+ 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,
+ 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;
+}
+
+
+
+/* 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;
+{
+ 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);
+ return CC_NORM;
+ }
+ return CC_ERROR;
+}
+
+
+/* vi_change_meta():
+ * Vi change prefix command
+ * [c]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_change_meta(el, c)
+ EditLine *el;
+ int c;
+{
+ /*
+ * 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 enter insert mode at the beginning of line
+ * [I]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_insert_at_bol(el, c)
+ EditLine *el;
+ int c;
+{
+ 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;
+}
+
+
+/* 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;
+{
+ 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;
+}
+
+
+/* vi_replace_mode():
+ * Vi enter replace mode
+ * [R]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_replace_mode(el, c)
+ EditLine *el;
+ int c;
+{
+ 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;
+}
+
+
+/* vi_substitute_char():
+ * Vi replace character under the cursor and enter insert mode
+ * [r]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_substitute_char(el, c)
+ EditLine *el;
+ int c;
+{
+ c_delafter(el, el->el_state.argument);
+ el->el_map.current = el->el_map.key;
+ return CC_REFRESH;
+}
+
+
+/* vi_substitute_line():
+ * Vi substitute entire line
+ * [S]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_substitute_line(el, c)
+ EditLine *el;
+ int c;
+{
+ (void) em_kill_line(el, 0);
+ el->el_map.current = el->el_map.key;
+ return CC_REFRESH;
+}
+
+
+/* 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;
+{
+ (void) ed_kill_line(el, 0);
+ el->el_map.current = el->el_map.key;
+ return CC_REFRESH;
+}
+
+
+/* vi_insert():
+ * Vi enter insert mode
+ * [i]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_insert(el, c)
+ EditLine *el;
+ int c;
+{
+ 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;
+}
+
+
+/* vi_add():
+ * Vi enter insert mode after the cursor
+ * [a]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_add(el, c)
+ EditLine *el;
+ int c;
+{
+ 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;
+
+ return ret;
+}
+
+
+/* vi_add_at_eol():
+ * Vi enter insert mode at end of line
+ * [A]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_add_at_eol(el, c)
+ EditLine *el;
+ int c;
+{
+ 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;
+}
+
+
+/* vi_delete_meta():
+ * Vi delete prefix command
+ * [d]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_delete_meta(el, c)
+ EditLine *el;
+ int c;
+{
+ return cv_action(el, DELETE);
+}
+
+
+/* vi_end_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;
+{
+ 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_chared.c_vcmd.action & DELETE) {
+ el->el_line.cursor++;
+ cv_delfini(el);
+ return CC_REFRESH;
+ }
+
+ return CC_CURSOR;
+}
+
+
+/* vi_to_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;
+{
+ 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_chared.c_vcmd.action & DELETE) {
+ el->el_line.cursor++;
+ cv_delfini(el);
+ return CC_REFRESH;
+ }
+
+ return CC_CURSOR;
+}
+
+
+/* vi_undo():
+ * Vi undo last change
+ * [u]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_undo(el, c)
+ EditLine *el;
+ int c;
+{
+ char *cp, *kp;
+ char temp;
+ int i, size;
+ c_undo_t *un = &el->el_chared.c_undo;
+
+#ifdef DEBUG_UNDO
+ (void) fprintf(el->el_errfile, "Undo: %x \"%s\" +%d -%d\n",
+ un->action, un->buf, un->isize, un->dsize);
+#endif
+ switch (un->action) {
+ case DELETE:
+ if (un->dsize == 0)
+ return CC_NORM;
+
+ (void) memcpy(un->buf, un->ptr, un->dsize);
+ for (cp = un->ptr; cp <= el->el_line.lastchar; cp++)
+ *cp = cp[un->dsize];
+
+ el->el_line.lastchar -= un->dsize;
+ el->el_line.cursor = un->ptr;
+
+ 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;
+
+ default:
+ return CC_ERROR;
+ }
+
+ return CC_REFRESH;
+}
+
+
+/* vi_command_mode():
+ * Vi enter command mode (use alternative key bindings)
+ * [<ESC>]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_command_mode(el, c)
+ EditLine *el;
+ int c;
+{
+ int size;
+ /* [Esc] cancels pending action */
+ el->el_chared.c_vcmd.ins = 0;
+ el->el_chared.c_vcmd.action = NOP;
+ el->el_chared.c_vcmd.pos = 0;
+
+ el->el_state.doingarg = 0;
+ size = el->el_chared.c_undo.ptr - el->el_line.cursor;
+ if (size < 0)
+ size = -size;
+ if (el->el_chared.c_undo.action == (INSERT|DELETE) ||
+ el->el_chared.c_undo.action == DELETE)
+ el->el_chared.c_undo.dsize = size;
+ else
+ el->el_chared.c_undo.isize = size;
+
+ el->el_state.inputmode = MODE_INSERT;
+ el->el_map.current = el->el_map.alt;
+#ifdef VI_MOVE
+ if (el->el_line.cursor > el->el_line.buffer)
+ el->el_line.cursor--;
+#endif
+ return CC_CURSOR;
+}
+
+/* vi_zero():
+ * Vi move to the beginning of line
+ * [0]
+ */
+protected el_action_t
+vi_zero(el, c)
+ EditLine *el;
+ int c;
+{
+ if (el->el_state.doingarg) {
+ if (el->el_state.argument > 1000000)
+ return CC_ERROR;
+ el->el_state.argument =
+ (el->el_state.argument * 10) + (c - '0');
+ return CC_ARGHACK;
+ }
+ else {
+ el->el_line.cursor = el->el_line.buffer;
+ if (el->el_chared.c_vcmd.action & DELETE) {
+ cv_delfini(el);
+ return CC_REFRESH;
+ }
+ return CC_CURSOR;
+ }
+}
+
+
+/* vi_delete_prev_char():
+ * Vi move to previous character (backspace)
+ * [^H]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_delete_prev_char(el, c)
+ EditLine *el;
+ int c;
+{
+ if (el->el_chared.c_vcmd.ins == 0)
+ return CC_ERROR;
+
+ if (el->el_chared.c_vcmd.ins >
+ el->el_line.cursor - el->el_state.argument)
+ return CC_ERROR;
+
+ c_delbefore(el, el->el_state.argument);
+ el->el_line.cursor -= el->el_state.argument;
+
+ return CC_REFRESH;
+} /* end v_del_char_prev */
+
+
+/* vi_list_or_eof():
+ * Vi list choices for completion or indicate end of file if empty line
+ * [^D]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_list_or_eof(el, c)
+ EditLine *el;
+ int c;
+{
+#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;
+ }
+#endif
+}
+
+
+/* vi_kill_line_prev():
+ * Vi cut from beginning of line to cursor
+ * [^U]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_kill_line_prev(el, c)
+ EditLine *el;
+ int c;
+{
+ 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;
+}
+
+
+/* vi_search_prev():
+ * Vi search history previous
+ * [?]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_search_prev(el, c)
+ EditLine *el;
+ int c;
+{
+ return cv_search(el, ED_SEARCH_PREV_HISTORY);
+}
+
+
+/* vi_search_next():
+ * Vi search history next
+ * [/]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_search_next(el, c)
+ EditLine *el;
+ int c;
+{
+ return cv_search(el, ED_SEARCH_NEXT_HISTORY);
+}
+
+
+/* vi_repeat_search_next():
+ * Vi repeat current search in the same search direction
+ * [n]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_repeat_search_next(el, c)
+ EditLine *el;
+ int c;
+{
+ if (el->el_search.patlen == 0)
+ return CC_ERROR;
+ else
+ return cv_repeat_srch(el, el->el_search.patdir);
+}
+
+
+/* vi_repeat_search_prev():
+ * Vi repeat current search in the opposite search direction
+ * [N]
+ */
+/*ARGSUSED*/
+protected el_action_t
+vi_repeat_search_prev(el, c)
+ EditLine *el;
+ int c;
+{
+ 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);
+}
+
+
+/* vi_next_char():
+ * Vi move to the character specified next
+ * [f]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_next_char(el, c)
+ EditLine *el;
+ int c;
+{
+ 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);
+
+}
+
+
+/* vi_prev_char():
+ * Vi move to the character specified previous
+ * [F]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_prev_char(el, c)
+ EditLine *el;
+ int c;
+{
+ 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);
+}
+
+
+/* vi_to_next_char():
+ * Vi move up to the character specified next
+ * [t]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_to_next_char(el, c)
+ EditLine *el;
+ int c;
+{
+ 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);
+
+}
+
+
+/* vi_to_prev_char():
+ * Vi move up to the character specified previous
+ * [T]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_to_prev_char(el, c)
+ EditLine *el;
+ int c;
+{
+ 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);
+}
+
+
+/* vi_repeat_next_char():
+ * Vi repeat current character search in the same search direction
+ * [;]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_repeat_next_char(el, c)
+ EditLine *el;
+ int c;
+{
+ 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);
+}
+
+
+/* vi_repeat_prev_char():
+ * Vi repeat current character search in the opposite search direction
+ * [,]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_repeat_prev_char(el, c)
+ EditLine *el;
+ int c;
+{
+ if (el->el_search.chacha == 0)
+ return CC_ERROR;
+
+ 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);
+}