summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@cvs.openbsd.org>2010-06-30 00:05:36 +0000
committerNicholas Marriott <nicm@cvs.openbsd.org>2010-06-30 00:05:36 +0000
commit4e317cd7d599f8bfe9b7906ba2f75a82e29a5f7a (patch)
tree7381b8c061e5ffffa2117ee119ec36681dde870f
parenta6429617a1d028ff60e599bcc583a0b56c844d85 (diff)
Update libedit to bring it into sync with the latest version from NetBSD.
ok deraadt
-rw-r--r--lib/libedit/Makefile43
-rw-r--r--lib/libedit/TEST/Makefile6
-rw-r--r--lib/libedit/TEST/tc1.c (renamed from lib/libedit/TEST/test.c)69
-rw-r--r--lib/libedit/chared.c232
-rw-r--r--lib/libedit/chared.h54
-rw-r--r--lib/libedit/chartype.c356
-rw-r--r--lib/libedit/chartype.h246
-rw-r--r--lib/libedit/common.c131
-rw-r--r--lib/libedit/common.h39
-rw-r--r--lib/libedit/config.h4
-rw-r--r--lib/libedit/editline.3314
-rw-r--r--lib/libedit/editline.c22
-rw-r--r--lib/libedit/editrc.550
-rw-r--r--lib/libedit/el.c297
-rw-r--r--lib/libedit/el.h36
-rw-r--r--lib/libedit/eln.c364
-rw-r--r--lib/libedit/emacs.c122
-rw-r--r--lib/libedit/emacs.h24
-rw-r--r--lib/libedit/fcns.c58
-rw-r--r--lib/libedit/fcns.h109
-rw-r--r--lib/libedit/filecomplete.c548
-rw-r--r--lib/libedit/filecomplete.h45
-rw-r--r--lib/libedit/help.c212
-rw-r--r--lib/libedit/help.h5
-rw-r--r--lib/libedit/hist.c47
-rw-r--r--lib/libedit/hist.h27
-rw-r--r--lib/libedit/histedit.h189
-rw-r--r--lib/libedit/history.c392
-rw-r--r--lib/libedit/key.c223
-rw-r--r--lib/libedit/key.h25
-rw-r--r--lib/libedit/makelist31
-rw-r--r--lib/libedit/map.c131
-rw-r--r--lib/libedit/map.h18
-rw-r--r--lib/libedit/parse.c93
-rw-r--r--lib/libedit/parse.h12
-rw-r--r--lib/libedit/prompt.c81
-rw-r--r--lib/libedit/prompt.h16
-rw-r--r--lib/libedit/read.c225
-rw-r--r--lib/libedit/read.h6
-rw-r--r--lib/libedit/readline.c1302
-rw-r--r--lib/libedit/readline/readline.h56
-rw-r--r--lib/libedit/refresh.c434
-rw-r--r--lib/libedit/refresh.h6
-rw-r--r--lib/libedit/search.c84
-rw-r--r--lib/libedit/search.h16
-rw-r--r--lib/libedit/shlib_version2
-rw-r--r--lib/libedit/sig.c80
-rw-r--r--lib/libedit/sig.h13
-rw-r--r--lib/libedit/sys.h27
-rw-r--r--lib/libedit/term.c635
-rw-r--r--lib/libedit/term.h29
-rw-r--r--lib/libedit/tokenizer.c148
-rw-r--r--lib/libedit/tty.c132
-rw-r--r--lib/libedit/tty.h11
-rw-r--r--lib/libedit/vi.c261
-rw-r--r--lib/libedit/vi.h51
56 files changed, 5824 insertions, 2365 deletions
diff --git a/lib/libedit/Makefile b/lib/libedit/Makefile
index f14359ebd7b..d0362180d3b 100644
--- a/lib/libedit/Makefile
+++ b/lib/libedit/Makefile
@@ -1,12 +1,13 @@
-# $OpenBSD: Makefile,v 1.9 2005/11/24 20:49:17 deraadt Exp $
-# $NetBSD: Makefile,v 1.28 2003/08/01 17:03:58 lukem Exp $
+# $OpenBSD: Makefile,v 1.10 2010/06/30 00:05:35 nicm Exp $
+# $NetBSD: Makefile,v 1.41 2010/02/03 15:34:43 roy Exp $
# @(#)Makefile 8.1 (Berkeley) 6/4/93
LIB= edit
WANTLINT=
USE_SHLIBDIR= yes
-OSRCS= chared.c common.c el.c emacs.c fcns.c help.c hist.c key.c map.c \
+OSRCS= chared.c common.c el.c emacs.c fcns.c filecomplete.c help.c \
+ hist.c key.c map.c chartype.c \
parse.c prompt.c read.c refresh.c search.c sig.c term.c tty.c vi.c
MAN= editline.3 editrc.5
@@ -16,13 +17,23 @@ MLINKS= editline.3 el_init.3 editline.3 el_end.3 editline.3 el_reset.3 \
editline.3 el_parse.3 editline.3 el_set.3 editline.3 el_get.3 \
editline.3 el_source.3 editline.3 el_resize.3 editline.3 el_line.3 \
editline.3 el_insertstr.3 editline.3 el_deletestr.3 \
- editline.3 history_init.3 editline.3 history_end.3 editline.3 history.3
+ editline.3 history_init.3 editline.3 history_end.3 \
+ editline.3 history.3 \
+ editline.3 tok_init.3 editline.3 tok_end.3 editline.3 tok_reset.3 \
+ editline.3 tok_line.3 editline.3 tok_str.3
# For speed and debugging
#SRCS= ${OSRCS} tokenizer.c history.c readline.c
# For protection
SRCS= editline.c tokenizer.c history.c readline.c
+.if "${WIDECHAR}" == "yes"
+OSRCS+= eln.c
+SRCS+= tokenizern.c historyn.c
+CLEANFILES+=tokenizern.c.tmp tokenizern.c historyn.c.tmp historyn.c
+CPPFLAGS+=-DWIDECHAR
+.endif
+
LIBEDITDIR?=${.CURDIR}
INCS= histedit.h
@@ -30,7 +41,7 @@ INCSDIR=/usr/include
CLEANFILES+=editline.c
CLEANFILES+=common.h.tmp editline.c.tmp emacs.h.tmp fcns.c.tmp fcns.h.tmp
-CLEANFILES+=help.c.tmp help.h.tmp vi.h.tmp
+CLEANFILES+=help.c.tmp help.h.tmp vi.h.tmp tc1.o tc1
CFLAGS+=-Wall
CPPFLAGS+=-I. -I${LIBEDITDIR}
CPPFLAGS+=-I. -I${.CURDIR}
@@ -69,7 +80,7 @@ fcns.c: ${AHDR} fcns.h help.h makelist
${HOST_SH} ${LIBEDITDIR}/makelist -fc ${AHDR} > ${.TARGET}.tmp && \
mv ${.TARGET}.tmp ${.TARGET}
-help.c: ${ASRC} makelist
+help.c: ${ASRC} makelist
${HOST_SH} ${LIBEDITDIR}/makelist -bc ${ASRC} > ${.TARGET}.tmp && \
mv ${.TARGET}.tmp ${.TARGET}
@@ -77,14 +88,22 @@ help.h: ${ASRC} makelist
${HOST_SH} ${LIBEDITDIR}/makelist -bh ${ASRC} > ${.TARGET}.tmp && \
mv ${.TARGET}.tmp ${.TARGET}
-editline.c: ${OSRCS}
- ${HOST_SH} ${LIBEDITDIR}/makelist -e ${.ALLSRC:T} > ${.TARGET}.tmp && \
+editline.c: ${OSRCS} makelist
+ ${HOST_SH} ${LIBEDITDIR}/makelist -e ${OSRCS:T} > ${.TARGET}.tmp && \
+ mv ${.TARGET}.tmp ${.TARGET}
+
+tokenizern.c: makelist
+ ${HOST_SH} ${LIBEDITDIR}/makelist -n tokenizer.c > ${.TARGET}.tmp && \
mv ${.TARGET}.tmp ${.TARGET}
-test.o: ${LIBEDITDIR}/TEST/test.c
-
-test: libedit.a test.o
- ${CC} ${LDFLAGS} ${.ALLSRC} -o ${.TARGET} libedit.a ${LDADD} -ltermcap
+historyn.c: makelist
+ ${HOST_SH} ${LIBEDITDIR}/makelist -n history.c > ${.TARGET}.tmp && \
+ mv ${.TARGET}.tmp ${.TARGET}
+
+tc1.o: ${LIBEDITDIR}/TEST/tc1.c
+
+tc1: libedit.a tc1.o
+ ${CC} ${LDFLAGS} ${.ALLSRC} -o ${.TARGET} libedit.a ${LDADD} -lcurses
includes:
-cd ${.CURDIR}; cmp -s histedit.h ${DESTDIR}/usr/include/histedit.h > \
diff --git a/lib/libedit/TEST/Makefile b/lib/libedit/TEST/Makefile
index 2881d408dc4..7e6aca9a890 100644
--- a/lib/libedit/TEST/Makefile
+++ b/lib/libedit/TEST/Makefile
@@ -1,8 +1,8 @@
-# $OpenBSD: Makefile,v 1.1 2003/11/25 20:12:39 otto Exp $
-# $NetBSD: Makefile,v 1.1 2003/10/16 21:41:46 christos Exp $
+# $OpenBSD: Makefile,v 1.2 2010/06/30 00:05:35 nicm Exp $
+# $NetBSD: Makefile,v 1.5 2010/02/03 15:34:43 roy Exp $
NOMAN=1
-PROG=test
+PROG=tc1
CPPFLAGS=-I${.CURDIR}/..
LDADD+=-ledit -ltermcap
DPADD+=${LIBEDIT} ${LIBTERMCAP}
diff --git a/lib/libedit/TEST/test.c b/lib/libedit/TEST/tc1.c
index a4f61e331e0..0f0bc9a669b 100644
--- a/lib/libedit/TEST/test.c
+++ b/lib/libedit/TEST/tc1.c
@@ -1,5 +1,4 @@
-/* $OpenBSD: test.c,v 1.8 2009/10/27 23:59:28 deraadt Exp $ */
-/* $NetBSD: test.c,v 1.13 2003/08/07 16:44:35 agc Exp $ */
+/* $NetBSD: tc1.c,v 1.5 2010/04/18 21:17:47 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -46,16 +45,14 @@
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
+#include <locale.h>
#include "histedit.h"
-#include "tokenizer.h"
static int continuation = 0;
-static EditLine *el = NULL;
-
volatile sig_atomic_t gotsig = 0;
-static u_char complete(EditLine *, int);
+static unsigned char complete(EditLine *, int);
int main(int, char **);
static char *prompt(EditLine *);
static void sig(int);
@@ -63,8 +60,8 @@ static void sig(int);
static char *
prompt(EditLine *el)
{
- static char a[] = "Edit$";
- static char b[] = "Edit>";
+ static char a[] = "\1\033[7m\1Edit$\1\033[0m\1 ";
+ static char b[] = "Edit> ";
return (continuation ? b : a);
}
@@ -83,33 +80,36 @@ complete(EditLine *el, int ch)
const char* ptr;
const LineInfo *lf = el_line(el);
int len;
+ int res = CC_ERROR;
/*
* Find the last word
*/
- for (ptr = lf->cursor - 1; !isspace(*ptr) && ptr > lf->buffer; ptr--)
+ for (ptr = lf->cursor - 1;
+ !isspace((unsigned char)*ptr) && ptr > lf->buffer; ptr--)
continue;
- len = lf->cursor - ++ptr;
+ 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);
+ res = CC_ERROR;
else
- return (CC_REFRESH);
+ res = CC_REFRESH;
+ break;
}
}
closedir(dd);
- return (CC_ERROR);
+ return res;
}
int
main(int argc, char *argv[])
{
+ EditLine *el = NULL;
int num;
const char *buf;
Tokenizer *tok;
@@ -120,6 +120,7 @@ main(int argc, char *argv[])
History *hist;
HistEvent ev;
+ (void) setlocale(LC_CTYPE, "");
(void) signal(SIGINT, sig);
(void) signal(SIGQUIT, sig);
(void) signal(SIGHUP, sig);
@@ -136,7 +137,7 @@ main(int argc, char *argv[])
el_set(el, EL_EDITOR, "vi"); /* Default editor is vi */
el_set(el, EL_SIGNAL, 1); /* Handle signals gracefully */
- el_set(el, EL_PROMPT, prompt); /* Set the prompt function */
+ el_set(el, EL_PROMPT_ESC, prompt, '\1');/* Set the prompt function */
/* Tell editline to use this history interface */
el_set(el, EL_HIST, history, hist);
@@ -160,10 +161,20 @@ main(int argc, char *argv[])
el_source(el, NULL);
while ((buf = el_gets(el, &num)) != NULL && num != 0) {
- int ac;
+ int ac, cc, co;
+#ifdef DEBUG
+ int i;
+#endif
const char **av;
+ const LineInfo *li;
+ li = el_line(el);
#ifdef DEBUG
- (void) fprintf(stderr, "got %d %s", num, buf);
+ (void) fprintf(stderr, "==> got %d %s", num, buf);
+ (void) fprintf(stderr, " > li `%.*s_%.*s'\n",
+ (li->cursor - li->buffer), li->buffer,
+ (li->lastchar - 1 - li->cursor),
+ (li->cursor >= li->lastchar) ? "" : li->cursor);
+
#endif
if (gotsig) {
(void) fprintf(stderr, "Got signal %d.\n", gotsig);
@@ -174,7 +185,17 @@ main(int argc, char *argv[])
if (!continuation && num == 1)
continue;
- ncontinuation = tok_line(tok, buf, &ac, &av) > 0;
+ ac = cc = co = 0;
+ ncontinuation = tok_line(tok, li, &ac, &av, &cc, &co);
+ if (ncontinuation < 0) {
+ (void) fprintf(stderr, "Internal error\n");
+ continuation = 0;
+ continue;
+ }
+#ifdef DEBUG
+ (void) fprintf(stderr, " > nc %d ac %d cc %d co %d\n",
+ ncontinuation, ac, cc, co);
+#endif
#if 0
if (continuation) {
/*
@@ -195,6 +216,18 @@ main(int argc, char *argv[])
continuation = ncontinuation;
ncontinuation = 0;
+ if (continuation)
+ continue;
+#ifdef DEBUG
+ for (i = 0; i < ac; i++) {
+ (void) fprintf(stderr, " > arg# %2d ", i);
+ if (i != cc)
+ (void) fprintf(stderr, "`%s'\n", av[i]);
+ else
+ (void) fprintf(stderr, "`%.*s_%s'\n",
+ co, av[i], av[i] + co);
+ }
+#endif
if (strcmp(av[0], "history") == 0) {
int rv;
diff --git a/lib/libedit/chared.c b/lib/libedit/chared.c
index 5a2ffa6b701..90c480d5b7e 100644
--- a/lib/libedit/chared.c
+++ b/lib/libedit/chared.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: chared.c,v 1.9 2009/10/27 23:59:28 deraadt Exp $ */
-/* $NetBSD: chared.c,v 1.21 2003/11/02 20:08:41 christos Exp $ */
+/* $OpenBSD: chared.c,v 1.10 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: chared.c,v 1.28 2009/12/30 22:37:40 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -41,6 +41,8 @@
#include <stdlib.h>
#include "el.h"
+private void ch__clearmacro (EditLine *);
+
/* value to leave unused in line buffer */
#define EL_LEAVE 2
@@ -52,13 +54,13 @@ cv_undo(EditLine *el)
{
c_undo_t *vu = &el->el_chared.c_undo;
c_redo_t *r = &el->el_chared.c_redo;
- uint size;
+ size_t size;
/* Save entire line for undo */
size = el->el_line.lastchar - el->el_line.buffer;
vu->len = size;
- vu->cursor = el->el_line.cursor - el->el_line.buffer;
- memcpy(vu->buf, el->el_line.buffer, size);
+ vu->cursor = (int)(el->el_line.cursor - el->el_line.buffer);
+ (void)memcpy(vu->buf, el->el_line.buffer, size * sizeof(*vu->buf));
/* save command info for redo */
r->count = el->el_state.doingarg ? el->el_state.argument : 0;
@@ -72,11 +74,11 @@ cv_undo(EditLine *el)
* Save yank/delete data for paste
*/
protected void
-cv_yank(EditLine *el, const char *ptr, int size)
+cv_yank(EditLine *el, const Char *ptr, int size)
{
c_kill_t *k = &el->el_chared.c_kill;
- memcpy(k->buf, ptr, size +0u);
+ (void)memcpy(k->buf, ptr, size * sizeof(*k->buf));
k->last = k->buf + size;
}
@@ -87,10 +89,10 @@ cv_yank(EditLine *el, const char *ptr, int size)
protected void
c_insert(EditLine *el, int num)
{
- char *cp;
+ Char *cp;
if (el->el_line.lastchar + num >= el->el_line.limit) {
- if (!ch_enlargebufs(el, num +0u))
+ if (!ch_enlargebufs(el, (size_t)num))
return; /* can't go past end of buffer */
}
@@ -111,7 +113,7 @@ c_delafter(EditLine *el, int num)
{
if (el->el_line.cursor + num > el->el_line.lastchar)
- num = el->el_line.lastchar - el->el_line.cursor;
+ num = (int)(el->el_line.lastchar - el->el_line.cursor);
if (el->el_map.current != el->el_map.emacs) {
cv_undo(el);
@@ -119,7 +121,7 @@ c_delafter(EditLine *el, int num)
}
if (num > 0) {
- char *cp;
+ Char *cp;
for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++)
*cp = cp[num];
@@ -129,6 +131,21 @@ c_delafter(EditLine *el, int num)
}
+/* c_delafter1():
+ * Delete the character after the cursor, do not yank
+ */
+protected void
+c_delafter1(EditLine *el)
+{
+ Char *cp;
+
+ for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++)
+ *cp = cp[1];
+
+ el->el_line.lastchar--;
+}
+
+
/* c_delbefore():
* Delete num characters before the cursor
*/
@@ -137,7 +154,7 @@ c_delbefore(EditLine *el, int num)
{
if (el->el_line.cursor - num < el->el_line.buffer)
- num = el->el_line.cursor - el->el_line.buffer;
+ num = (int)(el->el_line.cursor - el->el_line.buffer);
if (el->el_map.current != el->el_map.emacs) {
cv_undo(el);
@@ -145,7 +162,7 @@ c_delbefore(EditLine *el, int num)
}
if (num > 0) {
- char *cp;
+ Char *cp;
for (cp = el->el_line.cursor - num;
cp <= el->el_line.lastchar;
@@ -157,13 +174,28 @@ c_delbefore(EditLine *el, int num)
}
+/* c_delbefore1():
+ * Delete the character before the cursor, do not yank
+ */
+protected void
+c_delbefore1(EditLine *el)
+{
+ Char *cp;
+
+ for (cp = el->el_line.cursor - 1; cp <= el->el_line.lastchar; cp++)
+ *cp = cp[1];
+
+ el->el_line.lastchar--;
+}
+
+
/* ce__isword():
* Return if p is part of a word according to emacs
*/
protected int
-ce__isword(int p)
+ce__isword(Int p)
{
- return (isalnum(p) || strchr("*?_-.[]~=", p) != NULL);
+ return (Isalnum(p) || Strchr(STR("*?_-.[]~="), p) != NULL);
}
@@ -171,11 +203,11 @@ ce__isword(int p)
* Return if p is part of a word according to vi
*/
protected int
-cv__isword(int p)
+cv__isword(Int p)
{
- if (isalnum(p) || p == '_')
+ if (Isalnum(p) || p == '_')
return 1;
- if (isgraph(p))
+ if (Isgraph(p))
return 2;
return 0;
}
@@ -185,24 +217,24 @@ cv__isword(int p)
* Return if p is part of a big word according to vi
*/
protected int
-cv__isWord(int p)
+cv__isWord(Int p)
{
- return (!isspace(p));
+ return (!Isspace(p));
}
/* c__prev_word():
* Find the previous word
*/
-protected char *
-c__prev_word(char *p, char *low, int n, int (*wtest)(int))
+protected Char *
+c__prev_word(Char *p, Char *low, int n, int (*wtest)(Int))
{
p--;
while (n--) {
- while ((p >= low) && !(*wtest)((unsigned char) *p))
+ while ((p >= low) && !(*wtest)(*p))
p--;
- while ((p >= low) && (*wtest)((unsigned char) *p))
+ while ((p >= low) && (*wtest)(*p))
p--;
}
@@ -218,13 +250,13 @@ c__prev_word(char *p, char *low, int n, int (*wtest)(int))
/* c__next_word():
* Find the next word
*/
-protected char *
-c__next_word(char *p, char *high, int n, int (*wtest)(int))
+protected Char *
+c__next_word(Char *p, Char *high, int n, int (*wtest)(Int))
{
while (n--) {
- while ((p < high) && !(*wtest)((unsigned char) *p))
+ while ((p < high) && !(*wtest)(*p))
p++;
- while ((p < high) && (*wtest)((unsigned char) *p))
+ while ((p < high) && (*wtest)(*p))
p++;
}
if (p > high)
@@ -236,21 +268,21 @@ c__next_word(char *p, char *high, int n, int (*wtest)(int))
/* cv_next_word():
* Find the next word vi style
*/
-protected char *
-cv_next_word(EditLine *el, char *p, char *high, int n, int (*wtest)(int))
+protected Char *
+cv_next_word(EditLine *el, Char *p, Char *high, int n, int (*wtest)(Int))
{
int test;
while (n--) {
- test = (*wtest)((unsigned char) *p);
- while ((p < high) && (*wtest)((unsigned char) *p) == test)
+ test = (*wtest)(*p);
+ while ((p < high) && (*wtest)(*p) == test)
p++;
/*
* vi historically deletes with cw only the word preserving the
* trailing whitespace! This is not what 'w' does..
*/
if (n || el->el_chared.c_vcmd.action != (DELETE|INSERT))
- while ((p < high) && isspace((unsigned char) *p))
+ while ((p < high) && Isspace(*p))
p++;
}
@@ -265,17 +297,17 @@ cv_next_word(EditLine *el, char *p, char *high, int n, int (*wtest)(int))
/* cv_prev_word():
* Find the previous word vi style
*/
-protected char *
-cv_prev_word(char *p, char *low, int n, int (*wtest)(int))
+protected Char *
+cv_prev_word(Char *p, Char *low, int n, int (*wtest)(Int))
{
int test;
p--;
while (n--) {
- while ((p > low) && isspace((unsigned char) *p))
+ while ((p > low) && Isspace(*p))
p--;
- test = (*wtest)((unsigned char) *p);
- while ((p >= low) && (*wtest)((unsigned char) *p) == test)
+ test = (*wtest)(*p);
+ while ((p >= low) && (*wtest)(*p) == test)
p--;
}
p++;
@@ -294,9 +326,9 @@ cv_prev_word(char *p, char *low, int n, int (*wtest)(int))
* A '$' by itself means a big number; "$-" is for negative; '^' means 1.
* Return p pointing to last char used.
*/
-protected char *
+protected Char *
c__number(
- char *p, /* character position */
+ Char *p, /* character position */
int *num, /* Return value */
int dval) /* dval is the number to subtract from like $-3 */
{
@@ -315,7 +347,8 @@ c__number(
sign = -1; /* Handle $- */
++p;
}
- for (i = 0; isdigit((unsigned char) *p); i = 10 * i + *p++ - '0')
+ /* XXX: this assumes ASCII compatible digits */
+ for (i = 0; Isdigit(*p); i = 10 * i + *p++ - '0')
continue;
*num = (sign < 0 ? dval - i : i);
return (--p);
@@ -338,7 +371,7 @@ cv_delfini(EditLine *el)
/* sanity */
return;
- size = el->el_line.cursor - el->el_chared.c_vcmd.pos;
+ size = (int)(el->el_line.cursor - el->el_chared.c_vcmd.pos);
if (size == 0)
size = 1;
el->el_line.cursor = el->el_chared.c_vcmd.pos;
@@ -364,15 +397,15 @@ cv_delfini(EditLine *el)
/* ce__endword():
* Go to the end of this word according to emacs
*/
-protected char *
-ce__endword(char *p, char *high, int n)
+protected Char *
+ce__endword(Char *p, Char *high, int n)
{
p++;
while (n--) {
- while ((p < high) && isspace((unsigned char) *p))
+ while ((p < high) && Isspace(*p))
p++;
- while ((p < high) && !isspace((unsigned char) *p))
+ while ((p < high) && !Isspace(*p))
p++;
}
@@ -385,19 +418,19 @@ ce__endword(char *p, char *high, int n)
/* cv__endword():
* Go to the end of this word according to vi
*/
-protected char *
-cv__endword(char *p, char *high, int n, int (*wtest)(int))
+protected Char *
+cv__endword(Char *p, Char *high, int n, int (*wtest)(Int))
{
int test;
p++;
while (n--) {
- while ((p < high) && isspace((unsigned char) *p))
+ while ((p < high) && Isspace(*p))
p++;
- test = (*wtest)((unsigned char) *p);
- while ((p < high) && (*wtest)((unsigned char) *p) == test)
+ test = (*wtest)(*p);
+ while ((p < high) && (*wtest)(*p) == test)
p++;
}
p--;
@@ -410,22 +443,29 @@ cv__endword(char *p, char *high, int n, int (*wtest)(int))
protected int
ch_init(EditLine *el)
{
- el->el_line.buffer = (char *) el_malloc(EL_BUFSIZ);
+ c_macro_t *ma = &el->el_chared.c_macro;
+
+ el->el_line.buffer = el_malloc(EL_BUFSIZ *
+ sizeof(*el->el_line.buffer));
if (el->el_line.buffer == NULL)
return (-1);
- (void) memset(el->el_line.buffer, 0, EL_BUFSIZ);
+ (void) memset(el->el_line.buffer, 0, EL_BUFSIZ *
+ sizeof(*el->el_line.buffer));
el->el_line.cursor = el->el_line.buffer;
el->el_line.lastchar = el->el_line.buffer;
el->el_line.limit = &el->el_line.buffer[EL_BUFSIZ - EL_LEAVE];
- el->el_chared.c_undo.buf = (char *) el_malloc(EL_BUFSIZ);
+ el->el_chared.c_undo.buf = el_malloc(EL_BUFSIZ *
+ sizeof(*el->el_chared.c_undo.buf));
if (el->el_chared.c_undo.buf == NULL)
return (-1);
- (void) memset(el->el_chared.c_undo.buf, 0, EL_BUFSIZ);
+ (void) memset(el->el_chared.c_undo.buf, 0, EL_BUFSIZ *
+ sizeof(*el->el_chared.c_undo.buf));
el->el_chared.c_undo.len = -1;
el->el_chared.c_undo.cursor = 0;
- el->el_chared.c_redo.buf = (char *) el_malloc(EL_BUFSIZ);
+ el->el_chared.c_redo.buf = el_malloc(EL_BUFSIZ *
+ sizeof(*el->el_chared.c_redo.buf));
if (el->el_chared.c_redo.buf == NULL)
return (-1);
el->el_chared.c_redo.pos = el->el_chared.c_redo.buf;
@@ -435,10 +475,12 @@ ch_init(EditLine *el)
el->el_chared.c_vcmd.action = NOP;
el->el_chared.c_vcmd.pos = el->el_line.buffer;
- el->el_chared.c_kill.buf = (char *) el_malloc(EL_BUFSIZ);
+ el->el_chared.c_kill.buf = el_malloc(EL_BUFSIZ *
+ sizeof(*el->el_chared.c_kill.buf));
if (el->el_chared.c_kill.buf == NULL)
return (-1);
- (void) memset(el->el_chared.c_kill.buf, 0, EL_BUFSIZ);
+ (void) memset(el->el_chared.c_kill.buf, 0, EL_BUFSIZ *
+ sizeof(*el->el_chared.c_kill.buf));
el->el_chared.c_kill.mark = el->el_line.buffer;
el->el_chared.c_kill.last = el->el_chared.c_kill.buf;
@@ -450,11 +492,10 @@ ch_init(EditLine *el)
el->el_state.argument = 1;
el->el_state.lastcmd = ED_UNASSIGNED;
- el->el_chared.c_macro.level = -1;
- el->el_chared.c_macro.offset = 0;
- el->el_chared.c_macro.macro = (char **) el_malloc(EL_MAXMACRO *
- sizeof(char *));
- if (el->el_chared.c_macro.macro == NULL)
+ ma->level = -1;
+ ma->offset = 0;
+ ma->macro = el_malloc(EL_MAXMACRO * sizeof(*ma->macro));
+ if (ma->macro == NULL)
return (-1);
return (0);
}
@@ -463,7 +504,7 @@ ch_init(EditLine *el)
* Reset the character editor
*/
protected void
-ch_reset(EditLine *el)
+ch_reset(EditLine *el, int mclear)
{
el->el_line.cursor = el->el_line.buffer;
el->el_line.lastchar = el->el_line.buffer;
@@ -484,9 +525,18 @@ ch_reset(EditLine *el)
el->el_state.argument = 1;
el->el_state.lastcmd = ED_UNASSIGNED;
- el->el_chared.c_macro.level = -1;
-
el->el_history.eventno = 0;
+
+ if (mclear)
+ ch__clearmacro(el);
+}
+
+private void
+ch__clearmacro(EditLine *el)
+{
+ c_macro_t *ma = &el->el_chared.c_macro;
+ while (ma->level >= 0)
+ el_free((ptr_t)ma->macro[ma->level--]);
}
/* ch_enlargebufs():
@@ -494,12 +544,10 @@ ch_reset(EditLine *el)
* Returns 1 if successful, 0 if not.
*/
protected int
-ch_enlargebufs(el, addlen)
- EditLine *el;
- size_t addlen;
+ch_enlargebufs(EditLine *el, size_t addlen)
{
size_t sz, newsz;
- char *newbuffer, *oldbuf, *oldkbuf;
+ Char *newbuffer, *oldbuf, *oldkbuf;
sz = el->el_line.limit - el->el_line.buffer + EL_LEAVE;
newsz = sz * 2;
@@ -515,12 +563,12 @@ ch_enlargebufs(el, addlen)
/*
* Reallocate line buffer.
*/
- newbuffer = el_realloc(el->el_line.buffer, newsz);
+ newbuffer = el_realloc(el->el_line.buffer, newsz * sizeof(*newbuffer));
if (!newbuffer)
return 0;
/* zero the newly added memory, leave old data in */
- (void) memset(&newbuffer[sz], 0, newsz - sz);
+ (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer));
oldbuf = el->el_line.buffer;
@@ -533,12 +581,12 @@ ch_enlargebufs(el, addlen)
/*
* Reallocate kill buffer.
*/
- newbuffer = el_realloc(el->el_chared.c_kill.buf, newsz);
+ newbuffer = el_realloc(el->el_chared.c_kill.buf, newsz * sizeof(*newbuffer));
if (!newbuffer)
return 0;
/* zero the newly added memory, leave old data in */
- (void) memset(&newbuffer[sz], 0, newsz - sz);
+ (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer));
oldkbuf = el->el_chared.c_kill.buf;
@@ -551,15 +599,17 @@ ch_enlargebufs(el, addlen)
/*
* Reallocate undo buffer.
*/
- newbuffer = el_realloc(el->el_chared.c_undo.buf, newsz);
+ newbuffer = el_realloc(el->el_chared.c_undo.buf,
+ newsz * sizeof(*newbuffer));
if (!newbuffer)
return 0;
/* zero the newly added memory, leave old data in */
- (void) memset(&newbuffer[sz], 0, newsz - sz);
+ (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer));
el->el_chared.c_undo.buf = newbuffer;
- newbuffer = el_realloc(el->el_chared.c_redo.buf, newsz);
+ newbuffer = el_realloc(el->el_chared.c_redo.buf,
+ newsz * sizeof(*newbuffer));
if (!newbuffer)
return 0;
el->el_chared.c_redo.pos = newbuffer +
@@ -594,9 +644,9 @@ ch_end(EditLine *el)
el->el_chared.c_redo.cmd = ED_UNASSIGNED;
el_free((ptr_t) el->el_chared.c_kill.buf);
el->el_chared.c_kill.buf = NULL;
+ ch_reset(el, 1);
el_free((ptr_t) el->el_chared.c_macro.macro);
el->el_chared.c_macro.macro = NULL;
- ch_reset(el);
}
@@ -604,11 +654,11 @@ ch_end(EditLine *el)
* Insert string at cursorI
*/
public int
-el_insertstr(EditLine *el, const char *s)
+FUN(el,insertstr)(EditLine *el, const Char *s)
{
size_t len;
- if ((len = strlen(s)) == 0)
+ if ((len = Strlen(s)) == 0)
return (-1);
if (el->el_line.lastchar + len >= el->el_line.limit) {
if (!ch_enlargebufs(el, len))
@@ -644,15 +694,15 @@ el_deletestr(EditLine *el, int n)
* Get a string
*/
protected int
-c_gets(EditLine *el, char *buf, const char *prompt)
+c_gets(EditLine *el, Char *buf, const Char *prompt)
{
- char ch;
- int len;
- char *cp = el->el_line.buffer;
+ Char ch;
+ ssize_t len;
+ Char *cp = el->el_line.buffer;
if (prompt) {
- len = strlen(prompt);
- memcpy(cp, prompt, len + 0u);
+ len = Strlen(prompt);
+ (void)memcpy(cp, prompt, len * sizeof(*cp));
cp += len;
}
len = 0;
@@ -663,7 +713,7 @@ c_gets(EditLine *el, char *buf, const char *prompt)
el->el_line.lastchar = cp + 1;
re_refresh(el);
- if (el_getc(el, &ch) != 1) {
+ if (FUN(el,getc)(el, &ch) != 1) {
ed_end_of_file(el, 0);
len = -1;
break;
@@ -673,7 +723,7 @@ c_gets(EditLine *el, char *buf, const char *prompt)
case 0010: /* Delete and backspace */
case 0177:
- if (len <= 0) {
+ if (len == 0) {
len = -1;
break;
}
@@ -701,7 +751,7 @@ c_gets(EditLine *el, char *buf, const char *prompt)
el->el_line.buffer[0] = '\0';
el->el_line.lastchar = el->el_line.buffer;
el->el_line.cursor = el->el_line.buffer;
- return len;
+ return (int)len;
}
@@ -711,7 +761,7 @@ c_gets(EditLine *el, char *buf, const char *prompt)
protected int
c_hpos(EditLine *el)
{
- char *ptr;
+ Char *ptr;
/*
* Find how many characters till the beginning of this line.
@@ -723,6 +773,6 @@ c_hpos(EditLine *el)
ptr >= el->el_line.buffer && *ptr != '\n';
ptr--)
continue;
- return (el->el_line.cursor - ptr - 1);
+ return (int)(el->el_line.cursor - ptr - 1);
}
}
diff --git a/lib/libedit/chared.h b/lib/libedit/chared.h
index 1408237f946..694a6445660 100644
--- a/lib/libedit/chared.h
+++ b/lib/libedit/chared.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: chared.h,v 1.8 2003/11/25 20:12:38 otto Exp $ */
-/* $NetBSD: chared.h,v 1.13 2003/10/18 23:48:42 christos Exp $ */
+/* $OpenBSD: chared.h,v 1.9 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: chared.h,v 1.20 2010/04/15 00:57:33 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -49,7 +49,7 @@
#define EL_MAXMACRO 10
/*
- * This is a issue of basic "vi" look-and-feel. Defining VI_MOVE works
+ * This is an 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.
*
@@ -64,25 +64,25 @@
typedef struct c_macro_t {
int level;
int offset;
- char **macro;
+ Char **macro;
} c_macro_t;
/*
* Undo information for vi - no undo in emacs (yet)
*/
typedef struct c_undo_t {
- int len; /* length of saved line */
+ ssize_t len; /* length of saved line */
int cursor; /* position of saved cursor */
- char *buf; /* full saved text */
+ Char *buf; /* full saved text */
} c_undo_t;
/* redo for vi */
typedef struct c_redo_t {
- char *buf; /* redo insert key sequence */
- char *pos;
- char *lim;
+ Char *buf; /* redo insert key sequence */
+ Char *pos;
+ Char *lim;
el_action_t cmd; /* command to redo */
- char ch; /* char that invoked it */
+ Char ch; /* char that invoked it */
int count;
int action; /* from cv_action() */
} c_redo_t;
@@ -92,16 +92,16 @@ typedef struct c_redo_t {
*/
typedef struct c_vcmd_t {
int action;
- char *pos;
+ Char *pos;
} c_vcmd_t;
/*
* Kill buffer for emacs
*/
typedef struct c_kill_t {
- char *buf;
- char *last;
- char *mark;
+ Char *buf;
+ Char *last;
+ Char *mark;
} c_kill_t;
/*
@@ -117,11 +117,9 @@ typedef struct el_chared_t {
} 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
@@ -142,25 +140,27 @@ typedef struct el_chared_t {
#include "fcns.h"
-protected int cv__isword(int);
-protected int cv__isWord(int);
+protected int cv__isword(Int);
+protected int cv__isWord(Int);
protected void cv_delfini(EditLine *);
-protected char *cv__endword(char *, char *, int, int (*)(int));
-protected int ce__isword(int);
+protected Char *cv__endword(Char *, Char *, int, int (*)(Int));
+protected int ce__isword(Int);
protected void cv_undo(EditLine *);
-protected void cv_yank(EditLine *, const char *, int);
-protected char *cv_next_word(EditLine*, char *, char *, int, int (*)(int));
-protected char *cv_prev_word(char *, char *, int, int (*)(int));
-protected char *c__next_word(char *, char *, int, int (*)(int));
-protected char *c__prev_word(char *, char *, int, int (*)(int));
+protected void cv_yank(EditLine *, const Char *, int);
+protected Char *cv_next_word(EditLine*, Char *, Char *, int, int (*)(Int));
+protected Char *cv_prev_word(Char *, Char *, int, int (*)(Int));
+protected Char *c__next_word(Char *, Char *, int, int (*)(Int));
+protected Char *c__prev_word(Char *, Char *, int, int (*)(Int));
protected void c_insert(EditLine *, int);
protected void c_delbefore(EditLine *, int);
+protected void c_delbefore1(EditLine *);
protected void c_delafter(EditLine *, int);
-protected int c_gets(EditLine *, char *, const char *);
+protected void c_delafter1(EditLine *);
+protected int c_gets(EditLine *, Char *, const Char *);
protected int c_hpos(EditLine *);
protected int ch_init(EditLine *);
-protected void ch_reset(EditLine *);
+protected void ch_reset(EditLine *, int);
protected int ch_enlargebufs(EditLine *, size_t);
protected void ch_end(EditLine *);
diff --git a/lib/libedit/chartype.c b/lib/libedit/chartype.c
new file mode 100644
index 00000000000..bfa5a80d58b
--- /dev/null
+++ b/lib/libedit/chartype.c
@@ -0,0 +1,356 @@
+/* $OpenBSD: chartype.c,v 1.1 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: chartype.c,v 1.4 2010/04/15 00:55:57 christos Exp $ */
+
+/*-
+ * Copyright (c) 2009 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * chartype.c: character classification and meta information
+ */
+#include "config.h"
+
+#define CT_BUFSIZ 1024
+
+#ifdef WIDECHAR
+protected void
+ct_conv_buff_resize(ct_buffer_t *conv, size_t mincsize, size_t minwsize)
+{
+ void *p;
+ if (mincsize > conv->csize) {
+ conv->csize = mincsize;
+ p = el_realloc(conv->cbuff, conv->csize);
+ if (p == NULL) {
+ conv->csize = 0;
+ el_free(conv->cbuff);
+ conv->cbuff = NULL;
+ } else
+ conv->cbuff = p;
+ }
+
+ if (minwsize > conv->wsize) {
+ conv->wsize = minwsize;
+ p = el_realloc(conv->wbuff, conv->wsize);
+ if (p == NULL) {
+ conv->wsize = 0;
+ el_free(conv->wbuff);
+ conv->wbuff = NULL;
+ } else
+ conv->wbuff = p;
+ }
+}
+
+
+public char *
+ct_encode_string(const Char *s, ct_buffer_t *conv)
+{
+ char *dst;
+ ssize_t used = 0;
+
+ if (!s)
+ return NULL;
+ if (!conv->cbuff)
+ ct_conv_buff_resize(conv, CT_BUFSIZ, 0);
+ if (!conv->cbuff)
+ return NULL;
+
+ dst = conv->cbuff;
+ while (*s) {
+ used = ct_encode_char(dst, (int)(conv->csize -
+ (dst - conv->cbuff)), *s);
+ if (used == -1) { /* failed to encode, need more buffer space */
+ used = dst - conv->cbuff;
+ ct_conv_buff_resize(conv, conv->csize + CT_BUFSIZ, 0);
+ if (!conv->cbuff)
+ return NULL;
+ dst = conv->cbuff + used;
+ /* don't increment s here - we want to retry it! */
+ }
+ else
+ ++s;
+ dst += used;
+ }
+ if (dst >= (conv->cbuff + conv->csize)) {
+ used = dst - conv->cbuff;
+ ct_conv_buff_resize(conv, conv->csize + 1, 0);
+ if (!conv->cbuff)
+ return NULL;
+ dst = conv->cbuff + used;
+ }
+ *dst = '\0';
+ return conv->cbuff;
+}
+
+public Char *
+ct_decode_string(const char *s, ct_buffer_t *conv)
+{
+ size_t len = 0;
+
+ if (!s)
+ return NULL;
+ if (!conv->wbuff)
+ ct_conv_buff_resize(conv, 0, CT_BUFSIZ);
+ if (!conv->wbuff)
+ return NULL;
+
+ len = ct_mbstowcs(0, s, 0);
+ if (len > conv->wsize)
+ ct_conv_buff_resize(conv, 0, len + 1);
+ if (!conv->wbuff)
+ return NULL;
+ ct_mbstowcs(conv->wbuff, s, conv->wsize);
+ return conv->wbuff;
+}
+
+
+protected Char **
+ct_decode_argv(int argc, const char *argv[], ct_buffer_t *conv)
+{
+ size_t bufspace;
+ int i;
+ Char *p;
+ Char **wargv;
+ ssize_t bytes;
+
+ /* Make sure we have enough space in the conversion buffer to store all
+ * the argv strings. */
+ for (i = 0, bufspace = 0; i < argc; ++i)
+ bufspace += argv[i] ? strlen(argv[i]) + 1 : 0;
+ ct_conv_buff_resize(conv, 0, bufspace);
+ if (!conv->wsize)
+ return NULL;
+
+ wargv = el_malloc(argc * sizeof(*wargv));
+
+ for (i = 0, p = conv->wbuff; i < argc; ++i) {
+ if (!argv[i]) { /* don't pass null pointers to mbstowcs */
+ wargv[i] = NULL;
+ continue;
+ } else {
+ wargv[i] = p;
+ bytes = mbstowcs(p, argv[i], bufspace);
+ }
+ if (bytes == -1) {
+ el_free(wargv);
+ return NULL;
+ } else
+ bytes++; /* include '\0' in the count */
+ bufspace -= bytes;
+ p += bytes;
+ }
+
+ return wargv;
+}
+
+
+protected size_t
+ct_enc_width(Char c)
+{
+ /* UTF-8 encoding specific values */
+ if (c < 0x80)
+ return 1;
+ else if (c < 0x0800)
+ return 2;
+ else if (c < 0x10000)
+ return 3;
+ else if (c < 0x110000)
+ return 4;
+ else
+ return 0; /* not a valid codepoint */
+}
+
+protected ssize_t
+ct_encode_char(char *dst, size_t len, Char c)
+{
+ ssize_t l = 0;
+ if (len < ct_enc_width(c))
+ return -1;
+ l = ct_wctomb(dst, c);
+
+ if (l < 0) {
+ ct_wctomb_reset;
+ l = 0;
+ }
+ return l;
+}
+#endif
+
+protected const Char *
+ct_visual_string(const Char *s)
+{
+ static Char *buff = NULL;
+ static size_t buffsize = 0;
+ void *p;
+ Char *dst;
+ ssize_t used = 0;
+
+ if (!s)
+ return NULL;
+ if (!buff) {
+ buffsize = CT_BUFSIZ;
+ buff = el_malloc(buffsize * sizeof(*buff));
+ }
+ dst = buff;
+ while (*s) {
+ used = ct_visual_char(dst, buffsize - (dst - buff), *s);
+ if (used == -1) { /* failed to encode, need more buffer space */
+ used = dst - buff;
+ buffsize += CT_BUFSIZ;
+ p = el_realloc(buff, buffsize * sizeof(*buff));
+ if (p == NULL)
+ goto out;
+ buff = p;
+ dst = buff + used;
+ /* don't increment s here - we want to retry it! */
+ }
+ else
+ ++s;
+ dst += used;
+ }
+ if (dst >= (buff + buffsize)) { /* sigh */
+ buffsize += 1;
+ p = el_realloc(buff, buffsize * sizeof(*buff));
+ if (p == NULL)
+ goto out;
+ buff = p;
+ dst = buff + buffsize - 1;
+ }
+ *dst = 0;
+ return buff;
+out:
+ el_free(buff);
+ buffsize = 0;
+ return NULL;
+}
+
+
+
+protected int
+ct_visual_width(Char c)
+{
+ int t = ct_chr_class(c);
+ switch (t) {
+ case CHTYPE_ASCIICTL:
+ return 2; /* ^@ ^? etc. */
+ case CHTYPE_TAB:
+ return 1; /* Hmm, this really need to be handled outside! */
+ case CHTYPE_NL:
+ return 0; /* Should this be 1 instead? */
+#ifdef WIDECHAR
+ case CHTYPE_PRINT:
+ return wcwidth(c);
+ case CHTYPE_NONPRINT:
+ if (c > 0xffff) /* prefer standard 4-byte display over 5-byte */
+ return 8; /* \U+12345 */
+ else
+ return 7; /* \U+1234 */
+#else
+ case CHTYPE_PRINT:
+ return 1;
+ case CHTYPE_NONPRINT:
+ return 4; /* \123 */
+#endif
+ default:
+ return 0; /* should not happen */
+ }
+}
+
+
+protected ssize_t
+ct_visual_char(Char *dst, size_t len, Char c)
+{
+ int t = ct_chr_class(c);
+ switch (t) {
+ case CHTYPE_TAB:
+ case CHTYPE_NL:
+ case CHTYPE_ASCIICTL:
+ if (len < 2)
+ return -1; /* insufficient space */
+ *dst++ = '^';
+ if (c == '\177')
+ *dst = '?'; /* DEL -> ^? */
+ else
+ *dst = c | 0100; /* uncontrolify it */
+ return 2;
+ case CHTYPE_PRINT:
+ if (len < 1)
+ return -1; /* insufficient space */
+ *dst = c;
+ return 1;
+ case CHTYPE_NONPRINT:
+ /* we only use single-width glyphs for display,
+ * so this is right */
+ if ((ssize_t)len < ct_visual_width(c))
+ return -1; /* insufficient space */
+#ifdef WIDECHAR
+ *dst++ = '\\';
+ *dst++ = 'U';
+ *dst++ = '+';
+#define tohexdigit(v) "0123456789ABCDEF"[v]
+ if (c > 0xffff) /* prefer standard 4-byte display over 5-byte */
+ *dst++ = tohexdigit(((unsigned int) c >> 16) & 0xf);
+ *dst++ = tohexdigit(((unsigned int) c >> 12) & 0xf);
+ *dst++ = tohexdigit(((unsigned int) c >> 8) & 0xf);
+ *dst++ = tohexdigit(((unsigned int) c >> 4) & 0xf);
+ *dst = tohexdigit(((unsigned int) c ) & 0xf);
+ return (c > 0xffff) ? 8 : 7;
+#else
+ *dst++ = '\\';
+#define tooctaldigit(v) ((v) + '0')
+ *dst++ = tooctaldigit(((unsigned int) c >> 6) & 0x7);
+ *dst++ = tooctaldigit(((unsigned int) c >> 3) & 0x7);
+ *dst++ = tooctaldigit(((unsigned int) c ) & 0x7);
+#endif
+ /*FALLTHROUGH*/
+ /* these two should be handled outside this function */
+ default: /* we should never hit the default */
+ return 0;
+ }
+}
+
+
+
+
+protected int
+ct_chr_class(Char c)
+{
+ if (c == '\t')
+ return CHTYPE_TAB;
+ else if (c == '\n')
+ return CHTYPE_NL;
+ else if (IsASCII(c) && Iscntrl(c))
+ return CHTYPE_ASCIICTL;
+ else if (Isprint(c))
+ return CHTYPE_PRINT;
+ else
+ return CHTYPE_NONPRINT;
+}
diff --git a/lib/libedit/chartype.h b/lib/libedit/chartype.h
new file mode 100644
index 00000000000..db957bbc8e8
--- /dev/null
+++ b/lib/libedit/chartype.h
@@ -0,0 +1,246 @@
+/* $OpenBSD: chartype.h,v 1.1 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: chartype.h,v 1.5 2010/04/15 00:55:57 christos Exp $ */
+
+/*-
+ * Copyright (c) 2009 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _h_chartype_f
+#define _h_chartype_f
+
+
+
+#ifdef WIDECHAR
+
+/* Ideally we should also test the value of the define to see if it
+ * supports non-BMP code points without requiring UTF-16, but nothing
+ * seems to actually advertise this properly, despite Unicode 3.1 having
+ * been around since 2001... */
+#ifndef __NetBSD__
+#ifndef __STDC_ISO_10646__
+/* In many places it is assumed that the first 127 code points are ASCII
+ * compatible, so ensure wchar_t indeed does ISO 10646 and not some other
+ * funky encoding that could break us in weird and wonderful ways. */
+ #error wchar_t must store ISO 10646 characters
+#endif
+#endif
+
+/* Oh for a <uchar.h> with char32_t and __STDC_UTF_32__ in it...
+ * ref: ISO/IEC DTR 19769
+ */
+#if WCHAR_MAX < INT32_MAX
+#warning Build environment does not support non-BMP characters
+#endif
+
+#define ct_mbtowc mbtowc
+#define ct_mbtowc_reset mbtowc(0,0,0)
+#define ct_wctomb wctomb
+#define ct_wctomb_reset wctomb(0,0)
+#define ct_wcstombs wcstombs
+#define ct_mbstowcs mbstowcs
+
+#define Char wchar_t
+#define Int wint_t
+#define FUN(prefix,rest) prefix ## _w ## rest
+#define FUNW(type) type ## _w
+#define TYPE(type) type ## W
+#define FSTR "%ls"
+#define STR(x) L ## x
+#define UC(c) c
+#define Isalpha(x) iswalpha(x)
+#define Isalnum(x) iswalnum(x)
+#define Isgraph(x) iswgraph(x)
+#define Isspace(x) iswspace(x)
+#define Isdigit(x) iswdigit(x)
+#define Iscntrl(x) iswcntrl(x)
+#define Isprint(x) iswprint(x)
+
+#define Isupper(x) iswupper(x)
+#define Islower(x) iswlower(x)
+#define Toupper(x) towupper(x)
+#define Tolower(x) towlower(x)
+
+#define IsASCII(x) (x < 0x100)
+
+#define Strlen(x) wcslen(x)
+#define Strchr(s,c) wcschr(s,c)
+#define Strrchr(s,c) wcsrchr(s,c)
+#define Strstr(s,v) wcsstr(s,v)
+#define Strdup(x) wcsdup(x)
+/* #define Strcpy(d,s) wcscpy(d,s) */
+#define Strncpy(d,s,n) wcsncpy(d,s,n)
+#define Strncat(d,s,n) wcsncat(d,s,n)
+
+#define Strcmp(s,v) wcscmp(s,v)
+#define Strncmp(s,v,n) wcsncmp(s,v,n)
+#define Strcspn(s,r) wcscspn(s,r)
+
+#define Strtol(p,e,b) wcstol(p,e,b)
+
+#define Width(c) wcwidth(c)
+
+#else /* NARROW */
+
+#define ct_mbtowc error
+#define ct_mbtowc_reset
+#define ct_wctomb error
+#define ct_wctomb_reset
+#define ct_wcstombs(a, b, c) (strncpy(a, b, c), strlen(a))
+#define ct_mbstowcs(a, b, c) (strncpy(a, b, c), strlen(a))
+
+#define Char char
+#define Int int
+#define FUN(prefix,rest) prefix ## _ ## rest
+#define FUNW(type) type
+#define TYPE(type) type
+#define FSTR "%s"
+#define STR(x) x
+#define UC(c) (unsigned char)(c)
+
+#define Isalpha(x) isalpha((unsigned char)x)
+#define Isalnum(x) isalnum((unsigned char)x)
+#define Isgraph(x) isgraph((unsigned char)x)
+#define Isspace(x) isspace((unsigned char)x)
+#define Isdigit(x) isdigit((unsigned char)x)
+#define Iscntrl(x) iscntrl((unsigned char)x)
+#define Isprint(x) isprint((unsigned char)x)
+
+#define Isupper(x) isupper((unsigned char)x)
+#define Islower(x) islower((unsigned char)x)
+#define Toupper(x) toupper((unsigned char)x)
+#define Tolower(x) tolower((unsigned char)x)
+
+#define IsASCII(x) isascii((unsigned char)x)
+
+#define Strlen(x) strlen(x)
+#define Strchr(s,c) strchr(s,c)
+#define Strrchr(s,c) strrchr(s,c)
+#define Strstr(s,v) strstr(s,v)
+#define Strdup(x) strdup(x)
+/* #define Strcpy(d,s) strcpy(d,s) */
+#define Strncpy(d,s,n) strncpy(d,s,n)
+#define Strncat(d,s,n) strncat(d,s,n)
+
+#define Strcmp(s,v) strcmp(s,v)
+#define Strncmp(s,v,n) strncmp(s,v,n)
+#define Strcspn(s,r) strcspn(s,r)
+
+#define Strtol(p,e,b) strtol(p,e,b)
+
+#define Width(c) 1
+
+#endif
+
+
+#ifdef WIDECHAR
+/*
+ * Conversion buffer
+ */
+typedef struct ct_buffer_t {
+ char *cbuff;
+ size_t csize;
+ Char *wbuff;
+ size_t wsize;
+} ct_buffer_t;
+
+#define ct_encode_string __ct_encode_string
+/* Encode a wide character string and return the UTF-8 encoded result. */
+public char *ct_encode_string(const Char *, ct_buffer_t *);
+
+#define ct_decode_string __ct_decode_string
+/* Decode a (multi)?byte string and return the wide character string result. */
+public Char *ct_decode_string(const char *, ct_buffer_t *);
+
+/* Decode a (multi)?byte argv string array.
+ * The pointer returned must be free()d when done. */
+protected Char **ct_decode_argv(int, const char *[], ct_buffer_t *);
+
+/* Resizes the conversion buffer(s) if needed. */
+protected void ct_conv_buff_resize(ct_buffer_t *, size_t, size_t);
+protected ssize_t ct_encode_char(char *, size_t, Char);
+protected size_t ct_enc_width(Char);
+
+#define ct_free_argv(s) el_free(s)
+
+#else
+#define ct_encode_string(s, b) (s)
+#define ct_decode_string(s, b) (s)
+#define ct_decode_argv(l, s, b) (s)
+#define ct_conv_buff_resize(b, os, ns)
+#define ct_encode_char(d, l, s) (*d = s, 1)
+#define ct_free_argv(s)
+#endif
+
+#ifndef NARROWCHAR
+/* Encode a characted into the destination buffer, provided there is sufficent
+ * buffer space available. Returns the number of bytes used up (zero if the
+ * character cannot be encoded, -1 if there was not enough space available). */
+
+/* The maximum buffer size to hold the most unwieldly visual representation,
+ * in this case \U+nnnnn. */
+#define VISUAL_WIDTH_MAX 8
+
+/* The terminal is thought of in terms of X columns by Y lines. In the cases
+ * where a wide character takes up more than one column, the adjacent
+ * occupied column entries will contain this faux character. */
+#define MB_FILL_CHAR ((Char)-1)
+
+/* Visual width of character c, taking into account ^? , \0177 and \U+nnnnn
+ * style visual expansions. */
+protected int ct_visual_width(Char);
+
+/* Turn the given character into the appropriate visual format, matching
+ * the width given by ct_visual_width(). Returns the number of characters used
+ * up, or -1 if insufficient space. Buffer length is in count of Char's. */
+protected ssize_t ct_visual_char(Char *, size_t, Char);
+
+/* Convert the given string into visual format, using the ct_visual_char()
+ * function. Uses a static buffer, so not threadsafe. */
+protected const Char *ct_visual_string(const Char *);
+
+
+/* printable character, use ct_visual_width() to find out display width */
+#define CHTYPE_PRINT ( 0)
+/* control character found inside the ASCII portion of the charset */
+#define CHTYPE_ASCIICTL (-1)
+/* a \t */
+#define CHTYPE_TAB (-2)
+/* a \n */
+#define CHTYPE_NL (-3)
+/* non-printable character */
+#define CHTYPE_NONPRINT (-4)
+/* classification of character c, as one of the above defines */
+protected int ct_chr_class(Char c);
+#endif
+
+
+#endif /* _chartype_f */
diff --git a/lib/libedit/common.c b/lib/libedit/common.c
index 5bc5e36b895..185f949611c 100644
--- a/lib/libedit/common.c
+++ b/lib/libedit/common.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: common.c,v 1.7 2009/10/27 23:59:28 deraadt Exp $ */
-/* $NetBSD: common.c,v 1.16 2003/08/07 16:44:30 agc Exp $ */
+/* $OpenBSD: common.c,v 1.8 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: common.c,v 1.24 2009/12/30 22:37:40 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -46,7 +46,7 @@
*/
protected el_action_t
/*ARGSUSED*/
-ed_end_of_file(EditLine *el, int c __attribute__((__unused__)))
+ed_end_of_file(EditLine *el, Int c __attribute__((__unused__)))
{
re_goto_bottom(el);
@@ -60,7 +60,7 @@ ed_end_of_file(EditLine *el, int c __attribute__((__unused__)))
* Insert a character [bound to all insert keys]
*/
protected el_action_t
-ed_insert(EditLine *el, int c)
+ed_insert(EditLine *el, Int c)
{
int count = el->el_state.argument;
@@ -103,9 +103,9 @@ ed_insert(EditLine *el, int c)
*/
protected el_action_t
/*ARGSUSED*/
-ed_delete_prev_word(EditLine *el, int c __attribute__((__unused__)))
+ed_delete_prev_word(EditLine *el, Int c __attribute__((__unused__)))
{
- char *cp, *p, *kp;
+ Char *cp, *p, *kp;
if (el->el_line.cursor == el->el_line.buffer)
return (CC_ERROR);
@@ -117,7 +117,7 @@ ed_delete_prev_word(EditLine *el, int c __attribute__((__unused__)))
*kp++ = *p;
el->el_chared.c_kill.last = kp;
- c_delbefore(el, el->el_line.cursor - cp); /* delete before dot */
+ c_delbefore(el, (int)(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 */
@@ -131,7 +131,7 @@ ed_delete_prev_word(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-ed_delete_next_char(EditLine *el, int c __attribute__((__unused__)))
+ed_delete_next_char(EditLine *el, Int c)
{
#ifdef notdef /* XXX */
#define EL el->el_line
@@ -148,9 +148,8 @@ ed_delete_next_char(EditLine *el, int c __attribute__((__unused__)))
#ifdef KSHVI
return (CC_ERROR);
#else
- term_overwrite(el, STReof, 4);
- /* then do a EOF */
- term__flush();
+ /* then do an EOF */
+ term_writec(el, c);
return (CC_EOF);
#endif
} else {
@@ -182,9 +181,9 @@ ed_delete_next_char(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-ed_kill_line(EditLine *el, int c __attribute__((__unused__)))
+ed_kill_line(EditLine *el, Int c __attribute__((__unused__)))
{
- char *kp, *cp;
+ Char *kp, *cp;
cp = el->el_line.cursor;
kp = el->el_chared.c_kill.buf;
@@ -203,18 +202,18 @@ ed_kill_line(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-ed_move_to_end(EditLine *el, int c __attribute__((__unused__)))
+ed_move_to_end(EditLine *el, Int c __attribute__((__unused__)))
{
el->el_line.cursor = el->el_line.lastchar;
if (el->el_map.type == MAP_VI) {
-#ifdef VI_MOVE
- el->el_line.cursor--;
-#endif
if (el->el_chared.c_vcmd.action != NOP) {
cv_delfini(el);
return (CC_REFRESH);
}
+#ifdef VI_MOVE
+ el->el_line.cursor--;
+#endif
}
return (CC_CURSOR);
}
@@ -226,14 +225,14 @@ ed_move_to_end(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-ed_move_to_beg(EditLine *el, int c __attribute__((__unused__)))
+ed_move_to_beg(EditLine *el, Int c __attribute__((__unused__)))
{
el->el_line.cursor = el->el_line.buffer;
if (el->el_map.type == MAP_VI) {
/* We want FIRST non space character */
- while (isspace((unsigned char) *el->el_line.cursor))
+ while (Isspace(*el->el_line.cursor))
el->el_line.cursor++;
if (el->el_chared.c_vcmd.action != NOP) {
cv_delfini(el);
@@ -249,7 +248,7 @@ ed_move_to_beg(EditLine *el, int c __attribute__((__unused__)))
* [^T] [^T]
*/
protected el_action_t
-ed_transpose_chars(EditLine *el, int c)
+ed_transpose_chars(EditLine *el, Int c)
{
if (el->el_line.cursor < el->el_line.lastchar) {
@@ -275,9 +274,9 @@ ed_transpose_chars(EditLine *el, int c)
*/
protected el_action_t
/*ARGSUSED*/
-ed_next_char(EditLine *el, int c __attribute__((__unused__)))
+ed_next_char(EditLine *el, Int c __attribute__((__unused__)))
{
- char *lim = el->el_line.lastchar;
+ Char *lim = el->el_line.lastchar;
if (el->el_line.cursor >= lim ||
(el->el_line.cursor == lim - 1 &&
@@ -304,7 +303,7 @@ ed_next_char(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-ed_prev_word(EditLine *el, int c __attribute__((__unused__)))
+ed_prev_word(EditLine *el, Int c __attribute__((__unused__)))
{
if (el->el_line.cursor == el->el_line.buffer)
@@ -330,7 +329,7 @@ ed_prev_word(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-ed_prev_char(EditLine *el, int c __attribute__((__unused__)))
+ed_prev_char(EditLine *el, Int c __attribute__((__unused__)))
{
if (el->el_line.cursor > el->el_line.buffer) {
@@ -354,14 +353,14 @@ ed_prev_char(EditLine *el, int c __attribute__((__unused__)))
* [^V] [^V]
*/
protected el_action_t
-ed_quoted_insert(EditLine *el, int c)
+ed_quoted_insert(EditLine *el, Int c)
{
int num;
- char tc;
+ Char tc;
tty_quotemode(el);
- num = el_getc(el, &tc);
- c = (unsigned char) tc;
+ num = FUN(el,getc)(el, &tc);
+ c = tc;
tty_noquotemode(el);
if (num == 1)
return (ed_insert(el, c));
@@ -374,10 +373,10 @@ ed_quoted_insert(EditLine *el, int c)
* Adds to argument or enters a digit
*/
protected el_action_t
-ed_digit(EditLine *el, int c)
+ed_digit(EditLine *el, Int c)
{
- if (!isdigit(c))
+ if (!Isdigit(c))
return (CC_ERROR);
if (el->el_state.doingarg) {
@@ -402,10 +401,10 @@ ed_digit(EditLine *el, int c)
* For ESC-n
*/
protected el_action_t
-ed_argument_digit(EditLine *el, int c)
+ed_argument_digit(EditLine *el, Int c)
{
- if (!isdigit(c))
+ if (!Isdigit(c))
return (CC_ERROR);
if (el->el_state.doingarg) {
@@ -427,7 +426,7 @@ ed_argument_digit(EditLine *el, int c)
*/
protected el_action_t
/*ARGSUSED*/
-ed_unassigned(EditLine *el, int c __attribute__((__unused__)))
+ed_unassigned(EditLine *el, Int c __attribute__((__unused__)))
{
return (CC_ERROR);
@@ -445,7 +444,7 @@ ed_unassigned(EditLine *el, int c __attribute__((__unused__)))
protected el_action_t
/*ARGSUSED*/
ed_tty_sigint(EditLine *el __attribute__((__unused__)),
- int c __attribute__((__unused__)))
+ Int c __attribute__((__unused__)))
{
return (CC_NORM);
@@ -459,7 +458,7 @@ ed_tty_sigint(EditLine *el __attribute__((__unused__)),
protected el_action_t
/*ARGSUSED*/
ed_tty_dsusp(EditLine *el __attribute__((__unused__)),
- int c __attribute__((__unused__)))
+ Int c __attribute__((__unused__)))
{
return (CC_NORM);
@@ -473,7 +472,7 @@ ed_tty_dsusp(EditLine *el __attribute__((__unused__)),
protected el_action_t
/*ARGSUSED*/
ed_tty_flush_output(EditLine *el __attribute__((__unused__)),
- int c __attribute__((__unused__)))
+ Int c __attribute__((__unused__)))
{
return (CC_NORM);
@@ -487,7 +486,7 @@ ed_tty_flush_output(EditLine *el __attribute__((__unused__)),
protected el_action_t
/*ARGSUSED*/
ed_tty_sigquit(EditLine *el __attribute__((__unused__)),
- int c __attribute__((__unused__)))
+ Int c __attribute__((__unused__)))
{
return (CC_NORM);
@@ -501,7 +500,7 @@ ed_tty_sigquit(EditLine *el __attribute__((__unused__)),
protected el_action_t
/*ARGSUSED*/
ed_tty_sigtstp(EditLine *el __attribute__((__unused__)),
- int c __attribute__((__unused__)))
+ Int c __attribute__((__unused__)))
{
return (CC_NORM);
@@ -515,7 +514,7 @@ ed_tty_sigtstp(EditLine *el __attribute__((__unused__)),
protected el_action_t
/*ARGSUSED*/
ed_tty_stop_output(EditLine *el __attribute__((__unused__)),
- int c __attribute__((__unused__)))
+ Int c __attribute__((__unused__)))
{
return (CC_NORM);
@@ -529,7 +528,7 @@ ed_tty_stop_output(EditLine *el __attribute__((__unused__)),
protected el_action_t
/*ARGSUSED*/
ed_tty_start_output(EditLine *el __attribute__((__unused__)),
- int c __attribute__((__unused__)))
+ Int c __attribute__((__unused__)))
{
return (CC_NORM);
@@ -542,7 +541,7 @@ ed_tty_start_output(EditLine *el __attribute__((__unused__)),
*/
protected el_action_t
/*ARGSUSED*/
-ed_newline(EditLine *el, int c __attribute__((__unused__)))
+ed_newline(EditLine *el, Int c __attribute__((__unused__)))
{
re_goto_bottom(el);
@@ -558,7 +557,7 @@ ed_newline(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-ed_delete_prev_char(EditLine *el, int c __attribute__((__unused__)))
+ed_delete_prev_char(EditLine *el, Int c __attribute__((__unused__)))
{
if (el->el_line.cursor <= el->el_line.buffer)
@@ -578,7 +577,7 @@ ed_delete_prev_char(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-ed_clear_screen(EditLine *el, int c __attribute__((__unused__)))
+ed_clear_screen(EditLine *el, Int c __attribute__((__unused__)))
{
term_clear_screen(el); /* clear the whole real screen */
@@ -594,7 +593,7 @@ ed_clear_screen(EditLine *el, int c __attribute__((__unused__)))
protected el_action_t
/*ARGSUSED*/
ed_redisplay(EditLine *el __attribute__((__unused__)),
- int c __attribute__((__unused__)))
+ Int c __attribute__((__unused__)))
{
return (CC_REDISPLAY);
@@ -607,10 +606,10 @@ ed_redisplay(EditLine *el __attribute__((__unused__)),
*/
protected el_action_t
/*ARGSUSED*/
-ed_start_over(EditLine *el, int c __attribute__((__unused__)))
+ed_start_over(EditLine *el, Int c __attribute__((__unused__)))
{
- ch_reset(el);
+ ch_reset(el, 0);
return (CC_REFRESH);
}
@@ -622,7 +621,7 @@ ed_start_over(EditLine *el, int c __attribute__((__unused__)))
protected el_action_t
/*ARGSUSED*/
ed_sequence_lead_in(EditLine *el __attribute__((__unused__)),
- int c __attribute__((__unused__)))
+ Int c __attribute__((__unused__)))
{
return (CC_NORM);
@@ -635,7 +634,7 @@ ed_sequence_lead_in(EditLine *el __attribute__((__unused__)),
*/
protected el_action_t
/*ARGSUSED*/
-ed_prev_history(EditLine *el, int c __attribute__((__unused__)))
+ed_prev_history(EditLine *el, Int c __attribute__((__unused__)))
{
char beep = 0;
int sv_event = el->el_history.eventno;
@@ -645,7 +644,7 @@ ed_prev_history(EditLine *el, int c __attribute__((__unused__)))
if (el->el_history.eventno == 0) { /* save the current buffer
* away */
- (void) strncpy(el->el_history.buf, el->el_line.buffer,
+ (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);
@@ -655,7 +654,7 @@ ed_prev_history(EditLine *el, int c __attribute__((__unused__)))
if (hist_get(el) == CC_ERROR) {
if (el->el_map.type == MAP_VI) {
el->el_history.eventno = sv_event;
- return CC_ERROR;
+
}
beep = 1;
/* el->el_history.eventno was fixed by first call */
@@ -673,7 +672,7 @@ ed_prev_history(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-ed_next_history(EditLine *el, int c __attribute__((__unused__)))
+ed_next_history(EditLine *el, Int c __attribute__((__unused__)))
{
el_action_t beep = CC_REFRESH, rval;
@@ -700,9 +699,9 @@ ed_next_history(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-ed_search_prev_history(EditLine *el, int c __attribute__((__unused__)))
+ed_search_prev_history(EditLine *el, Int c __attribute__((__unused__)))
{
- const char *hp;
+ const Char *hp;
int h;
bool_t found = 0;
@@ -718,7 +717,7 @@ ed_search_prev_history(EditLine *el, int c __attribute__((__unused__)))
return (CC_ERROR);
}
if (el->el_history.eventno == 0) {
- (void) strncpy(el->el_history.buf, el->el_line.buffer,
+ (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);
@@ -739,7 +738,7 @@ ed_search_prev_history(EditLine *el, int c __attribute__((__unused__)))
#ifdef SDEBUG
(void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
#endif
- if ((strncmp(hp, el->el_line.buffer, (size_t)
+ if ((Strncmp(hp, el->el_line.buffer, (size_t)
(el->el_line.lastchar - el->el_line.buffer)) ||
hp[el->el_line.lastchar - el->el_line.buffer]) &&
c_hmatch(el, hp)) {
@@ -768,9 +767,9 @@ ed_search_prev_history(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-ed_search_next_history(EditLine *el, int c __attribute__((__unused__)))
+ed_search_next_history(EditLine *el, Int c __attribute__((__unused__)))
{
- const char *hp;
+ const Char *hp;
int h;
bool_t found = 0;
@@ -794,7 +793,7 @@ ed_search_next_history(EditLine *el, int c __attribute__((__unused__)))
#ifdef SDEBUG
(void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
#endif
- if ((strncmp(hp, el->el_line.buffer, (size_t)
+ if ((Strncmp(hp, el->el_line.buffer, (size_t)
(el->el_line.lastchar - el->el_line.buffer)) ||
hp[el->el_line.lastchar - el->el_line.buffer]) &&
c_hmatch(el, hp))
@@ -822,9 +821,9 @@ ed_search_next_history(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-ed_prev_line(EditLine *el, int c __attribute__((__unused__)))
+ed_prev_line(EditLine *el, Int c __attribute__((__unused__)))
{
- char *ptr;
+ Char *ptr;
int nchars = c_hpos(el);
/*
@@ -865,9 +864,9 @@ ed_prev_line(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-ed_next_line(EditLine *el, int c __attribute__((__unused__)))
+ed_next_line(EditLine *el, Int c __attribute__((__unused__)))
{
- char *ptr;
+ Char *ptr;
int nchars = c_hpos(el);
/*
@@ -899,13 +898,13 @@ ed_next_line(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-ed_command(EditLine *el, int c __attribute__((__unused__)))
+ed_command(EditLine *el, Int c __attribute__((__unused__)))
{
- char tmpbuf[EL_BUFSIZ];
+ Char tmpbuf[EL_BUFSIZ];
int tmplen;
- tmplen = c_gets(el, tmpbuf, "\n: ");
- term__putc('\n');
+ tmplen = c_gets(el, tmpbuf, STR("\n: "));
+ term__putc(el, '\n');
if (tmplen < 0 || (tmpbuf[tmplen] = 0, parse_line(el, tmpbuf)) == -1)
term_beep(el);
diff --git a/lib/libedit/common.h b/lib/libedit/common.h
new file mode 100644
index 00000000000..231b1e24f72
--- /dev/null
+++ b/lib/libedit/common.h
@@ -0,0 +1,39 @@
+/* Automatically generated file, do not edit */
+#ifndef _h_common_c
+#define _h_common_c
+protected el_action_t ed_end_of_file (EditLine *, Int);
+protected el_action_t ed_insert (EditLine *, Int);
+protected el_action_t ed_delete_prev_word (EditLine *, Int);
+protected el_action_t ed_delete_next_char (EditLine *, Int);
+protected el_action_t ed_kill_line (EditLine *, Int);
+protected el_action_t ed_move_to_end (EditLine *, Int);
+protected el_action_t ed_move_to_beg (EditLine *, Int);
+protected el_action_t ed_transpose_chars (EditLine *, Int);
+protected el_action_t ed_next_char (EditLine *, Int);
+protected el_action_t ed_prev_word (EditLine *, Int);
+protected el_action_t ed_prev_char (EditLine *, Int);
+protected el_action_t ed_quoted_insert (EditLine *, Int);
+protected el_action_t ed_digit (EditLine *, Int);
+protected el_action_t ed_argument_digit (EditLine *, Int);
+protected el_action_t ed_unassigned (EditLine *, Int);
+protected el_action_t ed_tty_sigint (EditLine *, Int);
+protected el_action_t ed_tty_dsusp (EditLine *, Int);
+protected el_action_t ed_tty_flush_output (EditLine *, Int);
+protected el_action_t ed_tty_sigquit (EditLine *, Int);
+protected el_action_t ed_tty_sigtstp (EditLine *, Int);
+protected el_action_t ed_tty_stop_output (EditLine *, Int);
+protected el_action_t ed_tty_start_output (EditLine *, Int);
+protected el_action_t ed_newline (EditLine *, Int);
+protected el_action_t ed_delete_prev_char (EditLine *, Int);
+protected el_action_t ed_clear_screen (EditLine *, Int);
+protected el_action_t ed_redisplay (EditLine *, Int);
+protected el_action_t ed_start_over (EditLine *, Int);
+protected el_action_t ed_sequence_lead_in (EditLine *, Int);
+protected el_action_t ed_prev_history (EditLine *, Int);
+protected el_action_t ed_next_history (EditLine *, Int);
+protected el_action_t ed_search_prev_history (EditLine *, Int);
+protected el_action_t ed_search_next_history (EditLine *, Int);
+protected el_action_t ed_prev_line (EditLine *, Int);
+protected el_action_t ed_next_line (EditLine *, Int);
+protected el_action_t ed_command (EditLine *, Int);
+#endif /* _h_common_c */
diff --git a/lib/libedit/config.h b/lib/libedit/config.h
index a3986766294..b8d838656f3 100644
--- a/lib/libedit/config.h
+++ b/lib/libedit/config.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: config.h,v 1.1 2003/10/31 08:42:24 otto Exp $ */
+/* $OpenBSD: config.h,v 1.2 2010/06/30 00:05:35 nicm Exp $ */
/* config.h. Generated automatically by configure. */
/* #undef SUNOS */
@@ -16,4 +16,6 @@
#define HAVE_STRVIS 1
#define HAVE_STRUNVIS 1
+#define HAVE_STRUCT_DIRENT_D_NAMLEN 1
+
#include "sys.h"
diff --git a/lib/libedit/editline.3 b/lib/libedit/editline.3
index aced91fece8..2061712a1b0 100644
--- a/lib/libedit/editline.3
+++ b/lib/libedit/editline.3
@@ -1,7 +1,7 @@
-.\" $OpenBSD: editline.3,v 1.27 2010/05/14 21:12:36 nicm Exp $
-.\" $NetBSD: editline.3,v 1.42 2003/11/04 13:22:19 christos Exp $
+.\" $OpenBSD: editline.3,v 1.28 2010/06/30 00:05:35 nicm Exp $
+.\" $NetBSD: editline.3,v 1.73 2010/01/03 19:05:26 wiz Exp $
.\"
-.\" Copyright (c) 1997-1999 The NetBSD Foundation, Inc.
+.\" Copyright (c) 1997-2003 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" This file was contributed to The NetBSD Foundation by Luke Mewburn.
@@ -27,7 +27,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd $Mdocdate: May 14 2010 $
+.Dd $Mdocdate: June 30 2010 $
.Dt EDITLINE 3
.Os
.Sh NAME
@@ -48,8 +48,15 @@
.Nm el_deletestr ,
.Nm history_init ,
.Nm history_end ,
-.Nm history
-.Nd line editor and history functions
+.Nm history ,
+.Nm tok_init ,
+.Nm tok_end ,
+.Nm tok_reset ,
+.Nm tok_line ,
+.Nm tok_str
+.Nd line editor, history and tokenization functions
+.Sh LIBRARY
+.Lb libedit
.Sh SYNOPSIS
.Fd #include <histedit.h>
.Ft EditLine *
@@ -69,7 +76,7 @@
.Ft int
.Fn el_set "EditLine *e" "int op" "..."
.Ft int
-.Fn el_get "EditLine *e" "int op" "void *result"
+.Fn el_get "EditLine *e" "int op" "..."
.Ft int
.Fn el_source "EditLine *e" "const char *file"
.Ft void
@@ -86,10 +93,20 @@
.Fn history_end "History *h"
.Ft int
.Fn history "History *h" "HistEvent *ev" "int op" "..."
+.Ft Tokenizer *
+.Fn tok_init "const char *IFS"
+.Ft void
+.Fn tok_end "Tokenizer *t"
+.Ft void
+.Fn tok_reset "Tokenizer *t"
+.Ft int
+.Fn tok_line "Tokenizer *t" "const LineInfo *li" "int *argc" "const char **argv[]" "int *cursorc" "int *cursoro"
+.Ft int
+.Fn tok_str "Tokenizer *t" "const char *str" "int *argc" "const char **argv[]"
.Sh DESCRIPTION
The
.Nm
-library provides generic line editing and history functions,
+library provides generic line editing, history and tokenization functions,
similar to those found in
.Xr sh 1 .
.Pp
@@ -143,6 +160,14 @@ is modified to contain the number of characters read.
Returns the line read if successful, or
.Dv NULL
if no characters were read or if an error occurred.
+If an error occurred,
+.Fa count
+is set to \-1 and
+.Dv errno
+contains the error code that caused it.
+The return value may not remain valid across calls to
+.Fn el_gets
+and must be copied if the data is to be retained.
.It Fn el_getc
Read a character from the tty.
.Fa ch
@@ -204,10 +229,30 @@ are supported, along with the required argument list:
Define prompt printing function as
.Fa f ,
which is to return a string that contains the prompt.
+.It Dv EL_PROMPT_ESC , Fa "char *(*f)(EditLine *)" , Fa "char c"
+Same as
+.Dv EL_PROMPT ,
+but the
+.Fa c
+argument indicates the start/stop literal prompt character.
+.Pp
+If a start/stop literal character is found in the prompt, the
+character itself
+is not printed, but characters after it are printed directly to the
+terminal without affecting the state of the current line.
+A subsequent second start/stop literal character ends this behavior.
+This is typically used to embed literal escape sequences that change the
+color/style of the terminal in the prompt.
+.Dv 0
+unsets it.
+.It Dv EL_REFRESH
+Re-display the current line on the next terminal line.
.It Dv EL_RPROMPT , Fa "char *(*f)(EditLine *)"
Define right side prompt printing function as
.Fa f ,
which is to return a string that contains the prompt.
+.It Dv EL_RPROMPT_ESC , Fa "char *(*f)(EditLine *)" , Fa "char c"
+Define the right prompt printing function but with a literal escape character.
.It Dv EL_TERMINAL , Fa "const char *type"
Define terminal type of the tty to be
.Fa type ,
@@ -241,66 +286,43 @@ reading command input:
and
.Dv SIGWINCH .
Otherwise, the current signal handlers will be used.
-.It Dv EL_BIND , Xo
-.Fa "const char *" ,
-.Fa "..." ,
-.Dv NULL
-.Xc
+.It Dv EL_BIND , Fa "const char *" , Fa "..." , Dv NULL
Perform the
.Ic bind
builtin command.
Refer to
.Xr editrc 5
for more information.
-.It Dv EL_ECHOTC , Xo
-.Fa "const char *" ,
-.Fa "..." ,
-.Dv NULL
-.Xc
+.It Dv EL_ECHOTC , Fa "const char *" , Fa "..." , Dv NULL
Perform the
.Ic echotc
builtin command.
Refer to
.Xr editrc 5
for more information.
-.It Dv EL_SETTC , Xo
-.Fa "const char *" ,
-.Fa "..." ,
-.Dv NULL
-.Xc
+.It Dv EL_SETTC , Fa "const char *" , Fa "..." , Dv NULL
Perform the
.Ic settc
builtin command.
Refer to
.Xr editrc 5
for more information.
-.It Dv EL_SETTY , Xo
-.Fa "const char *" ,
-.Fa "..." ,
-.Dv NULL
-.Xc
+.It Dv EL_SETTY , Fa "const char *" , Fa "..." , Dv NULL
Perform the
.Ic setty
builtin command.
Refer to
.Xr editrc 5
for more information.
-.It Dv EL_TELLTC , Xo
-.Fa "const char *" ,
-.Fa "..." ,
-.Dv NULL
-.Xc
+.It Dv EL_TELLTC , Fa "const char *" , Fa "..." , Dv NULL
Perform the
.Ic telltc
builtin command.
Refer to
.Xr editrc 5
for more information.
-.It Dv EL_ADDFN , Xo
-.Fa "const char *name" ,
-.Fa "const char *help" ,
-.Fa "unsigned char (*func)(EditLine *e, int ch)"
-.Xc
+.It Dv EL_ADDFN , Fa "const char *name" , Fa "const char *help" , \
+Fa "unsigned char (*func)(EditLine *e, int ch)"
Add a user defined function,
.Fn func ,
referred to as
@@ -342,10 +364,8 @@ Beep, and flush tty.
.It Dv CC_FATAL
Fatal error, reset tty to known state.
.El
-.It Dv EL_HIST , Xo
-.Fa "History *(*func)(History *, int op, ...)" ,
-.Fa "const char *ptr"
-.Xc
+.It Dv EL_HIST , Fa "History *(*func)(History *, int op, ...)" , \
+Fa "const char *ptr"
Defines which history function to use, which is usually
.Fn history .
.Fa ptr
@@ -374,7 +394,8 @@ This function is called internally by
and
.Fn el_getc .
The builtin function can be set or restored with the special function
-name ``EL_BUILTIN_GETCFN''.
+name
+.Dq Dv EL_BUILTIN_GETCFN .
.It Dv EL_CLIENTDATA , Fa "void *data"
Register
.Fa data
@@ -382,6 +403,25 @@ to be associated with this EditLine structure.
It can be retrieved with the corresponding
.Fn el_get
call.
+.It Dv EL_SETFP , Fa "int fd" , Fa "FILE *fp"
+Set the current
+.Nm editline
+file pointer for
+.Dq input
+.Fa fd
+=
+.Dv 0 ,
+.Dq output
+.Fa fd
+=
+.Dv 1 ,
+or
+.Dq error
+.Fa fd
+=
+.Dv 2
+from
+.Fa fp .
.El
.It Fn el_get
Get
@@ -397,39 +437,80 @@ The following values for
are supported, along with actual type of
.Fa result :
.Bl -tag -width 4n
-.It Dv EL_PROMPT , Fa "char *(*f)(EditLine *)"
-Return a pointer to the function that displays the prompt.
-.It Dv EL_RPROMPT , Fa "char *(*f)(EditLine *)"
-Return a pointer to the function that displays the rightside prompt.
+.It Dv EL_PROMPT , Fa "char *(*f)(EditLine *)" , Fa "char *c"
+Return a pointer to the function that displays the prompt in
+.Fa f .
+If
+.Fa c
+is not
+.Dv NULL ,
+return the start/stop literal prompt character in it.
+.It Dv EL_RPROMPT , Fa "char *(*f)(EditLine *)" , Fa "char *c"
+Return a pointer to the function that displays the prompt in
+.Fa f .
+If
+.Fa c
+is not
+.Dv NULL ,
+return the start/stop literal prompt character in it.
.It Dv EL_EDITOR , Fa "const char *"
Return the name of the editor, which will be one of
.Dq emacs
or
.Dq vi .
+.It Dv EL_GETTC , Fa "const char *name" , Fa "void *value"
+Return non-zero if
+.Fa name
+is a valid
+.Xr termcap 5
+capability
+and set
+.Fa value
+to the current value of that capability.
.It Dv EL_SIGNAL , Fa "int *"
Return non-zero if
.Nm
has installed private signal handlers (see
.Fn el_get
above).
-.It Dv EL_EDITMODE, Fa "int *"
+.It Dv EL_EDITMODE , Fa "int *"
Return non-zero if editing is enabled.
-.It Dv EL_GETCFN, Fa "int (**f)(EditLine *, char *)"
+.It Dv EL_GETCFN , Fa "int (**f)(EditLine *, char *)"
Return a pointer to the function that read characters, which is equal to
-``EL_BUILTIN_GETCFN'' in the case of the default builtin function.
+.Dq Dv EL_BUILTIN_GETCFN
+in the case of the default builtin function.
.It Dv EL_CLIENTDATA , Fa "void **data"
Retrieve
.Fa data
previously registered with the corresponding
.Fn el_set
call.
-.It Dv EL_UNBUFFERED, Fa "int"
+.It Dv EL_UNBUFFERED , Fa "int"
Sets or clears unbuffered mode.
In this mode,
.Fn el_gets
will return immediately after processing a single character.
-.It Dv EL_PREP_TERM, Fa "int"
+.It Dv EL_PREP_TERM , Fa "int"
Sets or clears terminal editing mode.
+.It Dv EL_GETFP , Fa "int fd", Fa "FILE **fp"
+Return in
+.Fa fp
+the current
+.Nm editline
+file pointer for
+.Dq input
+.Fa fd
+=
+.Dv 0 ,
+.Dq output
+.Fa fd
+=
+.Dv 1 ,
+or
+.Dq error
+.Fa fd
+=
+.Dv 2 .
.El
.It Fn el_source
Initialise
@@ -474,6 +555,16 @@ typedef struct lineinfo {
const char *lastchar; /* address of last character */
} LineInfo;
.Ed
+.Pp
+.Fa buffer
+is not NUL terminated.
+This function may be called after
+.Fn el_gets
+to obtain the
+.Fa LineInfo
+structure pertaining to line returned by that function,
+and from within user defined functions added with
+.Dv EL_ADDFN .
.It Fn el_insertstr
Insert
.Fa str
@@ -483,7 +574,7 @@ Returns \-1 if
is empty or won't fit, and 0 otherwise.
.It Fn el_deletestr
Delete
-.Fa num
+.Fa count
characters before the cursor.
.El
.Sh HISTORY LIST FUNCTIONS
@@ -530,18 +621,11 @@ assumed to be created with
.Fn history_init .
.It Dv H_CLEAR
Clear the history.
-.It Dv H_FUNC , Xo
-.Fa "void *ptr" ,
-.Fa "history_gfun_t first" ,
-.Fa "history_gfun_t next" ,
-.Fa "history_gfun_t last" ,
-.Fa "history_gfun_t prev" ,
-.Fa "history_gfun_t curr" ,
-.Fa "history_sfun_t set" ,
-.Fa "history_vfun_t clear" ,
-.Fa "history_efun_t enter" ,
-.Fa "history_efun_t add"
-.Xc
+.It Dv H_FUNC , Fa "void *ptr" , Fa "history_gfun_t first" , \
+Fa "history_gfun_t next" , Fa "history_gfun_t last" , \
+Fa "history_gfun_t prev" , Fa "history_gfun_t curr" , \
+Fa "history_sfun_t set" , Fa "history_vfun_t clear" , \
+Fa "history_efun_t enter" , Fa "history_efun_t add"
Define functions to perform various history operations.
.Fa ptr
is the argument given to a function when it's invoked.
@@ -604,29 +688,109 @@ Load the history list stored in
Save the history list to
.Fa file .
.It Dv H_SETUNIQUE , Fa "int unique"
-Set if the adjacent identical event strings should not be entered into
-the history.
+Set flag that adjacent identical event strings should not be entered
+into the history.
.It Dv H_GETUNIQUE
-Retrieve the current setting if adjacent elements should be entered into
-the history.
+Retrieve the current setting if adjacent identical elements should
+be entered into the history.
+.It Dv H_DEL , Fa "int e"
+Delete the event numbered
+.Fa e .
+This function is only provided for
+.Xr readline 3
+compatibility.
+The caller is responsible for free'ing the string in the returned
+.Fa HistEvent .
.El
.Pp
.Fn history
-returns \*(Ge 0 if the operation
+returns \*[Gt]= 0 if the operation
.Fa op
succeeds.
Otherwise, \-1 is returned and
.Fa ev
is updated to contain more details about the error.
.El
+.Sh TOKENIZATION FUNCTIONS
+The tokenization functions use a common data structure,
+.Fa Tokenizer ,
+which is created by
+.Fn tok_init
+and freed by
+.Fn tok_end .
+.Pp
+The following functions are available:
+.Bl -tag -width 4n
+.It Fn tok_init
+Initialise the tokenizer, and return a data structure
+to be used by all other tokenizer functions.
+.Fa IFS
+contains the Input Field Separators, which defaults to
+.Aq space ,
+.Aq tab ,
+and
+.Aq newline
+if
+.Dv NULL .
+.It Fn tok_end
+Clean up and finish with
+.Fa t ,
+assumed to have been created with
+.Fn tok_init .
+.It Fn tok_reset
+Reset the tokenizer state.
+Use after a line has been successfully tokenized
+by
+.Fn tok_line
+or
+.Fn tok_str
+and before a new line is to be tokenized.
+.It Fn tok_line
+Tokenize
+.Fa li ,
+If successful, modify:
+.Fa argv
+to contain the words,
+.Fa argc
+to contain the number of words,
+.Fa cursorc
+(if not
+.Dv NULL )
+to contain the index of the word containing the cursor,
+and
+.Fa cursoro
+(if not
+.Dv NULL )
+to contain the offset within
+.Fa argv[cursorc]
+of the cursor.
+.Pp
+Returns
+0 if successful,
+\-1 for an internal error,
+1 for an unmatched single quote,
+2 for an unmatched double quote,
+and
+3 for a backslash quoted
+.Aq newline .
+A positive exit code indicates that another line should be read
+and tokenization attempted again.
+.
+.It Fn tok_str
+A simpler form of
+.Fn tok_line ;
+.Fa str
+is a NUL terminated string to tokenize.
+.El
+.
.\"XXX.Sh EXAMPLES
.\"XXX: provide some examples
.Sh SEE ALSO
.Xr sh 1 ,
-.Xr curses 3 ,
+.Xr curses 3
.Xr signal 3 ,
-.Xr termcap 3 ,
-.Xr editrc 5
+.Xr editrc 5 ,
+.Xr termcap 5
.Sh HISTORY
The
.Nm
@@ -653,10 +817,8 @@ Luke Mewburn wrote this manual and implemented
and
.Dv EL_RPROMPT .
Jaromir Dolecek implemented the readline emulation.
+Johny Mattsson implemented wide character support.
.Sh BUGS
-The tokenization functions are not publicly defined in
-.Aq Pa histedit.h .
-.Pp
At this time, it is the responsibility of the caller to
check the result of the
.Dv EL_EDITMODE
diff --git a/lib/libedit/editline.c b/lib/libedit/editline.c
new file mode 100644
index 00000000000..cfdc48cdf3d
--- /dev/null
+++ b/lib/libedit/editline.c
@@ -0,0 +1,22 @@
+/* Automatically generated file, do not edit */
+#define protected static
+#include "chared.c"
+#include "common.c"
+#include "el.c"
+#include "emacs.c"
+#include "fcns.c"
+#include "filecomplete.c"
+#include "help.c"
+#include "hist.c"
+#include "key.c"
+#include "map.c"
+#include "chartype.c"
+#include "parse.c"
+#include "prompt.c"
+#include "read.c"
+#include "refresh.c"
+#include "search.c"
+#include "sig.c"
+#include "term.c"
+#include "tty.c"
+#include "vi.c"
diff --git a/lib/libedit/editrc.5 b/lib/libedit/editrc.5
index 53f186ae70d..eaf9be02e3b 100644
--- a/lib/libedit/editrc.5
+++ b/lib/libedit/editrc.5
@@ -1,5 +1,5 @@
-.\" $OpenBSD: editrc.5,v 1.23 2010/01/25 17:23:43 sobrado Exp $
-.\" $NetBSD: editrc.5,v 1.19 2003/11/01 23:35:33 christos Exp $
+.\" $OpenBSD: editrc.5,v 1.24 2010/06/30 00:05:35 nicm Exp $
+.\" $NetBSD: editrc.5,v 1.24 2009/04/11 22:17:52 wiz Exp $
.\"
.\" Copyright (c) 1997-2000 The NetBSD Foundation, Inc.
.\" All rights reserved.
@@ -27,9 +27,9 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd $Mdocdate: January 25 2010 $
-.Os
+.Dd $Mdocdate: June 30 2010 $
.Dt EDITRC 5
+.Os
.Sh NAME
.Nm editrc
.Nd configuration file for editline library
@@ -84,13 +84,12 @@ The
library has some builtin commands, which affect the way
that the line editing and history functions operate.
These are based on similar named builtins present in the
-.Xr tcsh
+.Xr tcsh 1
shell.
.Pp
The following builtin commands are available:
.Bl -tag -width 4n
-.It Ic bind Xo
-.Op Fl aeklrsv
+.It Ic bind Fl aeklrsv Xo
.Op Ar key Op Ar command
.Xc
Without options, list all bound keys, and the editor command to which
@@ -188,11 +187,7 @@ if it has any, notably
.Sq \e
and
.Sq ^ .
-.It Ic echotc Xo
-.Op Fl sv
-.Ar arg
-.Ar ...
-.Xc
+.It Ic echotc Oo Fl sv Oc Ar arg Ar ...
Exercise terminal capabilities given in
.Ar arg ... .
If
@@ -220,8 +215,24 @@ causes messages to be verbose.
Enable or disable the
.Nm editline
functionality in a program.
-.It Ic history
-List the history.
+.It Ic history Ar list | Ar size Dv n | Ar unique Dv n
+The
+.Ar list
+command lists all entries in the history.
+The
+.Ar size
+command sets the history size to
+.Dv n
+entries.
+The
+.Ar unique
+command controls if history should keep duplicate entries.
+If
+.Dv n
+is non zero, only keep unique history entries.
+If
+.Dv n
+is zero, then keep all entries (the default).
.It Ic settc Ar cap Ar val
Set the terminal capability
.Ar cap
@@ -276,6 +287,15 @@ fixes
on or off or removes control of
.Ar mode
in the chosen set.
+.Pp
+.Ic Setty
+can also be used to set tty characters to particular values using
+.Ar char=value .
+If
+.Ar value
+is empty
+then the character is set to
+.Dv _POSIX_VDISABLE .
.It Ic telltc
List the values of all the terminal capabilities (see
.Xr termcap 5 ) .
@@ -371,7 +391,7 @@ Vi comment out current command.
.It Ic vi-alias
Vi include shell alias.
.It Ic vi-to-history-line
-Vi go to specified history file line.
+Vi go to specified history file line..
.It Ic vi-histedit
Vi edit history line with vi.
.It Ic vi-history-word
diff --git a/lib/libedit/el.c b/lib/libedit/el.c
index c3fd43b4b2d..3ca3eb4fa0f 100644
--- a/lib/libedit/el.c
+++ b/lib/libedit/el.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: el.c,v 1.15 2009/10/27 23:59:28 deraadt Exp $ */
-/* $NetBSD: el.c,v 1.36 2003/10/18 23:48:42 christos Exp $ */
+/* $OpenBSD: el.c,v 1.16 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: el.c,v 1.59 2010/04/15 00:56:40 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -43,6 +43,9 @@
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
+#include <ctype.h>
+#include <locale.h>
+#include <langinfo.h>
#include "el.h"
/* el_init():
@@ -51,7 +54,6 @@
public EditLine *
el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr)
{
-
EditLine *el = (EditLine *) el_malloc(sizeof(EditLine));
if (el == NULL)
@@ -59,10 +61,14 @@ el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr)
memset(el, 0, sizeof(EditLine));
- el->el_infd = fileno(fin);
+ el->el_infile = fin;
el->el_outfile = fout;
el->el_errfile = ferr;
- if ((el->el_prog = el_strdup(prog)) == NULL) {
+
+ el->el_infd = fileno(fin);
+
+ el->el_prog = Strdup(ct_decode_string(prog, &el->el_scratch));
+ if (el->el_prog == NULL) {
el_free(el);
return NULL;
}
@@ -71,6 +77,12 @@ el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr)
* Initialize all the modules. Order is important!!!
*/
el->el_flags = 0;
+#ifdef WIDECHAR
+ if (setlocale(LC_CTYPE, NULL) != NULL){
+ if (strcmp(nl_langinfo(CODESET), "UTF-8") == 0)
+ el->el_flags |= CHARSET_IS_UTF8;
+ }
+#endif
if (term_init(el) == -1) {
el_free(el->el_prog);
@@ -116,6 +128,12 @@ el_end(EditLine *el)
el_free((ptr_t) el->el_prog);
el_free((ptr_t) el);
+#ifdef WIDECHAR
+ el_free((ptr_t) el->el_scratch.cbuff);
+ el_free((ptr_t) el->el_scratch.wbuff);
+ el_free((ptr_t) el->el_lgcyconv.cbuff);
+ el_free((ptr_t) el->el_lgcyconv.wbuff);
+#endif
}
@@ -127,7 +145,7 @@ el_reset(EditLine *el)
{
tty_cookedmode(el);
- ch_reset(el); /* XXX: Do we want that? */
+ ch_reset(el, 0); /* XXX: Do we want that? */
}
@@ -135,31 +153,43 @@ el_reset(EditLine *el)
* set the editline parameters
*/
public int
-el_set(EditLine *el, int op, ...)
+FUN(el,set)(EditLine *el, int op, ...)
{
- va_list va;
+ va_list ap;
int rv = 0;
if (el == NULL)
return (-1);
- va_start(va, op);
+ va_start(ap, op);
switch (op) {
case EL_PROMPT:
- case EL_RPROMPT:
- rv = prompt_set(el, va_arg(va, el_pfunc_t), op);
+ case EL_RPROMPT: {
+ el_pfunc_t p = va_arg(ap, el_pfunc_t);
+
+ rv = prompt_set(el, p, 0, op, 1);
+ break;
+ }
+
+ case EL_PROMPT_ESC:
+ case EL_RPROMPT_ESC: {
+ el_pfunc_t p = va_arg(ap, el_pfunc_t);
+ int c = va_arg(ap, int);
+
+ rv = prompt_set(el, p, c, op, 1);
break;
+ }
case EL_TERMINAL:
- rv = term_set(el, va_arg(va, char *));
+ rv = term_set(el, va_arg(ap, char *));
break;
case EL_EDITOR:
- rv = map_set_editor(el, va_arg(va, char *));
+ rv = map_set_editor(el, va_arg(ap, Char *));
break;
case EL_SIGNAL:
- if (va_arg(va, int))
+ if (va_arg(ap, int))
el->el_flags |= HANDLE_SIGNALS;
else
el->el_flags &= ~HANDLE_SIGNALS;
@@ -171,36 +201,36 @@ el_set(EditLine *el, int op, ...)
case EL_ECHOTC:
case EL_SETTY:
{
- const char *argv[20];
+ const Char *argv[20];
int i;
for (i = 1; i < 20; i++)
- if ((argv[i] = va_arg(va, char *)) == NULL)
+ if ((argv[i] = va_arg(ap, Char *)) == NULL)
break;
switch (op) {
case EL_BIND:
- argv[0] = "bind";
+ argv[0] = STR("bind");
rv = map_bind(el, i, argv);
break;
case EL_TELLTC:
- argv[0] = "telltc";
+ argv[0] = STR("telltc");
rv = term_telltc(el, i, argv);
break;
case EL_SETTC:
- argv[0] = "settc";
+ argv[0] = STR("settc");
rv = term_settc(el, i, argv);
break;
case EL_ECHOTC:
- argv[0] = "echotc";
+ argv[0] = STR("echotc");
rv = term_echotc(el, i, argv);
break;
case EL_SETTY:
- argv[0] = "setty";
+ argv[0] = STR("setty");
rv = tty_stty(el, i, argv);
break;
@@ -214,9 +244,9 @@ el_set(EditLine *el, int op, ...)
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);
+ Char *name = va_arg(ap, Char *);
+ Char *help = va_arg(ap, Char *);
+ el_func_t func = va_arg(ap, el_func_t);
rv = map_addfunc(el, name, help, func);
break;
@@ -224,15 +254,17 @@ el_set(EditLine *el, int op, ...)
case EL_HIST:
{
- hist_fun_t func = va_arg(va, hist_fun_t);
- ptr_t ptr = va_arg(va, char *);
+ hist_fun_t func = va_arg(ap, hist_fun_t);
+ ptr_t ptr = va_arg(ap, ptr_t);
rv = hist_set(el, func, ptr);
+ if (!(el->el_flags & CHARSET_IS_UTF8))
+ el->el_flags &= ~NARROW_HISTORY;
break;
}
case EL_EDITMODE:
- if (va_arg(va, int))
+ if (va_arg(ap, int))
el->el_flags &= ~EDIT_DISABLED;
else
el->el_flags |= EDIT_DISABLED;
@@ -241,17 +273,18 @@ el_set(EditLine *el, int op, ...)
case EL_GETCFN:
{
- el_rfunc_t rc = va_arg(va, el_rfunc_t);
+ el_rfunc_t rc = va_arg(ap, el_rfunc_t);
rv = el_read_setfn(el, rc);
+ el->el_flags &= ~NARROW_READ;
break;
}
case EL_CLIENTDATA:
- el->el_data = va_arg(va, void *);
+ el->el_data = va_arg(ap, void *);
break;
case EL_UNBUFFERED:
- rv = va_arg(va, int);
+ rv = va_arg(ap, int);
if (rv && !(el->el_flags & UNBUFFERED)) {
el->el_flags |= UNBUFFERED;
read_prepare(el);
@@ -263,20 +296,53 @@ el_set(EditLine *el, int op, ...)
break;
case EL_PREP_TERM:
- rv = va_arg(va, int);
+ rv = va_arg(ap, int);
if (rv)
- read_prepare(el);
+ (void) tty_rawmode(el);
else
- read_finish(el);
+ (void) tty_cookedmode(el);
rv = 0;
break;
+ case EL_SETFP:
+ {
+ FILE *fp;
+ int what;
+
+ what = va_arg(ap, int);
+ fp = va_arg(ap, FILE *);
+
+ rv = 0;
+ switch (what) {
+ case 0:
+ el->el_infile = fp;
+ el->el_infd = fileno(fp);
+ break;
+ case 1:
+ el->el_outfile = fp;
+ break;
+ case 2:
+ el->el_errfile = fp;
+ break;
+ default:
+ rv = -1;
+ break;
+ }
+ break;
+ }
+
+ case EL_REFRESH:
+ re_clear_display(el);
+ re_refresh(el);
+ term__flush(el);
+ break;
+
default:
rv = -1;
break;
}
- va_end(va);
+ va_end(ap);
return (rv);
}
@@ -285,122 +351,119 @@ el_set(EditLine *el, int op, ...)
* retrieve the editline parameters
*/
public int
-el_get(EditLine *el, int op, void *ret)
+FUN(el,get)(EditLine *el, int op, ...)
{
+ va_list ap;
int rv;
- if (el == NULL || ret == NULL)
- return (-1);
+ if (el == NULL)
+ return -1;
+
+ va_start(ap, op);
+
switch (op) {
case EL_PROMPT:
- case EL_RPROMPT:
- rv = prompt_get(el, (void *) &ret, op);
+ case EL_RPROMPT: {
+ el_pfunc_t *p = va_arg(ap, el_pfunc_t *);
+ rv = prompt_get(el, p, 0, op);
break;
+ }
+ case EL_PROMPT_ESC:
+ case EL_RPROMPT_ESC: {
+ el_pfunc_t *p = va_arg(ap, el_pfunc_t *);
+ Char *c = va_arg(ap, Char *);
+
+ rv = prompt_get(el, p, c, op);
+ break;
+ }
case EL_EDITOR:
- rv = map_get_editor(el, (void *) &ret);
+ rv = map_get_editor(el, va_arg(ap, const Char **));
break;
case EL_SIGNAL:
- *((int *) ret) = (el->el_flags & HANDLE_SIGNALS);
+ *va_arg(ap, int *) = (el->el_flags & HANDLE_SIGNALS);
rv = 0;
break;
case EL_EDITMODE:
- *((int *) ret) = (!(el->el_flags & EDIT_DISABLED));
+ *va_arg(ap, int *) = !(el->el_flags & EDIT_DISABLED);
rv = 0;
break;
case EL_TERMINAL:
- term_get(el, (const char **)ret);
+ term_get(el, va_arg(ap, const char **));
rv = 0;
break;
-#if 0 /* XXX */
- case EL_BIND:
- case EL_TELLTC:
- case EL_SETTC:
- case EL_ECHOTC:
- case EL_SETTY:
+ case EL_GETTC:
{
- const char *argv[20];
+ static char name[] = "gettc";
+ char *argv[20];
int i;
- for (i = 1; i < sizeof(argv) / sizeof(argv[0]); i++)
- if ((argv[i] = va_arg(va, char *)) == NULL)
+ for (i = 1; i < (int)(sizeof(argv) / sizeof(argv[0])); i++)
+ if ((argv[i] = va_arg(ap, 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);
+ case EL_GETTC:
+ argv[0] = name;
+ rv = term_gettc(el, i, argv);
break;
default:
rv = -1;
- EL_ABORT((el->errfile, "Bad op %d\n", op));
+ EL_ABORT((el->el_errfile, "Bad op %d\n", op));
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;
-#endif /* XXX */
-
case EL_GETCFN:
- *((el_rfunc_t *)ret) = el_read_getfn(el);
+ *va_arg(ap, el_rfunc_t *) = el_read_getfn(el);
rv = 0;
break;
case EL_CLIENTDATA:
- *((void **)ret) = el->el_data;
+ *va_arg(ap, void **) = el->el_data;
rv = 0;
break;
case EL_UNBUFFERED:
- *((int *) ret) = (!(el->el_flags & UNBUFFERED));
+ *va_arg(ap, int *) = (!(el->el_flags & UNBUFFERED));
rv = 0;
break;
+ case EL_GETFP:
+ {
+ int what;
+ FILE **fpp;
+
+ what = va_arg(ap, int);
+ fpp = va_arg(ap, FILE **);
+ rv = 0;
+ switch (what) {
+ case 0:
+ *fpp = el->el_infile;
+ break;
+ case 1:
+ *fpp = el->el_outfile;
+ break;
+ case 2:
+ *fpp = el->el_errfile;
+ break;
+ default:
+ rv = -1;
+ break;
+ }
+ break;
+ }
default:
rv = -1;
+ break;
}
+ va_end(ap);
return (rv);
}
@@ -409,11 +472,11 @@ el_get(EditLine *el, int op, void *ret)
/* el_line():
* Return editing info
*/
-public const LineInfo *
-el_line(EditLine *el)
+public const TYPE(LineInfo) *
+FUN(el,line)(EditLine *el)
{
- return (const LineInfo *) (void *) &el->el_line;
+ return (const TYPE(LineInfo) *) (void *) &el->el_line;
}
@@ -426,12 +489,15 @@ el_source(EditLine *el, const char *fname)
FILE *fp;
size_t len;
char *ptr, *lptr = NULL;
+#ifdef HAVE_ISSETUGID
+ char path[MAXPATHLEN];
+#endif
+ const Char *dptr;
fp = NULL;
if (fname == NULL) {
#ifdef HAVE_ISSETUGID
static const char elpath[] = "/.editrc";
- char path[MAXPATHLEN];
if (issetugid())
return (-1);
@@ -468,12 +534,23 @@ el_source(EditLine *el, const char *fname)
lptr[len] = '\0';
ptr = lptr;
}
- if (parse_line(el, ptr) == -1) {
+
+ dptr = ct_decode_string(ptr, &el->el_scratch);
+ if (!dptr)
+ continue;
+
+ /* loop until first non-space char or EOL */
+ while (*dptr != '\0' && Isspace(*dptr))
+ dptr++;
+ if (*dptr == '#')
+ continue; /* ignore, this is a comment line */
+ if (parse_line(el, dptr) == -1) {
free(lptr);
(void) fclose(fp);
return (-1);
}
}
+
free(lptr);
(void) fclose(fp);
return (0);
@@ -517,20 +594,24 @@ el_beep(EditLine *el)
*/
protected int
/*ARGSUSED*/
-el_editmode(EditLine *el, int argc, const char **argv)
+el_editmode(EditLine *el, int argc, const Char **argv)
{
- const char *how;
+ const Char *how;
if (argv == NULL || argc != 2 || argv[1] == NULL)
return (-1);
how = argv[1];
- if (strcmp(how, "on") == 0)
+ if (Strcmp(how, STR("on")) == 0) {
el->el_flags &= ~EDIT_DISABLED;
- else if (strcmp(how, "off") == 0)
+ tty_rawmode(el);
+ } else if (Strcmp(how, STR("off")) == 0) {
+ tty_cookedmode(el);
el->el_flags |= EDIT_DISABLED;
+ }
else {
- (void) fprintf(el->el_errfile, "edit: Bad value `%s'.\n", how);
+ (void) fprintf(el->el_errfile, "edit: Bad value `" FSTR "'.\n",
+ how);
return (-1);
}
return (0);
diff --git a/lib/libedit/el.h b/lib/libedit/el.h
index 53c10221be8..bdc61487501 100644
--- a/lib/libedit/el.h
+++ b/lib/libedit/el.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: el.h,v 1.6 2003/11/25 20:12:38 otto Exp $ */
-/* $NetBSD: el.h,v 1.16 2003/10/18 23:48:42 christos Exp $ */
+/* $OpenBSD: el.h,v 1.7 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: el.h,v 1.21 2009/12/31 15:58:26 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -47,6 +47,8 @@
#define VIDEFAULT
#define ANCHOR
+#include "histedit.h"
+#include "chartype.h"
#include <stdio.h>
#include <sys/types.h>
@@ -56,6 +58,10 @@
#define NO_TTY 0x02
#define EDIT_DISABLED 0x04
#define UNBUFFERED 0x08
+#define CHARSET_IS_UTF8 0x10
+#define IGNORE_EXTCHARS 0x20 /* Ignore characters read > 0xff */
+#define NARROW_HISTORY 0x40
+#define NARROW_READ 0x80
typedef int bool_t; /* True or not */
@@ -67,10 +73,10 @@ typedef struct coord_t { /* Position on the screen */
} coord_t;
typedef struct el_line_t {
- char *buffer; /* Input line */
- char *cursor; /* Cursor position */
- char *lastchar; /* Last character */
- const char *limit; /* Max position */
+ Char *buffer; /* Input line */
+ Char *cursor; /* Cursor position */
+ Char *lastchar; /* Last character */
+ const Char *limit; /* Max position */
} el_line_t;
/*
@@ -83,13 +89,12 @@ typedef struct el_state_t {
int metanext; /* Is the next char a meta char */
el_action_t lastcmd; /* Previous command */
el_action_t thiscmd; /* this command */
- char thisch; /* char that generated it */
+ Char thisch; /* char that generated it */
} el_state_t;
/*
* Until we come up with something better...
*/
-#define el_strdup(a) strdup(a)
#define el_malloc(a) malloc(a)
#define el_realloc(a,b) realloc(a, b)
#define el_free(a) free(a)
@@ -110,14 +115,16 @@ typedef struct el_state_t {
#include "read.h"
struct editline {
- char *el_prog; /* the program name */
+ Char *el_prog; /* the program name */
+ FILE *el_infile; /* Stdio stuff */
FILE *el_outfile; /* Stdio stuff */
FILE *el_errfile; /* Stdio stuff */
int el_infd; /* Input file descriptor */
int el_flags; /* Various flags. */
+ int el_errno; /* Local copy of errno */
coord_t el_cursor; /* Cursor location */
- char **el_display; /* Real screen image = what is there */
- char **el_vdisplay; /* Virtual screen image = what we see */
+ Char **el_display; /* Real screen image = what is there */
+ Char **el_vdisplay; /* Virtual screen image = what we see */
void *el_data; /* Client data */
el_line_t el_line; /* The current line information */
el_state_t el_state; /* Current editor state */
@@ -133,9 +140,14 @@ struct editline {
el_search_t el_search; /* Search stuff */
el_signal_t el_signal; /* Signal handling stuff */
el_read_t el_read; /* Character reading stuff */
+#ifdef WIDECHAR
+ ct_buffer_t el_scratch; /* Scratch conversion buffer */
+ ct_buffer_t el_lgcyconv; /* Buffer for legacy wrappers */
+ LineInfo el_lgcylinfo; /* Legacy LineInfo buffer */
+#endif
};
-protected int el_editmode(EditLine *, int, const char **);
+protected int el_editmode(EditLine *, int, const Char **);
#ifdef DEBUG
#define EL_ABORT(a) do { \
diff --git a/lib/libedit/eln.c b/lib/libedit/eln.c
new file mode 100644
index 00000000000..ce6b5714cae
--- /dev/null
+++ b/lib/libedit/eln.c
@@ -0,0 +1,364 @@
+/* $OpenBSD: eln.c,v 1.1 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: eln.c,v 1.7 2010/04/15 00:52:48 christos Exp $ */
+
+/*-
+ * Copyright (c) 2009 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "histedit.h"
+#include "el.h"
+#include "read.h"
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+public int
+el_getc(EditLine *el, char *cp)
+{
+ int num_read;
+ wchar_t wc = 0;
+
+ if (!(el->el_flags & CHARSET_IS_UTF8))
+ el->el_flags |= IGNORE_EXTCHARS;
+ num_read = el_wgetc (el, &wc);
+ if (!(el->el_flags & CHARSET_IS_UTF8))
+ el->el_flags &= ~IGNORE_EXTCHARS;
+
+ if (num_read > 0)
+ *cp = (unsigned char)wc;
+ return num_read;
+}
+
+
+public void
+el_push(EditLine *el, const char *str)
+{
+ /* Using multibyte->wide string decoding works fine under single-byte
+ * character sets too, and Does The Right Thing. */
+ el_wpush(el, ct_decode_string(str, &el->el_lgcyconv));
+}
+
+
+public const char *
+el_gets(EditLine *el, int *nread)
+{
+ const wchar_t *tmp;
+
+ el->el_flags |= IGNORE_EXTCHARS;
+ tmp = el_wgets(el, nread);
+ el->el_flags &= ~IGNORE_EXTCHARS;
+ return ct_encode_string(tmp, &el->el_lgcyconv);
+}
+
+
+public int
+el_parse(EditLine *el, int argc, const char *argv[])
+{
+ int ret;
+ const wchar_t **wargv;
+
+ wargv = (const wchar_t **)
+ ct_decode_argv(argc, argv, &el->el_lgcyconv);
+ if (!wargv)
+ return -1;
+ ret = el_wparse(el, argc, wargv);
+ ct_free_argv(wargv);
+
+ return ret;
+}
+
+
+public int
+el_set(EditLine *el, int op, ...)
+{
+ va_list ap;
+ int ret;
+
+ if (!el)
+ return -1;
+ va_start(ap, op);
+
+ switch (op) {
+ case EL_PROMPT: /* el_pfunc_t */
+ case EL_RPROMPT: {
+ el_pfunc_t p = va_arg(ap, el_pfunc_t);
+ ret = prompt_set(el, p, 0, op, 0);
+ break;
+ }
+
+ case EL_TERMINAL: /* const char * */
+ ret = el_wset(el, op, va_arg(ap, char *));
+ break;
+
+ case EL_EDITOR: /* const wchar_t * */
+ ret = el_wset(el, op, ct_decode_string(va_arg(ap, char *),
+ &el->el_lgcyconv));
+ break;
+
+ case EL_SIGNAL: /* int */
+ case EL_EDITMODE:
+ case EL_UNBUFFERED:
+ case EL_PREP_TERM:
+ ret = el_wset(el, op, va_arg(ap, int));
+ break;
+
+ case EL_BIND: /* const char * list -> const wchar_t * list */
+ case EL_TELLTC:
+ case EL_SETTC:
+ case EL_ECHOTC:
+ case EL_SETTY: {
+ const char *argv[20];
+ int i;
+ const wchar_t **wargv;
+ for (i = 1; i < (int)__arraycount(argv); ++i)
+ if ((argv[i] = va_arg(ap, char *)) == NULL)
+ break;
+ argv[0] = NULL;
+ wargv = (const wchar_t **)
+ ct_decode_argv(i, argv, &el->el_lgcyconv);
+ if (!wargv) {
+ ret = -1;
+ goto out;
+ }
+ /*
+ * AFAIK we can't portably pass through our new wargv to
+ * el_wset(), so we have to reimplement the body of
+ * el_wset() for these ops.
+ */
+ switch (op) {
+ case EL_BIND:
+ wargv[0] = STR("bind");
+ ret = map_bind(el, i, wargv);
+ break;
+ case EL_TELLTC:
+ wargv[0] = STR("telltc");
+ ret = term_telltc(el, i, wargv);
+ break;
+ case EL_SETTC:
+ wargv[0] = STR("settc");
+ ret = term_settc(el, i, wargv);
+ break;
+ case EL_ECHOTC:
+ wargv[0] = STR("echotc");
+ ret = term_echotc(el, i, wargv);
+ break;
+ case EL_SETTY:
+ wargv[0] = STR("setty");
+ ret = tty_stty(el, i, wargv);
+ break;
+ default:
+ ret = -1;
+ }
+ ct_free_argv(wargv);
+ break;
+ }
+
+ /* XXX: do we need to change el_func_t too? */
+ case EL_ADDFN: { /* const char *, const char *, el_func_t */
+ const char *args[2];
+ el_func_t func;
+ wchar_t **wargv;
+
+ args[0] = va_arg(ap, const char *);
+ args[1] = va_arg(ap, const char *);
+ func = va_arg(ap, el_func_t);
+
+ wargv = ct_decode_argv(2, args, &el->el_lgcyconv);
+ if (!wargv) {
+ ret = -1;
+ goto out;
+ }
+ // XXX: The two strdup's leak
+ ret = map_addfunc(el, Strdup(wargv[0]), Strdup(wargv[1]),
+ func);
+ ct_free_argv(wargv);
+ break;
+ }
+ case EL_HIST: { /* hist_fun_t, const char * */
+ hist_fun_t fun = va_arg(ap, hist_fun_t);
+ ptr_t ptr = va_arg(ap, ptr_t);
+ ret = hist_set(el, fun, ptr);
+ if (!(el->el_flags & CHARSET_IS_UTF8))
+ el->el_flags |= NARROW_HISTORY;
+ break;
+ }
+ /* XXX: do we need to change el_rfunc_t? */
+ case EL_GETCFN: /* el_rfunc_t */
+ ret = el_wset(el, op, va_arg(ap, el_rfunc_t));
+ el->el_flags |= NARROW_READ;
+ break;
+ case EL_CLIENTDATA: /* void * */
+ ret = el_wset(el, op, va_arg(ap, void *));
+ break;
+ case EL_SETFP: { /* int, FILE * */
+ int what = va_arg(ap, int);
+ FILE *fp = va_arg(ap, FILE *);
+ ret = el_wset(el, op, what, fp);
+ break;
+ }
+ case EL_PROMPT_ESC: /* el_pfunc_t, char */
+ case EL_RPROMPT_ESC: {
+ el_pfunc_t p = va_arg(ap, el_pfunc_t);
+ char c = va_arg(ap, int);
+ ret = prompt_set(el, p, c, op, 0);
+ break;
+ }
+ default:
+ ret = -1;
+ break;
+ }
+
+out:
+ va_end(ap);
+ return ret;
+}
+
+
+public int
+el_get(EditLine *el, int op, ...)
+{
+ va_list ap;
+ int ret;
+
+ if (!el)
+ return -1;
+
+ va_start(ap, op);
+
+ switch (op) {
+ case EL_PROMPT: /* el_pfunc_t * */
+ case EL_RPROMPT: {
+ el_pfunc_t *p = va_arg(ap, el_pfunc_t *);
+ ret = prompt_get(el, p, 0, op);
+ break;
+ }
+
+ case EL_PROMPT_ESC: /* el_pfunc_t *, char **/
+ case EL_RPROMPT_ESC: {
+ el_pfunc_t *p = va_arg(ap, el_pfunc_t *);
+ char *c = va_arg(ap, char *);
+ wchar_t wc;
+ ret = prompt_get(el, p, &wc, op);
+ *c = (unsigned char)wc;
+ break;
+ }
+
+ case EL_EDITOR: {
+ const char **p = va_arg(ap, const char **);
+ const wchar_t *pw;
+ ret = el_wget(el, op, &pw);
+ *p = ct_encode_string(pw, &el->el_lgcyconv);
+ if (!el->el_lgcyconv.csize)
+ ret = -1;
+ break;
+ }
+
+ case EL_TERMINAL: /* const char ** */
+ ret = el_wget(el, op, va_arg(ap, const char **));
+ break;
+
+ case EL_SIGNAL: /* int * */
+ case EL_EDITMODE:
+ case EL_UNBUFFERED:
+ case EL_PREP_TERM:
+ ret = el_wget(el, op, va_arg(ap, int *));
+ break;
+
+ case EL_GETTC: {
+ char *argv[20];
+ static char gettc[] = "gettc";
+ int i;
+ for (i = 1; i < (int)__arraycount(argv); ++i)
+ if ((argv[i] = va_arg(ap, char *)) == NULL)
+ break;
+ argv[0] = gettc;
+ ret = term_gettc(el, i, argv);
+ break;
+ }
+
+ /* XXX: do we need to change el_rfunc_t? */
+ case EL_GETCFN: /* el_rfunc_t */
+ ret = el_wget(el, op, va_arg(ap, el_rfunc_t *));
+ break;
+
+ case EL_CLIENTDATA: /* void ** */
+ ret = el_wget(el, op, va_arg(ap, void **));
+ break;
+
+ case EL_GETFP: { /* int, FILE ** */
+ int what = va_arg(ap, int);
+ FILE **fpp = va_arg(ap, FILE **);
+ ret = el_wget(el, op, what, fpp);
+ break;
+ }
+
+ default:
+ ret = -1;
+ break;
+ }
+
+ va_end(ap);
+ return ret;
+}
+
+
+const LineInfo *
+el_line(EditLine *el)
+{
+ const LineInfoW *winfo = el_wline(el);
+ LineInfo *info = &el->el_lgcylinfo;
+ size_t offset;
+ const Char *p;
+
+ info->buffer = ct_encode_string(winfo->buffer, &el->el_lgcyconv);
+
+ offset = 0;
+ for (p = winfo->buffer; p < winfo->cursor; p++)
+ offset += ct_enc_width(*p);
+ info->cursor = info->buffer + offset;
+
+ offset = 0;
+ for (p = winfo->buffer; p < winfo->lastchar; p++)
+ offset += ct_enc_width(*p);
+ info->lastchar = info->buffer + offset;
+
+ return info;
+}
+
+
+int
+el_insertstr(EditLine *el, const char *str)
+{
+ return el_winsertstr(el, ct_decode_string(str, &el->el_lgcyconv));
+}
diff --git a/lib/libedit/emacs.c b/lib/libedit/emacs.c
index 75f71f575ad..f2c4eae272e 100644
--- a/lib/libedit/emacs.c
+++ b/lib/libedit/emacs.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: emacs.c,v 1.8 2009/10/27 23:59:28 deraadt Exp $ */
-/* $NetBSD: emacs.c,v 1.16 2003/11/02 20:07:58 christos Exp $ */
+/* $OpenBSD: emacs.c,v 1.9 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: emacs.c,v 1.23 2009/12/30 22:37:40 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -46,15 +46,14 @@
*/
protected el_action_t
/*ARGSUSED*/
-em_delete_or_list(EditLine *el, int c __attribute__((__unused__)))
+em_delete_or_list(EditLine *el, Int c)
{
if (el->el_line.cursor == el->el_line.lastchar) {
/* if I'm at the end */
if (el->el_line.cursor == el->el_line.buffer) {
/* and the beginning */
- term_overwrite(el, STReof, 4); /* then do a EOF */
- term__flush();
+ term_writec(el, c); /* then do an EOF */
return (CC_EOF);
} else {
/*
@@ -65,7 +64,10 @@ em_delete_or_list(EditLine *el, int c __attribute__((__unused__)))
return (CC_ERROR);
}
} else {
- c_delafter(el, el->el_state.argument); /* delete after dot */
+ if (el->el_state.doingarg)
+ c_delafter(el, el->el_state.argument);
+ else
+ c_delafter1(el);
if (el->el_line.cursor > el->el_line.lastchar)
el->el_line.cursor = el->el_line.lastchar;
/* bounds check */
@@ -80,9 +82,9 @@ em_delete_or_list(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-em_delete_next_word(EditLine *el, int c __attribute__((__unused__)))
+em_delete_next_word(EditLine *el, Int c __attribute__((__unused__)))
{
- char *cp, *p, *kp;
+ Char *cp, *p, *kp;
if (el->el_line.cursor == el->el_line.lastchar)
return (CC_ERROR);
@@ -95,7 +97,7 @@ em_delete_next_word(EditLine *el, int c __attribute__((__unused__)))
*kp++ = *p;
el->el_chared.c_kill.last = kp;
- c_delafter(el, cp - el->el_line.cursor); /* delete after dot */
+ c_delafter(el, (int)(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 */
@@ -109,9 +111,9 @@ em_delete_next_word(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-em_yank(EditLine *el, int c __attribute__((__unused__)))
+em_yank(EditLine *el, Int c __attribute__((__unused__)))
{
- char *kp, *cp;
+ Char *kp, *cp;
if (el->el_chared.c_kill.last == el->el_chared.c_kill.buf)
return (CC_NORM);
@@ -125,7 +127,8 @@ em_yank(EditLine *el, int c __attribute__((__unused__)))
cp = el->el_line.cursor;
/* open the space, */
- c_insert(el, el->el_chared.c_kill.last - el->el_chared.c_kill.buf);
+ c_insert(el,
+ (int)(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;
@@ -144,9 +147,9 @@ em_yank(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-em_kill_line(EditLine *el, int c __attribute__((__unused__)))
+em_kill_line(EditLine *el, Int c __attribute__((__unused__)))
{
- char *kp, *cp;
+ Char *kp, *cp;
cp = el->el_line.buffer;
kp = el->el_chared.c_kill.buf;
@@ -166,9 +169,9 @@ em_kill_line(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-em_kill_region(EditLine *el, int c __attribute__((__unused__)))
+em_kill_region(EditLine *el, Int c __attribute__((__unused__)))
{
- char *kp, *cp;
+ Char *kp, *cp;
if (!el->el_chared.c_kill.mark)
return (CC_ERROR);
@@ -179,14 +182,14 @@ em_kill_region(EditLine *el, int c __attribute__((__unused__)))
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);
+ c_delafter(el, (int)(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);
+ c_delbefore(el, (int)(cp - el->el_chared.c_kill.mark));
el->el_line.cursor = el->el_chared.c_kill.mark;
}
return (CC_REFRESH);
@@ -199,9 +202,9 @@ em_kill_region(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-em_copy_region(EditLine *el, int c __attribute__((__unused__)))
+em_copy_region(EditLine *el, Int c __attribute__((__unused__)))
{
- char *kp, *cp;
+ Char *kp, *cp;
if (!el->el_chared.c_kill.mark)
return (CC_ERROR);
@@ -228,7 +231,7 @@ em_copy_region(EditLine *el, int c __attribute__((__unused__)))
* Gosling emacs transpose chars [^T]
*/
protected el_action_t
-em_gosmacs_transpose(EditLine *el, int c)
+em_gosmacs_transpose(EditLine *el, Int c)
{
if (el->el_line.cursor > &el->el_line.buffer[1]) {
@@ -248,7 +251,7 @@ em_gosmacs_transpose(EditLine *el, int c)
*/
protected el_action_t
/*ARGSUSED*/
-em_next_word(EditLine *el, int c __attribute__((__unused__)))
+em_next_word(EditLine *el, Int c __attribute__((__unused__)))
{
if (el->el_line.cursor == el->el_line.lastchar)
return (CC_ERROR);
@@ -273,16 +276,16 @@ em_next_word(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-em_upper_case(EditLine *el, int c __attribute__((__unused__)))
+em_upper_case(EditLine *el, Int c __attribute__((__unused__)))
{
- char *cp, *ep;
+ Char *cp, *ep;
ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
el->el_state.argument, ce__isword);
for (cp = el->el_line.cursor; cp < ep; cp++)
- if (islower((unsigned char) *cp))
- *cp = toupper(*cp);
+ if (Islower(*cp))
+ *cp = Toupper(*cp);
el->el_line.cursor = ep;
if (el->el_line.cursor > el->el_line.lastchar)
@@ -297,24 +300,24 @@ em_upper_case(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-em_capitol_case(EditLine *el, int c __attribute__((__unused__)))
+em_capitol_case(EditLine *el, Int c __attribute__((__unused__)))
{
- char *cp, *ep;
+ Char *cp, *ep;
ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
el->el_state.argument, ce__isword);
for (cp = el->el_line.cursor; cp < ep; cp++) {
- if (isalpha((unsigned char) *cp)) {
- if (islower((unsigned char) *cp))
- *cp = toupper(*cp);
+ if (Isalpha(*cp)) {
+ if (Islower(*cp))
+ *cp = Toupper(*cp);
cp++;
break;
}
}
for (; cp < ep; cp++)
- if (isupper((unsigned char) *cp))
- *cp = tolower(*cp);
+ if (Isupper(*cp))
+ *cp = Tolower(*cp);
el->el_line.cursor = ep;
if (el->el_line.cursor > el->el_line.lastchar)
@@ -329,16 +332,16 @@ em_capitol_case(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-em_lower_case(EditLine *el, int c __attribute__((__unused__)))
+em_lower_case(EditLine *el, Int c __attribute__((__unused__)))
{
- char *cp, *ep;
+ Char *cp, *ep;
ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
el->el_state.argument, ce__isword);
for (cp = el->el_line.cursor; cp < ep; cp++)
- if (isupper((unsigned char) *cp))
- *cp = tolower(*cp);
+ if (Isupper(*cp))
+ *cp = Tolower(*cp);
el->el_line.cursor = ep;
if (el->el_line.cursor > el->el_line.lastchar)
@@ -353,7 +356,7 @@ em_lower_case(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-em_set_mark(EditLine *el, int c __attribute__((__unused__)))
+em_set_mark(EditLine *el, Int c __attribute__((__unused__)))
{
el->el_chared.c_kill.mark = el->el_line.cursor;
@@ -367,9 +370,9 @@ em_set_mark(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-em_exchange_mark(EditLine *el, int c __attribute__((__unused__)))
+em_exchange_mark(EditLine *el, Int c __attribute__((__unused__)))
{
- char *cp;
+ Char *cp;
cp = el->el_line.cursor;
el->el_line.cursor = el->el_chared.c_kill.mark;
@@ -384,7 +387,7 @@ em_exchange_mark(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-em_universal_argument(EditLine *el, int c __attribute__((__unused__)))
+em_universal_argument(EditLine *el, Int c __attribute__((__unused__)))
{ /* multiply current argument by 4 */
if (el->el_state.argument > 1000000)
@@ -401,7 +404,7 @@ em_universal_argument(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-em_meta_next(EditLine *el, int c __attribute__((__unused__)))
+em_meta_next(EditLine *el, Int c __attribute__((__unused__)))
{
el->el_state.metanext = 1;
@@ -414,7 +417,7 @@ em_meta_next(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-em_toggle_overwrite(EditLine *el, int c __attribute__((__unused__)))
+em_toggle_overwrite(EditLine *el, Int c __attribute__((__unused__)))
{
el->el_state.inputmode = (el->el_state.inputmode == MODE_INSERT) ?
@@ -428,9 +431,9 @@ em_toggle_overwrite(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-em_copy_prev_word(EditLine *el, int c __attribute__((__unused__)))
+em_copy_prev_word(EditLine *el, Int c __attribute__((__unused__)))
{
- char *cp, *oldc, *dp;
+ Char *cp, *oldc, *dp;
if (el->el_line.cursor == el->el_line.buffer)
return (CC_ERROR);
@@ -440,7 +443,7 @@ em_copy_prev_word(EditLine *el, int c __attribute__((__unused__)))
cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
el->el_state.argument, ce__isword);
- c_insert(el, oldc - cp);
+ c_insert(el, (int)(oldc - cp));
for (dp = oldc; cp < oldc && dp < el->el_line.lastchar; cp++)
*dp++ = *cp;
@@ -455,7 +458,7 @@ em_copy_prev_word(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-em_inc_search_next(EditLine *el, int c __attribute__((__unused__)))
+em_inc_search_next(EditLine *el, Int c __attribute__((__unused__)))
{
el->el_search.patlen = 0;
@@ -468,9 +471,32 @@ em_inc_search_next(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-em_inc_search_prev(EditLine *el, int c __attribute__((__unused__)))
+em_inc_search_prev(EditLine *el, Int c __attribute__((__unused__)))
{
el->el_search.patlen = 0;
return (ce_inc_search(el, ED_SEARCH_PREV_HISTORY));
}
+
+
+/* em_delete_prev_char():
+ * Delete the character to the left of the cursor
+ * [^?]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_delete_prev_char(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+ if (el->el_line.cursor <= el->el_line.buffer)
+ return (CC_ERROR);
+
+ if (el->el_state.doingarg)
+ c_delbefore(el, el->el_state.argument);
+ else
+ c_delbefore1(el);
+ el->el_line.cursor -= el->el_state.argument;
+ if (el->el_line.cursor < el->el_line.buffer)
+ el->el_line.cursor = el->el_line.buffer;
+ return (CC_REFRESH);
+}
diff --git a/lib/libedit/emacs.h b/lib/libedit/emacs.h
new file mode 100644
index 00000000000..1f5ce3f16e9
--- /dev/null
+++ b/lib/libedit/emacs.h
@@ -0,0 +1,24 @@
+/* Automatically generated file, do not edit */
+#ifndef _h_emacs_c
+#define _h_emacs_c
+protected el_action_t em_delete_or_list (EditLine *, Int);
+protected el_action_t em_delete_next_word (EditLine *, Int);
+protected el_action_t em_yank (EditLine *, Int);
+protected el_action_t em_kill_line (EditLine *, Int);
+protected el_action_t em_kill_region (EditLine *, Int);
+protected el_action_t em_copy_region (EditLine *, Int);
+protected el_action_t em_gosmacs_transpose (EditLine *, Int);
+protected el_action_t em_next_word (EditLine *, Int);
+protected el_action_t em_upper_case (EditLine *, Int);
+protected el_action_t em_capitol_case (EditLine *, Int);
+protected el_action_t em_lower_case (EditLine *, Int);
+protected el_action_t em_set_mark (EditLine *, Int);
+protected el_action_t em_exchange_mark (EditLine *, Int);
+protected el_action_t em_universal_argument (EditLine *, Int);
+protected el_action_t em_meta_next (EditLine *, Int);
+protected el_action_t em_toggle_overwrite (EditLine *, Int);
+protected el_action_t em_copy_prev_word (EditLine *, Int);
+protected el_action_t em_inc_search_next (EditLine *, Int);
+protected el_action_t em_inc_search_prev (EditLine *, Int);
+protected el_action_t em_delete_prev_char (EditLine *, Int);
+#endif /* _h_emacs_c */
diff --git a/lib/libedit/fcns.c b/lib/libedit/fcns.c
new file mode 100644
index 00000000000..e7eedae14bc
--- /dev/null
+++ b/lib/libedit/fcns.c
@@ -0,0 +1,58 @@
+/* Automatically generated file, do not edit */
+#include "config.h"
+#include "el.h"
+private const el_func_t el_func[] = {
+ ed_argument_digit, ed_clear_screen,
+ ed_command, ed_delete_next_char,
+ ed_delete_prev_char, ed_delete_prev_word,
+ ed_digit, ed_end_of_file,
+ ed_insert, ed_kill_line,
+ ed_move_to_beg, ed_move_to_end,
+ ed_newline, ed_next_char,
+ ed_next_history, ed_next_line,
+ ed_prev_char, ed_prev_history,
+ ed_prev_line, ed_prev_word,
+ ed_quoted_insert, ed_redisplay,
+ ed_search_next_history, ed_search_prev_history,
+ ed_sequence_lead_in, ed_start_over,
+ ed_transpose_chars, ed_tty_dsusp,
+ ed_tty_flush_output, ed_tty_sigint,
+ ed_tty_sigquit, ed_tty_sigtstp,
+ ed_tty_start_output, ed_tty_stop_output,
+ ed_unassigned, em_capitol_case,
+ em_copy_prev_word, em_copy_region,
+ em_delete_next_word, em_delete_or_list,
+ em_delete_prev_char, em_exchange_mark,
+ em_gosmacs_transpose, em_inc_search_next,
+ em_inc_search_prev, em_kill_line,
+ em_kill_region, em_lower_case,
+ em_meta_next, em_next_word,
+ em_set_mark, em_toggle_overwrite,
+ em_universal_argument, em_upper_case,
+ em_yank, vi_add,
+ vi_add_at_eol, vi_alias,
+ vi_change_case, vi_change_meta,
+ vi_change_to_eol, vi_command_mode,
+ vi_comment_out, vi_delete_meta,
+ vi_delete_prev_char, vi_end_big_word,
+ vi_end_word, vi_histedit,
+ vi_history_word, vi_insert,
+ vi_insert_at_bol, vi_kill_line_prev,
+ vi_list_or_eof, vi_match,
+ vi_next_big_word, vi_next_char,
+ vi_next_word, vi_paste_next,
+ vi_paste_prev, vi_prev_big_word,
+ vi_prev_char, vi_prev_word,
+ vi_redo, vi_repeat_next_char,
+ vi_repeat_prev_char, vi_repeat_search_next,
+ vi_repeat_search_prev, vi_replace_char,
+ vi_replace_mode, vi_search_next,
+ vi_search_prev, vi_substitute_char,
+ vi_substitute_line, vi_to_column,
+ vi_to_history_line, vi_to_next_char,
+ vi_to_prev_char, vi_undo,
+ vi_undo_line, vi_yank,
+ vi_yank_end, vi_zero,
+};
+
+protected const el_func_t* func__get() { return el_func; }
diff --git a/lib/libedit/fcns.h b/lib/libedit/fcns.h
new file mode 100644
index 00000000000..7018b9c7d4a
--- /dev/null
+++ b/lib/libedit/fcns.h
@@ -0,0 +1,109 @@
+/* Automatically generated file, do not edit */
+#ifndef _h_fcns_c
+#define _h_fcns_c
+#define ED_ARGUMENT_DIGIT 0
+#define ED_CLEAR_SCREEN 1
+#define ED_COMMAND 2
+#define ED_DELETE_NEXT_CHAR 3
+#define ED_DELETE_PREV_CHAR 4
+#define ED_DELETE_PREV_WORD 5
+#define ED_DIGIT 6
+#define ED_END_OF_FILE 7
+#define ED_INSERT 8
+#define ED_KILL_LINE 9
+#define ED_MOVE_TO_BEG 10
+#define ED_MOVE_TO_END 11
+#define ED_NEWLINE 12
+#define ED_NEXT_CHAR 13
+#define ED_NEXT_HISTORY 14
+#define ED_NEXT_LINE 15
+#define ED_PREV_CHAR 16
+#define ED_PREV_HISTORY 17
+#define ED_PREV_LINE 18
+#define ED_PREV_WORD 19
+#define ED_QUOTED_INSERT 20
+#define ED_REDISPLAY 21
+#define ED_SEARCH_NEXT_HISTORY 22
+#define ED_SEARCH_PREV_HISTORY 23
+#define ED_SEQUENCE_LEAD_IN 24
+#define ED_START_OVER 25
+#define ED_TRANSPOSE_CHARS 26
+#define ED_TTY_DSUSP 27
+#define ED_TTY_FLUSH_OUTPUT 28
+#define ED_TTY_SIGINT 29
+#define ED_TTY_SIGQUIT 30
+#define ED_TTY_SIGTSTP 31
+#define ED_TTY_START_OUTPUT 32
+#define ED_TTY_STOP_OUTPUT 33
+#define ED_UNASSIGNED 34
+#define EM_CAPITOL_CASE 35
+#define EM_COPY_PREV_WORD 36
+#define EM_COPY_REGION 37
+#define EM_DELETE_NEXT_WORD 38
+#define EM_DELETE_OR_LIST 39
+#define EM_DELETE_PREV_CHAR 40
+#define EM_EXCHANGE_MARK 41
+#define EM_GOSMACS_TRANSPOSE 42
+#define EM_INC_SEARCH_NEXT 43
+#define EM_INC_SEARCH_PREV 44
+#define EM_KILL_LINE 45
+#define EM_KILL_REGION 46
+#define EM_LOWER_CASE 47
+#define EM_META_NEXT 48
+#define EM_NEXT_WORD 49
+#define EM_SET_MARK 50
+#define EM_TOGGLE_OVERWRITE 51
+#define EM_UNIVERSAL_ARGUMENT 52
+#define EM_UPPER_CASE 53
+#define EM_YANK 54
+#define VI_ADD 55
+#define VI_ADD_AT_EOL 56
+#define VI_ALIAS 57
+#define VI_CHANGE_CASE 58
+#define VI_CHANGE_META 59
+#define VI_CHANGE_TO_EOL 60
+#define VI_COMMAND_MODE 61
+#define VI_COMMENT_OUT 62
+#define VI_DELETE_META 63
+#define VI_DELETE_PREV_CHAR 64
+#define VI_END_BIG_WORD 65
+#define VI_END_WORD 66
+#define VI_HISTEDIT 67
+#define VI_HISTORY_WORD 68
+#define VI_INSERT 69
+#define VI_INSERT_AT_BOL 70
+#define VI_KILL_LINE_PREV 71
+#define VI_LIST_OR_EOF 72
+#define VI_MATCH 73
+#define VI_NEXT_BIG_WORD 74
+#define VI_NEXT_CHAR 75
+#define VI_NEXT_WORD 76
+#define VI_PASTE_NEXT 77
+#define VI_PASTE_PREV 78
+#define VI_PREV_BIG_WORD 79
+#define VI_PREV_CHAR 80
+#define VI_PREV_WORD 81
+#define VI_REDO 82
+#define VI_REPEAT_NEXT_CHAR 83
+#define VI_REPEAT_PREV_CHAR 84
+#define VI_REPEAT_SEARCH_NEXT 85
+#define VI_REPEAT_SEARCH_PREV 86
+#define VI_REPLACE_CHAR 87
+#define VI_REPLACE_MODE 88
+#define VI_SEARCH_NEXT 89
+#define VI_SEARCH_PREV 90
+#define VI_SUBSTITUTE_CHAR 91
+#define VI_SUBSTITUTE_LINE 92
+#define VI_TO_COLUMN 93
+#define VI_TO_HISTORY_LINE 94
+#define VI_TO_NEXT_CHAR 95
+#define VI_TO_PREV_CHAR 96
+#define VI_UNDO 97
+#define VI_UNDO_LINE 98
+#define VI_YANK 99
+#define VI_YANK_END 100
+#define VI_ZERO 101
+#define EL_NUM_FCNS 102
+typedef el_action_t (*el_func_t)(EditLine *, Int);
+protected const el_func_t* func__get(void);
+#endif /* _h_fcns_c */
diff --git a/lib/libedit/filecomplete.c b/lib/libedit/filecomplete.c
new file mode 100644
index 00000000000..46a503b47f2
--- /dev/null
+++ b/lib/libedit/filecomplete.c
@@ -0,0 +1,548 @@
+/* $OpenBSD: filecomplete.c,v 1.1 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: filecomplete.c,v 1.18 2010/01/18 19:17:42 christos Exp $ */
+
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jaromir Dolecek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <string.h>
+#include <pwd.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
+#include <fcntl.h>
+#ifdef HAVE_VIS_H
+#include <vis.h>
+#else
+#include "np/vis.h"
+#endif
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#endif
+#include "el.h"
+#include "fcns.h" /* for EL_NUM_FCNS */
+#include "histedit.h"
+#include "filecomplete.h"
+
+static Char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@',
+ '$', '>', '<', '=', ';', '|', '&', '{', '(', '\0' };
+
+
+/********************************/
+/* completion functions */
+
+/*
+ * does tilde expansion of strings of type ``~user/foo''
+ * if ``user'' isn't valid user name or ``txt'' doesn't start
+ * w/ '~', returns pointer to strdup()ed copy of ``txt''
+ *
+ * it's callers's responsibility to free() returned string
+ */
+char *
+fn_tilde_expand(const char *txt)
+{
+ struct passwd pwres, *pass;
+ char *temp;
+ size_t tempsz, len = 0;
+ char pwbuf[1024];
+
+ if (txt[0] != '~')
+ return (strdup(txt));
+
+ temp = strchr(txt + 1, '/');
+ if (temp == NULL) {
+ temp = strdup(txt + 1);
+ if (temp == NULL)
+ return NULL;
+ } else {
+ len = temp - txt + 1; /* text until string after slash */
+ temp = malloc(len);
+ if (temp == NULL)
+ return NULL;
+ (void)strncpy(temp, txt + 1, len - 2);
+ temp[len - 2] = '\0';
+ }
+ if (temp[0] == 0) {
+ if (getpwuid_r(getuid(), &pwres, pwbuf, sizeof(pwbuf), &pass) != 0)
+ pass = NULL;
+ } else {
+ if (getpwnam_r(temp, &pwres, pwbuf, sizeof(pwbuf), &pass) != 0)
+ pass = NULL;
+ }
+ free(temp); /* value no more needed */
+ if (pass == NULL)
+ return (strdup(txt));
+
+ /* update pointer txt to point at string immedially following */
+ /* first slash */
+ txt += len;
+
+ tempsz = strlen(pass->pw_dir) + 1 + strlen(txt) + 1;
+ temp = malloc(tempsz);
+ if (temp == NULL)
+ return NULL;
+ (void)snprintf(temp, tempsz, "%s/%s", pass->pw_dir, txt);
+
+ return (temp);
+}
+
+
+/*
+ * return first found file name starting by the ``text'' or NULL if no
+ * such file can be found
+ * value of ``state'' is ignored
+ *
+ * it's caller's responsibility to free returned string
+ */
+char *
+fn_filename_completion_function(const char *text, int state)
+{
+ static DIR *dir = NULL;
+ static char *filename = NULL, *dirname = NULL, *dirpath = NULL;
+ static size_t filename_len = 0;
+ struct dirent *entry;
+ char *temp;
+ size_t tempsz, len;
+
+ if (state == 0 || dir == NULL) {
+ temp = strrchr(text, '/');
+ if (temp) {
+ size_t sz = strlen(temp + 1) + 1;
+ char *nptr;
+ temp++;
+ nptr = realloc(filename, sz);
+ if (nptr == NULL) {
+ free(filename);
+ return NULL;
+ }
+ filename = nptr;
+ (void)strlcpy(filename, temp, sz);
+ len = temp - text; /* including last slash */
+ nptr = realloc(dirname, len + 1);
+ if (nptr == NULL) {
+ free(filename);
+ return NULL;
+ }
+ dirname = nptr;
+ (void)strncpy(dirname, text, len);
+ dirname[len] = '\0';
+ } else {
+ if (*text == 0)
+ filename = NULL;
+ else {
+ filename = strdup(text);
+ if (filename == NULL)
+ return NULL;
+ }
+ dirname = NULL;
+ }
+
+ if (dir != NULL) {
+ (void)closedir(dir);
+ dir = NULL;
+ }
+
+ /* support for ``~user'' syntax */
+ free(dirpath);
+
+ if (dirname == NULL && (dirname = strdup("./")) == NULL)
+ return NULL;
+
+ if (*dirname == '~')
+ dirpath = fn_tilde_expand(dirname);
+ else
+ dirpath = strdup(dirname);
+
+ if (dirpath == NULL)
+ return NULL;
+
+ dir = opendir(dirpath);
+ if (!dir)
+ return (NULL); /* cannot open the directory */
+
+ /* will be used in cycle */
+ filename_len = filename ? strlen(filename) : 0;
+ }
+
+ /* find the match */
+ while ((entry = readdir(dir)) != NULL) {
+ /* skip . and .. */
+ if (entry->d_name[0] == '.' && (!entry->d_name[1]
+ || (entry->d_name[1] == '.' && !entry->d_name[2])))
+ continue;
+ if (filename_len == 0)
+ break;
+ /* otherwise, get first entry where first */
+ /* filename_len characters are equal */
+ if (entry->d_name[0] == filename[0]
+#if HAVE_STRUCT_DIRENT_D_NAMLEN
+ && entry->d_namlen >= filename_len
+#else
+ && strlen(entry->d_name) >= filename_len
+#endif
+ && strncmp(entry->d_name, filename,
+ filename_len) == 0)
+ break;
+ }
+
+ if (entry) { /* match found */
+
+#if HAVE_STRUCT_DIRENT_D_NAMLEN
+ len = entry->d_namlen;
+#else
+ len = strlen(entry->d_name);
+#endif
+
+ tempsz = strlen(dirname) + len + 1;
+ temp = malloc(tempsz);
+ if (temp == NULL)
+ return NULL;
+ (void)snprintf(temp, tempsz, "%s%s", dirname, entry->d_name);
+ } else {
+ (void)closedir(dir);
+ dir = NULL;
+ temp = NULL;
+ }
+
+ return (temp);
+}
+
+
+static const char *
+append_char_function(const char *name)
+{
+ struct stat stbuf;
+ char *expname = *name == '~' ? fn_tilde_expand(name) : NULL;
+ const char *rs = " ";
+
+ if (stat(expname ? expname : name, &stbuf) == -1)
+ goto out;
+ if (S_ISDIR(stbuf.st_mode))
+ rs = "/";
+out:
+ if (expname)
+ free(expname);
+ return rs;
+}
+/*
+ * returns list of completions for text given
+ * non-static for readline.
+ */
+char ** completion_matches(const char *, char *(*)(const char *, int));
+char **
+completion_matches(const char *text, char *(*genfunc)(const char *, int))
+{
+ char **match_list = NULL, *retstr, *prevstr;
+ size_t match_list_len, max_equal, which, i;
+ size_t matches;
+
+ matches = 0;
+ match_list_len = 1;
+ while ((retstr = (*genfunc) (text, (int)matches)) != NULL) {
+ /* allow for list terminator here */
+ if (matches + 3 >= match_list_len) {
+ char **nmatch_list;
+ while (matches + 3 >= match_list_len)
+ match_list_len <<= 1;
+ nmatch_list = realloc(match_list,
+ match_list_len * sizeof(char *));
+ if (nmatch_list == NULL) {
+ free(match_list);
+ return NULL;
+ }
+ match_list = nmatch_list;
+
+ }
+ match_list[++matches] = retstr;
+ }
+
+ if (!match_list)
+ return NULL; /* nothing found */
+
+ /* find least denominator and insert it to match_list[0] */
+ which = 2;
+ prevstr = match_list[1];
+ max_equal = strlen(prevstr);
+ for (; which <= matches; which++) {
+ for (i = 0; i < max_equal &&
+ prevstr[i] == match_list[which][i]; i++)
+ continue;
+ max_equal = i;
+ }
+
+ retstr = malloc(max_equal + 1);
+ if (retstr == NULL) {
+ free(match_list);
+ return NULL;
+ }
+ (void)strncpy(retstr, match_list[1], max_equal);
+ retstr[max_equal] = '\0';
+ match_list[0] = retstr;
+
+ /* add NULL as last pointer to the array */
+ match_list[matches + 1] = (char *) NULL;
+
+ return (match_list);
+}
+
+/*
+ * Sort function for qsort(). Just wrapper around strcasecmp().
+ */
+static int
+_fn_qsort_string_compare(const void *i1, const void *i2)
+{
+ const char *s1 = ((const char * const *)i1)[0];
+ const char *s2 = ((const char * const *)i2)[0];
+
+ return strcasecmp(s1, s2);
+}
+
+/*
+ * Display list of strings in columnar format on readline's output stream.
+ * 'matches' is list of strings, 'len' is number of strings in 'matches',
+ * 'max' is maximum length of string in 'matches'.
+ */
+void
+fn_display_match_list (EditLine *el, char **matches, size_t len, size_t max)
+{
+ size_t i, idx, limit, count;
+ int screenwidth = el->el_term.t_size.h;
+
+ /*
+ * Find out how many entries can be put on one line, count
+ * with two spaces between strings.
+ */
+ limit = screenwidth / (max + 2);
+ if (limit == 0)
+ limit = 1;
+
+ /* how many lines of output */
+ count = len / limit;
+ if (count * limit < len)
+ count++;
+
+ /* Sort the items if they are not already sorted. */
+ qsort(&matches[1], (size_t)(len - 1), sizeof(char *),
+ _fn_qsort_string_compare);
+
+ idx = 1;
+ for(; count > 0; count--) {
+ int more = limit > 0 && matches[0];
+ for(i = 0; more; i++, idx++) {
+ more = ++i < limit && matches[idx + 1];
+ (void)fprintf(el->el_outfile, "%-*s%s", (int)max,
+ matches[idx], more ? " " : "");
+ }
+ (void)fprintf(el->el_outfile, "\n");
+ }
+}
+
+/*
+ * Complete the word at or before point,
+ * 'what_to_do' says what to do with the completion.
+ * \t means do standard completion.
+ * `?' means list the possible completions.
+ * `*' means insert all of the possible completions.
+ * `!' means to do standard completion, and list all possible completions if
+ * there is more than one.
+ *
+ * Note: '*' support is not implemented
+ * '!' could never be invoked
+ */
+int
+fn_complete(EditLine *el,
+ char *(*complet_func)(const char *, int),
+ char **(*attempted_completion_function)(const char *, int, int),
+ const Char *word_break, const Char *special_prefixes,
+ const char *(*app_func)(const char *), size_t query_items,
+ int *completion_type, int *over, int *point, int *end)
+{
+ const TYPE(LineInfo) *li;
+ Char *temp;
+ char **matches;
+ const Char *ctemp;
+ size_t len;
+ int what_to_do = '\t';
+ int retval = CC_NORM;
+
+ if (el->el_state.lastcmd == el->el_state.thiscmd)
+ what_to_do = '?';
+
+ /* readline's rl_complete() has to be told what we did... */
+ if (completion_type != NULL)
+ *completion_type = what_to_do;
+
+ if (!complet_func)
+ complet_func = fn_filename_completion_function;
+ if (!app_func)
+ app_func = append_char_function;
+
+ /* We now look backwards for the start of a filename/variable word */
+ li = FUN(el,line)(el);
+ ctemp = li->cursor;
+ while (ctemp > li->buffer
+ && !Strchr(word_break, ctemp[-1])
+ && (!special_prefixes || !Strchr(special_prefixes, ctemp[-1]) ) )
+ ctemp--;
+
+ len = li->cursor - ctemp;
+#if defined(__SSP__) || defined(__SSP_ALL__)
+ temp = malloc(sizeof(*temp) * (len + 1));
+#else
+ temp = alloca(sizeof(*temp) * (len + 1));
+#endif
+ (void)Strncpy(temp, ctemp, len);
+ temp[len] = '\0';
+
+ /* these can be used by function called in completion_matches() */
+ /* or (*attempted_completion_function)() */
+ if (point != 0)
+ *point = (int)(li->cursor - li->buffer);
+ if (end != NULL)
+ *end = (int)(li->lastchar - li->buffer);
+
+ if (attempted_completion_function) {
+ int cur_off = (int)(li->cursor - li->buffer);
+ matches = (*attempted_completion_function) (ct_encode_string(temp, &el->el_scratch),
+ (int)(cur_off - len), cur_off);
+ } else
+ matches = 0;
+ if (!attempted_completion_function ||
+ (over != NULL && !*over && !matches))
+ matches = completion_matches(ct_encode_string(temp, &el->el_scratch), complet_func);
+
+ if (over != NULL)
+ *over = 0;
+
+ if (matches) {
+ int i;
+ size_t matches_num, maxlen, match_len, match_display=1;
+
+ retval = CC_REFRESH;
+ /*
+ * Only replace the completed string with common part of
+ * possible matches if there is possible completion.
+ */
+ if (matches[0][0] != '\0') {
+ el_deletestr(el, (int) len);
+ FUN(el,insertstr)(el,
+ ct_decode_string(matches[0], &el->el_scratch));
+ }
+
+ if (what_to_do == '?')
+ goto display_matches;
+
+ if (matches[2] == NULL && strcmp(matches[0], matches[1]) == 0) {
+ /*
+ * We found exact match. Add a space after
+ * it, unless we do filename completion and the
+ * object is a directory.
+ */
+ FUN(el,insertstr)(el,
+ ct_decode_string((*app_func)(matches[0]),
+ &el->el_scratch));
+ } else if (what_to_do == '!') {
+ display_matches:
+ /*
+ * More than one match and requested to list possible
+ * matches.
+ */
+
+ for(i = 1, maxlen = 0; matches[i]; i++) {
+ match_len = strlen(matches[i]);
+ if (match_len > maxlen)
+ maxlen = match_len;
+ }
+ matches_num = i - 1;
+
+ /* newline to get on next line from command line */
+ (void)fprintf(el->el_outfile, "\n");
+
+ /*
+ * If there are too many items, ask user for display
+ * confirmation.
+ */
+ if (matches_num > query_items) {
+ (void)fprintf(el->el_outfile,
+ "Display all %zu possibilities? (y or n) ",
+ matches_num);
+ (void)fflush(el->el_outfile);
+ if (getc(stdin) != 'y')
+ match_display = 0;
+ (void)fprintf(el->el_outfile, "\n");
+ }
+
+ if (match_display)
+ fn_display_match_list(el, matches, matches_num,
+ maxlen);
+ retval = CC_REDISPLAY;
+ } else if (matches[0][0]) {
+ /*
+ * There was some common match, but the name was
+ * not complete enough. Next tab will print possible
+ * completions.
+ */
+ el_beep(el);
+ } else {
+ /* lcd is not a valid object - further specification */
+ /* is needed */
+ el_beep(el);
+ retval = CC_NORM;
+ }
+
+ /* free elements of array and the array itself */
+ for (i = 0; matches[i]; i++)
+ free(matches[i]);
+ free(matches);
+ matches = NULL;
+ }
+#if defined(__SSP__) || defined(__SSP_ALL__)
+ free(temp);
+#endif
+ return retval;
+}
+
+/*
+ * el-compatible wrapper around rl_complete; needed for key binding
+ */
+/* ARGSUSED */
+unsigned char
+_el_fn_complete(EditLine *el, int ch __attribute__((__unused__)))
+{
+ return (unsigned char)fn_complete(el, NULL, NULL,
+ break_chars, NULL, NULL, 100,
+ NULL, NULL, NULL, NULL);
+}
diff --git a/lib/libedit/filecomplete.h b/lib/libedit/filecomplete.h
new file mode 100644
index 00000000000..3830244eb76
--- /dev/null
+++ b/lib/libedit/filecomplete.h
@@ -0,0 +1,45 @@
+/* $OpenBSD: filecomplete.h,v 1.1 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: filecomplete.h,v 1.9 2009/12/30 22:37:40 christos Exp $ */
+
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jaromir Dolecek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _FILECOMPLETE_H_
+#define _FILECOMPLETE_H_
+
+int fn_complete(EditLine *,
+ char *(*)(const char *, int),
+ char **(*)(const char *, int, int),
+ const Char *, const Char *, const char *(*)(const char *), size_t,
+ int *, int *, int *, int *);
+
+void fn_display_match_list(EditLine *, char **, size_t, size_t);
+char *fn_tilde_expand(const char *);
+char *fn_filename_completion_function(const char *, int);
+
+#endif
diff --git a/lib/libedit/help.c b/lib/libedit/help.c
new file mode 100644
index 00000000000..4a2248eb904
--- /dev/null
+++ b/lib/libedit/help.c
@@ -0,0 +1,212 @@
+/* Automatically generated file, do not edit */
+#include "config.h"
+#include "el.h"
+#include "chartype.h"
+private const struct el_bindings_t el_func_help[] = {
+ { STR("vi-paste-next"), VI_PASTE_NEXT,
+ STR("Vi paste previous deletion to the right of the cursor") },
+ { STR("vi-paste-prev"), VI_PASTE_PREV,
+ STR("Vi paste previous deletion to the left of the cursor") },
+ { STR("vi-prev-big-word"), VI_PREV_BIG_WORD,
+ STR("Vi move to the previous space delimited word") },
+ { STR("vi-prev-word"), VI_PREV_WORD,
+ STR("Vi move to the previous word") },
+ { STR("vi-next-big-word"), VI_NEXT_BIG_WORD,
+ STR("Vi move to the next space delimited word") },
+ { STR("vi-next-word"), VI_NEXT_WORD,
+ STR("Vi move to the next word") },
+ { STR("vi-change-case"), VI_CHANGE_CASE,
+ STR("Vi change case of character under the cursor and advance one character") },
+ { STR("vi-change-meta"), VI_CHANGE_META,
+ STR("Vi change prefix command") },
+ { STR("vi-insert-at-bol"), VI_INSERT_AT_BOL,
+ STR("Vi enter insert mode at the beginning of line") },
+ { STR("vi-replace-char"), VI_REPLACE_CHAR,
+ STR("Vi replace character under the cursor with the next character typed") },
+ { STR("vi-replace-mode"), VI_REPLACE_MODE,
+ STR("Vi enter replace mode") },
+ { STR("vi-substitute-char"), VI_SUBSTITUTE_CHAR,
+ STR("Vi replace character under the cursor and enter insert mode") },
+ { STR("vi-substitute-line"), VI_SUBSTITUTE_LINE,
+ STR("Vi substitute entire line") },
+ { STR("vi-change-to-eol"), VI_CHANGE_TO_EOL,
+ STR("Vi change to end of line") },
+ { STR("vi-insert"), VI_INSERT,
+ STR("Vi enter insert mode") },
+ { STR("vi-add"), VI_ADD,
+ STR("Vi enter insert mode after the cursor") },
+ { STR("vi-add-at-eol"), VI_ADD_AT_EOL,
+ STR("Vi enter insert mode at end of line") },
+ { STR("vi-delete-meta"), VI_DELETE_META,
+ STR("Vi delete prefix command") },
+ { STR("vi-end-big-word"), VI_END_BIG_WORD,
+ STR("Vi move to the end of the current space delimited word") },
+ { STR("vi-end-word"), VI_END_WORD,
+ STR("Vi move to the end of the current word") },
+ { STR("vi-undo"), VI_UNDO,
+ STR("Vi undo last change") },
+ { STR("vi-command-mode"), VI_COMMAND_MODE,
+ STR("Vi enter command mode (use alternative key bindings)") },
+ { STR("vi-zero"), VI_ZERO,
+ STR("Vi move to the beginning of line") },
+ { STR("vi-delete-prev-char"), VI_DELETE_PREV_CHAR,
+ STR("Vi move to previous character (backspace)") },
+ { STR("vi-list-or-eof"), VI_LIST_OR_EOF,
+ STR("Vi list choices for completion or indicate end of file if empty line") },
+ { STR("vi-kill-line-prev"), VI_KILL_LINE_PREV,
+ STR("Vi cut from beginning of line to cursor") },
+ { STR("vi-search-prev"), VI_SEARCH_PREV,
+ STR("Vi search history previous") },
+ { STR("vi-search-next"), VI_SEARCH_NEXT,
+ STR("Vi search history next") },
+ { STR("vi-repeat-search-next"), VI_REPEAT_SEARCH_NEXT,
+ STR("Vi repeat current search in the same search direction") },
+ { STR("vi-repeat-search-prev"), VI_REPEAT_SEARCH_PREV,
+ STR("Vi repeat current search in the opposite search direction") },
+ { STR("vi-next-char"), VI_NEXT_CHAR,
+ STR("Vi move to the character specified next") },
+ { STR("vi-prev-char"), VI_PREV_CHAR,
+ STR("Vi move to the character specified previous") },
+ { STR("vi-to-next-char"), VI_TO_NEXT_CHAR,
+ STR("Vi move up to the character specified next") },
+ { STR("vi-to-prev-char"), VI_TO_PREV_CHAR,
+ STR("Vi move up to the character specified previous") },
+ { STR("vi-repeat-next-char"), VI_REPEAT_NEXT_CHAR,
+ STR("Vi repeat current character search in the same search direction") },
+ { STR("vi-repeat-prev-char"), VI_REPEAT_PREV_CHAR,
+ STR("Vi repeat current character search in the opposite search direction") },
+ { STR("vi-match"), VI_MATCH,
+ STR("Vi go to matching () {} or []") },
+ { STR("vi-undo-line"), VI_UNDO_LINE,
+ STR("Vi undo all changes to line") },
+ { STR("vi-to-column"), VI_TO_COLUMN,
+ STR("Vi go to specified column") },
+ { STR("vi-yank-end"), VI_YANK_END,
+ STR("Vi yank to end of line") },
+ { STR("vi-yank"), VI_YANK,
+ STR("Vi yank") },
+ { STR("vi-comment-out"), VI_COMMENT_OUT,
+ STR("Vi comment out current command") },
+ { STR("vi-alias"), VI_ALIAS,
+ STR("Vi include shell alias") },
+ { STR("vi-to-history-line"), VI_TO_HISTORY_LINE,
+ STR("Vi go to specified history file line.") },
+ { STR("vi-histedit"), VI_HISTEDIT,
+ STR("Vi edit history line with vi") },
+ { STR("vi-history-word"), VI_HISTORY_WORD,
+ STR("Vi append word from previous input line") },
+ { STR("vi-redo"), VI_REDO,
+ STR("Vi redo last non-motion command") },
+ { STR("em-delete-or-list"), EM_DELETE_OR_LIST,
+ STR("Delete character under cursor or list completions if at end of line") },
+ { STR("em-delete-next-word"), EM_DELETE_NEXT_WORD,
+ STR("Cut from cursor to end of current word") },
+ { STR("em-yank"), EM_YANK,
+ STR("Paste cut buffer at cursor position") },
+ { STR("em-kill-line"), EM_KILL_LINE,
+ STR("Cut the entire line and save in cut buffer") },
+ { STR("em-kill-region"), EM_KILL_REGION,
+ STR("Cut area between mark and cursor and save in cut buffer") },
+ { STR("em-copy-region"), EM_COPY_REGION,
+ STR("Copy area between mark and cursor to cut buffer") },
+ { STR("em-gosmacs-transpose"), EM_GOSMACS_TRANSPOSE,
+ STR("Exchange the two characters before the cursor") },
+ { STR("em-next-word"), EM_NEXT_WORD,
+ STR("Move next to end of current word") },
+ { STR("em-upper-case"), EM_UPPER_CASE,
+ STR("Uppercase the characters from cursor to end of current word") },
+ { STR("em-capitol-case"), EM_CAPITOL_CASE,
+ STR("Capitalize the characters from cursor to end of current word") },
+ { STR("em-lower-case"), EM_LOWER_CASE,
+ STR("Lowercase the characters from cursor to end of current word") },
+ { STR("em-set-mark"), EM_SET_MARK,
+ STR("Set the mark at cursor") },
+ { STR("em-exchange-mark"), EM_EXCHANGE_MARK,
+ STR("Exchange the cursor and mark") },
+ { STR("em-universal-argument"), EM_UNIVERSAL_ARGUMENT,
+ STR("Universal argument (argument times 4)") },
+ { STR("em-meta-next"), EM_META_NEXT,
+ STR("Add 8th bit to next character typed") },
+ { STR("em-toggle-overwrite"), EM_TOGGLE_OVERWRITE,
+ STR("Switch from insert to overwrite mode or vice versa") },
+ { STR("em-copy-prev-word"), EM_COPY_PREV_WORD,
+ STR("Copy current word to cursor") },
+ { STR("em-inc-search-next"), EM_INC_SEARCH_NEXT,
+ STR("Emacs incremental next search") },
+ { STR("em-inc-search-prev"), EM_INC_SEARCH_PREV,
+ STR("Emacs incremental reverse search") },
+ { STR("em-delete-prev-char"), EM_DELETE_PREV_CHAR,
+ STR("Delete the character to the left of the cursor") },
+ { STR("ed-end-of-file"), ED_END_OF_FILE,
+ STR("Indicate end of file") },
+ { STR("ed-insert"), ED_INSERT,
+ STR("Add character to the line") },
+ { STR("ed-delete-prev-word"), ED_DELETE_PREV_WORD,
+ STR("Delete from beginning of current word to cursor") },
+ { STR("ed-delete-next-char"), ED_DELETE_NEXT_CHAR,
+ STR("Delete character under cursor") },
+ { STR("ed-kill-line"), ED_KILL_LINE,
+ STR("Cut to the end of line") },
+ { STR("ed-move-to-end"), ED_MOVE_TO_END,
+ STR("Move cursor to the end of line") },
+ { STR("ed-move-to-beg"), ED_MOVE_TO_BEG,
+ STR("Move cursor to the beginning of line") },
+ { STR("ed-transpose-chars"), ED_TRANSPOSE_CHARS,
+ STR("Exchange the character to the left of the cursor with the one under it") },
+ { STR("ed-next-char"), ED_NEXT_CHAR,
+ STR("Move to the right one character") },
+ { STR("ed-prev-word"), ED_PREV_WORD,
+ STR("Move to the beginning of the current word") },
+ { STR("ed-prev-char"), ED_PREV_CHAR,
+ STR("Move to the left one character") },
+ { STR("ed-quoted-insert"), ED_QUOTED_INSERT,
+ STR("Add the next character typed verbatim") },
+ { STR("ed-digit"), ED_DIGIT,
+ STR("Adds to argument or enters a digit") },
+ { STR("ed-argument-digit"), ED_ARGUMENT_DIGIT,
+ STR("Digit that starts argument") },
+ { STR("ed-unassigned"), ED_UNASSIGNED,
+ STR("Indicates unbound character") },
+ { STR("ed-tty-sigint"), ED_TTY_SIGINT,
+ STR("Tty interrupt character") },
+ { STR("ed-tty-dsusp"), ED_TTY_DSUSP,
+ STR("Tty delayed suspend character") },
+ { STR("ed-tty-flush-output"), ED_TTY_FLUSH_OUTPUT,
+ STR("Tty flush output characters") },
+ { STR("ed-tty-sigquit"), ED_TTY_SIGQUIT,
+ STR("Tty quit character") },
+ { STR("ed-tty-sigtstp"), ED_TTY_SIGTSTP,
+ STR("Tty suspend character") },
+ { STR("ed-tty-stop-output"), ED_TTY_STOP_OUTPUT,
+ STR("Tty disallow output characters") },
+ { STR("ed-tty-start-output"), ED_TTY_START_OUTPUT,
+ STR("Tty allow output characters") },
+ { STR("ed-newline"), ED_NEWLINE,
+ STR("Execute command") },
+ { STR("ed-delete-prev-char"), ED_DELETE_PREV_CHAR,
+ STR("Delete the character to the left of the cursor") },
+ { STR("ed-clear-screen"), ED_CLEAR_SCREEN,
+ STR("Clear screen leaving current line at the top") },
+ { STR("ed-redisplay"), ED_REDISPLAY,
+ STR("Redisplay everything") },
+ { STR("ed-start-over"), ED_START_OVER,
+ STR("Erase current line and start from scratch") },
+ { STR("ed-sequence-lead-in"), ED_SEQUENCE_LEAD_IN,
+ STR("First character in a bound sequence") },
+ { STR("ed-prev-history"), ED_PREV_HISTORY,
+ STR("Move to the previous history line") },
+ { STR("ed-next-history"), ED_NEXT_HISTORY,
+ STR("Move to the next history line") },
+ { STR("ed-search-prev-history"), ED_SEARCH_PREV_HISTORY,
+ STR("Search previous in history for a line matching the current") },
+ { STR("ed-search-next-history"), ED_SEARCH_NEXT_HISTORY,
+ STR("Search next in history for a line matching the current") },
+ { STR("ed-prev-line"), ED_PREV_LINE,
+ STR("Move up one line") },
+ { STR("ed-next-line"), ED_NEXT_LINE,
+ STR("Move down one line") },
+ { STR("ed-command"), ED_COMMAND,
+ STR("Editline extended command") },
+};
+
+protected const el_bindings_t* help__get(){ return el_func_help; }
diff --git a/lib/libedit/help.h b/lib/libedit/help.h
new file mode 100644
index 00000000000..a7e89a1af09
--- /dev/null
+++ b/lib/libedit/help.h
@@ -0,0 +1,5 @@
+/* Automatically generated file, do not edit */
+#ifndef _h_help_c
+#define _h_help_c
+protected const el_bindings_t *help__get(void);
+#endif /* _h_help_c */
diff --git a/lib/libedit/hist.c b/lib/libedit/hist.c
index 25d4aeb38e3..7d38be971ae 100644
--- a/lib/libedit/hist.c
+++ b/lib/libedit/hist.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: hist.c,v 1.8 2009/10/27 23:59:28 deraadt Exp $ */
-/* $NetBSD: hist.c,v 1.15 2003/11/01 23:36:39 christos Exp $ */
+/* $OpenBSD: hist.c,v 1.9 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: hist.c,v 1.17 2009/12/30 23:54:52 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -50,7 +50,7 @@ hist_init(EditLine *el)
el->el_history.fun = NULL;
el->el_history.ref = NULL;
- el->el_history.buf = (char *) el_malloc(EL_BUFSIZ);
+ el->el_history.buf = el_malloc(EL_BUFSIZ * sizeof(*el->el_history.buf));
el->el_history.sz = EL_BUFSIZ;
if (el->el_history.buf == NULL)
return (-1);
@@ -91,11 +91,11 @@ hist_set(EditLine *el, hist_fun_t fun, ptr_t ptr)
protected el_action_t
hist_get(EditLine *el)
{
- const char *hp;
+ 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,
+ (void) Strncpy(el->el_line.buffer, el->el_history.buf,
el->el_history.sz);
el->el_line.lastchar = el->el_line.buffer +
(el->el_history.last - el->el_history.buf);
@@ -122,9 +122,10 @@ hist_get(EditLine *el)
el->el_history.eventno = h;
return (CC_ERROR);
}
- (void) strlcpy(el->el_line.buffer, hp,
+ (void) Strncpy(el->el_line.buffer, hp,
(size_t)(el->el_line.limit - el->el_line.buffer));
- el->el_line.lastchar = el->el_line.buffer + strlen(el->el_line.buffer);
+ el->el_line.buffer[el->el_line.limit - el->el_line.buffer - 1] = '\0';
+ el->el_line.lastchar = el->el_line.buffer + Strlen(el->el_line.buffer);
if (el->el_line.lastchar > el->el_line.buffer
&& el->el_line.lastchar[-1] == '\n')
@@ -147,33 +148,33 @@ hist_get(EditLine *el)
* process a history command
*/
protected int
-hist_command(EditLine *el, int argc, const char **argv)
+hist_command(EditLine *el, int argc, const Char **argv)
{
- const char *str;
+ const Char *str;
int num;
HistEvent ev;
if (el->el_history.ref == NULL)
return (-1);
- if (argc == 1 || strcmp(argv[1], "list") == 0) {
+ if (argc == 1 || Strcmp(argv[1], STR("list")) == 0) {
/* List history entries */
for (str = HIST_LAST(el); str != NULL; str = HIST_PREV(el))
(void) fprintf(el->el_outfile, "%d %s",
- el->el_history.ev.num, str);
+ el->el_history.ev.num, ct_encode_string(str, &el->el_scratch));
return (0);
}
if (argc != 3)
return (-1);
- num = (int)strtol(argv[2], NULL, 0);
+ num = (int)Strtol(argv[2], NULL, 0);
- if (strcmp(argv[1], "size") == 0)
+ if (Strcmp(argv[1], STR("size")) == 0)
return history(el->el_history.ref, &ev, H_SETSIZE, num);
- if (strcmp(argv[1], "unique") == 0)
+ if (Strcmp(argv[1], STR("unique")) == 0)
return history(el->el_history.ref, &ev, H_SETUNIQUE, num);
return -1;
@@ -187,13 +188,13 @@ protected int
/*ARGSUSED*/
hist_enlargebuf(EditLine *el, size_t oldsz, size_t newsz)
{
- char *newbuf;
+ Char *newbuf;
- newbuf = realloc(el->el_history.buf, newsz);
+ newbuf = el_realloc(el->el_history.buf, newsz * sizeof(*newbuf));
if (!newbuf)
return 0;
- (void) memset(&newbuf[oldsz], '\0', newsz - oldsz);
+ (void) memset(&newbuf[oldsz], '\0', (newsz - oldsz) * sizeof(*newbuf));
el->el_history.last = newbuf +
(el->el_history.last - el->el_history.buf);
@@ -202,3 +203,15 @@ hist_enlargebuf(EditLine *el, size_t oldsz, size_t newsz)
return 1;
}
+
+#ifdef WIDECHAR
+protected wchar_t *
+hist_convert(EditLine *el, int fn, ptr_t arg)
+{
+ HistEventW ev;
+ if ((*(el)->el_history.fun)((el)->el_history.ref, &ev, fn, arg) == -1)
+ return NULL;
+ return ct_decode_string((const char *)(const void *)ev.str,
+ &el->el_scratch);
+}
+#endif
diff --git a/lib/libedit/hist.h b/lib/libedit/hist.h
index 60c49a9ca59..1f14fd9dec0 100644
--- a/lib/libedit/hist.h
+++ b/lib/libedit/hist.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: hist.h,v 1.7 2003/10/31 08:42:24 otto Exp $ */
-/* $NetBSD: hist.h,v 1.10 2003/08/07 16:44:31 agc Exp $ */
+/* $OpenBSD: hist.h,v 1.8 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: hist.h,v 1.12 2009/12/30 23:54:52 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -43,21 +43,29 @@
#include "histedit.h"
-typedef int (*hist_fun_t)(ptr_t, HistEvent *, int, ...);
+typedef int (*hist_fun_t)(ptr_t, TYPE(HistEvent) *, int, ...);
typedef struct el_history_t {
- char *buf; /* The history buffer */
+ Char *buf; /* The history buffer */
size_t sz; /* Size of history buffer */
- char *last; /* The last character */
+ Char *last; /* The last character */
int eventno; /* Event we are looking for */
ptr_t ref; /* Argument for history fcns */
hist_fun_t fun; /* Event access */
- HistEvent ev; /* Event cookie */
+ TYPE(HistEvent) ev; /* Event cookie */
} el_history_t;
-#define HIST_FUN(el, fn, arg) \
+#define HIST_FUN_INTERNAL(el, fn, arg) \
((((*(el)->el_history.fun) ((el)->el_history.ref, &(el)->el_history.ev, \
fn, arg)) == -1) ? NULL : (el)->el_history.ev.str)
+#ifdef WIDECHAR
+#define HIST_FUN(el, fn, arg) \
+ (((el)->el_flags & NARROW_HISTORY) ? hist_convert(el, fn, arg) : \
+ HIST_FUN_INTERNAL(el, fn, arg))
+#else
+#define HIST_FUN(el, fn, arg) HIST_FUN_INTERNAL(el, fn, arg)
+#endif
+
#define HIST_NEXT(el) HIST_FUN(el, H_NEXT, NULL)
#define HIST_FIRST(el) HIST_FUN(el, H_FIRST, NULL)
@@ -71,7 +79,10 @@ protected int hist_init(EditLine *);
protected void hist_end(EditLine *);
protected el_action_t hist_get(EditLine *);
protected int hist_set(EditLine *, hist_fun_t, ptr_t);
-protected int hist_command(EditLine *, int, const char **);
+protected int hist_command(EditLine *, int, const Char **);
protected int hist_enlargebuf(EditLine *, size_t, size_t);
+#ifdef WIDECHAR
+protected wchar_t *hist_convert(EditLine *, int, ptr_t);
+#endif
#endif /* _h_el_hist */
diff --git a/lib/libedit/histedit.h b/lib/libedit/histedit.h
index 86b372fe284..4dacfdf18df 100644
--- a/lib/libedit/histedit.h
+++ b/lib/libedit/histedit.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: histedit.h,v 1.9 2003/11/25 20:12:38 otto Exp $ */
-/* $NetBSD: histedit.h,v 1.24 2003/10/16 22:26:32 christos Exp $ */
+/* $OpenBSD: histedit.h,v 1.10 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: histedit.h,v 1.46 2010/04/15 00:50:03 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -42,14 +42,21 @@
#define _HISTEDIT_H_
#define LIBEDIT_MAJOR 2
-#define LIBEDIT_MINOR 8
+#define LIBEDIT_MINOR 11
+
+#include <stdint.h>
#include <sys/types.h>
#include <stdio.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/*
* ==== Editing ====
*/
+
typedef struct editline EditLine;
/*
@@ -61,7 +68,6 @@ typedef struct lineinfo {
const char *lastchar;
} LineInfo;
-
/*
* EditLine editor function return codes.
* For user-defined function interface
@@ -81,16 +87,15 @@ typedef struct lineinfo {
* Initialization, cleanup, and resetting
*/
EditLine *el_init(const char *, FILE *, FILE *, FILE *);
-void el_reset(EditLine *);
void el_end(EditLine *);
-
+void el_reset(EditLine *);
/*
* Get a line, a character or push a string back in the input queue
*/
const char *el_gets(EditLine *, int *);
int el_getc(EditLine *, char *);
-void el_push(EditLine *, char *);
+void el_push(EditLine *, const char *);
/*
* Beep!
@@ -107,31 +112,52 @@ int el_parse(EditLine *, int, const char **);
* Low level editline access functions
*/
int el_set(EditLine *, int, ...);
-int el_get(EditLine *, int, void *);
+int el_get(EditLine *, int, ...);
+unsigned char _el_fn_complete(EditLine *, int);
/*
* el_set/el_get parameters
+ *
+ * When using el_wset/el_wget (as opposed to el_set/el_get):
+ * Char is wchar_t, otherwise it is char.
+ * prompt_func is el_wpfunc_t, otherwise it is el_pfunc_t .
+
+ * Prompt function prototypes are:
+ * typedef char *(*el_pfunct_t) (EditLine *);
+ * typedef wchar_t *(*el_wpfunct_t) (EditLine *);
+ *
+ * For operations that support set or set/get, the argument types listed are for
+ * the "set" operation. For "get", each listed type must be a pointer.
+ * E.g. EL_EDITMODE takes an int when set, but an int* when get.
+ *
+ * Operations that only support "get" have the correct argument types listed.
*/
-#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 *); */
-#define EL_EDITMODE 11 /* , int); */
-#define EL_RPROMPT 12 /* , el_pfunc_t); */
-#define EL_GETCFN 13 /* , el_rfunc_t); */
-#define EL_CLIENTDATA 14 /* , void *); */
-#define EL_UNBUFFERED 15 /* , int); */
-#define EL_PREP_TERM 16 /* , int); */
-
-#define EL_BUILTIN_GETCFN (NULL)
+#define EL_PROMPT 0 /* , prompt_func); set/get */
+#define EL_TERMINAL 1 /* , const char *); set/get */
+#define EL_EDITOR 2 /* , const Char *); set/get */
+#define EL_SIGNAL 3 /* , int); set/get */
+#define EL_BIND 4 /* , const Char *, ..., NULL); set */
+#define EL_TELLTC 5 /* , const Char *, ..., NULL); set */
+#define EL_SETTC 6 /* , const Char *, ..., NULL); set */
+#define EL_ECHOTC 7 /* , const Char *, ..., NULL); set */
+#define EL_SETTY 8 /* , const Char *, ..., NULL); set */
+#define EL_ADDFN 9 /* , const Char *, const Char, set */
+ /* el_func_t); */
+#define EL_HIST 10 /* , hist_fun_t, const ptr_t); set */
+#define EL_EDITMODE 11 /* , int); set/get */
+#define EL_RPROMPT 12 /* , prompt_func); set/get */
+#define EL_GETCFN 13 /* , el_rfunc_t); set/get */
+#define EL_CLIENTDATA 14 /* , void *); set/get */
+#define EL_UNBUFFERED 15 /* , int); set/get */
+#define EL_PREP_TERM 16 /* , int); set */
+#define EL_GETTC 17 /* , const Char *, ..., NULL); get */
+#define EL_GETFP 18 /* , int, FILE **); get */
+#define EL_SETFP 19 /* , int, FILE *); set */
+#define EL_REFRESH 20 /* , void); set */
+#define EL_PROMPT_ESC 21 /* , prompt_func, Char); set/get */
+#define EL_RPROMPT_ESC 22 /* , prompt_func, Char); set/get */
+
+#define EL_BUILTIN_GETCFN (NULL)
/*
* Source named file or $PWD/.editrc or $HOME/.editrc
@@ -145,7 +171,6 @@ int el_source(EditLine *, const char *);
*/
void el_resize(EditLine *);
-
/*
* User-defined function interface.
*/
@@ -153,6 +178,7 @@ const LineInfo *el_line(EditLine *);
int el_insertstr(EditLine *, const char *);
void el_deletestr(EditLine *, int);
+
/*
* ==== History ====
*/
@@ -181,12 +207,12 @@ int history(History *, HistEvent *, int, ...);
#define H_NEXT 6 /* , void); */
#define H_CURR 8 /* , const int); */
#define H_SET 7 /* , int); */
-#define H_ADD 9 /* , const char *); */
-#define H_ENTER 10 /* , const char *); */
-#define H_APPEND 11 /* , const char *); */
+#define H_ADD 9 /* , const wchar_t *); */
+#define H_ENTER 10 /* , const wchar_t *); */
+#define H_APPEND 11 /* , const wchar_t *); */
#define H_END 12 /* , void); */
-#define H_NEXT_STR 13 /* , const char *); */
-#define H_PREV_STR 14 /* , const char *); */
+#define H_NEXT_STR 13 /* , const wchar_t *); */
+#define H_PREV_STR 14 /* , const wchar_t *); */
#define H_NEXT_EVENT 15 /* , const int); */
#define H_PREV_EVENT 16 /* , const int); */
#define H_LOAD 17 /* , const char *); */
@@ -194,5 +220,100 @@ int history(History *, HistEvent *, int, ...);
#define H_CLEAR 19 /* , void); */
#define H_SETUNIQUE 20 /* , int); */
#define H_GETUNIQUE 21 /* , void); */
+#define H_DEL 22 /* , int); */
+#define H_NEXT_EVDATA 23 /* , const int, histdata_t *); */
+#define H_DELDATA 24 /* , int, histdata_t *);*/
+#define H_REPLACE 25 /* , const char *, histdata_t); */
+
+
+
+/*
+ * ==== Tokenization ====
+ */
+
+typedef struct tokenizer Tokenizer;
+
+/*
+ * String tokenization functions, using simplified sh(1) quoting rules
+ */
+Tokenizer *tok_init(const char *);
+void tok_end(Tokenizer *);
+void tok_reset(Tokenizer *);
+int tok_line(Tokenizer *, const LineInfo *,
+ int *, const char ***, int *, int *);
+int tok_str(Tokenizer *, const char *,
+ int *, const char ***);
+
+/*
+ * Begin Wide Character Support
+ */
+#ifdef __linux__
+/* Apparently we need _GNU_SOURCE defined to get access to wcsdup on Linux */
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#endif
+
+#include <wchar.h>
+#include <wctype.h>
+
+/*
+ * Wide character versions
+ */
+
+/*
+ * ==== Editing ====
+ */
+typedef struct lineinfow {
+ const wchar_t *buffer;
+ const wchar_t *cursor;
+ const wchar_t *lastchar;
+} LineInfoW;
+
+const wchar_t *el_wgets(EditLine *, int *);
+int el_wgetc(EditLine *, wchar_t *);
+void el_wpush(EditLine *, const wchar_t *);
+
+int el_wparse(EditLine *, int, const wchar_t **);
+
+int el_wset(EditLine *, int, ...);
+int el_wget(EditLine *, int, ...);
+
+const LineInfoW *el_wline(EditLine *);
+int el_winsertstr(EditLine *, const wchar_t *);
+#define el_wdeletestr el_deletestr
+
+/*
+ * ==== History ====
+ */
+typedef struct histeventW {
+ int num;
+ const wchar_t *str;
+} HistEventW;
+
+typedef struct historyW HistoryW;
+
+HistoryW * history_winit(void);
+void history_wend(HistoryW *);
+
+int history_w(HistoryW *, HistEventW *, int, ...);
+
+/*
+ * ==== Tokenization ====
+ */
+typedef struct tokenizerW TokenizerW;
+
+/* Wide character tokenizer support */
+TokenizerW *tok_winit(const wchar_t *);
+void tok_wend(TokenizerW *);
+void tok_wreset(TokenizerW *);
+int tok_wline(TokenizerW *, const LineInfoW *,
+ int *, const wchar_t ***, int *, int *);
+int tok_wstr(TokenizerW *, const wchar_t *,
+ int *, const wchar_t ***);
+
+#ifdef __cplusplus
+}
+#endif
#endif /* _HISTEDIT_H_ */
diff --git a/lib/libedit/history.c b/lib/libedit/history.c
index c72f0eab0d6..06295af835c 100644
--- a/lib/libedit/history.c
+++ b/lib/libedit/history.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: history.c,v 1.14 2009/10/27 23:59:28 deraadt Exp $ */
-/* $NetBSD: history.c,v 1.25 2003/10/18 23:48:42 christos Exp $ */
+/* $OpenBSD: history.c,v 1.15 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: history.c,v 1.37 2010/01/03 18:27:10 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -36,7 +36,7 @@
#include "config.h"
/*
- * hist.c: History access functions
+ * hist.c: TYPE(History) access functions
*/
#include <string.h>
#include <stdlib.h>
@@ -51,13 +51,14 @@
static const char hist_cookie[] = "_HiStOrY_V2_\n";
#include "histedit.h"
+#include "chartype.h"
-typedef int (*history_gfun_t)(ptr_t, HistEvent *);
-typedef int (*history_efun_t)(ptr_t, HistEvent *, const char *);
-typedef void (*history_vfun_t)(ptr_t, HistEvent *);
-typedef int (*history_sfun_t)(ptr_t, HistEvent *, const int);
+typedef int (*history_gfun_t)(ptr_t, TYPE(HistEvent) *);
+typedef int (*history_efun_t)(ptr_t, TYPE(HistEvent) *, const Char *);
+typedef void (*history_vfun_t)(ptr_t, TYPE(HistEvent) *);
+typedef int (*history_sfun_t)(ptr_t, TYPE(HistEvent) *, const int);
-struct history {
+struct TYPE(history) {
ptr_t h_ref; /* Argument for history fcns */
int h_ent; /* Last entry point for history */
history_gfun_t h_first; /* Get the first element */
@@ -66,6 +67,7 @@ struct history {
history_gfun_t h_prev; /* Get the previous element */
history_gfun_t h_curr; /* Get the current element */
history_sfun_t h_set; /* Set the current element */
+ history_sfun_t h_del; /* Set the given element */
history_vfun_t h_clear; /* Clear the history list */
history_efun_t h_enter; /* Add an element */
history_efun_t h_add; /* Append to an element */
@@ -80,30 +82,31 @@ struct history {
#define HCLEAR(h, ev) (*(h)->h_clear)((h)->h_ref, ev)
#define HENTER(h, ev, str) (*(h)->h_enter)((h)->h_ref, ev, str)
#define HADD(h, ev, str) (*(h)->h_add)((h)->h_ref, ev, str)
+#define HDEL(h, ev, n) (*(h)->h_del)((h)->h_ref, ev, n)
-#define h_strdup(a) strdup(a)
+#define h_strdup(a) Strdup(a)
#define h_malloc(a) malloc(a)
#define h_realloc(a, b) realloc((a), (b))
#define h_free(a) free(a)
typedef struct {
int num;
- char *str;
+ Char *str;
} HistEventPrivate;
-private int history_setsize(History *, HistEvent *, int);
-private int history_getsize(History *, HistEvent *);
-private int history_setunique(History *, HistEvent *, int);
-private int history_getunique(History *, HistEvent *);
-private int history_set_fun(History *, History *);
-private int history_load(History *, const char *);
-private int history_save(History *, const char *);
-private int history_prev_event(History *, HistEvent *, int);
-private int history_next_event(History *, HistEvent *, int);
-private int history_next_string(History *, HistEvent *, const char *);
-private int history_prev_string(History *, HistEvent *, const char *);
+private int history_setsize(TYPE(History) *, TYPE(HistEvent) *, int);
+private int history_getsize(TYPE(History) *, TYPE(HistEvent) *);
+private int history_setunique(TYPE(History) *, TYPE(HistEvent) *, int);
+private int history_getunique(TYPE(History) *, TYPE(HistEvent) *);
+private int history_set_fun(TYPE(History) *, TYPE(History) *);
+private int history_load(TYPE(History) *, const char *);
+private int history_save(TYPE(History) *, const char *);
+private int history_prev_event(TYPE(History) *, TYPE(HistEvent) *, int);
+private int history_next_event(TYPE(History) *, TYPE(HistEvent) *, int);
+private int history_next_string(TYPE(History) *, TYPE(HistEvent) *, const Char *);
+private int history_prev_string(TYPE(History) *, TYPE(HistEvent) *, const Char *);
/***********************************************************************/
@@ -112,7 +115,8 @@ private int history_prev_string(History *, HistEvent *, const char *);
* Builtin- history implementation
*/
typedef struct hentry_t {
- HistEvent ev; /* What we return */
+ TYPE(HistEvent) ev; /* What we return */
+ void *data; /* data */
struct hentry_t *next; /* Next entry */
struct hentry_t *prev; /* Previous entry */
} hentry_t;
@@ -123,22 +127,27 @@ typedef struct history_t {
int max; /* Maximum number of events */
int cur; /* Current number of events */
int eventid; /* For generation of unique event id */
- int flags; /* History flags */
+ int flags; /* TYPE(History) flags */
#define H_UNIQUE 1 /* Store only unique elements */
} history_t;
-private int history_def_first(ptr_t, HistEvent *);
-private int history_def_last(ptr_t, HistEvent *);
-private int history_def_next(ptr_t, HistEvent *);
-private int history_def_prev(ptr_t, HistEvent *);
-private int history_def_curr(ptr_t, HistEvent *);
-private int history_def_set(ptr_t, HistEvent *, const int n);
-private int history_def_enter(ptr_t, HistEvent *, const char *);
-private int history_def_add(ptr_t, HistEvent *, const char *);
-private int history_def_init(ptr_t *, HistEvent *, int);
-private void history_def_clear(ptr_t, HistEvent *);
-private int history_def_insert(history_t *, HistEvent *, const char *);
-private void history_def_delete(history_t *, HistEvent *, hentry_t *);
+private int history_def_next(ptr_t, TYPE(HistEvent) *);
+private int history_def_first(ptr_t, TYPE(HistEvent) *);
+private int history_def_prev(ptr_t, TYPE(HistEvent) *);
+private int history_def_last(ptr_t, TYPE(HistEvent) *);
+private int history_def_curr(ptr_t, TYPE(HistEvent) *);
+private int history_def_set(ptr_t, TYPE(HistEvent) *, const int);
+private void history_def_clear(ptr_t, TYPE(HistEvent) *);
+private int history_def_enter(ptr_t, TYPE(HistEvent) *, const Char *);
+private int history_def_add(ptr_t, TYPE(HistEvent) *, const Char *);
+private int history_def_del(ptr_t, TYPE(HistEvent) *, const int);
+
+private int history_def_init(ptr_t *, TYPE(HistEvent) *, int);
+private int history_def_insert(history_t *, TYPE(HistEvent) *, const Char *);
+private void history_def_delete(history_t *, TYPE(HistEvent) *, hentry_t *);
+
+private int history_deldata_nth(history_t *, TYPE(HistEvent) *, int, void **);
+private int history_set_nth(ptr_t, TYPE(HistEvent) *, int);
#define history_def_setsize(p, num)(void) (((history_t *)p)->max = (num))
#define history_def_getsize(p) (((history_t *)p)->cur)
@@ -156,23 +165,23 @@ private void history_def_delete(history_t *, HistEvent *, hentry_t *);
}
/* error messages */
-static const char *const he_errlist[] = {
- "OK",
- "unknown error",
- "malloc() failed",
- "first event not found",
- "last event not found",
- "empty list",
- "no next event",
- "no previous event",
- "current event is invalid",
- "event not found",
- "can't read history from file",
- "can't write history",
- "required parameter(s) not supplied",
- "history size negative",
- "function not allowed with other history-functions-set the default",
- "bad parameters"
+static const Char *const he_errlist[] = {
+ STR("OK"),
+ STR("unknown error"),
+ STR("malloc() failed"),
+ STR("first event not found"),
+ STR("last event not found"),
+ STR("empty list"),
+ STR("no next event"),
+ STR("no previous event"),
+ STR("current event is invalid"),
+ STR("event not found"),
+ STR("can't read history from file"),
+ STR("can't write history"),
+ STR("required parameter(s) not supplied"),
+ STR("history size negative"),
+ STR("function not allowed with other history-functions-set the default"),
+ STR("bad parameters")
};
/* error codes */
#define _HE_OK 0
@@ -196,7 +205,7 @@ static const char *const he_errlist[] = {
* Default function to return the first event in the history.
*/
private int
-history_def_first(ptr_t p, HistEvent *ev)
+history_def_first(ptr_t p, TYPE(HistEvent) *ev)
{
history_t *h = (history_t *) p;
@@ -216,7 +225,7 @@ history_def_first(ptr_t p, HistEvent *ev)
* Default function to return the last event in the history.
*/
private int
-history_def_last(ptr_t p, HistEvent *ev)
+history_def_last(ptr_t p, TYPE(HistEvent) *ev)
{
history_t *h = (history_t *) p;
@@ -236,24 +245,23 @@ history_def_last(ptr_t p, HistEvent *ev)
* Default function to return the next event in the history.
*/
private int
-history_def_next(ptr_t p, HistEvent *ev)
+history_def_next(ptr_t p, TYPE(HistEvent) *ev)
{
history_t *h = (history_t *) p;
- if (h->cursor != &h->list)
- h->cursor = h->cursor->next;
- else {
+ if (h->cursor == &h->list) {
he_seterrev(ev, _HE_EMPTY_LIST);
return (-1);
}
- if (h->cursor != &h->list)
- *ev = h->cursor->ev;
- else {
+ if (h->cursor->next == &h->list) {
he_seterrev(ev, _HE_END_REACHED);
return (-1);
}
+ h->cursor = h->cursor->next;
+ *ev = h->cursor->ev;
+
return (0);
}
@@ -262,25 +270,24 @@ history_def_next(ptr_t p, HistEvent *ev)
* Default function to return the previous event in the history.
*/
private int
-history_def_prev(ptr_t p, HistEvent *ev)
+history_def_prev(ptr_t p, TYPE(HistEvent) *ev)
{
history_t *h = (history_t *) p;
- if (h->cursor != &h->list)
- h->cursor = h->cursor->prev;
- else {
+ if (h->cursor == &h->list) {
he_seterrev(ev,
(h->cur > 0) ? _HE_END_REACHED : _HE_EMPTY_LIST);
return (-1);
}
- if (h->cursor != &h->list)
- *ev = h->cursor->ev;
- else {
+ if (h->cursor->prev == &h->list) {
he_seterrev(ev, _HE_START_REACHED);
return (-1);
}
+ h->cursor = h->cursor->prev;
+ *ev = h->cursor->ev;
+
return (0);
}
@@ -289,7 +296,7 @@ history_def_prev(ptr_t p, HistEvent *ev)
* Default function to return the current event in the history.
*/
private int
-history_def_curr(ptr_t p, HistEvent *ev)
+history_def_curr(ptr_t p, TYPE(HistEvent) *ev)
{
history_t *h = (history_t *) p;
@@ -310,7 +317,7 @@ history_def_curr(ptr_t p, HistEvent *ev)
* given one.
*/
private int
-history_def_set(ptr_t p, HistEvent *ev, const int n)
+history_def_set(ptr_t p, TYPE(HistEvent) *ev, const int n)
{
history_t *h = (history_t *) p;
@@ -332,27 +339,53 @@ history_def_set(ptr_t p, HistEvent *ev, const int n)
}
+/* history_set_nth():
+ * Default function to set the current event in the history to the
+ * n-th one.
+ */
+private int
+history_set_nth(ptr_t p, TYPE(HistEvent) *ev, int n)
+{
+ history_t *h = (history_t *) p;
+
+ if (h->cur == 0) {
+ he_seterrev(ev, _HE_EMPTY_LIST);
+ return (-1);
+ }
+ for (h->cursor = h->list.prev; h->cursor != &h->list;
+ h->cursor = h->cursor->prev)
+ if (n-- <= 0)
+ break;
+ if (h->cursor == &h->list) {
+ he_seterrev(ev, _HE_NOT_FOUND);
+ return (-1);
+ }
+ return (0);
+}
+
+
/* history_def_add():
* Append string to element
*/
private int
-history_def_add(ptr_t p, HistEvent *ev, const char *str)
+history_def_add(ptr_t p, TYPE(HistEvent) *ev, const Char *str)
{
history_t *h = (history_t *) p;
size_t len;
- char *s;
+ Char *s;
HistEventPrivate *evp = (void *)&h->cursor->ev;
if (h->cursor == &h->list)
return (history_def_enter(p, ev, str));
- len = strlen(evp->str) + strlen(str) + 1;
- s = (char *) h_malloc(len);
+ len = Strlen(evp->str) + Strlen(str) + 1;
+ s = h_malloc(len * sizeof(*s));
if (s == NULL) {
he_seterrev(ev, _HE_MALLOC_FAILED);
return (-1);
}
- (void) strlcpy(s, h->cursor->ev.str, len);
- (void) strlcat(s, str, len);
+ (void) Strncpy(s, h->cursor->ev.str, len);
+ s[len - 1] = '\0';
+ (void) Strncat(s, str, len - Strlen(s) - 1);
h_free((ptr_t)evp->str);
evp->str = s;
*ev = h->cursor->ev;
@@ -360,17 +393,58 @@ history_def_add(ptr_t p, HistEvent *ev, const char *str)
}
+private int
+history_deldata_nth(history_t *h, TYPE(HistEvent) *ev,
+ int num, void **data)
+{
+ if (history_set_nth(h, ev, num) != 0)
+ return (-1);
+ /* magic value to skip delete (just set to n-th history) */
+ if (data == (void **)-1)
+ return (0);
+ ev->str = Strdup(h->cursor->ev.str);
+ ev->num = h->cursor->ev.num;
+ if (data)
+ *data = h->cursor->data;
+ history_def_delete(h, ev, h->cursor);
+ return (0);
+}
+
+
+/* history_def_del():
+ * Delete element hp of the h list
+ */
+/* ARGSUSED */
+private int
+history_def_del(ptr_t p, TYPE(HistEvent) *ev __attribute__((__unused__)),
+ const int num)
+{
+ history_t *h = (history_t *) p;
+ if (history_def_set(h, ev, num) != 0)
+ return (-1);
+ ev->str = Strdup(h->cursor->ev.str);
+ ev->num = h->cursor->ev.num;
+ history_def_delete(h, ev, h->cursor);
+ return (0);
+}
+
+
/* history_def_delete():
* Delete element hp of the h list
*/
/* ARGSUSED */
private void
history_def_delete(history_t *h,
- HistEvent *ev __attribute__((__unused__)), hentry_t *hp)
+ TYPE(HistEvent) *ev __attribute__((__unused__)), hentry_t *hp)
{
HistEventPrivate *evp = (void *)&hp->ev;
if (hp == &h->list)
abort();
+ if (h->cursor == hp) {
+ h->cursor = hp->prev;
+ if (h->cursor == &h->list)
+ h->cursor = hp->next;
+ }
hp->prev->next = hp->next;
hp->next->prev = hp->prev;
h_free((ptr_t) evp->str);
@@ -383,7 +457,7 @@ history_def_delete(history_t *h,
* Insert element with string str in the h list
*/
private int
-history_def_insert(history_t *h, HistEvent *ev, const char *str)
+history_def_insert(history_t *h, TYPE(HistEvent) *ev, const Char *str)
{
h->cursor = (hentry_t *) h_malloc(sizeof(hentry_t));
@@ -393,6 +467,7 @@ history_def_insert(history_t *h, HistEvent *ev, const char *str)
h_free((ptr_t)h->cursor);
goto oomem;
}
+ h->cursor->data = NULL;
h->cursor->ev.num = ++h->eventid;
h->cursor->next = h->list.next;
h->cursor->prev = &h->list;
@@ -412,12 +487,12 @@ oomem:
* Default function to enter an item in the history
*/
private int
-history_def_enter(ptr_t p, HistEvent *ev, const char *str)
+history_def_enter(ptr_t p, TYPE(HistEvent) *ev, const Char *str)
{
history_t *h = (history_t *) p;
if ((h->flags & H_UNIQUE) != 0 && h->list.next != &h->list &&
- strcmp(h->list.next->ev.str, str) == 0)
+ Strcmp(h->list.next->ev.str, str) == 0)
return (0);
if (history_def_insert(h, ev, str) == -1)
@@ -439,7 +514,7 @@ history_def_enter(ptr_t p, HistEvent *ev, const char *str)
*/
/* ARGSUSED */
private int
-history_def_init(ptr_t *p, HistEvent *ev __attribute__((__unused__)), int n)
+history_def_init(ptr_t *p, TYPE(HistEvent) *ev __attribute__((__unused__)), int n)
{
history_t *h = (history_t *) h_malloc(sizeof(history_t));
if (h == NULL)
@@ -464,7 +539,7 @@ history_def_init(ptr_t *p, HistEvent *ev __attribute__((__unused__)), int n)
* Default history cleanup function
*/
private void
-history_def_clear(ptr_t p, HistEvent *ev)
+history_def_clear(ptr_t p, TYPE(HistEvent) *ev)
{
history_t *h = (history_t *) p;
@@ -482,11 +557,11 @@ history_def_clear(ptr_t p, HistEvent *ev)
/* history_init():
* Initialization function.
*/
-public History *
-history_init(void)
+public TYPE(History) *
+FUN(history,init)(void)
{
- HistEvent ev;
- History *h = (History *) h_malloc(sizeof(History));
+ TYPE(HistEvent) ev;
+ TYPE(History) *h = (TYPE(History) *) h_malloc(sizeof(TYPE(History)));
if (h == NULL)
return NULL;
@@ -504,6 +579,7 @@ history_init(void)
h->h_clear = history_def_clear;
h->h_enter = history_def_enter;
h->h_add = history_def_add;
+ h->h_del = history_def_del;
return (h);
}
@@ -513,12 +589,14 @@ history_init(void)
* clean up history;
*/
public void
-history_end(History *h)
+FUN(history,end)(TYPE(History) *h)
{
- HistEvent ev;
+ TYPE(HistEvent) ev;
if (h->h_next == history_def_next)
history_def_clear(h->h_ref, &ev);
+ h_free(h->h_ref);
+ h_free(h);
}
@@ -527,7 +605,7 @@ history_end(History *h)
* Set history number of events
*/
private int
-history_setsize(History *h, HistEvent *ev, int num)
+history_setsize(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
{
if (h->h_next != history_def_next) {
@@ -547,7 +625,7 @@ history_setsize(History *h, HistEvent *ev, int num)
* Get number of events currently in history
*/
private int
-history_getsize(History *h, HistEvent *ev)
+history_getsize(TYPE(History) *h, TYPE(HistEvent) *ev)
{
if (h->h_next != history_def_next) {
he_seterrev(ev, _HE_NOT_ALLOWED);
@@ -566,7 +644,7 @@ history_getsize(History *h, HistEvent *ev)
* Set if adjacent equal events should not be entered in history.
*/
private int
-history_setunique(History *h, HistEvent *ev, int uni)
+history_setunique(TYPE(History) *h, TYPE(HistEvent) *ev, int uni)
{
if (h->h_next != history_def_next) {
@@ -582,7 +660,7 @@ history_setunique(History *h, HistEvent *ev, int uni)
* Get if adjacent equal events should not be entered in history.
*/
private int
-history_getunique(History *h, HistEvent *ev)
+history_getunique(TYPE(History) *h, TYPE(HistEvent) *ev)
{
if (h->h_next != history_def_next) {
he_seterrev(ev, _HE_NOT_ALLOWED);
@@ -597,14 +675,14 @@ history_getunique(History *h, HistEvent *ev)
* Set history functions
*/
private int
-history_set_fun(History *h, History *nh)
+history_set_fun(TYPE(History) *h, TYPE(History) *nh)
{
- HistEvent ev;
+ TYPE(HistEvent) ev;
if (nh->h_first == NULL || nh->h_next == NULL || nh->h_last == NULL ||
nh->h_prev == NULL || nh->h_curr == NULL || nh->h_set == NULL ||
nh->h_enter == NULL || nh->h_add == NULL || nh->h_clear == NULL ||
- nh->h_ref == NULL) {
+ nh->h_del == NULL || nh->h_ref == NULL) {
if (h->h_next != history_def_next) {
history_def_init(&h->h_ref, &ev, 0);
h->h_first = history_def_first;
@@ -616,6 +694,7 @@ history_set_fun(History *h, History *nh)
h->h_clear = history_def_clear;
h->h_enter = history_def_enter;
h->h_add = history_def_add;
+ h->h_del = history_def_del;
}
return (-1);
}
@@ -632,23 +711,27 @@ history_set_fun(History *h, History *nh)
h->h_clear = nh->h_clear;
h->h_enter = nh->h_enter;
h->h_add = nh->h_add;
+ h->h_del = nh->h_del;
return (0);
}
/* history_load():
- * History load function
+ * TYPE(History) load function
*/
private int
-history_load(History *h, const char *fname)
+history_load(TYPE(History) *h, const char *fname)
{
FILE *fp;
char *line, *lbuf;
size_t sz, max_size;
char *ptr;
int i = -1;
- HistEvent ev;
+ TYPE(HistEvent) ev;
+#ifdef WIDECHAR
+ static ct_buffer_t conv;
+#endif
lbuf = NULL;
if ((fp = fopen(fname, "r")) == NULL)
@@ -678,7 +761,7 @@ history_load(History *h, const char *fname)
}
if (sz > max_size) {
char *nptr;
- max_size = (sz + 1023) & ~1023;
+ max_size = (sz + 1024) & ~1023;
nptr = h_realloc(ptr, max_size);
if (nptr == NULL) {
i = -1;
@@ -687,9 +770,9 @@ history_load(History *h, const char *fname)
ptr = nptr;
}
(void) strunvis(ptr, line);
- if (HENTER(h, &ev, ptr) == -1) {
- h_free((ptr_t)ptr);
- return -1;
+ if (HENTER(h, &ev, ct_decode_string(ptr, &conv)) == -1) {
+ i = -1;
+ goto oomem;
}
}
oomem:
@@ -702,16 +785,19 @@ done:
/* history_save():
- * History save function
+ * TYPE(History) save function
*/
private int
-history_save(History *h, const char *fname)
+history_save(TYPE(History) *h, const char *fname)
{
FILE *fp;
- HistEvent ev;
+ TYPE(HistEvent) ev;
int i = -1, retval;
size_t len, max_size;
char *ptr;
+#ifdef WIDECHAR
+ static ct_buffer_t conv;
+#endif
if ((fp = fopen(fname, "w")) == NULL)
return (-1);
@@ -726,10 +812,10 @@ history_save(History *h, const char *fname)
for (i = 0, retval = HLAST(h, &ev);
retval != -1;
retval = HPREV(h, &ev), i++) {
- len = strlen(ev.str) * 4 + 1;
+ len = Strlen(ev.str) * 4 + 1;
if (len > max_size) {
char *nptr;
- max_size = (len + 1023) & ~1023;
+ max_size = (len + 1024) & ~1023;
nptr = h_realloc(ptr, max_size);
if (nptr == NULL) {
i = -1;
@@ -737,7 +823,8 @@ history_save(History *h, const char *fname)
}
ptr = nptr;
}
- (void) strnvis(ptr, ev.str, max_size, VIS_WHITE);
+ (void) strnvis(ptr, ct_encode_string(ev.str, &conv), max_size,
+ VIS_WHITE);
(void) fprintf(fp, "%s\n", ptr);
}
oomem:
@@ -752,7 +839,7 @@ done:
* Find the previous event, with number given
*/
private int
-history_prev_event(History *h, HistEvent *ev, int num)
+history_prev_event(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
{
int retval;
@@ -765,11 +852,28 @@ history_prev_event(History *h, HistEvent *ev, int num)
}
+private int
+history_next_evdata(TYPE(History) *h, TYPE(HistEvent) *ev, int num, void **d)
+{
+ int retval;
+
+ for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
+ if (num-- <= 0) {
+ if (d)
+ *d = ((history_t *)h->h_ref)->cursor->data;
+ return (0);
+ }
+
+ he_seterrev(ev, _HE_NOT_FOUND);
+ return (-1);
+}
+
+
/* history_next_event():
* Find the next event, with number given
*/
private int
-history_next_event(History *h, HistEvent *ev, int num)
+history_next_event(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
{
int retval;
@@ -786,13 +890,13 @@ history_next_event(History *h, HistEvent *ev, int num)
* Find the previous event beginning with string
*/
private int
-history_prev_string(History *h, HistEvent *ev, const char *str)
+history_prev_string(TYPE(History) *h, TYPE(HistEvent) *ev, const Char *str)
{
- size_t len = strlen(str);
+ size_t len = Strlen(str);
int retval;
for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev))
- if (strncmp(str, ev->str, len) == 0)
+ if (Strncmp(str, ev->str, len) == 0)
return (0);
he_seterrev(ev, _HE_NOT_FOUND);
@@ -804,13 +908,13 @@ history_prev_string(History *h, HistEvent *ev, const char *str)
* Find the next event beginning with string
*/
private int
-history_next_string(History *h, HistEvent *ev, const char *str)
+history_next_string(TYPE(History) *h, TYPE(HistEvent) *ev, const Char *str)
{
- size_t len = strlen(str);
+ size_t len = Strlen(str);
int retval;
for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
- if (strncmp(str, ev->str, len) == 0)
+ if (Strncmp(str, ev->str, len) == 0)
return (0);
he_seterrev(ev, _HE_NOT_FOUND);
@@ -822,10 +926,10 @@ history_next_string(History *h, HistEvent *ev, const char *str)
* User interface to history functions.
*/
int
-history(History *h, HistEvent *ev, int fun, ...)
+FUNW(history)(TYPE(History) *h, TYPE(HistEvent) *ev, int fun, ...)
{
va_list va;
- const char *str;
+ const Char *str;
int retval;
va_start(va, fun);
@@ -850,18 +954,22 @@ history(History *h, HistEvent *ev, int fun, ...)
break;
case H_ADD:
- str = va_arg(va, const char *);
+ str = va_arg(va, const Char *);
retval = HADD(h, ev, str);
break;
+ case H_DEL:
+ retval = HDEL(h, ev, va_arg(va, const int));
+ break;
+
case H_ENTER:
- str = va_arg(va, const char *);
+ str = va_arg(va, const Char *);
if ((retval = HENTER(h, ev, str)) != -1)
h->h_ent = ev->num;
break;
case H_APPEND:
- str = va_arg(va, const char *);
+ str = va_arg(va, const Char *);
if ((retval = HSET(h, ev, h->h_ent)) != -1)
retval = HADD(h, ev, str);
break;
@@ -916,16 +1024,16 @@ history(History *h, HistEvent *ev, int fun, ...)
break;
case H_PREV_STR:
- retval = history_prev_string(h, ev, va_arg(va, const char *));
+ retval = history_prev_string(h, ev, va_arg(va, const Char *));
break;
case H_NEXT_STR:
- retval = history_next_string(h, ev, va_arg(va, const char *));
+ retval = history_next_string(h, ev, va_arg(va, const Char *));
break;
case H_FUNC:
{
- History hf;
+ TYPE(History) hf;
hf.h_ref = va_arg(va, ptr_t);
h->h_ent = -1;
@@ -938,6 +1046,7 @@ history(History *h, HistEvent *ev, int fun, ...)
hf.h_clear = va_arg(va, history_vfun_t);
hf.h_enter = va_arg(va, history_efun_t);
hf.h_add = va_arg(va, history_efun_t);
+ hf.h_del = va_arg(va, history_sfun_t);
if ((retval = history_set_fun(h, &hf)) == -1)
he_seterrev(ev, _HE_PARAM_MISSING);
@@ -945,15 +1054,46 @@ history(History *h, HistEvent *ev, int fun, ...)
}
case H_END:
- history_end(h);
+ FUN(history,end)(h);
retval = 0;
break;
+ case H_NEXT_EVDATA:
+ {
+ int num = va_arg(va, int);
+ void **d = va_arg(va, void **);
+ retval = history_next_evdata(h, ev, num, d);
+ break;
+ }
+
+ case H_DELDATA:
+ {
+ int num = va_arg(va, int);
+ void **d = va_arg(va, void **);
+ retval = history_deldata_nth((history_t *)h->h_ref, ev, num, d);
+ break;
+ }
+
+ case H_REPLACE: /* only use after H_NEXT_EVDATA */
+ {
+ const Char *line = va_arg(va, const Char *);
+ void *d = va_arg(va, void *);
+ const Char *s;
+ if(!line || !(s = Strdup(line))) {
+ retval = -1;
+ break;
+ }
+ ((history_t *)h->h_ref)->cursor->ev.str = s;
+ ((history_t *)h->h_ref)->cursor->data = d;
+ retval = 0;
+ break;
+ }
+
default:
retval = -1;
he_seterrev(ev, _HE_UNKNOWN);
break;
}
va_end(va);
- return (retval);
+ return retval;
}
diff --git a/lib/libedit/key.c b/lib/libedit/key.c
index 5a32bef030e..40ded0a2549 100644
--- a/lib/libedit/key.c
+++ b/lib/libedit/key.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: key.c,v 1.10 2009/10/27 23:59:28 deraadt Exp $ */
-/* $NetBSD: key.c,v 1.15 2003/10/18 23:48:42 christos Exp $ */
+/* $OpenBSD: key.c,v 1.11 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: key.c,v 1.23 2009/12/30 22:37:40 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -40,7 +40,7 @@
* the extended-key map.
*
* An extended-key (key) is a sequence of keystrokes introduced
- * with an sequence introducer and consisting of an arbitrary
+ * with a 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).
@@ -66,7 +66,7 @@
* of these node elements
*/
struct key_node_t {
- char ch; /* single character of key */
+ 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 */
@@ -74,17 +74,17 @@ struct key_node_t {
struct key_node_t *sibling; /* ptr to another key with same prefix*/
};
-private int node_trav(EditLine *, key_node_t *, char *,
+private int node_trav(EditLine *, key_node_t *, Char *,
key_value_t *);
-private int node__try(EditLine *, key_node_t *, const char *,
+private int node__try(EditLine *, key_node_t *, const Char *,
key_value_t *, int);
-private key_node_t *node__get(int);
+private key_node_t *node__get(Int);
+private void node__free(key_node_t *);
private void node__put(EditLine *, key_node_t *);
-private int node__delete(EditLine *, key_node_t **, const char *);
-private int node_lookup(EditLine *, const char *, key_node_t *,
- int);
-private int node_enum(EditLine *, key_node_t *, int);
-private int key__decode_char(char *, int, int);
+private int node__delete(EditLine *, key_node_t **, const Char *);
+private int node_lookup(EditLine *, const Char *, key_node_t *,
+ size_t);
+private int node_enum(EditLine *, key_node_t *, size_t);
#define KEY_BUFSIZ EL_BUFSIZ
@@ -96,7 +96,7 @@ protected int
key_init(EditLine *el)
{
- el->el_key.buf = (char *) el_malloc(KEY_BUFSIZ);
+ el->el_key.buf = el_malloc(KEY_BUFSIZ * sizeof(*el->el_key.buf));
if (el->el_key.buf == NULL)
return (-1);
el->el_key.map = NULL;
@@ -104,7 +104,6 @@ key_init(EditLine *el)
return (0);
}
-
/* key_end():
* Free the key maps
*/
@@ -114,8 +113,7 @@ key_end(EditLine *el)
el_free((ptr_t) el->el_key.buf);
el->el_key.buf = NULL;
- /* XXX: provide a function to clear the keys */
- el->el_key.map = NULL;
+ node__free(el->el_key.map);
}
@@ -135,7 +133,7 @@ key_map_cmd(EditLine *el, int cmd)
* Associate str with a key value
*/
protected key_value_t *
-key_map_str(EditLine *el, char *str)
+key_map_str(EditLine *el, Char *str)
{
el->el_key.val.str = str;
@@ -167,7 +165,7 @@ key_reset(EditLine *el)
* The last character read is returned in *ch.
*/
protected int
-key_get(EditLine *el, char *ch, key_value_t *val)
+key_get(EditLine *el, Char *ch, key_value_t *val)
{
return (node_trav(el, el->el_key.map, ch, val));
@@ -181,7 +179,7 @@ key_get(EditLine *el, char *ch, key_value_t *val)
* out str or a unix command.
*/
protected void
-key_add(EditLine *el, const char *key, key_value_t *val, int ntype)
+key_add(EditLine *el, const Char *key, key_value_t *val, int ntype)
{
if (key[0] == '\0') {
@@ -209,9 +207,12 @@ key_add(EditLine *el, const char *key, key_value_t *val, int ntype)
*
*/
protected void
-key_clear(EditLine *el, el_action_t *map, const char *in)
+key_clear(EditLine *el, el_action_t *map, const Char *in)
{
-
+#ifdef WIDECHAR
+ if (*in > N_KEYS) /* can't be in the map */
+ return;
+#endif
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) ||
@@ -226,7 +227,7 @@ key_clear(EditLine *el, el_action_t *map, const char *in)
* they exists.
*/
protected int
-key_delete(EditLine *el, const char *key)
+key_delete(EditLine *el, const Char *key)
{
if (key[0] == '\0') {
@@ -247,7 +248,7 @@ key_delete(EditLine *el, const char *key)
* Print entire el->el_key.map if null
*/
protected void
-key_print(EditLine *el, const char *key)
+key_print(EditLine *el, const Char *key)
{
/* do nothing if el->el_key.map is empty and null key specified */
@@ -257,7 +258,7 @@ key_print(EditLine *el, const char *key)
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",
+ (void) fprintf(el->el_errfile, "Unbound extended key \"" FSTR "\"\n",
key);
return;
}
@@ -268,14 +269,14 @@ key_print(EditLine *el, const char *key)
* found. May read in more characters.
*/
private int
-node_trav(EditLine *el, key_node_t *ptr, char *ch, key_value_t *val)
+node_trav(EditLine *el, key_node_t *ptr, Char *ch, key_value_t *val)
{
if (ptr->ch == *ch) {
/* match found */
if (ptr->next) {
/* key not complete so get next char */
- if (el_getc(el, ch) != 1) { /* if EOF or error */
+ if (FUN(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 */
@@ -305,7 +306,7 @@ node_trav(EditLine *el, key_node_t *ptr, char *ch, key_value_t *val)
* Find a node that matches *str or allocate a new one
*/
private int
-node__try(EditLine *el, key_node_t *ptr, const char *str, key_value_t *val, int ntype)
+node__try(EditLine *el, key_node_t *ptr, const Char *str, key_value_t *val, int ntype)
{
if (ptr->ch != *str) {
@@ -346,7 +347,7 @@ node__try(EditLine *el, key_node_t *ptr, const char *str, key_value_t *val, int
break;
case XK_STR:
case XK_EXE:
- if ((ptr->val.str = el_strdup(val->str)) == NULL)
+ if ((ptr->val.str = Strdup(val->str)) == NULL)
return -1;
break;
default:
@@ -367,7 +368,7 @@ node__try(EditLine *el, key_node_t *ptr, const char *str, key_value_t *val, int
* Delete node that matches str
*/
private int
-node__delete(EditLine *el, key_node_t **inptr, const char *str)
+node__delete(EditLine *el, key_node_t **inptr, const Char *str)
{
key_node_t *ptr;
key_node_t *prev_ptr = NULL;
@@ -444,10 +445,10 @@ node__put(EditLine *el, key_node_t *ptr)
/* node__get():
- * Returns pointer to an key_node_t for ch.
+ * Returns pointer to a key_node_t for ch.
*/
private key_node_t *
-node__get(int ch)
+node__get(Int ch)
{
key_node_t *ptr;
@@ -462,21 +463,29 @@ node__get(int ch)
return (ptr);
}
-
+private void
+node__free(key_node_t *k)
+{
+ if (k == NULL)
+ return;
+ node__free(k->sibling);
+ node__free(k->next);
+ el_free((ptr_t) k);
+}
/* node_lookup():
* look for the str starting at node ptr.
* Print if last node
*/
private int
-node_lookup(EditLine *el, const char *str, key_node_t *ptr, int cnt)
+node_lookup(EditLine *el, const Char *str, key_node_t *ptr, size_t cnt)
{
- int ncnt;
+ ssize_t used;
if (ptr == NULL)
return (-1); /* cannot have null ptr */
- if (*str == 0) {
+ if (!str || *str == 0) {
/* no more chars in str. node_enum from here. */
(void) node_enum(el, ptr, cnt);
return (0);
@@ -484,17 +493,19 @@ node_lookup(EditLine *el, const char *str, key_node_t *ptr, int cnt)
/* 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);
+ used = ct_visual_char(el->el_key.buf + cnt,
+ KEY_BUFSIZ - cnt, ptr->ch);
+ if (used == -1)
+ return (-1); /* ran out of buffer space */
if (ptr->next != NULL)
/* not yet at leaf */
return (node_lookup(el, str + 1, ptr->next,
- ncnt + 1));
+ used + cnt));
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';
+ el->el_key.buf[cnt + used ] = '"';
+ el->el_key.buf[cnt + used + 1] = '\0';
key_kprint(el, el->el_key.buf,
&ptr->val, ptr->type);
return (0);
@@ -518,16 +529,16 @@ node_lookup(EditLine *el, const char *str, key_node_t *ptr, int cnt)
* Traverse the node printing the characters it is bound in buffer
*/
private int
-node_enum(EditLine *el, key_node_t *ptr, int cnt)
+node_enum(EditLine *el, key_node_t *ptr, size_t cnt)
{
- int ncnt;
+ ssize_t used;
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);
+ (void) fprintf(el->el_errfile, " \"" FSTR "...\"\n", el->el_key.buf);
return (0);
}
if (ptr == NULL) {
@@ -538,14 +549,14 @@ node_enum(EditLine *el, key_node_t *ptr, int cnt)
return (-1);
}
/* put this char at end of str */
- ncnt = key__decode_char(el->el_key.buf, cnt, (unsigned char) ptr->ch);
+ used = ct_visual_char(el->el_key.buf + cnt, KEY_BUFSIZ - cnt, ptr->ch);
if (ptr->next == NULL) {
/* print this key and function */
- el->el_key.buf[ncnt + 1] = '"';
- el->el_key.buf[ncnt + 2] = '\0';
+ el->el_key.buf[cnt + used ] = '"';
+ el->el_key.buf[cnt + used + 1] = '\0';
key_kprint(el, el->el_key.buf, &ptr->val, ptr->type);
} else
- (void) node_enum(el, ptr->next, ncnt + 1);
+ (void) node_enum(el, ptr->next, cnt + used);
/* go to sibling if there is one */
if (ptr->sibling)
@@ -559,7 +570,7 @@ node_enum(EditLine *el, key_node_t *ptr, int cnt)
* function specified by val
*/
protected void
-key_kprint(EditLine *el, const char *key, key_value_t *val, int ntype)
+key_kprint(EditLine *el, const Char *key, key_value_t *val, int ntype)
{
el_bindings_t *fp;
char unparsbuf[EL_BUFSIZ];
@@ -569,15 +580,19 @@ key_kprint(EditLine *el, const char *key, key_value_t *val, int ntype)
switch (ntype) {
case XK_STR:
case XK_EXE:
- (void) fprintf(el->el_outfile, fmt, key,
- key__decode_str(val->str, unparsbuf,
- ntype == XK_STR ? "\"\"" : "[]"));
+ (void) key__decode_str(val->str, unparsbuf,
+ sizeof(unparsbuf),
+ ntype == XK_STR ? "\"\"" : "[]");
+ (void) fprintf(el->el_outfile, fmt,
+ ct_encode_string(key, &el->el_scratch), unparsbuf);
break;
case XK_CMD:
for (fp = el->el_map.help; fp->name; fp++)
if (val->cmd == fp->func) {
+ ct_wcstombs(unparsbuf, fp->name, sizeof(unparsbuf));
+ unparsbuf[sizeof(unparsbuf) -1] = '\0';
(void) fprintf(el->el_outfile, fmt,
- key, fp->name);
+ ct_encode_string(key, &el->el_scratch), unparsbuf);
break;
}
#ifdef DEBUG_KEY
@@ -592,87 +607,53 @@ key_kprint(EditLine *el, const char *key, key_value_t *val, int ntype)
break;
}
else
- (void) fprintf(el->el_outfile, fmt, key, "no input");
-}
-
-
-/* key__decode_char():
- * Put a printable form of char in buf.
- */
-private int
-key__decode_char(char *buf, int cnt, int ch)
-{
- if (ch == 0) {
- buf[cnt++] = '^';
- buf[cnt] = '@';
- return (cnt);
- }
- if (iscntrl(ch)) {
- buf[cnt++] = '^';
- if (ch == '\177')
- buf[cnt] = '?';
- else
- buf[cnt] = ch | 0100;
- } else if (ch == '^') {
- buf[cnt++] = '\\';
- buf[cnt] = '^';
- } else if (ch == '\\') {
- buf[cnt++] = '\\';
- buf[cnt] = '\\';
- } else if (ch == ' ' || (isprint(ch) && !isspace(ch))) {
- buf[cnt] = ch;
- } else {
- buf[cnt++] = '\\';
- buf[cnt++] = (((unsigned int) ch >> 6) & 7) + '0';
- buf[cnt++] = (((unsigned int) ch >> 3) & 7) + '0';
- buf[cnt] = (ch & 7) + '0';
- }
- return (cnt);
+ (void) fprintf(el->el_outfile, fmt, ct_encode_string(key,
+ &el->el_scratch), "no input");
}
+#define ADDC(c) \
+ if (b < eb) \
+ *b++ = c; \
+ else \
+ b++
/* key__decode_str():
* Make a printable version of the ey
*/
-protected char *
-key__decode_str(const char *str, char *buf, const char *sep)
+protected size_t
+key__decode_str(const Char *str, char *buf, size_t len, const char *sep)
{
- char *b;
- const char *p;
+ char *b = buf, *eb = b + len;
+ const Char *p;
b = buf;
- if (sep[0] != '\0')
- *b++ = sep[0];
- if (*str == 0) {
- *b++ = '^';
- *b++ = '@';
- if (sep[0] != '\0' && sep[1] != '\0')
- *b++ = sep[1];
- *b++ = 0;
- return (buf);
+ if (sep[0] != '\0') {
+ ADDC(sep[0]);
+ }
+ if (*str == '\0') {
+ ADDC('^');
+ ADDC('@');
+ goto add_endsep;
}
for (p = str; *p != 0; p++) {
- if (iscntrl((unsigned char) *p)) {
- *b++ = '^';
- if (*p == '\177')
- *b++ = '?';
+ Char dbuf[VISUAL_WIDTH_MAX];
+ Char *p2 = dbuf;
+ ssize_t l = ct_visual_char(dbuf, VISUAL_WIDTH_MAX, *p);
+ while (l-- > 0) {
+ ssize_t n = ct_encode_char(b, (size_t)(eb - b), *p2++);
+ if (n == -1) /* ran out of space */
+ goto add_endsep;
else
- *b++ = *p | 0100;
- } else if (*p == '^' || *p == '\\') {
- *b++ = '\\';
- *b++ = *p;
- } else if (*p == ' ' || (isprint((unsigned char) *p) &&
- !isspace((unsigned char) *p))) {
- *b++ = *p;
- } else {
- *b++ = '\\';
- *b++ = (((unsigned int) *p >> 6) & 7) + '0';
- *b++ = (((unsigned int) *p >> 3) & 7) + '0';
- *b++ = (*p & 7) + '0';
+ b += n;
}
}
- if (sep[0] != '\0' && sep[1] != '\0')
- *b++ = sep[1];
- *b++ = 0;
- return (buf); /* should check for overflow */
+add_endsep:
+ if (sep[0] != '\0' && sep[1] != '\0') {
+ ADDC(sep[1]);
+ }
+ ADDC('\0');
+ if ((size_t)(b - buf) >= len)
+ buf[len - 1] = '\0';
+ return (size_t)(b - buf);
}
+
diff --git a/lib/libedit/key.h b/lib/libedit/key.h
index 86584417253..b6a2780e689 100644
--- a/lib/libedit/key.h
+++ b/lib/libedit/key.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: key.h,v 1.7 2003/10/31 08:42:24 otto Exp $ */
-/* $NetBSD: key.h,v 1.8 2003/08/07 16:44:32 agc Exp $ */
+/* $OpenBSD: key.h,v 1.8 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: key.h,v 1.13 2009/12/30 22:37:40 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -43,13 +43,13 @@
typedef union key_value_t {
el_action_t cmd; /* If it is a command the # */
- char *str; /* If it is a string... */
+ 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 */
+ Char *buf; /* Key print buffer */
key_node_t *map; /* Key map */
key_value_t val; /* Local conversion buffer */
} el_key_t;
@@ -66,15 +66,16 @@ typedef struct el_key_t {
protected int key_init(EditLine *);
protected void key_end(EditLine *);
protected key_value_t *key_map_cmd(EditLine *, int);
-protected key_value_t *key_map_str(EditLine *, char *);
+protected key_value_t *key_map_str(EditLine *, Char *);
protected void key_reset(EditLine *);
-protected int key_get(EditLine *, char *, key_value_t *);
-protected void key_add(EditLine *, const char *, key_value_t *, int);
-protected void key_clear(EditLine *, el_action_t *, const char *);
-protected int key_delete(EditLine *, const char *);
-protected void key_print(EditLine *, const char *);
-protected void key_kprint(EditLine *, const char *, key_value_t *,
+protected int key_get(EditLine *, Char *, key_value_t *);
+protected void key_add(EditLine *, const Char *, key_value_t *, int);
+protected void key_clear(EditLine *, el_action_t *, const Char *);
+protected int key_delete(EditLine *, const Char *);
+protected void key_print(EditLine *, const Char *);
+protected void key_kprint(EditLine *, const Char *, key_value_t *,
int);
-protected char *key__decode_str(const char *, char *, const char *);
+protected size_t key__decode_str(const Char *, char *, size_t,
+ const char *);
#endif /* _h_el_key */
diff --git a/lib/libedit/makelist b/lib/libedit/makelist
index 61ebed4fba4..98ca5318347 100644
--- a/lib/libedit/makelist
+++ b/lib/libedit/makelist
@@ -1,6 +1,5 @@
#!/bin/sh -
-# $OpenBSD: makelist,v 1.8 2009/10/28 23:22:45 schwarze Exp $
-# $NetBSD: makelist,v 1.8 2003/03/10 21:21:10 christos Exp $
+# $NetBSD: makelist,v 1.16 2010/04/18 21:17:05 christos Exp $
#
# Copyright (c) 1992, 1993
# The Regents of the University of California. All rights reserved.
@@ -37,7 +36,7 @@
# makelist.sh: Automatically generate header files...
AWK=awk
-USAGE="Usage: $0 -h|-e|-fc|-fh|-bc|-bh|-m <filenames>"
+USAGE="Usage: $0 -n|-h|-e|-fc|-fh|-bc|-bh|-m <filenames>"
if [ "x$1" = "x" ]
then
@@ -54,6 +53,14 @@ case $FLAG in
# generate foo.h file from foo.c
#
+-n)
+ cat << _EOF
+#undef WIDECHAR
+#define NARROWCHAR
+#include "${FILES}"
+_EOF
+ ;;
+
-h)
set - `echo $FILES | sed -e 's/\\./_/g'`
hdr="_h_`basename $1`"
@@ -70,7 +77,7 @@ case $FLAG in
# XXX: need a space between name and prototype so that -fc and -fh
# parsing is much easier
#
- printf("protected el_action_t\t%s (EditLine *, int);\n", name);
+ printf("protected el_action_t\t%s (EditLine *, Int);\n", name);
}
}
END {
@@ -84,7 +91,8 @@ case $FLAG in
cat $FILES | $AWK '
BEGIN {
printf("/* Automatically generated file, do not edit */\n");
- printf("#include \"sys.h\"\n#include \"el.h\"\n");
+ printf("#include \"config.h\"\n#include \"el.h\"\n");
+ printf("#include \"chartype.h\"\n");
printf("private const struct el_bindings_t el_func_help[] = {\n");
low = "abcdefghijklmnopqrstuvwxyz_";
high = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_";
@@ -105,21 +113,20 @@ case $FLAG in
fname = fname s;
}
- printf(" { %-30.30s %-30.30s\n","\"" fname "\",", uname ",");
+ printf(" { %-30.30s %-30.30s\n","STR(\"" fname "\"),", uname ",");
ok = 1;
}
}
/^ \*/ {
if (ok) {
- printf(" \"");
+ printf(" STR(\"");
for (i = 2; i < NF; i++)
printf("%s ", $i);
- printf("%s\" },\n", $i);
+ printf("%s\") },\n", $i);
ok = 0;
}
}
END {
- printf(" { NULL, 0, NULL }\n");
printf("};\n");
printf("\nprotected const el_bindings_t* help__get()");
printf("{ return el_func_help; }\n");
@@ -142,7 +149,7 @@ case $FLAG in
#
-fh)
cat $FILES | $AWK '/el_action_t/ { print $3 }' | \
- sort | tr '[a-z]' '[A-Z]' | $AWK '
+ sort | tr '[:lower:]' '[:upper:]' | $AWK '
BEGIN {
printf("/* Automatically generated file, do not edit */\n");
printf("#ifndef _h_fcns_c\n#define _h_fcns_c\n");
@@ -154,7 +161,7 @@ case $FLAG in
END {
printf("#define\t%-30.30s\t%3d\n", "EL_NUM_FCNS", count);
- printf("typedef el_action_t (*el_func_t)(EditLine *, int);");
+ printf("typedef el_action_t (*el_func_t)(EditLine *, Int);");
printf("\nprotected const el_func_t* func__get(void);\n");
printf("#endif /* _h_fcns_c */\n");
}'
@@ -166,7 +173,7 @@ case $FLAG in
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("#include \"config.h\"\n#include \"el.h\"\n");
printf("private const el_func_t el_func[] = {");
maxlen = 80;
needn = 1;
diff --git a/lib/libedit/map.c b/lib/libedit/map.c
index 54a165c9f86..ffe2c9e5a67 100644
--- a/lib/libedit/map.c
+++ b/lib/libedit/map.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: map.c,v 1.10 2009/10/27 23:59:28 deraadt Exp $ */
-/* $NetBSD: map.c,v 1.19 2003/08/07 16:44:32 agc Exp $ */
+/* $OpenBSD: map.c,v 1.11 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: map.c,v 1.25 2009/12/30 22:37:40 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -41,10 +41,8 @@
#include <stdlib.h>
#include "el.h"
-#define N_KEYS 256
-
-private void map_print_key(EditLine *, el_action_t *, const char *);
-private void map_print_some_keys(EditLine *, el_action_t *, int, int);
+private void map_print_key(EditLine *, el_action_t *, const Char *);
+private void map_print_some_keys(EditLine *, el_action_t *, Int, Int);
private void map_print_all_keys(EditLine *);
private void map_init_nls(EditLine *);
private void map_init_meta(EditLine *);
@@ -61,7 +59,7 @@ private const el_action_t el_map_emacs[] = {
/* 5 */ ED_MOVE_TO_END, /* ^E */
/* 6 */ ED_NEXT_CHAR, /* ^F */
/* 7 */ ED_UNASSIGNED, /* ^G */
- /* 8 */ ED_DELETE_PREV_CHAR, /* ^H */
+ /* 8 */ EM_DELETE_PREV_CHAR, /* ^H */
/* 9 */ ED_UNASSIGNED, /* ^I */
/* 10 */ ED_NEWLINE, /* ^J */
/* 11 */ ED_KILL_LINE, /* ^K */
@@ -180,7 +178,7 @@ private const el_action_t el_map_emacs[] = {
/* 124 */ ED_INSERT, /* | */
/* 125 */ ED_INSERT, /* } */
/* 126 */ ED_INSERT, /* ~ */
- /* 127 */ ED_DELETE_PREV_CHAR, /* ^? */
+ /* 127 */ EM_DELETE_PREV_CHAR, /* ^? */
/* 128 */ ED_UNASSIGNED, /* M-^@ */
/* 129 */ ED_UNASSIGNED, /* M-^A */
/* 130 */ ED_UNASSIGNED, /* M-^B */
@@ -277,7 +275,7 @@ private const el_action_t el_map_emacs[] = {
/* 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 */
@@ -962,7 +960,7 @@ map_init_nls(EditLine *el)
el_action_t *map = el->el_map.key;
for (i = 0200; i <= 0377; i++)
- if (isprint(i))
+ if (Isprint(i))
map[i] = ED_INSERT;
}
@@ -973,7 +971,7 @@ map_init_nls(EditLine *el)
private void
map_init_meta(EditLine *el)
{
- char buf[3];
+ Char buf[3];
int i;
el_action_t *map = el->el_map.key;
el_action_t *alt = el->el_map.alt;
@@ -991,7 +989,7 @@ map_init_meta(EditLine *el)
} else
map = alt;
}
- buf[0] = (char) i;
+ buf[0] = (Char) i;
buf[2] = 0;
for (i = 0200; i <= 0377; i++)
switch (map[i]) {
@@ -1045,7 +1043,7 @@ protected void
map_init_emacs(EditLine *el)
{
int i;
- char buf[3];
+ Char buf[3];
el_action_t *key = el->el_map.key;
el_action_t *alt = el->el_map.alt;
const el_action_t *emacs = el->el_map.emacs;
@@ -1076,14 +1074,14 @@ map_init_emacs(EditLine *el)
* Set the editor
*/
protected int
-map_set_editor(EditLine *el, char *editor)
+map_set_editor(EditLine *el, Char *editor)
{
- if (strcmp(editor, "emacs") == 0) {
+ if (Strcmp(editor, STR("emacs")) == 0) {
map_init_emacs(el);
return (0);
}
- if (strcmp(editor, "vi") == 0) {
+ if (Strcmp(editor, STR("vi")) == 0) {
map_init_vi(el);
return (0);
}
@@ -1095,17 +1093,17 @@ map_set_editor(EditLine *el, char *editor)
* Retrieve the editor
*/
protected int
-map_get_editor(EditLine *el, const char **editor)
+map_get_editor(EditLine *el, const Char **editor)
{
if (editor == NULL)
return (-1);
switch (el->el_map.type) {
case MAP_EMACS:
- *editor = "emacs";
+ *editor = STR("emacs");
return (0);
case MAP_VI:
- *editor = "vi";
+ *editor = STR("vi");
return (0);
}
return (-1);
@@ -1116,17 +1114,18 @@ map_get_editor(EditLine *el, const char **editor)
* Print the function description for 1 key
*/
private void
-map_print_key(EditLine *el, el_action_t *map, const char *in)
+map_print_key(EditLine *el, el_action_t *map, const Char *in)
{
char outbuf[EL_BUFSIZ];
- el_bindings_t *bp;
+ el_bindings_t *bp, *ep;
if (in[0] == '\0' || in[1] == '\0') {
- (void) key__decode_str(in, outbuf, "");
- for (bp = el->el_map.help; bp->name != NULL; bp++)
+ (void) key__decode_str(in, outbuf, sizeof(outbuf), "");
+ ep = &el->el_map.help[el->el_map.nfunc];
+ for (bp = el->el_map.help; bp < ep; bp++)
if (bp->func == map[(unsigned char) *in]) {
(void) fprintf(el->el_outfile,
- "%s\t->\t%s\n", outbuf, bp->name);
+ "%s\t->\t" FSTR "\n", outbuf, bp->name);
return;
}
} else
@@ -1138,10 +1137,10 @@ map_print_key(EditLine *el, el_action_t *map, const char *in)
* Print keys from first to last
*/
private void
-map_print_some_keys(EditLine *el, el_action_t *map, int first, int last)
+map_print_some_keys(EditLine *el, el_action_t *map, Int first, Int last)
{
- el_bindings_t *bp;
- char firstbuf[2], lastbuf[2];
+ el_bindings_t *bp, *ep;
+ Char firstbuf[2], lastbuf[2];
char unparsbuf[EL_BUFSIZ], extrabuf[EL_BUFSIZ];
firstbuf[0] = first;
@@ -1149,39 +1148,47 @@ map_print_some_keys(EditLine *el, el_action_t *map, int first, int last)
lastbuf[0] = last;
lastbuf[1] = 0;
if (map[first] == ED_UNASSIGNED) {
- if (first == last)
+ if (first == last) {
+ (void) key__decode_str(firstbuf, unparsbuf,
+ sizeof(unparsbuf), STRQQ);
(void) fprintf(el->el_outfile,
- "%-15s-> is undefined\n",
- key__decode_str(firstbuf, unparsbuf, STRQQ));
+ "%-15s-> is undefined\n", unparsbuf);
+ }
return;
}
- for (bp = el->el_map.help; bp->name != NULL; bp++) {
+ ep = &el->el_map.help[el->el_map.nfunc];
+ for (bp = el->el_map.help; bp < ep; 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);
+ (void) key__decode_str(firstbuf, unparsbuf,
+ sizeof(unparsbuf), STRQQ);
+ (void) fprintf(el->el_outfile, "%-15s-> " FSTR "\n",
+ unparsbuf, bp->name);
} else {
+ (void) key__decode_str(firstbuf, unparsbuf,
+ sizeof(unparsbuf), STRQQ);
+ (void) key__decode_str(lastbuf, extrabuf,
+ sizeof(extrabuf), STRQQ);
(void) fprintf(el->el_outfile,
- "%-4s to %-7s-> %s\n",
- key__decode_str(firstbuf, unparsbuf, STRQQ),
- key__decode_str(lastbuf, extrabuf, STRQQ),
- bp->name);
+ "%-4s to %-7s-> " FSTR "\n",
+ unparsbuf, extrabuf, bp->name);
}
return;
}
}
#ifdef MAP_DEBUG
if (map == el->el_map.key) {
+ (void) key__decode_str(firstbuf, unparsbuf,
+ sizeof(unparsbuf), STRQQ);
(void) fprintf(el->el_outfile,
- "BUG!!! %s isn't bound to anything.\n",
- key__decode_str(firstbuf, unparsbuf, STRQQ));
+ "BUG!!! %s isn't bound to anything.\n", unparsbuf);
(void) fprintf(el->el_outfile, "el->el_map.key[%d] == %d\n",
first, el->el_map.key[first]);
} else {
+ (void) key__decode_str(firstbuf, unparsbuf,
+ sizeof(unparsbuf), STRQQ);
(void) fprintf(el->el_outfile,
- "BUG!!! %s isn't bound to anything.\n",
- key__decode_str(firstbuf, unparsbuf, STRQQ));
+ "BUG!!! %s isn't bound to anything.\n", unparsbuf);
(void) fprintf(el->el_outfile, "el->el_map.alt[%d] == %d\n",
first, el->el_map.alt[first]);
}
@@ -1219,9 +1226,9 @@ map_print_all_keys(EditLine *el)
map_print_some_keys(el, el->el_map.alt, prev, i - 1);
(void) fprintf(el->el_outfile, "Multi-character bindings\n");
- key_print(el, "");
+ key_print(el, STR(""));
(void) fprintf(el->el_outfile, "Arrow key bindings\n");
- term_print_arrow(el, "");
+ term_print_arrow(el, STR(""));
}
@@ -1229,16 +1236,16 @@ map_print_all_keys(EditLine *el)
* Add/remove/change bindings
*/
protected int
-map_bind(EditLine *el, int argc, const char **argv)
+map_bind(EditLine *el, int argc, const Char **argv)
{
el_action_t *map;
int ntype, rem;
- const char *p;
- char inbuf[EL_BUFSIZ];
- char outbuf[EL_BUFSIZ];
- const char *in = NULL;
- char *out = NULL;
- el_bindings_t *bp;
+ const Char *p;
+ Char inbuf[EL_BUFSIZ];
+ Char outbuf[EL_BUFSIZ];
+ const Char *in = NULL;
+ Char *out = NULL;
+ el_bindings_t *bp, *ep;
int cmd;
int key;
@@ -1280,15 +1287,15 @@ map_bind(EditLine *el, int argc, const char **argv)
return (0);
case 'l':
- for (bp = el->el_map.help; bp->name != NULL;
- bp++)
+ ep = &el->el_map.help[el->el_map.nfunc];
+ for (bp = el->el_map.help; bp < ep; bp++)
(void) fprintf(el->el_outfile,
- "%s\n\t%s\n",
+ "" FSTR "\n\t" FSTR "\n",
bp->name, bp->description);
return (0);
default:
(void) fprintf(el->el_errfile,
- "%s: Invalid switch `%c'.\n",
+ "" FSTR ": Invalid switch `%c'.\n",
argv[0], p[1]);
}
else
@@ -1302,7 +1309,7 @@ map_bind(EditLine *el, int argc, const char **argv)
in = argv[argc++];
else if ((in = parse__string(inbuf, argv[argc++])) == NULL) {
(void) fprintf(el->el_errfile,
- "%s: Invalid \\ or ^ in instring.\n",
+ "" FSTR ": Invalid \\ or ^ in instring.\n",
argv[0]);
return (-1);
}
@@ -1338,7 +1345,7 @@ map_bind(EditLine *el, int argc, const char **argv)
case XK_EXE:
if ((out = parse__string(outbuf, argv[argc])) == NULL) {
(void) fprintf(el->el_errfile,
- "%s: Invalid \\ or ^ in outstring.\n", argv[0]);
+ "" FSTR ": Invalid \\ or ^ in outstring.\n", argv[0]);
return (-1);
}
if (key)
@@ -1351,7 +1358,8 @@ map_bind(EditLine *el, int argc, const char **argv)
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]);
+ "" FSTR ": Invalid command `" FSTR "'.\n",
+ argv[0], argv[argc]);
return (-1);
}
if (key)
@@ -1368,7 +1376,7 @@ map_bind(EditLine *el, int argc, const char **argv)
break;
default:
- EL_ABORT((el->el_errfile, "Bad XK_ type\n", ntype));
+ EL_ABORT((el->el_errfile, "Bad XK_ type %d\n", ntype));
break;
}
return (0);
@@ -1379,10 +1387,10 @@ map_bind(EditLine *el, int argc, const char **argv)
* add a user defined function
*/
protected int
-map_addfunc(EditLine *el, const char *name, const char *help, el_func_t func)
+map_addfunc(EditLine *el, const Char *name, const Char *help, el_func_t func)
{
void *p;
- int nf = el->el_map.nfunc + 2;
+ int nf = el->el_map.nfunc + 1;
if (name == NULL || help == NULL || func == NULL)
return (-1);
@@ -1401,7 +1409,6 @@ map_addfunc(EditLine *el, const char *name, const char *help, el_func_t func)
el->el_map.help[nf].name = name;
el->el_map.help[nf].func = nf;
el->el_map.help[nf].description = help;
- el->el_map.help[++nf].name = NULL;
el->el_map.nfunc++;
return (0);
diff --git a/lib/libedit/map.h b/lib/libedit/map.h
index 5eacd97512d..1dedbef6802 100644
--- a/lib/libedit/map.h
+++ b/lib/libedit/map.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: map.h,v 1.7 2003/10/31 08:42:24 otto Exp $ */
-/* $NetBSD: map.h,v 1.8 2003/08/07 16:44:32 agc Exp $ */
+/* $OpenBSD: map.h,v 1.8 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: map.h,v 1.9 2009/12/30 22:37:40 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -42,9 +42,9 @@
#define _h_el_map
typedef struct el_bindings_t { /* for the "bind" shell command */
- const char *name; /* function name for bind command */
+ const Char *name; /* function name for bind command */
int func; /* function numeric value */
- const char *description; /* description of function */
+ const Char *description; /* description of function */
} el_bindings_t;
@@ -64,13 +64,15 @@ typedef struct el_map_t {
#define MAP_EMACS 0
#define MAP_VI 1
-protected int map_bind(EditLine *, int, const char **);
+#define N_KEYS 256
+
+protected int map_bind(EditLine *, int, const Char **);
protected int map_init(EditLine *);
protected void map_end(EditLine *);
protected void map_init_vi(EditLine *);
protected void map_init_emacs(EditLine *);
-protected int map_set_editor(EditLine *, char *);
-protected int map_get_editor(EditLine *, const char **);
-protected int map_addfunc(EditLine *, const char *, const char *, el_func_t);
+protected int map_set_editor(EditLine *, Char *);
+protected int map_get_editor(EditLine *, const Char **);
+protected int map_addfunc(EditLine *, const Char *, const Char *, el_func_t);
#endif /* _h_el_map */
diff --git a/lib/libedit/parse.c b/lib/libedit/parse.c
index 29670ac5df2..844b3b4b622 100644
--- a/lib/libedit/parse.c
+++ b/lib/libedit/parse.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: parse.c,v 1.9 2009/10/27 23:59:28 deraadt Exp $ */
-/* $NetBSD: parse.c,v 1.19 2003/11/02 20:06:57 christos Exp $ */
+/* $OpenBSD: parse.c,v 1.10 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: parse.c,v 1.23 2009/12/30 22:37:40 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -49,21 +49,20 @@
* setty
*/
#include "el.h"
-#include "tokenizer.h"
#include <stdlib.h>
private const struct {
- const char *name;
- int (*func)(EditLine *, int, const char **);
+ const Char *name;
+ int (*func)(EditLine *, int, const Char **);
} cmds[] = {
- { "bind", map_bind },
- { "echotc", term_echotc },
- { "edit", el_editmode },
- { "history", hist_command },
- { "telltc", term_telltc },
- { "settc", term_settc },
- { "setty", tty_stty },
- { NULL, NULL }
+ { STR("bind"), map_bind },
+ { STR("echotc"), term_echotc },
+ { STR("edit"), el_editmode },
+ { STR("history"), hist_command },
+ { STR("telltc"), term_telltc },
+ { STR("settc"), term_settc },
+ { STR("setty"), tty_stty },
+ { NULL, NULL }
};
@@ -71,16 +70,16 @@ private const struct {
* Parse a line and dispatch it
*/
protected int
-parse_line(EditLine *el, const char *line)
+parse_line(EditLine *el, const Char *line)
{
- const char **argv;
+ const Char **argv;
int argc;
- Tokenizer *tok;
+ TYPE(Tokenizer) *tok;
- tok = tok_init(NULL);
- tok_line(tok, line, &argc, &argv);
- argc = el_parse(el, argc, argv);
- tok_end(tok);
+ tok = FUN(tok,init)(NULL);
+ FUN(tok,str)(tok, line, &argc, &argv);
+ argc = FUN(el,parse)(el, argc, argv);
+ FUN(tok,end)(tok);
return (argc);
}
@@ -89,25 +88,25 @@ parse_line(EditLine *el, const char *line)
* Command dispatcher
*/
public int
-el_parse(EditLine *el, int argc, const char *argv[])
+FUN(el,parse)(EditLine *el, int argc, const Char *argv[])
{
- const char *ptr;
+ const Char *ptr;
int i;
if (argc < 1)
return (-1);
- ptr = strchr(argv[0], ':');
+ ptr = Strchr(argv[0], ':');
if (ptr != NULL) {
- char *tprog;
+ Char *tprog;
size_t l;
if (ptr == argv[0])
return (0);
l = ptr - argv[0] - 1;
- tprog = (char *) el_malloc(l + 1);
+ tprog = el_malloc((l + 1) * sizeof(*tprog));
if (tprog == NULL)
return (0);
- (void) strncpy(tprog, argv[0], l);
+ (void) Strncpy(tprog, argv[0], l);
tprog[l] = '\0';
ptr++;
l = el_match(el->el_prog, tprog);
@@ -118,7 +117,7 @@ el_parse(EditLine *el, int argc, const char *argv[])
ptr = argv[0];
for (i = 0; cmds[i].name != NULL; i++)
- if (strcmp(cmds[i].name, ptr) == 0) {
+ if (Strcmp(cmds[i].name, ptr) == 0) {
i = (*cmds[i].func) (el, argc, argv);
return (-i);
}
@@ -127,14 +126,14 @@ el_parse(EditLine *el, int argc, const char *argv[])
/* parse__escape():
- * Parse a string of the form ^<char> \<odigit> \<char> and return
+ * Parse a string of the form ^<char> \<odigit> \<char> \U+xxxx and return
* the appropriate character or -1 if the escape is not valid
*/
protected int
-parse__escape(const char **const ptr)
+parse__escape(const Char **ptr)
{
- const char *p;
- int c;
+ const Char *p;
+ Int c;
p = *ptr;
@@ -168,6 +167,28 @@ parse__escape(const char **const ptr)
case 'e':
c = '\033'; /* Escape */
break;
+ case 'U': /* Unicode \U+xxxx or \U+xxxxx format */
+ {
+ int i;
+ const Char hex[] = STR("0123456789ABCDEF");
+ const Char *h;
+ ++p;
+ if (*p++ != '+')
+ return (-1);
+ c = 0;
+ for (i = 0; i < 5; ++i) {
+ h = Strchr(hex, *p++);
+ if (!h && i < 4)
+ return (-1);
+ else if (h)
+ c = (c << 4) | ((int)(h - hex));
+ else
+ --p;
+ }
+ if (c > 0x10FFFF) /* outside valid character range */
+ return -1;
+ break;
+ }
case '0':
case '1':
case '2':
@@ -208,10 +229,10 @@ parse__escape(const char **const ptr)
/* parse__string():
* Parse the escapes from in and put the raw string out
*/
-protected char *
-parse__string(char *out, const char *in)
+protected Char *
+parse__string(Char *out, const Char *in)
{
- char *rv = out;
+ Char *rv = out;
int n;
for (;;)
@@ -247,12 +268,12 @@ parse__string(char *out, const char *in)
* or -1 if one is not found
*/
protected int
-parse_cmd(EditLine *el, const char *cmd)
+parse_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)
+ if (Strcmp(b->name, cmd) == 0)
return (b->func);
return (-1);
}
diff --git a/lib/libedit/parse.h b/lib/libedit/parse.h
index 51b1207c89a..b2dfdebe19c 100644
--- a/lib/libedit/parse.h
+++ b/lib/libedit/parse.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: parse.h,v 1.6 2003/10/31 08:42:24 otto Exp $ */
-/* $NetBSD: parse.h,v 1.5 2003/08/07 16:44:32 agc Exp $ */
+/* $OpenBSD: parse.h,v 1.7 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: parse.h,v 1.7 2009/12/30 22:37:40 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -41,9 +41,9 @@
#ifndef _h_el_parse
#define _h_el_parse
-protected int parse_line(EditLine *, const char *);
-protected int parse__escape(const char ** const);
-protected char *parse__string(char *, const char *);
-protected int parse_cmd(EditLine *, const char *);
+protected int parse_line(EditLine *, const Char *);
+protected int parse__escape(const Char **);
+protected Char *parse__string(Char *, const Char *);
+protected int parse_cmd(EditLine *, const Char *);
#endif /* _h_el_parse */
diff --git a/lib/libedit/prompt.c b/lib/libedit/prompt.c
index 0ad61143164..f07470c4d36 100644
--- a/lib/libedit/prompt.c
+++ b/lib/libedit/prompt.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: prompt.c,v 1.8 2009/10/27 23:59:28 deraadt Exp $ */
-/* $NetBSD: prompt.c,v 1.11 2003/08/07 16:44:32 agc Exp $ */
+/* $OpenBSD: prompt.c,v 1.9 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: prompt.c,v 1.18 2009/12/31 15:58:26 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -41,17 +41,17 @@
#include <stdio.h>
#include "el.h"
-private char *prompt_default(EditLine *);
-private char *prompt_default_r(EditLine *);
+private Char *prompt_default(EditLine *);
+private Char *prompt_default_r(EditLine *);
/* prompt_default():
* Just a default prompt, in case the user did not provide one
*/
-private char *
+private Char *
/*ARGSUSED*/
prompt_default(EditLine *el __attribute__((__unused__)))
{
- static char a[3] = {'?', ' ', '\0'};
+ static Char a[3] = {'?', ' ', '\0'};
return (a);
}
@@ -60,11 +60,11 @@ prompt_default(EditLine *el __attribute__((__unused__)))
/* prompt_default_r():
* Just a default rprompt, in case the user did not provide one
*/
-private char *
+private Char *
/*ARGSUSED*/
prompt_default_r(EditLine *el __attribute__((__unused__)))
{
- static char a[1] = {'\0'};
+ static Char a[1] = {'\0'};
return (a);
}
@@ -72,23 +72,35 @@ prompt_default_r(EditLine *el __attribute__((__unused__)))
/* 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(EditLine *el, int op)
{
el_prompt_t *elp;
- char *p;
+ Char *p;
+ int ignore = 0;
if (op == EL_PROMPT)
elp = &el->el_prompt;
else
elp = &el->el_rprompt;
- p = (elp->p_func) (el);
- while (*p)
- re_putc(el, *p++, 1);
+
+ if (elp->p_wide)
+ p = (*elp->p_func)(el);
+ else
+ p = ct_decode_string((char *)(void *)(*elp->p_func)(el),
+ &el->el_scratch);
+
+ for (; *p; p++) {
+ if (elp->p_ignore == *p) {
+ ignore = !ignore;
+ continue;
+ }
+ if (ignore)
+ term__putc(el, *p);
+ else
+ re_putc(el, *p, 1);
+ }
elp->p_pos.v = el->el_refresh.r_cursor.v;
elp->p_pos.h = el->el_refresh.r_cursor.h;
@@ -105,10 +117,12 @@ prompt_init(EditLine *el)
el->el_prompt.p_func = prompt_default;
el->el_prompt.p_pos.v = 0;
el->el_prompt.p_pos.h = 0;
+ el->el_prompt.p_ignore = '\0';
el->el_rprompt.p_func = prompt_default_r;
el->el_rprompt.p_pos.v = 0;
el->el_rprompt.p_pos.h = 0;
- return (0);
+ el->el_rprompt.p_ignore = '\0';
+ return 0;
}
@@ -126,24 +140,31 @@ prompt_end(EditLine *el __attribute__((__unused__)))
* Install a prompt printing function
*/
protected int
-prompt_set(EditLine *el, el_pfunc_t prf, int op)
+prompt_set(EditLine *el, el_pfunc_t prf, Char c, int op, int wide)
{
el_prompt_t *p;
- if (op == EL_PROMPT)
+ if (op == EL_PROMPT || op == EL_PROMPT_ESC)
p = &el->el_prompt;
else
p = &el->el_rprompt;
+
if (prf == NULL) {
- if (op == EL_PROMPT)
+ if (op == EL_PROMPT || op == EL_PROMPT_ESC)
p->p_func = prompt_default;
else
p->p_func = prompt_default_r;
- } else
+ } else {
p->p_func = prf;
+ }
+
+ p->p_ignore = c;
+
p->p_pos.v = 0;
p->p_pos.h = 0;
- return (0);
+ p->p_wide = wide;
+
+ return 0;
}
@@ -151,14 +172,22 @@ prompt_set(EditLine *el, el_pfunc_t prf, int op)
* Retrieve the prompt printing function
*/
protected int
-prompt_get(EditLine *el, el_pfunc_t *prf, int op)
+prompt_get(EditLine *el, el_pfunc_t *prf, Char *c, int op)
{
+ el_prompt_t *p;
if (prf == NULL)
- return (-1);
+ return -1;
+
if (op == EL_PROMPT)
- *prf = el->el_prompt.p_func;
+ p = &el->el_prompt;
else
- *prf = el->el_rprompt.p_func;
- return (0);
+ p = &el->el_rprompt;
+
+ if (prf)
+ *prf = p->p_func;
+ if (c)
+ *c = p->p_ignore;
+
+ return 0;
}
diff --git a/lib/libedit/prompt.h b/lib/libedit/prompt.h
index 9236fcbffc0..e0a22035031 100644
--- a/lib/libedit/prompt.h
+++ b/lib/libedit/prompt.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: prompt.h,v 1.6 2003/10/31 08:42:24 otto Exp $ */
-/* $NetBSD: prompt.h,v 1.6 2003/08/07 16:44:32 agc Exp $ */
+/* $OpenBSD: prompt.h,v 1.7 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: prompt.h,v 1.10 2009/12/30 22:37:40 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -43,16 +43,18 @@
#include "histedit.h"
-typedef char * (*el_pfunc_t)(EditLine*);
+typedef Char *(*el_pfunc_t)(EditLine *);
typedef struct el_prompt_t {
- el_pfunc_t p_func; /* Function to return the prompt */
- coord_t p_pos; /* position in the line after prompt */
+ el_pfunc_t p_func; /* Function to return the prompt */
+ coord_t p_pos; /* position in the line after prompt */
+ Char p_ignore; /* character to start/end literal */
+ int p_wide;
} el_prompt_t;
protected void prompt_print(EditLine *, int);
-protected int prompt_set(EditLine *, el_pfunc_t, int);
-protected int prompt_get(EditLine *, el_pfunc_t *, int);
+protected int prompt_set(EditLine *, el_pfunc_t, Char, int, int);
+protected int prompt_get(EditLine *, el_pfunc_t *, Char *, int);
protected int prompt_init(EditLine *);
protected void prompt_end(EditLine *);
diff --git a/lib/libedit/read.c b/lib/libedit/read.c
index 6fa9cf097cb..cda66f16474 100644
--- a/lib/libedit/read.c
+++ b/lib/libedit/read.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: read.c,v 1.12 2009/10/27 23:59:28 deraadt Exp $ */
-/* $NetBSD: read.c,v 1.30 2003/10/18 23:48:42 christos Exp $ */
+/* $OpenBSD: read.c,v 1.13 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: read.c,v 1.55 2010/03/22 22:59:06 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -43,14 +43,16 @@
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
+#include <limits.h>
#include "el.h"
-#define OKCMD -1
+#define OKCMD -1 /* must be -1! */
private int read__fixio(int, int);
private int read_preread(EditLine *);
-private int read_char(EditLine *, char *);
-private int read_getcmd(EditLine *, el_action_t *, char *);
+private int read_char(EditLine *, Char *);
+private int read_getcmd(EditLine *, el_action_t *, Char *);
+private void read_pop(c_macro_t *);
/* read_init():
* Initialize the read stuff
@@ -184,6 +186,9 @@ read_preread(EditLine *el)
if (el->el_tty.t_mode == ED_IO)
return (0);
+#ifndef WIDECHAR
+/* FIONREAD attempts to buffer up multiple bytes, and to make that work
+ * properly with partial wide/UTF-8 characters would need some careful work. */
#ifdef FIONREAD
(void) ioctl(el->el_infd, FIONREAD, (ioctl_t) & chrs);
if (chrs > 0) {
@@ -197,7 +202,7 @@ read_preread(EditLine *el)
}
}
#endif /* FIONREAD */
-
+#endif
return (chrs > 0);
}
@@ -206,33 +211,37 @@ read_preread(EditLine *el)
* Push a macro
*/
public void
-el_push(EditLine *el, char *str)
+FUN(el,push)(EditLine *el, const Char *str)
{
c_macro_t *ma = &el->el_chared.c_macro;
if (str != NULL && ma->level + 1 < EL_MAXMACRO) {
ma->level++;
- if ((ma->macro[ma->level] = el_strdup(str)) != NULL)
+ if ((ma->macro[ma->level] = Strdup(str)) != NULL)
return;
ma->level--;
}
term_beep(el);
- term__flush();
+ term__flush(el);
}
/* read_getcmd():
* Return next command from the input stream.
+ * Character values > 255 are not looked up in the map, but inserted.
*/
private int
-read_getcmd(EditLine *el, el_action_t *cmdnum, char *ch)
+read_getcmd(EditLine *el, el_action_t *cmdnum, Char *ch)
{
el_action_t cmd;
int num;
+ el->el_errno = 0;
do {
- if ((num = el_getc(el, ch)) != 1) /* if EOF or error */
+ if ((num = FUN(el,getc)(el, ch)) != 1) {/* if EOF or error */
+ el->el_errno = num == 0 ? 0 : errno;
return (num);
+ }
#ifdef KANJI
if ((*ch & 0200)) {
@@ -246,7 +255,12 @@ read_getcmd(EditLine *el, el_action_t *cmdnum, char *ch)
el->el_state.metanext = 0;
*ch |= 0200;
}
- cmd = el->el_map.current[(unsigned char) *ch];
+#ifdef WIDECHAR
+ if (*ch >= N_KEYS)
+ cmd = ED_INSERT;
+ else
+#endif
+ cmd = el->el_map.current[(unsigned char) *ch];
if (cmd == ED_SEQUENCE_LEAD_IN) {
key_value_t val;
switch (key_get(el, ch, &val)) {
@@ -254,7 +268,7 @@ read_getcmd(EditLine *el, el_action_t *cmdnum, char *ch)
cmd = val.cmd;
break;
case XK_STR:
- el_push(el, val.str);
+ FUN(el,push)(el, val.str);
break;
#ifdef notyet
case XK_EXE:
@@ -274,57 +288,117 @@ read_getcmd(EditLine *el, el_action_t *cmdnum, char *ch)
return (OKCMD);
}
+#ifdef WIDECHAR
+/* utf8_islead():
+ * Test whether a byte is a leading byte of a UTF-8 sequence.
+ */
+private int
+utf8_islead(unsigned char c)
+{
+ return (c < 0x80) || /* single byte char */
+ (c >= 0xc2 && c <= 0xf4); /* start of multibyte sequence */
+}
+#endif
/* read_char():
* Read a character from the tty.
*/
private int
-read_char(EditLine *el, char *cp)
+read_char(EditLine *el, Char *cp)
{
- int num_read;
+ ssize_t num_read;
int tried = 0;
-
- while ((num_read = read(el->el_infd, cp, 1)) == -1)
+ char cbuf[MB_LEN_MAX];
+ int cbp = 0;
+ int bytes = 0;
+
+ again:
+ el->el_signal->sig_no = 0;
+ while ((num_read = read(el->el_infd, cbuf + cbp, 1)) == -1) {
+ if (el->el_signal->sig_no == SIGCONT) {
+ sig_set(el);
+ el_set(el, EL_REFRESH);
+ goto again;
+ }
if (!tried && read__fixio(el->el_infd, errno) == 0)
tried = 1;
else {
*cp = '\0';
return (-1);
}
+ }
- return (num_read);
+#ifdef WIDECHAR
+ if (el->el_flags & CHARSET_IS_UTF8) {
+ if (!utf8_islead((unsigned char)cbuf[0]))
+ goto again; /* discard the byte we read and try again */
+ ++cbp;
+ if ((bytes = ct_mbtowc(cp, cbuf, cbp)) == -1) {
+ ct_mbtowc_reset;
+ if (cbp >= MB_LEN_MAX) { /* "shouldn't happen" */
+ *cp = '\0';
+ return (-1);
+ }
+ goto again;
+ }
+ } else /* we don't support other multibyte charsets */
+#endif
+ *cp = (unsigned char)cbuf[0];
+
+ if ((el->el_flags & IGNORE_EXTCHARS) && bytes > 1) {
+ cbp = 0; /* skip this character */
+ goto again;
+ }
+
+ return (int)num_read;
}
+/* read_pop():
+ * Pop a macro from the stack
+ */
+private void
+read_pop(c_macro_t *ma)
+{
+ int i;
+
+ el_free(ma->macro[0]);
+ for (i = 0; i < ma->level; i++)
+ ma->macro[i] = ma->macro[i + 1];
+ ma->level--;
+ ma->offset = 0;
+}
/* el_getc():
* Read a character
*/
public int
-el_getc(EditLine *el, char *cp)
+FUN(el,getc)(EditLine *el, Char *cp)
{
int num_read;
c_macro_t *ma = &el->el_chared.c_macro;
- term__flush();
+ term__flush(el);
for (;;) {
if (ma->level < 0) {
if (!read_preread(el))
break;
}
+
if (ma->level < 0)
break;
- if (ma->macro[ma->level][ma->offset] == '\0') {
- el_free(ma->macro[ma->level--]);
- ma->offset = 0;
+ if (ma->macro[0][ma->offset] == '\0') {
+ read_pop(ma);
continue;
}
- *cp = ma->macro[ma->level][ma->offset++] & 0377;
- if (ma->macro[ma->level][ma->offset] == '\0') {
+
+ *cp = ma->macro[0][ma->offset++];
+
+ if (ma->macro[0][ma->offset] == '\0') {
/* Needed for QuoteMode On */
- el_free(ma->macro[ma->level--]);
- ma->offset = 0;
+ read_pop(ma);
}
+
return (1);
}
@@ -338,6 +412,10 @@ el_getc(EditLine *el, char *cp)
(void) fprintf(el->el_errfile, "Reading a character\n");
#endif /* DEBUG_READ */
num_read = (*el->el_read.read_char)(el, cp);
+#ifdef WIDECHAR
+ if (el->el_flags & NARROW_READ)
+ *cp = *(char *)(void *)cp;
+#endif
#ifdef DEBUG_READ
(void) fprintf(el->el_errfile, "Got it %c\n", *cp);
#endif /* DEBUG_READ */
@@ -358,8 +436,11 @@ read_prepare(EditLine *el)
we have the wrong size. */
el_resize(el);
re_clear_display(el); /* reset the display stuff */
- ch_reset(el);
+ ch_reset(el, 0);
re_refresh(el); /* print the prompt */
+
+ if (el->el_flags & UNBUFFERED)
+ term__flush(el);
}
protected void
@@ -371,23 +452,28 @@ read_finish(EditLine *el)
sig_clr(el);
}
-public const char *
-el_gets(EditLine *el, int *nread)
+public const Char *
+FUN(el,gets)(EditLine *el, int *nread)
{
int retval;
el_action_t cmdnum = 0;
int num; /* how many chars we have read at NL */
- char ch;
+ Char ch;
int crlf = 0;
+ int nrb;
#ifdef FIONREAD
c_macro_t *ma = &el->el_chared.c_macro;
#endif /* FIONREAD */
+ if (nread == NULL)
+ nread = &nrb;
+ *nread = 0;
+
if (el->el_flags & NO_TTY) {
- char *cp = el->el_line.buffer;
+ Char *cp = el->el_line.buffer;
size_t idx;
- while ((*el->el_read.read_char)(el, cp) == 1) {
+ while ((num = (*el->el_read.read_char)(el, cp)) == 1) {
/* make sure there is space for next character */
if (cp + 1 >= el->el_line.limit) {
idx = (cp - el->el_line.buffer);
@@ -401,12 +487,16 @@ el_gets(EditLine *el, int *nread)
if (cp[-1] == '\r' || cp[-1] == '\n')
break;
}
+ if (num == -1) {
+ if (errno == EINTR)
+ cp = el->el_line.buffer;
+ el->el_errno = errno;
+ }
el->el_line.cursor = el->el_line.lastchar = cp;
*cp = '\0';
- if (nread)
- *nread = el->el_line.cursor - el->el_line.buffer;
- return (el->el_line.buffer);
+ *nread = (int)(el->el_line.cursor - el->el_line.buffer);
+ goto done;
}
@@ -417,8 +507,8 @@ el_gets(EditLine *el, int *nread)
(void) ioctl(el->el_infd, FIONREAD, (ioctl_t) & chrs);
if (chrs == 0) {
if (tty_rawmode(el) < 0) {
- if (nread)
- *nread = 0;
+ errno = 0;
+ *nread = 0;
return (NULL);
}
}
@@ -429,12 +519,17 @@ el_gets(EditLine *el, int *nread)
read_prepare(el);
if (el->el_flags & EDIT_DISABLED) {
- char *cp = el->el_line.buffer;
+ Char *cp;
size_t idx;
- term__flush();
+ if ((el->el_flags & UNBUFFERED) == 0)
+ cp = el->el_line.buffer;
+ else
+ cp = el->el_line.lastchar;
- while ((*el->el_read.read_char)(el, cp) == 1) {
+ term__flush(el);
+
+ while ((num = (*el->el_read.read_char)(el, cp)) == 1) {
/* make sure there is space next character */
if (cp + 1 >= el->el_line.limit) {
idx = (cp - el->el_line.buffer);
@@ -442,8 +537,6 @@ el_gets(EditLine *el, int *nread)
break;
cp = &el->el_line.buffer[idx];
}
- if (*cp == 4) /* ought to be stty eof */
- break;
cp++;
crlf = cp[-1] == '\r' || cp[-1] == '\n';
if (el->el_flags & UNBUFFERED)
@@ -452,11 +545,15 @@ el_gets(EditLine *el, int *nread)
break;
}
+ if (num == -1) {
+ if (errno == EINTR)
+ cp = el->el_line.buffer;
+ el->el_errno = errno;
+ }
+
el->el_line.cursor = el->el_line.lastchar = cp;
*cp = '\0';
- if (nread)
- *nread = el->el_line.cursor - el->el_line.buffer;
- return (el->el_line.buffer);
+ goto done;
}
for (num = OKCMD; num == OKCMD;) { /* while still editing this
@@ -472,7 +569,13 @@ el_gets(EditLine *el, int *nread)
#endif /* DEBUG_READ */
break;
}
- if ((uint)cmdnum >= el->el_map.nfunc) { /* BUG CHECK command */
+ if (el->el_errno == EINTR) {
+ el->el_line.buffer[0] = '\0';
+ el->el_line.lastchar =
+ el->el_line.cursor = el->el_line.buffer;
+ break;
+ }
+ if ((unsigned int)cmdnum >= (unsigned int)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);
@@ -502,7 +605,7 @@ el_gets(EditLine *el, int *nread)
el->el_chared.c_redo.pos < el->el_chared.c_redo.lim) {
if (cmdnum == VI_DELETE_PREV_CHAR &&
el->el_chared.c_redo.pos != el->el_chared.c_redo.buf
- && isprint(el->el_chared.c_redo.pos[-1]))
+ && Isprint(el->el_chared.c_redo.pos[-1]))
el->el_chared.c_redo.pos--;
else
*el->el_chared.c_redo.pos++ = ch;
@@ -547,14 +650,14 @@ el_gets(EditLine *el, int *nread)
if ((el->el_flags & UNBUFFERED) == 0)
num = 0;
else if (num == -1) {
- *el->el_line.lastchar++ = CTRL('d');
+ *el->el_line.lastchar++ = CONTROL('d');
el->el_line.cursor = el->el_line.lastchar;
num = 1;
}
break;
case CC_NEWLINE: /* normal end of line */
- num = el->el_line.lastchar - el->el_line.buffer;
+ num = (int)(el->el_line.lastchar - el->el_line.buffer);
break;
case CC_FATAL: /* fatal error, reset to known state */
@@ -564,7 +667,7 @@ el_gets(EditLine *el, int *nread)
#endif /* DEBUG_READ */
/* put (real) cursor in a known place */
re_clear_display(el); /* reset the display stuff */
- ch_reset(el); /* reset the input pointers */
+ ch_reset(el, 1); /* reset the input pointers */
re_refresh(el); /* print the prompt again */
break;
@@ -575,7 +678,7 @@ el_gets(EditLine *el, int *nread)
"*** editor ERROR ***\r\n\n");
#endif /* DEBUG_READ */
term_beep(el);
- term__flush();
+ term__flush(el);
break;
}
el->el_state.argument = 1;
@@ -585,15 +688,21 @@ el_gets(EditLine *el, int *nread)
break;
}
- term__flush(); /* flush any buffered output */
+ term__flush(el); /* flush any buffered output */
/* make sure the tty is set up correctly */
if ((el->el_flags & UNBUFFERED) == 0) {
read_finish(el);
- if (nread)
- *nread = num;
+ *nread = num != -1 ? num : 0;
} else {
- if (nread)
- *nread = el->el_line.lastchar - el->el_line.buffer;
+ *nread = (int)(el->el_line.lastchar - el->el_line.buffer);
}
- return (num ? el->el_line.buffer : NULL);
+done:
+ if (*nread == 0) {
+ if (num == -1) {
+ *nread = -1;
+ errno = el->el_errno;
+ }
+ return NULL;
+ } else
+ return el->el_line.buffer;
}
diff --git a/lib/libedit/read.h b/lib/libedit/read.h
index 412a44f2d97..b0a7aaf113f 100644
--- a/lib/libedit/read.h
+++ b/lib/libedit/read.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: read.h,v 1.2 2008/06/26 05:42:05 ray Exp $ */
-/* $NetBSD: read.h,v 1.2 2003/09/26 17:44:51 christos Exp $ */
+/* $OpenBSD: read.h,v 1.3 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: read.h,v 1.7 2009/12/30 22:37:40 christos Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -36,7 +36,7 @@
#ifndef _h_el_read
#define _h_el_read
-typedef int (*el_rfunc_t)(EditLine *, char *);
+typedef int (*el_rfunc_t)(EditLine *, Char *);
typedef struct el_read_t {
el_rfunc_t read_char; /* Function to read a character */
diff --git a/lib/libedit/readline.c b/lib/libedit/readline.c
index 267527fa7c8..067b0402d60 100644
--- a/lib/libedit/readline.c
+++ b/lib/libedit/readline.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: readline.c,v 1.7 2009/10/27 23:59:28 deraadt Exp $ */
-/* $NetBSD: readline.c,v 1.43 2003/11/03 03:22:55 christos Exp $ */
+/* $OpenBSD: readline.c,v 1.8 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: readline.c,v 1.89 2010/04/15 00:57:33 christos Exp $ */
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -44,19 +44,20 @@
#include <limits.h>
#include <errno.h>
#include <fcntl.h>
+#include <setjmp.h>
#ifdef HAVE_VIS_H
#include <vis.h>
#else
#include "np/vis.h"
#endif
-#ifdef HAVE_ALLOCA_H
-#include <alloca.h>
-#endif
-#include "histedit.h"
#include "readline/readline.h"
#include "el.h"
-#include "tokenizer.h"
#include "fcns.h" /* for EL_NUM_FCNS */
+#include "histedit.h"
+#include "filecomplete.h"
+
+void rl_prep_terminal(int);
+void rl_deprep_terminal(void);
/* for rl_complete() */
#define TAB '\r'
@@ -67,6 +68,7 @@
/* readline compatibility stuff - look at readline sources/documentation */
/* to see what these variables mean */
const char *rl_library_version = "EditLine wrapper";
+int rl_readline_version = RL_READLINE_VERSION;
static char empty[] = { '\0' };
static char expand_chars[] = { ' ', '\t', '\n', '=', '(', '\0' };
static char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', '$',
@@ -77,9 +79,12 @@ FILE *rl_outstream = NULL;
int rl_point = 0;
int rl_end = 0;
char *rl_line_buffer = NULL;
-VFunction *rl_linefunc = NULL;
+VCPFunction *rl_linefunc = NULL;
int rl_done = 0;
VFunction *rl_event_hook = NULL;
+KEYMAP_ENTRY_ARRAY emacs_standard_keymap,
+ emacs_meta_keymap,
+ emacs_ctlx_keymap;
int history_base = 1; /* probably never subject to change */
int history_length = 0;
@@ -99,17 +104,24 @@ Function *rl_completion_entry_function = NULL;
CPPFunction *rl_attempted_completion_function = NULL;
Function *rl_pre_input_hook = NULL;
Function *rl_startup1_hook = NULL;
-Function *rl_getc_function = NULL;
+int (*rl_getc_function)(FILE *) = NULL;
char *rl_terminal_name = NULL;
int rl_already_prompted = 0;
int rl_filename_completion_desired = 0;
int rl_ignore_completion_duplicates = 0;
int rl_catch_signals = 1;
+int readline_echoing_p = 1;
+int _rl_print_completions_horizontally = 0;
VFunction *rl_redisplay_function = NULL;
Function *rl_startup_hook = NULL;
VFunction *rl_completion_display_matches_hook = NULL;
-VFunction *rl_prep_term_function = NULL;
-VFunction *rl_deprep_term_function = NULL;
+VFunction *rl_prep_term_function = (VFunction *)rl_prep_terminal;
+VFunction *rl_deprep_term_function = (VFunction *)rl_deprep_terminal;
+KEYMAP_ENTRY_ARRAY emacs_meta_keymap;
+
+#ifdef WIDECHAR
+static ct_buffer_t conv;
+#endif
/*
* The current prompt string.
@@ -133,7 +145,7 @@ int rl_completion_query_items = 100;
* in the parsed text when it is passed to the completion function.
* Shell uses this to help determine what kind of completing to do.
*/
-char *rl_special_prefixes = (char *)NULL;
+char *rl_special_prefixes = NULL;
/*
* This is the character appended to the completed words if at the end of
@@ -143,25 +155,23 @@ int rl_completion_append_character = ' ';
/* stuff below is used internally by libedit for readline emulation */
-/* if not zero, non-unique completions always show list of possible matches */
-static int _rl_complete_show_all = 0;
-
-static History *h = NULL;
+static TYPE(History) *h = NULL;
static EditLine *e = NULL;
static Function *map[256];
-static int el_rl_complete_cmdnum = 0;
+static jmp_buf topbuf;
/* internal functions */
static unsigned char _el_rl_complete(EditLine *, int);
+static unsigned char _el_rl_tstp(EditLine *, int);
static char *_get_prompt(EditLine *);
+static int _getc_function(EditLine *, char *);
static HIST_ENTRY *_move_history(int);
static int _history_expand_command(const char *, size_t, size_t,
char **);
static char *_rl_compat_sub(const char *, const char *,
const char *, int);
-static int rl_complete_internal(int);
-static int _rl_qsort_string_compare(const void *, const void *);
static int _rl_event_read_char(EditLine *, char *);
+static void _rl_update_pos(void);
/* ARGSUSED */
@@ -179,13 +189,13 @@ _get_prompt(EditLine *el __attribute__((__unused__)))
static HIST_ENTRY *
_move_history(int op)
{
- HistEvent ev;
+ TYPE(HistEvent) ev;
static HIST_ENTRY rl_he;
- if (history(h, &ev, op) != 0)
+ if (FUNW(history)(h, &ev, op) != 0)
return (HIST_ENTRY *) NULL;
- rl_he.line = ev.str;
+ rl_he.line = ct_encode_string(ev.str, &conv);
rl_he.data = NULL;
return (&rl_he);
@@ -193,25 +203,81 @@ _move_history(int op)
/*
+ * read one key from user defined input function
+ */
+static int
+/*ARGSUSED*/
+_getc_function(EditLine *el, char *c)
+{
+ int i;
+
+ i = (*rl_getc_function)(NULL);
+ if (i == -1)
+ return 0;
+ *c = i;
+ return 1;
+}
+
+static const char _dothistory[] = "/.history";
+
+static const char *
+_default_history_file(void)
+{
+ struct passwd *p;
+ static char path[PATH_MAX];
+
+ if (*path)
+ return path;
+ if ((p = getpwuid(getuid())) == NULL)
+ return NULL;
+ strlcpy(path, p->pw_dir, PATH_MAX);
+ strlcat(path, _dothistory, PATH_MAX);
+ return path;
+}
+
+/*
* READLINE compatibility stuff
*/
/*
+ * Set the prompt
+ */
+int
+rl_set_prompt(const char *prompt)
+{
+ char *p;
+
+ if (!prompt)
+ prompt = "";
+ if (rl_prompt != NULL && strcmp(rl_prompt, prompt) == 0)
+ return 0;
+ if (rl_prompt)
+ free(rl_prompt);
+ rl_prompt = strdup(prompt);
+ if (rl_prompt == NULL)
+ return -1;
+
+ while ((p = strchr(rl_prompt, RL_PROMPT_END_IGNORE)) != NULL)
+ *p = RL_PROMPT_START_IGNORE;
+
+ return 0;
+}
+
+/*
* initialize rl compat stuff
*/
int
rl_initialize(void)
{
- HistEvent ev;
+ TYPE(HistEvent) ev;
const LineInfo *li;
- int i;
int editmode = 1;
struct termios t;
if (e != NULL)
el_end(e);
if (h != NULL)
- history_end(h);
+ FUN(history,end)(h);
if (!rl_instream)
rl_instream = stdin;
@@ -227,29 +293,32 @@ rl_initialize(void)
e = el_init(rl_readline_name, rl_instream, rl_outstream, stderr);
if (!editmode)
- el_set(e, EL_EDITMODE, 0);
+ FUN(el,set)(e, EL_EDITMODE, 0);
- h = history_init();
+ h = FUN(history,init)();
if (!e || !h)
return (-1);
- history(h, &ev, H_SETSIZE, INT_MAX); /* unlimited */
+ FUNW(history)(h, &ev, H_SETSIZE, INT_MAX); /* unlimited */
history_length = 0;
max_input_history = INT_MAX;
el_set(e, EL_HIST, history, h);
+ /* setup getc function if valid */
+ if (rl_getc_function)
+ el_set(e, EL_GETCFN, _getc_function);
+
/* for proper prompt printing in readline() */
- rl_prompt = strdup("");
- if (rl_prompt == NULL) {
- history_end(h);
+ if (rl_set_prompt("") == -1) {
+ FUN(history,end)(h);
el_end(e);
return -1;
}
- el_set(e, EL_PROMPT, _get_prompt);
+ el_set(e, EL_PROMPT, _get_prompt, RL_PROMPT_START_IGNORE);
el_set(e, EL_SIGNAL, rl_catch_signals);
/* set default mode to "emacs"-style and read setting afterwards */
- /* so this can be overridden */
+ /* so this can be overriden */
el_set(e, EL_EDITOR, "emacs");
if (rl_terminal_name != NULL)
el_set(e, EL_TERMINAL, rl_terminal_name);
@@ -264,16 +333,14 @@ rl_initialize(void)
"ReadLine compatible completion function",
_el_rl_complete);
el_set(e, EL_BIND, "^I", "rl_complete", NULL);
+
/*
- * Find out where the rl_complete function was added; this is
- * used later to detect that lastcmd was also rl_complete.
+ * Send TSTP when ^Z is pressed.
*/
- for(i=EL_NUM_FCNS; i < e->el_map.nfunc; i++) {
- if (e->el_map.func[i] == _el_rl_complete) {
- el_rl_complete_cmdnum = i;
- break;
- }
- }
+ el_set(e, EL_ADDFN, "rl_tstp",
+ "ReadLine compatible suspend function",
+ _el_rl_tstp);
+ el_set(e, EL_BIND, "^Z", "rl_tstp", NULL);
/* read settings from configuration file */
el_source(e, NULL);
@@ -285,7 +352,7 @@ rl_initialize(void)
li = el_line(e);
/* a cheesy way to get rid of const cast. */
rl_line_buffer = memchr(li->buffer, *li->buffer, 1);
- rl_point = rl_end = 0;
+ _rl_update_pos();
if (rl_startup_hook)
(*rl_startup_hook)(NULL, 0);
@@ -299,9 +366,10 @@ rl_initialize(void)
* trailing newline (if there is any)
*/
char *
-readline(const char *prompt)
+readline(const char *p)
{
- HistEvent ev;
+ TYPE(HistEvent) ev;
+ const char * volatile prompt = p;
int count;
const char *ret;
char *buf;
@@ -312,15 +380,11 @@ readline(const char *prompt)
rl_done = 0;
+ (void)setjmp(topbuf);
+
/* update prompt accordingly to what has been passed */
- if (!prompt)
- prompt = "";
- if (strcmp(rl_prompt, prompt) != 0) {
- free(rl_prompt);
- rl_prompt = strdup(prompt);
- if (rl_prompt == NULL)
- return NULL;
- }
+ if (rl_set_prompt(prompt) == -1)
+ return NULL;
if (rl_pre_input_hook)
(*rl_pre_input_hook)(NULL, 0);
@@ -352,7 +416,7 @@ readline(const char *prompt)
} else
buf = NULL;
- history(h, &ev, H_GETSIZE);
+ FUNW(history)(h, &ev, H_GETSIZE);
history_length = ev.num;
return buf;
@@ -402,8 +466,7 @@ _rl_compat_sub(const char *str, const char *what, const char *with,
} else
s++;
}
- len++;
- r = result = malloc(len);
+ r = result = malloc(len + 1);
if (result == NULL)
return NULL;
s = str;
@@ -411,7 +474,6 @@ _rl_compat_sub(const char *str, const char *what, const char *with,
if (*s == *what && !strncmp(s, what, what_len)) {
(void)strncpy(r, with, with_len);
r += with_len;
- len -= with_len;
s += what_len;
if (!globally) {
(void)strlcpy(r, s, len);
@@ -420,7 +482,7 @@ _rl_compat_sub(const char *str, const char *what, const char *with,
} else
*r++ = *s++;
}
- *r = 0;
+ *r = '\0';
return(result);
}
@@ -434,18 +496,18 @@ get_history_event(const char *cmd, int *cindex, int qchar)
size_t len;
char *pat;
const char *rptr;
- HistEvent ev;
+ TYPE(HistEvent) ev;
idx = *cindex;
if (cmd[idx++] != history_expansion_char)
return(NULL);
/* find out which event to take */
- if (cmd[idx] == history_expansion_char || cmd[idx] == 0) {
- if (history(h, &ev, H_FIRST) != 0)
+ if (cmd[idx] == history_expansion_char || cmd[idx] == '\0') {
+ if (FUNW(history)(h, &ev, H_FIRST) != 0)
return(NULL);
*cindex = cmd[idx]? (idx + 1):idx;
- return(ev.str);
+ return ct_encode_string(ev.str, &conv);
}
sign = 0;
if (cmd[idx] == '-') {
@@ -500,7 +562,7 @@ get_history_event(const char *cmd, int *cindex, int qchar)
pat[len] = '\0';
}
- if (history(h, &ev, H_CURR) != 0) {
+ if (FUNW(history)(h, &ev, H_CURR) != 0) {
if (pat != last_search_pat)
free(pat);
return (NULL);
@@ -519,7 +581,7 @@ get_history_event(const char *cmd, int *cindex, int qchar)
if (ret == -1) {
/* restore to end of list on failed search */
- history(h, &ev, H_FIRST);
+ FUNW(history)(h, &ev, H_FIRST);
(void)fprintf(rl_outstream, "%s: Event not found\n", pat);
if (pat != last_search_pat)
free(pat);
@@ -535,13 +597,13 @@ get_history_event(const char *cmd, int *cindex, int qchar)
if (pat != last_search_pat)
free(pat);
- if (history(h, &ev, H_CURR) != 0)
+ if (FUNW(history)(h, &ev, H_CURR) != 0)
return(NULL);
*cindex = idx;
- rptr = ev.str;
+ rptr = ct_encode_string(ev.str, &conv);
/* roll back to original position */
- (void)history(h, &ev, H_SET, num);
+ (void)FUNW(history)(h, &ev, H_SET, num);
return rptr;
}
@@ -606,9 +668,11 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen,
return(-1);
if (!has_mods) {
- *result = strdup(aptr? aptr : ptr);
+ *result = strdup(aptr ? aptr : ptr);
if (aptr)
free(aptr);
+ if (*result == NULL)
+ return -1;
return(1);
}
@@ -663,7 +727,7 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen,
if (aptr)
free(aptr);
- if (*cmd == 0 || (cmd - (command + offs) >= cmdlen)) {
+ if (*cmd == '\0' || ((size_t)(cmd - (command + offs)) >= cmdlen)) {
*result = tmp;
return(1);
}
@@ -673,7 +737,7 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen,
continue;
else if (*cmd == 'h') { /* remove trailing path */
if ((aptr = strrchr(tmp, '/')) != NULL)
- *aptr = 0;
+ *aptr = '\0';
} else if (*cmd == 't') { /* remove leading path */
if ((aptr = strrchr(tmp, '/')) != NULL) {
aptr = strdup(aptr + 1);
@@ -682,7 +746,7 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen,
}
} else if (*cmd == 'r') { /* remove trailing suffix */
if ((aptr = strrchr(tmp, '.')) != NULL)
- *aptr = 0;
+ *aptr = '\0';
} else if (*cmd == 'e') { /* remove all but suffix */
if ((aptr = strrchr(tmp, '.')) != NULL) {
aptr = strdup(aptr);
@@ -706,6 +770,7 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen,
what = realloc(from, size);
if (what == NULL) {
free(from);
+ free(tmp);
return 0;
}
len = 0;
@@ -718,6 +783,7 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen,
(size <<= 1));
if (nwhat == NULL) {
free(what);
+ free(tmp);
return 0;
}
what = nwhat;
@@ -730,10 +796,13 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen,
free(what);
if (search) {
from = strdup(search);
- if (from == NULL)
+ if (from == NULL) {
+ free(tmp);
return 0;
+ }
} else {
from = NULL;
+ free(tmp);
return (-1);
}
}
@@ -745,6 +814,7 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen,
with = realloc(to, size);
if (with == NULL) {
free(to);
+ free(tmp);
return -1;
}
len = 0;
@@ -756,13 +826,15 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen,
nwith = realloc(with, size);
if (nwith == NULL) {
free(with);
+ free(tmp);
return -1;
}
with = nwith;
}
if (*cmd == '&') {
+ /* safe */
(void)strlcpy(&with[len], from,
- size - len);
+ size - len);
len += from_len;
continue;
}
@@ -825,12 +897,14 @@ history_expand(char *str, char **output)
return 0;
}
-#define ADD_STRING(what, len) \
+#define ADD_STRING(what, len, fr) \
{ \
if (idx + len + 1 > size) { \
char *nresult = realloc(result, (size += len + 1));\
if (nresult == NULL) { \
free(*output); \
+ if (/*CONSTCOND*/fr) \
+ free(tmp); \
return 0; \
} \
result = nresult; \
@@ -842,6 +916,7 @@ history_expand(char *str, char **output)
result = NULL;
size = idx = 0;
+ tmp = NULL;
for (i = 0; str[i];) {
int qchar, loop_again;
size_t len, start, j;
@@ -880,13 +955,11 @@ loop:
goto loop;
}
len = i - start;
- tmp = &str[start];
- ADD_STRING(tmp, len);
+ ADD_STRING(&str[start], len, 0);
if (str[i] == '\0' || str[i] != history_expansion_char) {
len = j - i;
- tmp = &str[i];
- ADD_STRING(tmp, len);
+ ADD_STRING(&str[i], len, 0);
if (start == 0)
ret = 0;
else
@@ -896,8 +969,11 @@ loop:
ret = _history_expand_command (str, i, (j - i), &tmp);
if (ret > 0 && tmp) {
len = strlen(tmp);
- ADD_STRING(tmp, len);
+ ADD_STRING(tmp, len, 1);
+ }
+ if (tmp) {
free(tmp);
+ tmp = NULL;
}
i = j;
}
@@ -926,53 +1002,53 @@ char *
history_arg_extract(int start, int end, const char *str)
{
size_t i, len, max;
- char **arr, *result;
+ char **arr, *result = NULL;
arr = history_tokenize(str);
if (!arr)
- return(NULL);
- if (arr && *arr == NULL) {
- free(arr);
- return(NULL);
- }
+ return NULL;
+ if (arr && *arr == NULL)
+ goto out;
for (max = 0; arr[max]; max++)
continue;
max--;
if (start == '$')
- start = max;
+ start = (int)max;
if (end == '$')
- end = max;
+ end = (int)max;
if (end < 0)
- end = max + end + 1;
+ end = (int)max + end + 1;
if (start < 0)
start = end;
- if (start < 0 || end < 0 || start > max || end > max || start > end)
- return(NULL);
+ if (start < 0 || end < 0 || (size_t)start > max ||
+ (size_t)end > max || start > end)
+ goto out;
- for (i = start, len = 0; i <= end; i++)
+ for (i = start, len = 0; i <= (size_t)end; i++)
len += strlen(arr[i]) + 1;
len++;
max = len;
result = malloc(len);
if (result == NULL)
- return NULL;
+ goto out;
- for (i = start, len = 0; i <= end; i++) {
+ for (i = start, len = 0; i <= (size_t)end; i++) {
(void)strlcpy(result + len, arr[i], max - len);
len += strlen(arr[i]);
- if (i < end)
+ if (i < (size_t)end)
result[len++] = ' ';
}
- result[len] = 0;
+ result[len] = '\0';
+out:
for (i = 0; arr[i]; i++)
free(arr[i]);
free(arr);
- return(result);
+ return result;
}
/*
@@ -1041,12 +1117,12 @@ history_tokenize(const char *str)
void
stifle_history(int max)
{
- HistEvent ev;
+ TYPE(HistEvent) ev;
if (h == NULL || e == NULL)
rl_initialize();
- if (history(h, &ev, H_SETSIZE, max) == 0)
+ if (FUNW(history)(h, &ev, H_SETSIZE, max) == 0)
max_input_history = max;
}
@@ -1057,10 +1133,10 @@ stifle_history(int max)
int
unstifle_history(void)
{
- HistEvent ev;
+ TYPE(HistEvent) ev;
int omax;
- history(h, &ev, H_SETSIZE, INT_MAX);
+ FUNW(history)(h, &ev, H_SETSIZE, INT_MAX);
omax = max_input_history;
max_input_history = INT_MAX;
return (omax); /* some value _must_ be returned */
@@ -1075,6 +1151,142 @@ history_is_stifled(void)
return (max_input_history != INT_MAX);
}
+static const char _history_tmp_template[] = "/tmp/.historyXXXXXX";
+
+int
+history_truncate_file (const char *filename, int nlines)
+{
+ int ret = 0;
+ FILE *fp, *tp;
+ char template[sizeof(_history_tmp_template)];
+ char buf[4096];
+ int fd;
+ char *cp;
+ off_t off;
+ int count = 0;
+ ssize_t left = 0;
+
+ if (filename == NULL && (filename = _default_history_file()) == NULL)
+ return errno;
+ if ((fp = fopen(filename, "r+")) == NULL)
+ return errno;
+ strlcpy(template, _history_tmp_template, sizeof(template));
+ if ((fd = mkstemp(template)) == -1) {
+ ret = errno;
+ goto out1;
+ }
+
+ if ((tp = fdopen(fd, "r+")) == NULL) {
+ close(fd);
+ ret = errno;
+ goto out2;
+ }
+
+ for(;;) {
+ if (fread(buf, sizeof(buf), 1, fp) != 1) {
+ if (ferror(fp)) {
+ ret = errno;
+ break;
+ }
+ if (fseeko(fp, (off_t)sizeof(buf) * count, SEEK_SET) ==
+ (off_t)-1) {
+ ret = errno;
+ break;
+ }
+ left = fread(buf, 1, sizeof(buf), fp);
+ if (ferror(fp)) {
+ ret = errno;
+ break;
+ }
+ if (left == 0) {
+ count--;
+ left = sizeof(buf);
+ } else if (fwrite(buf, (size_t)left, 1, tp) != 1) {
+ ret = errno;
+ break;
+ }
+ fflush(tp);
+ break;
+ }
+ if (fwrite(buf, sizeof(buf), 1, tp) != 1) {
+ ret = errno;
+ break;
+ }
+ count++;
+ }
+ if (ret)
+ goto out3;
+ cp = buf + left - 1;
+ if(*cp != '\n')
+ cp++;
+ for(;;) {
+ while (--cp >= buf) {
+ if (*cp == '\n') {
+ if (--nlines == 0) {
+ if (++cp >= buf + sizeof(buf)) {
+ count++;
+ cp = buf;
+ }
+ break;
+ }
+ }
+ }
+ if (nlines <= 0 || count == 0)
+ break;
+ count--;
+ if (fseeko(tp, (off_t)sizeof(buf) * count, SEEK_SET) < 0) {
+ ret = errno;
+ break;
+ }
+ if (fread(buf, sizeof(buf), 1, tp) != 1) {
+ if (ferror(tp)) {
+ ret = errno;
+ break;
+ }
+ ret = EAGAIN;
+ break;
+ }
+ cp = buf + sizeof(buf);
+ }
+
+ if (ret || nlines > 0)
+ goto out3;
+
+ if (fseeko(fp, 0, SEEK_SET) == (off_t)-1) {
+ ret = errno;
+ goto out3;
+ }
+
+ if (fseeko(tp, (off_t)sizeof(buf) * count + (cp - buf), SEEK_SET) ==
+ (off_t)-1) {
+ ret = errno;
+ goto out3;
+ }
+
+ for(;;) {
+ if ((left = fread(buf, 1, sizeof(buf), tp)) == 0) {
+ if (ferror(fp))
+ ret = errno;
+ break;
+ }
+ if (fwrite(buf, (size_t)left, 1, fp) != 1) {
+ ret = errno;
+ break;
+ }
+ }
+ fflush(fp);
+ if((off = ftello(fp)) > 0)
+ (void)ftruncate(fileno(fp), off);
+out3:
+ fclose(tp);
+out2:
+ unlink(template);
+out1:
+ fclose(fp);
+
+ return ret;
+}
+
/*
* read history from a file given
@@ -1082,11 +1294,14 @@ history_is_stifled(void)
int
read_history(const char *filename)
{
- HistEvent ev;
+ TYPE(HistEvent) ev;
if (h == NULL || e == NULL)
rl_initialize();
- return (history(h, &ev, H_LOAD, filename));
+ if (filename == NULL && (filename = _default_history_file()) == NULL)
+ return errno;
+ return (FUNW(history)(h, &ev, H_LOAD, filename) == -1 ?
+ (errno ? errno : EINVAL) : 0);
}
@@ -1096,11 +1311,14 @@ read_history(const char *filename)
int
write_history(const char *filename)
{
- HistEvent ev;
+ TYPE(HistEvent) ev;
if (h == NULL || e == NULL)
rl_initialize();
- return (history(h, &ev, H_SAVE, filename));
+ if (filename == NULL && (filename = _default_history_file()) == NULL)
+ return errno;
+ return (FUNW(history)(h, &ev, H_SAVE, filename) == -1 ?
+ (errno ? errno : EINVAL) : 0);
}
@@ -1113,30 +1331,29 @@ HIST_ENTRY *
history_get(int num)
{
static HIST_ENTRY she;
- HistEvent ev;
+ TYPE(HistEvent) ev;
int curr_num;
if (h == NULL || e == NULL)
rl_initialize();
/* save current position */
- if (history(h, &ev, H_CURR) != 0)
+ if (FUNW(history)(h, &ev, H_CURR) != 0)
return (NULL);
curr_num = ev.num;
- /* start from most recent */
- if (history(h, &ev, H_FIRST) != 0)
+ /* start from the oldest */
+ if (FUNW(history)(h, &ev, H_LAST) != 0)
return (NULL); /* error */
- /* look backwards for event matching specified offset */
- if (history(h, &ev, H_NEXT_EVENT, num))
+ /* look forwards for event matching specified offset */
+ if (FUNW(history)(h, &ev, H_NEXT_EVDATA, num, &she.data))
return (NULL);
- she.line = ev.str;
- she.data = NULL;
+ she.line = ct_encode_string(ev.str, &conv);
/* restore pointer to where it was */
- (void)history(h, &ev, H_SET, curr_num);
+ (void)FUNW(history)(h, &ev, H_SET, curr_num);
return (&she);
}
@@ -1148,13 +1365,16 @@ history_get(int num)
int
add_history(const char *line)
{
- HistEvent ev;
+ TYPE(HistEvent) ev;
+ const Char *wline;
if (h == NULL || e == NULL)
rl_initialize();
- (void)history(h, &ev, H_ENTER, line);
- if (history(h, &ev, H_GETSIZE) == 0)
+ wline = ct_decode_string(line, &conv);
+
+ (void)FUNW(history)(h, &ev, H_ENTER, wline);
+ if (FUNW(history)(h, &ev, H_GETSIZE) == 0)
history_length = ev.num;
return (!(history_length > 0)); /* return 0 if all is okay */
@@ -1162,14 +1382,89 @@ add_history(const char *line)
/*
+ * remove the specified entry from the history list and return it.
+ */
+HIST_ENTRY *
+remove_history(int num)
+{
+ HIST_ENTRY *he;
+ TYPE(HistEvent) ev;
+
+ if (h == NULL || e == NULL)
+ rl_initialize();
+
+ if ((he = malloc(sizeof(*he))) == NULL)
+ return NULL;
+
+ if (FUNW(history)(h, &ev, H_DELDATA, num, &he->data) != 0) {
+ free(he);
+ return NULL;
+ }
+
+ he->line = ct_encode_string(ev.str, &conv);
+ if (FUNW(history)(h, &ev, H_GETSIZE) == 0)
+ history_length = ev.num;
+
+ return he;
+}
+
+
+/*
+ * replace the line and data of the num-th entry
+ */
+HIST_ENTRY *
+replace_history_entry(int num, const char *line, histdata_t data)
+{
+ HIST_ENTRY *he;
+ TYPE(HistEvent) ev;
+ int curr_num;
+
+ if (h == NULL || e == NULL)
+ rl_initialize();
+
+ /* save current position */
+ if (FUNW(history)(h, &ev, H_CURR) != 0)
+ return NULL;
+ curr_num = ev.num;
+
+ /* start from the oldest */
+ if (FUNW(history)(h, &ev, H_LAST) != 0)
+ return NULL; /* error */
+
+ if ((he = malloc(sizeof(*he))) == NULL)
+ return NULL;
+
+ /* look forwards for event matching specified offset */
+ if (FUNW(history)(h, &ev, H_NEXT_EVDATA, num, &he->data))
+ goto out;
+
+ he->line = strdup(ct_encode_string(ev.str, &e->el_scratch));
+ if (he->line == NULL)
+ goto out;
+
+ if (FUNW(history)(h, &ev, H_REPLACE, line, data))
+ goto out;
+
+ /* restore pointer to where it was */
+ if (FUNW(history)(h, &ev, H_SET, curr_num))
+ goto out;
+
+ return he;
+out:
+ free(he);
+ return NULL;
+}
+
+/*
* clear the history list - delete all entries
*/
void
clear_history(void)
{
- HistEvent ev;
+ TYPE(HistEvent) ev;
- history(h, &ev, H_CLEAR);
+ (void)FUNW(history)(h, &ev, H_CLEAR);
+ history_length = 0;
}
@@ -1179,16 +1474,16 @@ clear_history(void)
int
where_history(void)
{
- HistEvent ev;
+ TYPE(HistEvent) ev;
int curr_num, off;
- if (history(h, &ev, H_CURR) != 0)
+ if (FUNW(history)(h, &ev, H_CURR) != 0)
return (0);
curr_num = ev.num;
- history(h, &ev, H_FIRST);
+ (void)FUNW(history)(h, &ev, H_FIRST);
off = 1;
- while (ev.num != curr_num && history(h, &ev, H_NEXT) == 0)
+ while (ev.num != curr_num && FUNW(history)(h, &ev, H_NEXT) == 0)
off++;
return (off);
@@ -1212,23 +1507,24 @@ current_history(void)
int
history_total_bytes(void)
{
- HistEvent ev;
- int curr_num, size;
+ TYPE(HistEvent) ev;
+ int curr_num;
+ size_t size;
- if (history(h, &ev, H_CURR) != 0)
+ if (FUNW(history)(h, &ev, H_CURR) != 0)
return (-1);
curr_num = ev.num;
- history(h, &ev, H_FIRST);
+ (void)FUNW(history)(h, &ev, H_FIRST);
size = 0;
do
- size += strlen(ev.str);
- while (history(h, &ev, H_NEXT) == 0);
+ size += Strlen(ev.str) * sizeof(*ev.str);
+ while (FUNW(history)(h, &ev, H_NEXT) == 0);
/* get to the same position as before */
- history(h, &ev, H_PREV_EVENT, curr_num);
+ FUNW(history)(h, &ev, H_PREV_EVENT, curr_num);
- return (size);
+ return (int)(size);
}
@@ -1238,17 +1534,21 @@ history_total_bytes(void)
int
history_set_pos(int pos)
{
- HistEvent ev;
+ TYPE(HistEvent) ev;
int curr_num;
- if (pos > history_length || pos < 0)
+ if (pos >= history_length || pos < 0)
return (-1);
- history(h, &ev, H_CURR);
+ (void)FUNW(history)(h, &ev, H_CURR);
curr_num = ev.num;
- if (history(h, &ev, H_SET, pos)) {
- history(h, &ev, H_SET, curr_num);
+ /*
+ * use H_DELDATA to set to nth history (without delete) by passing
+ * (void **)-1
+ */
+ if (FUNW(history)(h, &ev, H_DELDATA, pos, (void **)-1)) {
+ (void)FUNW(history)(h, &ev, H_SET, curr_num);
return(-1);
}
return (0);
@@ -1283,21 +1583,23 @@ next_history(void)
int
history_search(const char *str, int direction)
{
- HistEvent ev;
- const char *strp;
+ TYPE(HistEvent) ev;
+ const Char *strp;
+ const Char *wstr;
int curr_num;
- if (history(h, &ev, H_CURR) != 0)
+ if (FUNW(history)(h, &ev, H_CURR) != 0)
return (-1);
curr_num = ev.num;
+ wstr = ct_decode_string(str, &conv);
for (;;) {
- if ((strp = strstr(ev.str, str)) != NULL)
+ if ((strp = Strstr(ev.str, wstr)) != NULL)
return (int) (strp - ev.str);
- if (history(h, &ev, direction < 0 ? H_NEXT:H_PREV) != 0)
+ if (FUNW(history)(h, &ev, direction < 0 ? H_NEXT:H_PREV) != 0)
break;
}
- history(h, &ev, H_SET, curr_num);
+ (void)FUNW(history)(h, &ev, H_SET, curr_num);
return (-1);
}
@@ -1308,9 +1610,10 @@ history_search(const char *str, int direction)
int
history_search_prefix(const char *str, int direction)
{
- HistEvent ev;
+ TYPE(HistEvent) ev;
- return (history(h, &ev, direction < 0? H_PREV_STR:H_NEXT_STR, str));
+ return (FUNW(history)(h, &ev, direction < 0 ?
+ H_PREV_STR : H_NEXT_STR, str));
}
@@ -1323,29 +1626,31 @@ int
history_search_pos(const char *str,
int direction __attribute__((__unused__)), int pos)
{
- HistEvent ev;
+ TYPE(HistEvent) ev;
int curr_num, off;
+ const Char *wstr;
off = (pos > 0) ? pos : -pos;
pos = (pos > 0) ? 1 : -1;
- if (history(h, &ev, H_CURR) != 0)
+ if (FUNW(history)(h, &ev, H_CURR) != 0)
return (-1);
curr_num = ev.num;
- if (history_set_pos(off) != 0 || history(h, &ev, H_CURR) != 0)
+ if (history_set_pos(off) != 0 || FUNW(history)(h, &ev, H_CURR) != 0)
return (-1);
-
+ wstr = ct_decode_string(str, &conv);
for (;;) {
- if (strstr(ev.str, str))
+ if (Strstr(ev.str, wstr))
return (off);
- if (history(h, &ev, (pos < 0) ? H_PREV : H_NEXT) != 0)
+ if (FUNW(history)(h, &ev, (pos < 0) ? H_PREV : H_NEXT) != 0)
break;
}
/* set "current" pointer back to previous state */
- history(h, &ev, (pos < 0) ? H_NEXT_EVENT : H_PREV_EVENT, curr_num);
+ (void)FUNW(history)(h, &ev,
+ pos < 0 ? H_NEXT_EVENT : H_PREV_EVENT, curr_num);
return (-1);
}
@@ -1354,180 +1659,18 @@ history_search_pos(const char *str,
/********************************/
/* completion functions */
-/*
- * does tilde expansion of strings of type ``~user/foo''
- * if ``user'' isn't valid user name or ``txt'' doesn't start
- * w/ '~', returns pointer to strdup()ed copy of ``txt''
- *
- * it's callers's responsibility to free() returned string
- */
char *
-tilde_expand(char *txt)
+tilde_expand(char *name)
{
- struct passwd *pass;
- char *temp;
- size_t len = 0;
-
- if (txt[0] != '~')
- return (strdup(txt));
-
- temp = strchr(txt + 1, '/');
- if (temp == NULL) {
- temp = strdup(txt + 1);
- if (temp == NULL)
- return NULL;
- } else {
- len = temp - txt + 1; /* text until string after slash */
- temp = malloc(len);
- if (temp == NULL)
- return NULL;
- (void)strncpy(temp, txt + 1, len - 2);
- temp[len - 2] = '\0';
- }
- pass = getpwnam(temp);
- free(temp); /* value no more needed */
- if (pass == NULL)
- return (strdup(txt));
-
- /* update pointer txt to point at string immedially following */
- /* first slash */
- txt += len;
-
- if (asprintf(&temp, "%s/%s", pass->pw_dir, txt) == -1)
- return NULL;
-
- return (temp);
+ return fn_tilde_expand(name);
}
-
-/*
- * return first found file name starting by the ``text'' or NULL if no
- * such file can be found
- * value of ``state'' is ignored
- *
- * it's caller's responsibility to free returned string
- */
char *
-filename_completion_function(const char *text, int state)
+filename_completion_function(const char *name, int state)
{
- static DIR *dir = NULL;
- static char *filename = NULL, *dirname = NULL;
- static size_t filename_len = 0;
- struct dirent *entry;
- char *temp;
- size_t len;
-
- if (state == 0 || dir == NULL) {
- temp = strrchr(text, '/');
- if (temp) {
- char *nptr;
- size_t sz;
- temp++;
- sz = strlen(temp) + 1;
- nptr = realloc(filename, sz);
- if (nptr == NULL) {
- free(filename);
- return NULL;
- }
- filename = nptr;
- (void)strlcpy(filename, temp, sz);
- len = temp - text; /* including last slash */
- nptr = realloc(dirname, len + 1);
- if (nptr == NULL) {
- free(filename);
- return NULL;
- }
- dirname = nptr;
- (void)strncpy(dirname, text, len);
- dirname[len] = '\0';
- } else {
- if (*text == 0)
- filename = NULL;
- else {
- filename = strdup(text);
- if (filename == NULL)
- return NULL;
- }
- dirname = NULL;
- }
-
- /* support for ``~user'' syntax */
- if (dirname && *dirname == '~') {
- char *nptr;
- size_t sz;
- temp = tilde_expand(dirname);
- if (temp == NULL)
- return NULL;
- sz = strlen(temp) + 1;
- nptr = realloc(dirname, sz);
- if (nptr == NULL) {
- free(dirname);
- return NULL;
- }
- dirname = nptr;
- (void)strlcpy(dirname, temp, sz);
- free(temp); /* no longer needed */
- }
- /* will be used in cycle */
- filename_len = filename ? strlen(filename) : 0;
-
- if (dir != NULL) {
- (void)closedir(dir);
- dir = NULL;
- }
- dir = opendir(dirname ? dirname : ".");
- if (!dir)
- return (NULL); /* cannot open the directory */
- }
- /* find the match */
- while ((entry = readdir(dir)) != NULL) {
- /* skip . and .. */
- if (entry->d_name[0] == '.' && (!entry->d_name[1]
- || (entry->d_name[1] == '.' && !entry->d_name[2])))
- continue;
- if (filename_len == 0)
- break;
- /* otherwise, get first entry where first */
- /* filename_len characters are equal */
- if (entry->d_name[0] == filename[0]
-#if defined(__SVR4) || defined(__linux__)
- && strlen(entry->d_name) >= filename_len
-#else
- && entry->d_namlen >= filename_len
-#endif
- && strncmp(entry->d_name, filename,
- filename_len) == 0)
- break;
- }
-
- if (entry) { /* match found */
-
- struct stat stbuf;
-#if defined(__SVR4) || defined(__linux__)
- len = strlen(entry->d_name) +
-#else
- len = entry->d_namlen +
-#endif
- ((dirname) ? strlen(dirname) : 0) + 1 + 1;
- temp = malloc(len);
- if (temp == NULL)
- return NULL;
- (void)snprintf(temp, len, "%s%s",
- dirname ? dirname : "", entry->d_name);
-
- /* test, if it's directory */
- if (stat(temp, &stbuf) == 0 && S_ISDIR(stbuf.st_mode))
- strlcat(temp, "/", len);
- } else {
- (void)closedir(dir);
- dir = NULL;
- temp = NULL;
- }
-
- return (temp);
+ return fn_filename_completion_function(name, state);
}
-
/*
* a completion generator for usernames; returns _first_ username
* which starts with supplied text
@@ -1549,101 +1692,26 @@ username_completion_function(const char *text, int state)
if (state == 0)
setpwent();
- while ((pwd = getpwent()) && text[0] == pwd->pw_name[0]
+ while ((pwd = getpwent()) != NULL && text[0] == pwd->pw_name[0]
&& strcmp(text, pwd->pw_name) == 0);
if (pwd == NULL) {
endpwent();
- return (NULL);
+ return NULL;
}
- return (strdup(pwd->pw_name));
+ return strdup(pwd->pw_name);
}
/*
- * el-compatible wrapper around rl_complete; needed for key binding
+ * el-compatible wrapper to send TSTP on ^Z
*/
/* ARGSUSED */
static unsigned char
-_el_rl_complete(EditLine *el __attribute__((__unused__)), int ch)
+_el_rl_tstp(EditLine *el __attribute__((__unused__)), int ch __attribute__((__unused__)))
{
- return (unsigned char) rl_complete(0, ch);
-}
-
-
-/*
- * returns list of completions for text given
- */
-char **
-completion_matches(const char *text, CPFunction *genfunc)
-{
- char **match_list = NULL, *retstr, *prevstr;
- size_t match_list_len, max_equal, which, i;
- size_t matches;
-
- if (h == NULL || e == NULL)
- rl_initialize();
-
- matches = 0;
- match_list_len = 1;
- while ((retstr = (*genfunc) (text, (int)matches)) != NULL) {
- /* allow for list terminator here */
- if (matches + 3 >= match_list_len) {
- char **nmatch_list;
- while (matches + 3 >= match_list_len)
- match_list_len <<= 1;
- nmatch_list = realloc(match_list,
- match_list_len * sizeof(char *));
- if (nmatch_list == NULL) {
- free(match_list);
- return NULL;
- }
- match_list = nmatch_list;
-
- }
- match_list[++matches] = retstr;
- }
-
- if (!match_list)
- return NULL; /* nothing found */
-
- /* find least denominator and insert it to match_list[0] */
- which = 2;
- prevstr = match_list[1];
- max_equal = strlen(prevstr);
- for (; which <= matches; which++) {
- for (i = 0; i < max_equal &&
- prevstr[i] == match_list[which][i]; i++)
- continue;
- max_equal = i;
- }
-
- retstr = malloc(max_equal + 1);
- if (retstr == NULL) {
- free(match_list);
- return NULL;
- }
- (void)strncpy(retstr, match_list[1], max_equal);
- retstr[max_equal] = '\0';
- match_list[0] = retstr;
-
- /* add NULL as last pointer to the array */
- match_list[matches + 1] = (char *) NULL;
-
- return (match_list);
-}
-
-/*
- * Sort function for qsort(). Just wrapper around strcasecmp().
- */
-static int
-_rl_qsort_string_compare(i1, i2)
- const void *i1, *i2;
-{
- const char *s1 = ((const char * const *)i1)[0];
- const char *s2 = ((const char * const *)i2)[0];
-
- return strcasecmp(s1, s2);
+ (void)kill(0, SIGTSTP);
+ return CC_NORM;
}
/*
@@ -1652,209 +1720,66 @@ _rl_qsort_string_compare(i1, i2)
* 'max' is maximum length of string in 'matches'.
*/
void
-rl_display_match_list (matches, len, max)
- char **matches;
- int len, max;
+rl_display_match_list(char **matches, int len, int max)
{
- int i, idx, limit, count;
- int screenwidth = e->el_term.t_size.h;
-
- /*
- * Find out how many entries can be put on one line, count
- * with two spaces between strings.
- */
- limit = screenwidth / (max + 2);
- if (limit == 0)
- limit = 1;
-
- /* how many lines of output */
- count = len / limit;
- if (count * limit < len)
- count++;
-
- /* Sort the items if they are not already sorted. */
- qsort(&matches[1], (size_t)(len - 1), sizeof(char *),
- _rl_qsort_string_compare);
- idx = 1;
- for(; count > 0; count--) {
- for(i = 0; i < limit && matches[idx]; i++, idx++)
- (void)fprintf(e->el_outfile, "%-*s ", max,
- matches[idx]);
- (void)fprintf(e->el_outfile, "\n");
- }
+ fn_display_match_list(e, matches, (size_t)len, (size_t)max);
}
-/*
- * Complete the word at or before point, called by rl_complete()
- * 'what_to_do' says what to do with the completion.
- * `?' means list the possible completions.
- * TAB means do standard completion.
- * `*' means insert all of the possible completions.
- * `!' means to do standard completion, and list all possible completions if
- * there is more than one.
- *
- * Note: '*' support is not implemented
- */
-static int
-rl_complete_internal(int what_to_do)
+static const char *
+/*ARGSUSED*/
+_rl_completion_append_character_function(const char *dummy
+ __attribute__((__unused__)))
{
- Function *complet_func;
- const LineInfo *li;
- char *temp, **matches;
- const char *ctemp;
- size_t len;
-
- rl_completion_type = what_to_do;
-
- if (h == NULL || e == NULL)
- rl_initialize();
-
- complet_func = rl_completion_entry_function;
- if (!complet_func)
- complet_func = (Function *)(void *)filename_completion_function;
-
- /* We now look backwards for the start of a filename/variable word */
- li = el_line(e);
- ctemp = (const char *) li->cursor;
- while (ctemp > li->buffer
- && !strchr(rl_basic_word_break_characters, ctemp[-1])
- && (!rl_special_prefixes
- || !strchr(rl_special_prefixes, ctemp[-1]) ) )
- ctemp--;
-
- len = li->cursor - ctemp;
- temp = alloca(len + 1);
- (void)strncpy(temp, ctemp, len);
- temp[len] = '\0';
-
- /* these can be used by function called in completion_matches() */
- /* or (*rl_attempted_completion_function)() */
- rl_point = li->cursor - li->buffer;
- rl_end = li->lastchar - li->buffer;
-
- if (rl_attempted_completion_function) {
- int end = li->cursor - li->buffer;
- matches = (*rl_attempted_completion_function) (temp, (int)
- (end - len), end);
- } else
- matches = 0;
- if (!rl_attempted_completion_function || !matches)
- matches = completion_matches(temp, (CPFunction *)complet_func);
-
- if (matches) {
- int i, retval = CC_REFRESH;
- int matches_num, maxlen, match_len, match_display=1;
-
- /*
- * Only replace the completed string with common part of
- * possible matches if there is possible completion.
- */
- if (matches[0][0] != '\0') {
- el_deletestr(e, (int) len);
- el_insertstr(e, matches[0]);
- }
-
- if (what_to_do == '?')
- goto display_matches;
-
- if (matches[2] == NULL && strcmp(matches[0], matches[1]) == 0) {
- /*
- * We found exact match. Add a space after
- * it, unless we do filename completion and the
- * object is a directory.
- */
- size_t alen = strlen(matches[0]);
- if ((complet_func !=
- (Function *)filename_completion_function
- || (alen > 0 && (matches[0])[alen - 1] != '/'))
- && rl_completion_append_character) {
- char buf[2];
- buf[0] = rl_completion_append_character;
- buf[1] = '\0';
- el_insertstr(e, buf);
- }
- } else if (what_to_do == '!') {
- display_matches:
- /*
- * More than one match and requested to list possible
- * matches.
- */
-
- for(i=1, maxlen=0; matches[i]; i++) {
- match_len = strlen(matches[i]);
- if (match_len > maxlen)
- maxlen = match_len;
- }
- matches_num = i - 1;
-
- /* newline to get on next line from command line */
- (void)fprintf(e->el_outfile, "\n");
-
- /*
- * If there are too many items, ask user for display
- * confirmation.
- */
- if (matches_num > rl_completion_query_items) {
- (void)fprintf(e->el_outfile,
- "Display all %d possibilities? (y or n) ",
- matches_num);
- (void)fflush(e->el_outfile);
- if (getc(stdin) != 'y')
- match_display = 0;
- (void)fprintf(e->el_outfile, "\n");
- }
-
- if (match_display)
- rl_display_match_list(matches, matches_num,
- maxlen);
- retval = CC_REDISPLAY;
- } else if (matches[0][0]) {
- /*
- * There was some common match, but the name was
- * not complete enough. Next tab will print possible
- * completions.
- */
- el_beep(e);
- } else {
- /* lcd is not a valid object - further specification */
- /* is needed */
- el_beep(e);
- retval = CC_NORM;
- }
-
- /* free elements of array and the array itself */
- for (i = 0; matches[i]; i++)
- free(matches[i]);
- free(matches), matches = NULL;
-
- return (retval);
- }
- return (CC_NORM);
+ static char buf[2];
+ buf[0] = rl_completion_append_character;
+ buf[1] = '\0';
+ return buf;
}
/*
* complete word at current point
*/
+/* ARGSUSED */
int
-rl_complete(int ignore, int invoking_key)
+rl_complete(int ignore __attribute__((__unused__)), int invoking_key)
{
+#ifdef WIDECHAR
+ static ct_buffer_t wbreak_conv, sprefix_conv;
+#endif
+
if (h == NULL || e == NULL)
rl_initialize();
if (rl_inhibit_completion) {
- rl_insert(ignore, invoking_key);
+ char arr[2];
+ arr[0] = (char)invoking_key;
+ arr[1] = '\0';
+ el_insertstr(e, arr);
return (CC_REFRESH);
- } else if (e->el_state.lastcmd == el_rl_complete_cmdnum)
- return rl_complete_internal('?');
- else if (_rl_complete_show_all)
- return rl_complete_internal('!');
- else
- return (rl_complete_internal(TAB));
+ }
+
+ /* Just look at how many global variables modify this operation! */
+ return fn_complete(e,
+ (CPFunction *)rl_completion_entry_function,
+ rl_attempted_completion_function,
+ ct_decode_string(rl_basic_word_break_characters, &wbreak_conv),
+ ct_decode_string(rl_special_prefixes, &sprefix_conv),
+ _rl_completion_append_character_function,
+ (size_t)rl_completion_query_items,
+ &rl_completion_type, &rl_attempted_completion_over,
+ &rl_point, &rl_end);
}
+/* ARGSUSED */
+static unsigned char
+_el_rl_complete(EditLine *el __attribute__((__unused__)), int ch)
+{
+ return (unsigned char)rl_complete(0, ch);
+}
+
/*
* misc other functions
*/
@@ -1863,7 +1788,7 @@ rl_complete(int ignore, int invoking_key)
* bind key c to readline-type function func
*/
int
-rl_bind_key(int c, int func(int, int))
+rl_bind_key(int c, rl_command_func_t *func)
{
int retval = -1;
@@ -1930,6 +1855,20 @@ rl_insert(int count, int c)
return (0);
}
+int
+rl_insert_text(const char *text)
+{
+ if (!text || *text == 0)
+ return (0);
+
+ if (h == NULL || e == NULL)
+ rl_initialize();
+
+ if (el_insertstr(e, text) < 0)
+ return (0);
+ return (int)strlen(text);
+}
+
/*ARGSUSED*/
int
rl_newline(int count, int c)
@@ -1946,6 +1885,9 @@ rl_bind_wrapper(EditLine *el, unsigned char c)
{
if (map[c] == NULL)
return CC_ERROR;
+
+ _rl_update_pos();
+
(*map[c])(NULL, c);
/* If rl_done was set by the above call, deal with it here */
@@ -1959,7 +1901,7 @@ int
rl_add_defun(const char *name, Function *fun, int c)
{
char dest[8];
- if (c >= sizeof(map) / sizeof(map[0]) || c < 0)
+ if ((size_t)c >= sizeof(map) / sizeof(map[0]) || c < 0)
return -1;
map[(unsigned char)c] = fun;
el_set(e, EL_ADDFN, name, name, rl_bind_wrapper);
@@ -1977,7 +1919,7 @@ rl_callback_read_char()
if (buf == NULL || count-- <= 0)
return;
- if (count == 0 && buf[0] == CTRL('d'))
+ if (count == 0 && buf[0] == e->el_tty.t_c[TS_IO][C_EOF])
done = 1;
if (buf[count] == '\n' || buf[count] == '\r')
done = 2;
@@ -1990,18 +1932,17 @@ rl_callback_read_char()
} else
wbuf = NULL;
(*(void (*)(const char *))rl_linefunc)(wbuf);
+ //el_set(e, EL_UNBUFFERED, 1);
}
}
void
-rl_callback_handler_install (const char *prompt, VFunction *linefunc)
+rl_callback_handler_install(const char *prompt, VCPFunction *linefunc)
{
if (e == NULL) {
rl_initialize();
}
- if (rl_prompt)
- free(rl_prompt);
- rl_prompt = prompt ? strdup(strchr(prompt, *prompt)) : NULL;
+ (void)rl_set_prompt(prompt);
rl_linefunc = linefunc;
el_set(e, EL_UNBUFFERED, 1);
}
@@ -2010,13 +1951,14 @@ void
rl_callback_handler_remove(void)
{
el_set(e, EL_UNBUFFERED, 0);
+ rl_linefunc = NULL;
}
void
rl_redisplay(void)
{
char a[2];
- a[0] = CTRL('r');
+ a[0] = e->el_tty.t_c[TS_IO][C_REPRINT];
a[1] = '\0';
el_push(e, a);
}
@@ -2040,7 +1982,7 @@ rl_prep_terminal(int meta_flag)
}
void
-rl_deprep_terminal()
+rl_deprep_terminal(void)
{
el_set(e, EL_PREP_TERM, 0);
}
@@ -2059,12 +2001,22 @@ rl_parse_and_bind(const char *line)
Tokenizer *tok;
tok = tok_init(NULL);
- tok_line(tok, line, &argc, &argv);
+ tok_str(tok, line, &argc, &argv);
argc = el_parse(e, argc, argv);
tok_end(tok);
return (argc ? 1 : 0);
}
+int
+rl_variable_bind(const char *var, const char *value)
+{
+ /*
+ * The proper return value is undocument, but this is what the
+ * readline source seems to do.
+ */
+ return ((el_set(e, EL_BIND, "", var, value) == -1) ? 1 : 0);
+}
+
void
rl_stuff_char(int c)
{
@@ -2078,9 +2030,10 @@ rl_stuff_char(int c)
static int
_rl_event_read_char(EditLine *el, char *cp)
{
- int n, num_read = 0;
+ int n;
+ ssize_t num_read = 0;
- *cp = 0;
+ *cp = '\0';
while (rl_event_hook) {
(*rl_event_hook)();
@@ -2114,5 +2067,170 @@ _rl_event_read_char(EditLine *el, char *cp)
}
if (!rl_event_hook)
el_set(el, EL_GETCFN, EL_BUILTIN_GETCFN);
- return(num_read);
+ return (int)num_read;
+}
+
+static void
+_rl_update_pos(void)
+{
+ const LineInfo *li = el_line(e);
+
+ rl_point = (int)(li->cursor - li->buffer);
+ rl_end = (int)(li->lastchar - li->buffer);
+}
+
+void
+rl_get_screen_size(int *rows, int *cols)
+{
+ if (rows)
+ el_get(e, EL_GETTC, "li", rows);
+ if (cols)
+ el_get(e, EL_GETTC, "co", cols);
+}
+
+void
+rl_set_screen_size(int rows, int cols)
+{
+ char buf[64];
+ (void)snprintf(buf, sizeof(buf), "%d", rows);
+ el_set(e, EL_SETTC, "li", buf);
+ (void)snprintf(buf, sizeof(buf), "%d", cols);
+ el_set(e, EL_SETTC, "co", buf);
+}
+
+char **
+rl_completion_matches(const char *str, rl_compentry_func_t *fun)
+{
+ size_t len, max, i, j, min;
+ char **list, *match, *a, *b;
+
+ len = 1;
+ max = 10;
+ if ((list = malloc(max * sizeof(*list))) == NULL)
+ return NULL;
+
+ while ((match = (*fun)(str, (int)(len - 1))) != NULL) {
+ list[len++] = match;
+ if (len == max) {
+ char **nl;
+ max += 10;
+ if ((nl = realloc(list, max * sizeof(*nl))) == NULL)
+ goto out;
+ list = nl;
+ }
+ }
+ if (len == 1)
+ goto out;
+ list[len] = NULL;
+ if (len == 2) {
+ if ((list[0] = strdup(list[1])) == NULL)
+ goto out;
+ return list;
+ }
+ qsort(&list[1], len - 1, sizeof(*list),
+ (int (*)(const void *, const void *)) strcmp);
+ min = SIZE_T_MAX;
+ for (i = 1, a = list[i]; i < len - 1; i++, a = b) {
+ b = list[i + 1];
+ for (j = 0; a[j] && a[j] == b[j]; j++)
+ continue;
+ if (min > j)
+ min = j;
+ }
+ if (min == 0 && *str) {
+ if ((list[0] = strdup(str)) == NULL)
+ goto out;
+ } else {
+ if ((list[0] = malloc(min + 1)) == NULL)
+ goto out;
+ (void)memcpy(list[0], list[1], min);
+ list[0][min] = '\0';
+ }
+ return list;
+
+out:
+ free(list);
+ return NULL;
+}
+
+char *
+rl_filename_completion_function (const char *text, int state)
+{
+ return fn_filename_completion_function(text, state);
+}
+
+void
+rl_forced_update_display(void)
+{
+ el_set(e, EL_REFRESH);
+}
+
+int
+_rl_abort_internal(void)
+{
+ el_beep(e);
+ longjmp(topbuf, 1);
+ /*NOTREACHED*/
+}
+
+int
+_rl_qsort_string_compare(char **s1, char **s2)
+{
+ return strcoll(*s1, *s2);
+}
+
+HISTORY_STATE *
+history_get_history_state(void)
+{
+ HISTORY_STATE *hs;
+
+ if ((hs = malloc(sizeof(HISTORY_STATE))) == NULL)
+ return (NULL);
+ hs->length = history_length;
+ return (hs);
+}
+
+int
+/*ARGSUSED*/
+rl_kill_text(int from, int to)
+{
+ return 0;
+}
+
+Keymap
+rl_make_bare_keymap(void)
+{
+ return NULL;
+}
+
+Keymap
+rl_get_keymap(void)
+{
+ return NULL;
+}
+
+void
+/*ARGSUSED*/
+rl_set_keymap(Keymap k)
+{
+}
+
+int
+/*ARGSUSED*/
+rl_generic_bind(int type, const char * keyseq, const char * data, Keymap k)
+{
+ return 0;
+}
+
+int
+/*ARGSUSED*/
+rl_bind_key_in_map(int key, rl_command_func_t *fun, Keymap k)
+{
+ return 0;
+}
+
+/* unsupported, but needed by python */
+void
+rl_cleanup_after_signal(void)
+{
}
diff --git a/lib/libedit/readline/readline.h b/lib/libedit/readline/readline.h
index 2177fbe06d7..f9c8094a396 100644
--- a/lib/libedit/readline/readline.h
+++ b/lib/libedit/readline/readline.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: readline.h,v 1.3 2008/06/26 05:42:05 ray Exp $ */
-/* $NetBSD: readline.h,v 1.10 2003/10/27 22:26:35 christos Exp $ */
+/* $OpenBSD: readline.h,v 1.4 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: readline.h,v 1.30 2009/09/07 21:24:34 christos Exp $ */
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -33,18 +33,29 @@
#define _READLINE_H_
#include <sys/types.h>
+#include <stdio.h>
/* list of readline stuff supported by editline library's readline wrapper */
/* typedefs */
typedef int Function(const char *, int);
typedef void VFunction(void);
+typedef void VCPFunction(char *);
typedef char *CPFunction(const char *, int);
typedef char **CPPFunction(const char *, int, int);
+typedef char *rl_compentry_func_t(const char *, int);
+typedef int rl_command_func_t(int, int);
+
+/* only supports length */
+typedef struct {
+ int length;
+} HISTORY_STATE;
+
+typedef void *histdata_t;
typedef struct _hist_entry {
const char *line;
- const char *data;
+ histdata_t data;
} HIST_ENTRY;
typedef struct _keymap_entry {
@@ -65,7 +76,9 @@ typedef KEYMAP_ENTRY *Keymap;
#ifndef CTRL
#include <sys/ioctl.h>
+#if !defined(__sun) && !defined(__hpux) && !defined(_AIX)
#include <sys/ttydefaults.h>
+#endif
#ifndef CTRL
#define CTRL(c) ((c) & 037)
#endif
@@ -76,12 +89,16 @@ typedef KEYMAP_ENTRY *Keymap;
#define RUBOUT 0x7f
#define ABORT_CHAR CTRL('G')
+#define RL_READLINE_VERSION 0x0402
+#define RL_PROMPT_START_IGNORE '\1'
+#define RL_PROMPT_END_IGNORE '\2'
/* global variables used by readline enabled applications */
#ifdef __cplusplus
extern "C" {
#endif
extern const char *rl_library_version;
+extern int rl_readline_version;
extern char *rl_readline_name;
extern FILE *rl_instream;
extern FILE *rl_outstream;
@@ -94,17 +111,17 @@ extern char *rl_completer_word_break_characters;
extern char *rl_completer_quote_characters;
extern Function *rl_completion_entry_function;
extern CPPFunction *rl_attempted_completion_function;
+extern int rl_attempted_completion_over;
extern int rl_completion_type;
extern int rl_completion_query_items;
extern char *rl_special_prefixes;
extern int rl_completion_append_character;
+extern int rl_inhibit_completion;
extern Function *rl_pre_input_hook;
extern Function *rl_startup_hook;
extern char *rl_terminal_name;
extern int rl_already_prompted;
extern char *rl_prompt;
-extern VFunction *rl_event_hook;
-
/*
* The following is not implemented
*/
@@ -113,11 +130,13 @@ extern KEYMAP_ENTRY_ARRAY emacs_standard_keymap,
emacs_ctlx_keymap;
extern int rl_filename_completion_desired;
extern int rl_ignore_completion_duplicates;
-extern Function *rl_getc_function;
+extern int (*rl_getc_function)(FILE *);
extern VFunction *rl_redisplay_function;
extern VFunction *rl_completion_display_matches_hook;
extern VFunction *rl_prep_term_function;
extern VFunction *rl_deprep_term_function;
+extern int readline_echoing_p;
+extern int _rl_print_completions_horizontally;
/* supported functions */
char *readline(const char *);
@@ -132,6 +151,9 @@ int history_is_stifled(void);
int where_history(void);
HIST_ENTRY *current_history(void);
HIST_ENTRY *history_get(int);
+HIST_ENTRY *remove_history(int);
+/*###152 [lint] syntax error 'histdata_t' [249]%%%*/
+HIST_ENTRY *replace_history_entry(int, const char *, histdata_t);
int history_total_bytes(void);
int history_set_pos(int);
HIST_ENTRY *previous_history(void);
@@ -141,6 +163,7 @@ int history_search_prefix(const char *, int);
int history_search_pos(const char *, int, int);
int read_history(const char *);
int write_history(const char *);
+int history_truncate_file (const char *, int);
int history_expand(char *, char **);
char **history_tokenize(const char *);
const char *get_history_event(const char *, int *, int);
@@ -155,11 +178,12 @@ char **completion_matches(const char *, CPFunction *);
void rl_display_match_list(char **, int, int);
int rl_insert(int, int);
+int rl_insert_text(const char *);
void rl_reset_terminal(const char *);
-int rl_bind_key(int, int (*)(int, int));
+int rl_bind_key(int, rl_command_func_t *);
int rl_newline(int, int);
void rl_callback_read_char(void);
-void rl_callback_handler_install(const char *, VFunction *);
+void rl_callback_handler_install(const char *, VCPFunction *);
void rl_callback_handler_remove(void);
void rl_redisplay(void);
int rl_get_previous_history(int, int);
@@ -167,16 +191,30 @@ void rl_prep_terminal(int);
void rl_deprep_terminal(void);
int rl_read_init_file(const char *);
int rl_parse_and_bind(const char *);
+int rl_variable_bind(const char *, const char *);
void rl_stuff_char(int);
int rl_add_defun(const char *, Function *, int);
+HISTORY_STATE *history_get_history_state(void);
+void rl_get_screen_size(int *, int *);
+void rl_set_screen_size(int, int);
+char *rl_filename_completion_function (const char *, int);
+int _rl_abort_internal(void);
+int _rl_qsort_string_compare(char **, char **);
+char **rl_completion_matches(const char *, rl_compentry_func_t *);
+void rl_forced_update_display(void);
+int rl_set_prompt(const char *);
/*
* The following are not implemented
*/
+int rl_kill_text(int, int);
Keymap rl_get_keymap(void);
+void rl_set_keymap(Keymap);
Keymap rl_make_bare_keymap(void);
int rl_generic_bind(int, const char *, const char *, Keymap);
-int rl_bind_key_in_map(int, Function *, Keymap);
+int rl_bind_key_in_map(int, rl_command_func_t *, Keymap);
+void rl_cleanup_after_signal(void);
+void rl_free_line_state(void);
#ifdef __cplusplus
}
#endif
diff --git a/lib/libedit/refresh.c b/lib/libedit/refresh.c
index f2b909ea8e2..a28c813606c 100644
--- a/lib/libedit/refresh.c
+++ b/lib/libedit/refresh.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: refresh.c,v 1.10 2009/10/27 23:59:28 deraadt Exp $ */
-/* $NetBSD: refresh.c,v 1.26 2003/08/07 16:44:33 agc Exp $ */
+/* $OpenBSD: refresh.c,v 1.11 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: refresh.c,v 1.35 2009/12/30 22:37:40 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -45,13 +45,15 @@
#include "el.h"
-private void re_addc(EditLine *, int);
-private void re_update_line(EditLine *, char *, char *, int);
-private void re_insert (EditLine *, char *, int, int, char *, int);
-private void re_delete(EditLine *, char *, int, int, int);
-private void re_fastputc(EditLine *, int);
-private void re__strncopy(char *, char *, size_t);
-private void re__copy_and_pad(char *, const char *, size_t);
+private void re_nextline(EditLine *);
+private void re_addc(EditLine *, Int);
+private void re_update_line(EditLine *, Char *, Char *, int);
+private void re_insert (EditLine *, Char *, int, int, Char *, int);
+private void re_delete(EditLine *, Char *, int, int, int);
+private void re_fastputc(EditLine *, Int);
+private void re_clear_eol(EditLine *, int, int, int);
+private void re__strncopy(Char *, Char *, size_t);
+private void re__copy_and_pad(Char *, const Char *, size_t);
#ifdef DEBUG_REFRESH
private void re_printstr(EditLine *, const char *, char *, char *);
@@ -81,45 +83,70 @@ re_printstr(EditLine *el, const char *str, char *f, char *t)
#define ELRE_DEBUG(a, b)
#endif
+/* re_nextline():
+ * Move to the next line or scroll
+ */
+private void
+re_nextline(EditLine *el)
+{
+ el->el_refresh.r_cursor.h = 0; /* reset it. */
+
+ /*
+ * If we would overflow (input is longer than terminal size),
+ * emulate scroll by dropping first line and shuffling the rest.
+ * We do this via pointer shuffling - it's safe in this case
+ * and we avoid memcpy().
+ */
+ if (el->el_refresh.r_cursor.v + 1 >= el->el_term.t_size.v) {
+ int i, lins = el->el_term.t_size.v;
+ Char *firstline = el->el_vdisplay[0];
+
+ for(i = 1; i < lins; i++)
+ el->el_vdisplay[i - 1] = el->el_vdisplay[i];
+
+ firstline[0] = '\0'; /* empty the string */
+ el->el_vdisplay[i - 1] = firstline;
+ } else
+ el->el_refresh.r_cursor.v++;
+
+ ELRE_ASSERT(el->el_refresh.r_cursor.v >= el->el_term.t_size.v,
+ (__F, "\r\nre_putc: overflow! r_cursor.v == %d > %d\r\n",
+ el->el_refresh.r_cursor.v, el->el_term.t_size.v),
+ abort());
+}
/* re_addc():
* Draw c, expanding tabs, control chars etc.
*/
private void
-re_addc(EditLine *el, int c)
+re_addc(EditLine *el, Int c)
{
-
- if (isprint(c)) {
- re_putc(el, c, 1);
- return;
- }
- if (c == '\n') { /* expand the newline */
- int oldv = el->el_refresh.r_cursor.v;
- re_putc(el, '\0', 0); /* assure end of line */
- if (oldv == el->el_refresh.r_cursor.v) { /* XXX */
- el->el_refresh.r_cursor.h = 0; /* reset cursor pos */
- el->el_refresh.r_cursor.v++;
- }
- return;
- }
- if (c == '\t') { /* expand the tab */
+ switch (ct_chr_class((Char)c)) {
+ case CHTYPE_TAB: /* expand the tab */
for (;;) {
re_putc(el, ' ', 1);
if ((el->el_refresh.r_cursor.h & 07) == 0)
break; /* go until tab stop */
}
- } else if (iscntrl(c)) {
- re_putc(el, '^', 1);
- if (c == '\177')
- re_putc(el, '?', 1);
- else
- /* uncontrolify it; works only for iso8859-1 like sets */
- re_putc(el, (c | 0100), 1);
- } else {
- re_putc(el, '\\', 1);
- re_putc(el, (int) ((((unsigned int) c >> 6) & 07) + '0'), 1);
- re_putc(el, (int) ((((unsigned int) c >> 3) & 07) + '0'), 1);
- re_putc(el, (c & 07) + '0', 1);
+ break;
+ case CHTYPE_NL: {
+ int oldv = el->el_refresh.r_cursor.v;
+ re_putc(el, '\0', 0); /* assure end of line */
+ if (oldv == el->el_refresh.r_cursor.v) /* XXX */
+ re_nextline(el);
+ break;
+ }
+ case CHTYPE_PRINT:
+ re_putc(el, c, 1);
+ break;
+ default: {
+ Char visbuf[VISUAL_WIDTH_MAX];
+ ssize_t i, n =
+ ct_visual_char(visbuf, VISUAL_WIDTH_MAX, (Char)c);
+ for (i = 0; n-- > 0; ++i)
+ re_putc(el, visbuf[i], 1);
+ break;
+ }
}
}
@@ -128,43 +155,31 @@ re_addc(EditLine *el, int c)
* Draw the character given
*/
protected void
-re_putc(EditLine *el, int c, int shift)
+re_putc(EditLine *el, Int c, int shift)
{
+ int i, w = Width(c);
+ ELRE_DEBUG(1, (__F, "printing %5x '%c'\r\n", c, c));
- ELRE_DEBUG(1, (__F, "printing %3.3o '%c'\r\n", c, c));
+ while (shift && (el->el_refresh.r_cursor.h + w > el->el_term.t_size.h))
+ re_putc(el, ' ', 1);
+
+ el->el_vdisplay[el->el_refresh.r_cursor.v]
+ [el->el_refresh.r_cursor.h] = c;
+ /* assumes !shift is only used for single-column chars */
+ i = w;
+ while (--i > 0)
+ el->el_vdisplay[el->el_refresh.r_cursor.v]
+ [el->el_refresh.r_cursor.h + i] = MB_FILL_CHAR;
- el->el_vdisplay[el->el_refresh.r_cursor.v][el->el_refresh.r_cursor.h] = c;
if (!shift)
return;
- el->el_refresh.r_cursor.h++; /* advance to next place */
+ el->el_refresh.r_cursor.h += w; /* advance to next place */
if (el->el_refresh.r_cursor.h >= el->el_term.t_size.h) {
- el->el_vdisplay[el->el_refresh.r_cursor.v][el->el_term.t_size.h] = '\0';
/* assure end of line */
- el->el_refresh.r_cursor.h = 0; /* reset it. */
-
- /*
- * If we would overflow (input is longer than terminal size),
- * emulate scroll by dropping first line and shuffling the rest.
- * We do this via pointer shuffling - it's safe in this case
- * and we avoid memcpy().
- */
- if (el->el_refresh.r_cursor.v + 1 >= el->el_term.t_size.v) {
- int i, lins = el->el_term.t_size.v;
- char *firstline = el->el_vdisplay[0];
-
- for(i=1; i < lins; i++)
- el->el_vdisplay[i-1] = el->el_vdisplay[i];
-
- firstline[0] = '\0'; /* empty the string */
- el->el_vdisplay[i-1] = firstline;
- } else
- el->el_refresh.r_cursor.v++;
-
- ELRE_ASSERT(el->el_refresh.r_cursor.v >= el->el_term.t_size.v,
- (__F, "\r\nre_putc: overflow! r_cursor.v == %d > %d\r\n",
- el->el_refresh.r_cursor.v, el->el_term.t_size.v),
- abort());
+ el->el_vdisplay[el->el_refresh.r_cursor.v][el->el_term.t_size.h]
+ = '\0';
+ re_nextline(el);
}
}
@@ -179,7 +194,7 @@ protected void
re_refresh(EditLine *el)
{
int i, rhdiff;
- char *cp, *st;
+ Char *cp, *st;
coord_t cur;
#ifdef notyet
size_t termsz;
@@ -231,11 +246,18 @@ re_refresh(EditLine *el)
for (cp = st; cp < el->el_line.lastchar; cp++) {
if (cp == el->el_line.cursor) {
+ int w = Width(*cp);
/* save for later */
cur.h = el->el_refresh.r_cursor.h;
cur.v = el->el_refresh.r_cursor.v;
+ /* handle being at a linebroken doublewidth char */
+ if (w > 1 && el->el_refresh.r_cursor.h + w >
+ el->el_term.t_size.h) {
+ cur.h = 0;
+ cur.v++;
+ }
}
- re_addc(el, (unsigned char) *cp);
+ re_addc(el, *cp);
}
if (cur.h == -1) { /* if I haven't been set yet, I'm at the end */
@@ -266,7 +288,7 @@ re_refresh(EditLine *el)
ELRE_DEBUG(1, (__F,
"term.h=%d vcur.h=%d vcur.v=%d vdisplay[0]=\r\n:%80.80s:\r\n",
el->el_term.t_size.h, el->el_refresh.r_cursor.h,
- el->el_refresh.r_cursor.v, el->el_vdisplay[0]));
+ el->el_refresh.r_cursor.v, ct_encode_string(el->el_vdisplay[0])));
ELRE_DEBUG(1, (__F, "updating %d lines.\r\n", el->el_refresh.r_newcv));
for (i = 0; i <= el->el_refresh.r_newcv; i++) {
@@ -291,9 +313,10 @@ re_refresh(EditLine *el)
for (; i <= el->el_refresh.r_oldcv; i++) {
term_move_to_line(el, i);
term_move_to_char(el, 0);
- term_clear_EOL(el, (int) strlen(el->el_display[i]));
+ /* This Strlen should be safe even with MB_FILL_CHARs */
+ term_clear_EOL(el, (int) Strlen(el->el_display[i]));
#ifdef DEBUG_REFRESH
- term_overwrite(el, "C\b", 2);
+ term_overwrite(el, "C\b", (size_t)2);
#endif /* DEBUG_REFRESH */
el->el_display[i][0] = '\0';
}
@@ -316,9 +339,9 @@ re_goto_bottom(EditLine *el)
{
term_move_to_line(el, el->el_refresh.r_oldcv);
- term__putc('\n');
+ term__putc(el, '\n');
re_clear_display(el);
- term__flush();
+ term__flush(el);
}
@@ -329,9 +352,9 @@ re_goto_bottom(EditLine *el)
private void
/*ARGSUSED*/
re_insert(EditLine *el __attribute__((__unused__)),
- char *d, int dat, int dlen, char *s, int num)
+ Char *d, int dat, int dlen, Char *s, int num)
{
- char *a, *b;
+ Char *a, *b;
if (num <= 0)
return;
@@ -340,8 +363,8 @@ re_insert(EditLine *el __attribute__((__unused__)),
ELRE_DEBUG(1,
(__F, "re_insert() starting: %d at %d max %d, d == \"%s\"\n",
- num, dat, dlen, d));
- ELRE_DEBUG(1, (__F, "s == \"%s\"n", s));
+ num, dat, dlen, ct_encode_string(d)));
+ ELRE_DEBUG(1, (__F, "s == \"%s\"\n", ct_encode_string(s)));
/* open up the space for num chars */
if (num > 0) {
@@ -351,19 +374,24 @@ re_insert(EditLine *el __attribute__((__unused__)),
*b-- = *a--;
d[dlen] = '\0'; /* just in case */
}
+
ELRE_DEBUG(1, (__F,
"re_insert() after insert: %d at %d max %d, d == \"%s\"\n",
- num, dat, dlen, d));
- ELRE_DEBUG(1, (__F, "s == \"%s\"n", s));
+ num, dat, dlen, ct_encode_string(d)));
+ ELRE_DEBUG(1, (__F, "s == \"%s\"\n", ct_encode_string(s)));
/* copy the characters */
for (a = d + dat; (a < d + dlen) && (num > 0); num--)
*a++ = *s++;
+#ifdef notyet
+ /* ct_encode_string() uses a static buffer, so we can't conveniently
+ * encode both d & s here */
ELRE_DEBUG(1,
(__F, "re_insert() after copy: %d at %d max %d, %s == \"%s\"\n",
num, dat, dlen, d, s));
- ELRE_DEBUG(1, (__F, "s == \"%s\"n", s));
+ ELRE_DEBUG(1, (__F, "s == \"%s\"\n", s));
+#endif
}
@@ -373,9 +401,9 @@ re_insert(EditLine *el __attribute__((__unused__)),
private void
/*ARGSUSED*/
re_delete(EditLine *el __attribute__((__unused__)),
- char *d, int dat, int dlen, int num)
+ Char *d, int dat, int dlen, int num)
{
- char *a, *b;
+ Char *a, *b;
if (num <= 0)
return;
@@ -385,7 +413,7 @@ re_delete(EditLine *el __attribute__((__unused__)),
}
ELRE_DEBUG(1,
(__F, "re_delete() starting: %d at %d max %d, d == \"%s\"\n",
- num, dat, dlen, d));
+ num, dat, dlen, ct_encode_string(d)));
/* open up the space for num chars */
if (num > 0) {
@@ -397,7 +425,7 @@ re_delete(EditLine *el __attribute__((__unused__)),
}
ELRE_DEBUG(1,
(__F, "re_delete() after delete: %d at %d max %d, d == \"%s\"\n",
- num, dat, dlen, d));
+ num, dat, dlen, ct_encode_string(d)));
}
@@ -405,13 +433,39 @@ re_delete(EditLine *el __attribute__((__unused__)),
* Like strncpy without padding.
*/
private void
-re__strncopy(char *a, char *b, size_t n)
+re__strncopy(Char *a, Char *b, size_t n)
{
while (n-- && *b)
*a++ = *b++;
}
+/* re_clear_eol():
+ * Find the number of characters we need to clear till the end of line
+ * in order to make sure that we have cleared the previous contents of
+ * the line. fx and sx is the number of characters inserted or deleted
+ * in the first or second diff, diff is the difference between the
+ * number of characters between the new and old line.
+ */
+private void
+re_clear_eol(EditLine *el, int fx, int sx, int diff)
+{
+
+ ELRE_DEBUG(1, (__F, "re_clear_eol sx %d, fx %d, diff %d\n",
+ sx, fx, diff));
+
+ if (fx < 0)
+ fx = -fx;
+ if (sx < 0)
+ sx = -sx;
+ if (fx > diff)
+ diff = fx;
+ if (sx > diff)
+ diff = sx;
+
+ ELRE_DEBUG(1, (__F, "re_clear_eol %d\n", diff));
+ term_clear_EOL(el, diff);
+}
/*****************************************************************
re_update_line() is based on finding the middle difference of each line
@@ -438,12 +492,13 @@ new: eddie> Oh, my little buggy says to me, as lurgid as
#define MIN_END_KEEP 4
private void
-re_update_line(EditLine *el, char *old, char *new, int i)
+re_update_line(EditLine *el, Char *old, Char *new, int i)
{
- char *o, *n, *p, c;
- char *ofd, *ols, *oe, *nfd, *nls, *ne;
- char *osb, *ose, *nsb, *nse;
+ Char *o, *n, *p, c;
+ Char *ofd, *ols, *oe, *nfd, *nls, *ne;
+ Char *osb, *ose, *nsb, *nse;
int fx, sx;
+ size_t len;
/*
* find first diff
@@ -570,12 +625,12 @@ re_update_line(EditLine *el, char *old, char *new, int i)
* 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);
+ fx = (int)((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);
+ sx = (int)((nls - nse) - (ols - ose));
if (!EL_CAN_INSERT) {
if (fx > 0) {
@@ -624,10 +679,10 @@ re_update_line(EditLine *el, char *old, char *new, int i)
/*
* Now that we are done with pragmatics we recompute fx, sx
*/
- fx = (nsb - nfd) - (osb - ofd);
- sx = (nls - nse) - (ols - ose);
+ fx = (int)((nsb - nfd) - (osb - ofd));
+ sx = (int)((nls - nse) - (ols - ose));
- ELRE_DEBUG(1, (__F, "\n"));
+ ELRE_DEBUG(1, (__F, "fx %d, sx %d\n", fx, sx));
ELRE_DEBUG(1, (__F, "ofd %d, osb %d, ose %d, ols %d, oe %d\n",
ofd - old, osb - old, ose - old, ols - old, oe - old));
ELRE_DEBUG(1, (__F, "nfd %d, nsb %d, nse %d, nls %d, ne %d\n",
@@ -708,7 +763,7 @@ re_update_line(EditLine *el, char *old, char *new, int i)
/*
* Move to the first char to insert, where the first diff is.
*/
- term_move_to_char(el, nfd - new);
+ term_move_to_char(el, (int)(nfd - new));
/*
* Check if we have stuff to keep at end
*/
@@ -721,20 +776,21 @@ re_update_line(EditLine *el, char *old, char *new, int i)
ELRE_DEBUG(!EL_CAN_INSERT, (__F,
"ERROR: cannot insert in early first diff\n"));
term_insertwrite(el, nfd, fx);
- re_insert(el, old, ofd - old,
+ re_insert(el, old, (int)(ofd - old),
el->el_term.t_size.h, nfd, fx);
}
/*
* write (nsb-nfd) - fx chars of new starting at
* (nfd + fx)
*/
- term_overwrite(el, nfd + fx, (nsb - nfd) - fx);
- re__strncopy(ofd + fx, nfd + fx,
- (size_t) ((nsb - nfd) - fx));
+ len = (size_t) ((nsb - nfd) - fx);
+ term_overwrite(el, (nfd + fx), len);
+ re__strncopy(ofd + fx, nfd + fx, len);
} else {
ELRE_DEBUG(1, (__F, "without anything to save\r\n"));
- term_overwrite(el, nfd, (nsb - nfd));
- re__strncopy(ofd, nfd, (size_t) (nsb - nfd));
+ len = (size_t)(nsb - nfd);
+ term_overwrite(el, nfd, len);
+ re__strncopy(ofd, nfd, len);
/*
* Done
*/
@@ -746,7 +802,7 @@ re_update_line(EditLine *el, char *old, char *new, int i)
/*
* move to the first char to delete where the first diff is
*/
- term_move_to_char(el, ofd - old);
+ term_move_to_char(el, (int)(ofd - old));
/*
* Check if we have stuff to save
*/
@@ -760,14 +816,15 @@ re_update_line(EditLine *el, char *old, char *new, int i)
ELRE_DEBUG(!EL_CAN_DELETE, (__F,
"ERROR: cannot delete in first diff\n"));
term_deletechars(el, -fx);
- re_delete(el, old, ofd - old,
+ re_delete(el, old, (int)(ofd - old),
el->el_term.t_size.h, -fx);
}
/*
* write (nsb-nfd) chars of new starting at nfd
*/
- term_overwrite(el, nfd, (nsb - nfd));
- re__strncopy(ofd, nfd, (size_t) (nsb - nfd));
+ len = (size_t) (nsb - nfd);
+ term_overwrite(el, nfd, len);
+ re__strncopy(ofd, nfd, len);
} else {
ELRE_DEBUG(1, (__F,
@@ -775,10 +832,9 @@ re_update_line(EditLine *el, char *old, char *new, int i)
/*
* write (nsb-nfd) chars of new starting at nfd
*/
- term_overwrite(el, nfd, (nsb - nfd));
- ELRE_DEBUG(1, (__F,
- "cleareol %d\n", (oe - old) - (ne - new)));
- term_clear_EOL(el, (oe - old) - (ne - new));
+ term_overwrite(el, nfd, (size_t)(nsb - nfd));
+ re_clear_eol(el, fx, sx,
+ (int)((oe - old) - (ne - new)));
/*
* Done
*/
@@ -797,7 +853,7 @@ re_update_line(EditLine *el, char *old, char *new, int i)
* fx is the number of characters inserted (+) or deleted (-)
*/
- term_move_to_char(el, (ose - old) + fx);
+ term_move_to_char(el, (int)((ose - old) + fx));
/*
* Check if we have stuff to save
*/
@@ -814,15 +870,13 @@ re_update_line(EditLine *el, char *old, char *new, int i)
/*
* write (nls-nse) chars of new starting at nse
*/
- term_overwrite(el, nse, (nls - nse));
+ term_overwrite(el, nse, (size_t)(nls - nse));
} else {
ELRE_DEBUG(1, (__F,
"but with nothing left to save\r\n"));
- term_overwrite(el, nse, (nls - nse));
- ELRE_DEBUG(1, (__F,
- "cleareol %d\n", (oe - old) - (ne - new)));
- if ((oe - old) - (ne - new) != 0)
- term_clear_EOL(el, (oe - old) - (ne - new));
+ term_overwrite(el, nse, (size_t)(nls - nse));
+ re_clear_eol(el, fx, sx,
+ (int)((oe - old) - (ne - new)));
}
}
/*
@@ -832,7 +886,7 @@ re_update_line(EditLine *el, char *old, char *new, int i)
ELRE_DEBUG(1, (__F, "late first diff insert at %d...\r\n",
nfd - new));
- term_move_to_char(el, nfd - new);
+ term_move_to_char(el, (int)(nfd - new));
/*
* Check if we have stuff to keep at the end
*/
@@ -843,7 +897,7 @@ re_update_line(EditLine *el, char *old, char *new, int i)
* to zero above as a flag saying that we hadn't done
* an early first insert.
*/
- fx = (nsb - nfd) - (osb - ofd);
+ fx = (int)((nsb - nfd) - (osb - ofd));
if (fx > 0) {
/*
* insert fx chars of new starting at nfd
@@ -851,20 +905,21 @@ re_update_line(EditLine *el, char *old, char *new, int i)
ELRE_DEBUG(!EL_CAN_INSERT, (__F,
"ERROR: cannot insert in late first diff\n"));
term_insertwrite(el, nfd, fx);
- re_insert(el, old, ofd - old,
+ re_insert(el, old, (int)(ofd - old),
el->el_term.t_size.h, nfd, fx);
}
/*
* write (nsb-nfd) - fx chars of new starting at
* (nfd + fx)
*/
- term_overwrite(el, nfd + fx, (nsb - nfd) - fx);
- re__strncopy(ofd + fx, nfd + fx,
- (size_t) ((nsb - nfd) - fx));
+ len = (size_t) ((nsb - nfd) - fx);
+ term_overwrite(el, (nfd + fx), len);
+ re__strncopy(ofd + fx, nfd + fx, len);
} else {
ELRE_DEBUG(1, (__F, "without anything to save\r\n"));
- term_overwrite(el, nfd, (nsb - nfd));
- re__strncopy(ofd, nfd, (size_t) (nsb - nfd));
+ len = (size_t) (nsb - nfd);
+ term_overwrite(el, nfd, len);
+ re__strncopy(ofd, nfd, len);
}
}
/*
@@ -872,8 +927,8 @@ re_update_line(EditLine *el, char *old, char *new, int i)
*/
if (sx >= 0) {
ELRE_DEBUG(1, (__F,
- "second diff insert at %d...\r\n", nse - new));
- term_move_to_char(el, nse - new);
+ "second diff insert at %d...\r\n", (int)(nse - new)));
+ term_move_to_char(el, (int)(nse - new));
if (ols != oe) {
ELRE_DEBUG(1, (__F, "with stuff to keep at end\r\n"));
if (sx > 0) {
@@ -886,10 +941,11 @@ re_update_line(EditLine *el, char *old, char *new, int i)
* write (nls-nse) - sx chars of new starting at
* (nse + sx)
*/
- term_overwrite(el, nse + sx, (nls - nse) - sx);
+ term_overwrite(el, (nse + sx),
+ (size_t)((nls - nse) - sx));
} else {
ELRE_DEBUG(1, (__F, "without anything to save\r\n"));
- term_overwrite(el, nse, (nls - nse));
+ term_overwrite(el, nse, (size_t)(nls - nse));
/*
* No need to do a clear-to-end here because we were
@@ -906,7 +962,7 @@ re_update_line(EditLine *el, char *old, char *new, int i)
* Copy string and pad with spaces
*/
private void
-re__copy_and_pad(char *dst, const char *src, size_t width)
+re__copy_and_pad(Char *dst, const Char *src, size_t width)
{
size_t i;
@@ -929,8 +985,8 @@ re__copy_and_pad(char *dst, const char *src, size_t width)
protected void
re_refresh_cursor(EditLine *el)
{
- char *cp, c;
- int h, v, th;
+ Char *cp;
+ int h, v, th, w;
if (el->el_line.cursor >= el->el_line.lastchar) {
if (el->el_map.current == el->el_map.alt
@@ -947,43 +1003,42 @@ re_refresh_cursor(EditLine *el)
/* do input buffer to el->el_line.cursor */
for (cp = el->el_line.buffer; cp < el->el_line.cursor; cp++) {
- c = *cp;
- h++; /* all chars at least this long */
-
- if (c == '\n') {/* handle newline in data part too */
+ switch (ct_chr_class(*cp)) {
+ case CHTYPE_NL: /* handle newline in data part too */
h = 0;
v++;
- } else {
- if (c == '\t') { /* if a tab, to next tab stop */
- while (h & 07) {
- h++;
- }
- } else if (iscntrl((unsigned char) c)) {
- /* if control char */
- h++;
- if (h > th) { /* if overflow, compensate */
- h = 1;
- v++;
- }
- } else if (!isprint((unsigned char) c)) {
- h += 3;
- if (h > th) { /* if overflow, compensate */
- h = h - th;
- v++;
- }
+ break;
+ case CHTYPE_TAB: /* if a tab, to next tab stop */
+ while (++h & 07)
+ continue;
+ break;
+ default:
+ w = Width(*cp);
+ if (w > 1 && h + w > th) { /* won't fit on line */
+ h = 0;
+ v++;
}
- }
+ h += ct_visual_width(*cp);
+ break;
+ }
if (h >= th) { /* check, extra long tabs picked up here also */
- h = 0;
+ h -= th;
v++;
}
}
+ /* if we have a next character, and it's a doublewidth one, we need to
+ * check whether we need to linebreak for it to fit */
+ if (cp < el->el_line.lastchar && (w = Width(*cp)) > 1)
+ if (h + w > th) {
+ h = 0;
+ v++;
+ }
/* now go there */
term_move_to_line(el, v);
term_move_to_char(el, h);
- term__flush();
+ term__flush(el);
}
@@ -991,11 +1046,18 @@ re_refresh_cursor(EditLine *el)
* Add a character fast.
*/
private void
-re_fastputc(EditLine *el, int c)
+re_fastputc(EditLine *el, Int c)
{
+ int w = Width((Char)c);
+ while (w > 1 && el->el_cursor.h + w > el->el_term.t_size.h)
+ re_fastputc(el, ' ');
- term__putc(c);
+ term__putc(el, c);
el->el_display[el->el_cursor.v][el->el_cursor.h++] = c;
+ while (--w > 0)
+ el->el_display[el->el_cursor.v][el->el_cursor.h++]
+ = MB_FILL_CHAR;
+
if (el->el_cursor.h >= el->el_term.t_size.h) {
/* if we must overflow */
el->el_cursor.h = 0;
@@ -1008,25 +1070,25 @@ re_fastputc(EditLine *el, int c)
*/
if (el->el_cursor.v + 1 >= el->el_term.t_size.v) {
int i, lins = el->el_term.t_size.v;
- char *firstline = el->el_display[0];
+ Char *firstline = el->el_display[0];
- for(i=1; i < lins; i++)
- el->el_display[i-1] = el->el_display[i];
+ for(i = 1; i < lins; i++)
+ el->el_display[i - 1] = el->el_display[i];
- re__copy_and_pad(firstline, "", 0);
- el->el_display[i-1] = firstline;
+ re__copy_and_pad(firstline, STR(""), 0);
+ el->el_display[i - 1] = firstline;
} else {
el->el_cursor.v++;
el->el_refresh.r_oldcv++;
}
if (EL_HAS_AUTO_MARGINS) {
if (EL_HAS_MAGIC_MARGINS) {
- term__putc(' ');
- term__putc('\b');
+ term__putc(el, ' ');
+ term__putc(el, '\b');
}
} else {
- term__putc('\r');
- term__putc('\n');
+ term__putc(el, '\r');
+ term__putc(el, '\n');
}
}
}
@@ -1039,7 +1101,7 @@ re_fastputc(EditLine *el, int c)
protected void
re_fastaddc(EditLine *el)
{
- char c;
+ Char c;
int rhdiff;
c = el->el_line.cursor[-1];
@@ -1054,19 +1116,24 @@ re_fastaddc(EditLine *el)
re_refresh(el); /* clear out rprompt if less than 1 char gap */
return;
} /* else (only do at end of line, no TAB) */
- if (iscntrl((unsigned char) c)) { /* if control char, do caret */
- char mc = (c == '\177') ? '?' : (c | 0100);
- re_fastputc(el, '^');
- re_fastputc(el, mc);
- } else if (isprint((unsigned char) c)) { /* normal char */
+ switch (ct_chr_class(c)) {
+ case CHTYPE_TAB: /* already handled, should never happen here */
+ break;
+ case CHTYPE_NL:
+ case CHTYPE_PRINT:
re_fastputc(el, c);
- } else {
- re_fastputc(el, '\\');
- re_fastputc(el, (int)(((((unsigned int)c) >> 6) & 3) + '0'));
- re_fastputc(el, (int)(((((unsigned int)c) >> 3) & 7) + '0'));
- re_fastputc(el, (c & 7) + '0');
+ break;
+ case CHTYPE_ASCIICTL:
+ case CHTYPE_NONPRINT: {
+ Char visbuf[VISUAL_WIDTH_MAX];
+ ssize_t i, n =
+ ct_visual_char(visbuf, VISUAL_WIDTH_MAX, (Char)c);
+ for (i = 0; n-- > 0; ++i)
+ re_fastputc(el, visbuf[i]);
+ break;
+ }
}
- term__flush();
+ term__flush(el);
}
@@ -1095,17 +1162,16 @@ re_clear_lines(EditLine *el)
if (EL_CAN_CEOL) {
int i;
- term_move_to_char(el, 0);
- for (i = 0; i <= el->el_refresh.r_oldcv; i++) {
+ for (i = el->el_refresh.r_oldcv; i >= 0; i--) {
/* for each line on the screen */
term_move_to_line(el, i);
+ term_move_to_char(el, 0);
term_clear_EOL(el, el->el_term.t_size.h);
}
- term_move_to_line(el, 0);
} else {
term_move_to_line(el, el->el_refresh.r_oldcv);
/* go to last line */
- term__putc('\r'); /* go to BOL */
- term__putc('\n'); /* go to new line */
+ term__putc(el, '\r'); /* go to BOL */
+ term__putc(el, '\n'); /* go to new line */
}
}
diff --git a/lib/libedit/refresh.h b/lib/libedit/refresh.h
index 66f4ffc6a11..9992525b05f 100644
--- a/lib/libedit/refresh.h
+++ b/lib/libedit/refresh.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: refresh.h,v 1.6 2003/10/31 08:42:24 otto Exp $ */
-/* $NetBSD: refresh.h,v 1.5 2003/08/07 16:44:33 agc Exp $ */
+/* $OpenBSD: refresh.h,v 1.7 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: refresh.h,v 1.6 2009/12/30 22:37:40 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -49,7 +49,7 @@ typedef struct {
int r_newcv;
} el_refresh_t;
-protected void re_putc(EditLine *, int, int);
+protected void re_putc(EditLine *, Int, int);
protected void re_clear_lines(EditLine *);
protected void re_clear_display(EditLine *);
protected void re_refresh(EditLine *);
diff --git a/lib/libedit/search.c b/lib/libedit/search.c
index e9112b24564..6af282ae3f9 100644
--- a/lib/libedit/search.c
+++ b/lib/libedit/search.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: search.c,v 1.11 2009/10/27 23:59:28 deraadt Exp $ */
-/* $NetBSD: search.c,v 1.19 2003/10/25 06:42:41 christos Exp $ */
+/* $OpenBSD: search.c,v 1.12 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: search.c,v 1.24 2010/04/15 00:57:33 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -60,7 +60,8 @@ protected int
search_init(EditLine *el)
{
- el->el_search.patbuf = (char *) el_malloc(EL_BUFSIZ);
+ el->el_search.patbuf = el_malloc(EL_BUFSIZ *
+ sizeof(*el->el_search.patbuf));
if (el->el_search.patbuf == NULL)
return (-1);
el->el_search.patlen = 0;
@@ -100,8 +101,11 @@ regerror(const char *msg)
* Return if string matches pattern
*/
protected int
-el_match(const char *str, const char *pat)
+el_match(const Char *str, const Char *pat)
{
+#ifdef WIDECHAR
+ static ct_buffer_t conv;
+#endif
#if defined (REGEX)
regex_t re;
int rv;
@@ -113,30 +117,30 @@ el_match(const char *str, const char *pat)
extern int re_exec(const char *);
#endif
- if (strstr(str, pat) != NULL)
+ if (Strstr(str, pat) != 0)
return (1);
#if defined(REGEX)
- if (regcomp(&re, pat, 0) == 0) {
- rv = regexec(&re, str, 0, NULL, 0) == 0;
+ if (regcomp(&re, ct_encode_string(pat, &conv), 0) == 0) {
+ rv = regexec(&re, ct_encode_string(str, &conv), 0, NULL, 0) == 0;
regfree(&re);
} else {
rv = 0;
}
return (rv);
#elif defined(REGEXP)
- if ((re = regcomp(pat)) != NULL) {
- rv = regexec(re, str);
+ if ((re = regcomp(ct_encode_string(pat, &conv))) != NULL) {
+ rv = regexec(re, ct_encode_string(str, &conv));
free((ptr_t) re);
} else {
rv = 0;
}
return (rv);
#else
- if (re_comp(pat) != NULL)
+ if (re_comp(ct_encode_string(pat, &conv)) != NULL)
return (0);
else
- return (re_exec(str) == 1);
+ return (re_exec(ct_encode_string(str, &conv)) == 1);
#endif
}
@@ -145,7 +149,7 @@ el_match(const char *str, const char *pat)
* return True if the pattern matches the prefix
*/
protected int
-c_hmatch(EditLine *el, const char *str)
+c_hmatch(EditLine *el, const Char *str)
{
#ifdef SDEBUG
(void) fprintf(el->el_errfile, "match `%s' with `%s'\n",
@@ -168,11 +172,11 @@ c_setpat(EditLine *el)
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,
+ (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);
+ el->el_search.patlen = Strlen(el->el_search.patbuf);
}
#ifdef SDEBUG
(void) fprintf(el->el_errfile, "\neventno = %d\n",
@@ -193,21 +197,22 @@ c_setpat(EditLine *el)
protected el_action_t
ce_inc_search(EditLine *el, int dir)
{
- static const char STRfwd[] = {'f', 'w', 'd', '\0'},
+ static const Char STRfwd[] = {'f', 'w', 'd', '\0'},
STRbck[] = {'b', 'c', 'k', '\0'};
- static char pchar = ':';/* ':' = normal, '?' = failed */
- static char endcmd[2] = {'\0', '\0'};
- char ch, *ocursor = el->el_line.cursor, oldpchar = pchar;
- const char *cp;
+ static Char pchar = ':';/* ':' = normal, '?' = failed */
+ static Char endcmd[2] = {'\0', '\0'};
+ Char ch, *ocursor = el->el_line.cursor, oldpchar = pchar;
+ const Char *cp;
el_action_t ret = CC_NORM;
int ohisteventno = el->el_history.eventno;
- int oldpatlen = el->el_search.patlen;
+ size_t oldpatlen = el->el_search.patlen;
int newdir = dir;
int done, redo;
- if (el->el_line.lastchar + sizeof(STRfwd) / sizeof(char) + 2 +
+ if (el->el_line.lastchar + sizeof(STRfwd) /
+ sizeof(*el->el_line.lastchar) + 2 +
el->el_search.patlen >= el->el_line.limit)
return (CC_ERROR);
@@ -236,7 +241,7 @@ ce_inc_search(EditLine *el, int dir)
*el->el_line.lastchar = '\0';
re_refresh(el);
- if (el_getc(el, &ch) != 1)
+ if (FUN(el,getc)(el, &ch) != 1)
return (ed_end_of_file(el, 0));
switch (el->el_map.current[(unsigned char) ch]) {
@@ -263,6 +268,7 @@ ce_inc_search(EditLine *el, int dir)
redo++;
break;
+ case EM_DELETE_PREV_CHAR:
case ED_DELETE_PREV_CHAR:
if (el->el_search.patlen > LEN)
done++;
@@ -311,7 +317,7 @@ ce_inc_search(EditLine *el, int dir)
default: /* Terminate and execute cmd */
endcmd[0] = ch;
- el_push(el, endcmd);
+ FUN(el,push)(el, endcmd);
/* FALLTHROUGH */
case 0033: /* ESC: Terminate */
@@ -438,8 +444,8 @@ ce_inc_search(EditLine *el, int dir)
protected el_action_t
cv_search(EditLine *el, int dir)
{
- char ch;
- char tmpbuf[EL_BUFSIZ];
+ Char ch;
+ Char tmpbuf[EL_BUFSIZ];
int tmplen;
#ifdef ANCHOR
@@ -451,7 +457,7 @@ cv_search(EditLine *el, int dir)
el->el_search.patdir = dir;
tmplen = c_gets(el, &tmpbuf[LEN],
- dir == ED_SEARCH_PREV_HISTORY ? "\n/" : "\n?" );
+ dir == ED_SEARCH_PREV_HISTORY ? STR("\n/") : STR("\n?") );
if (tmplen == -1)
return CC_REFRESH;
@@ -470,11 +476,11 @@ cv_search(EditLine *el, int dir)
#ifdef ANCHOR
if (el->el_search.patbuf[0] != '.' &&
el->el_search.patbuf[0] != '*') {
- (void) strncpy(tmpbuf, el->el_search.patbuf,
- sizeof(tmpbuf) - 1);
+ (void) Strncpy(tmpbuf, el->el_search.patbuf,
+ sizeof(tmpbuf) / sizeof(*tmpbuf) - 1);
el->el_search.patbuf[0] = '.';
el->el_search.patbuf[1] = '*';
- (void) strncpy(&el->el_search.patbuf[2], tmpbuf,
+ (void) Strncpy(&el->el_search.patbuf[2], tmpbuf,
EL_BUFSIZ - 3);
el->el_search.patlen++;
el->el_search.patbuf[el->el_search.patlen++] = '.';
@@ -488,7 +494,7 @@ cv_search(EditLine *el, int dir)
tmpbuf[tmplen++] = '*';
#endif
tmpbuf[tmplen] = '\0';
- (void) strncpy(el->el_search.patbuf, tmpbuf, EL_BUFSIZ - 1);
+ (void) Strncpy(el->el_search.patbuf, tmpbuf, EL_BUFSIZ - 1);
el->el_search.patlen = tmplen;
}
el->el_state.lastcmd = (el_action_t) dir; /* avoid c_setpat */
@@ -512,9 +518,9 @@ cv_search(EditLine *el, int dir)
protected el_action_t
ce_search_line(EditLine *el, int dir)
{
- char *cp = el->el_line.cursor;
- char *pattern = el->el_search.patbuf;
- char oc, *ocp;
+ Char *cp = el->el_line.cursor;
+ Char *pattern = el->el_search.patbuf;
+ Char oc, *ocp;
#ifdef ANCHOR
ocp = &pattern[1];
oc = *ocp;
@@ -552,12 +558,12 @@ ce_search_line(EditLine *el, int dir)
* Vi repeat search
*/
protected el_action_t
-cv_repeat_srch(EditLine *el, int c)
+cv_repeat_srch(EditLine *el, Int c)
{
#ifdef SDEBUG
(void) fprintf(el->el_errfile, "dir %d patlen %d patbuf %s\n",
- c, el->el_search.patlen, el->el_search.patbuf);
+ c, el->el_search.patlen, ct_encode_string(el->el_search.patbuf));
#endif
el->el_state.lastcmd = (el_action_t) c; /* Hack to stop c_setpat */
@@ -578,16 +584,16 @@ cv_repeat_srch(EditLine *el, int c)
* Vi character search
*/
protected el_action_t
-cv_csearch(EditLine *el, int direction, int ch, int count, int tflag)
+cv_csearch(EditLine *el, int direction, Int ch, int count, int tflag)
{
- char *cp;
+ Char *cp;
if (ch == 0)
return CC_ERROR;
if (ch == -1) {
- char c;
- if (el_getc(el, &c) != 1)
+ Char c;
+ if (FUN(el,getc)(el, &c) != 1)
return ed_end_of_file(el, 0);
ch = c;
}
diff --git a/lib/libedit/search.h b/lib/libedit/search.h
index 68f7dcfad74..1f8d774c0b3 100644
--- a/lib/libedit/search.h
+++ b/lib/libedit/search.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: search.h,v 1.7 2003/11/25 20:12:38 otto Exp $ */
-/* $NetBSD: search.h,v 1.8 2003/10/18 23:27:36 christos Exp $ */
+/* $OpenBSD: search.h,v 1.8 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: search.h,v 1.9 2009/12/30 22:37:40 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -44,24 +44,24 @@
#include "histedit.h"
typedef struct el_search_t {
- char *patbuf; /* The pattern buffer */
+ Char *patbuf; /* The pattern buffer */
size_t patlen; /* Length of the pattern buffer */
int patdir; /* Direction of the last search */
int chadir; /* Character search direction */
- char chacha; /* Character we are looking for */
+ Char chacha; /* Character we are looking for */
char chatflg; /* 0 if f, 1 if t */
} el_search_t;
-protected int el_match(const char *, const char *);
+protected int el_match(const Char *, const Char *);
protected int search_init(EditLine *);
protected void search_end(EditLine *);
-protected int c_hmatch(EditLine *, const char *);
+protected int c_hmatch(EditLine *, const Char *);
protected void c_setpat(EditLine *);
protected el_action_t ce_inc_search(EditLine *, int);
protected el_action_t cv_search(EditLine *, int);
protected el_action_t ce_search_line(EditLine *, int);
-protected el_action_t cv_repeat_srch(EditLine *, int);
-protected el_action_t cv_csearch(EditLine *, int, int, int, int);
+protected el_action_t cv_repeat_srch(EditLine *, Int);
+protected el_action_t cv_csearch(EditLine *, int, Int, int, int);
#endif /* _h_el_search */
diff --git a/lib/libedit/shlib_version b/lib/libedit/shlib_version
index 012c14171d3..d9961ea9fef 100644
--- a/lib/libedit/shlib_version
+++ b/lib/libedit/shlib_version
@@ -1,2 +1,2 @@
-major=3
+major=4
minor=0
diff --git a/lib/libedit/sig.c b/lib/libedit/sig.c
index 58a62eabe4f..7e22486738b 100644
--- a/lib/libedit/sig.c
+++ b/lib/libedit/sig.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: sig.c,v 1.11 2009/10/27 23:59:28 deraadt Exp $ */
-/* $NetBSD: sig.c,v 1.11 2003/08/07 16:44:33 agc Exp $ */
+/* $OpenBSD: sig.c,v 1.12 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: sig.c,v 1.15 2009/02/19 15:20:22 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -69,12 +69,14 @@ sig_handler(int signo)
(void) sigaddset(&nset, signo);
(void) sigprocmask(SIG_BLOCK, &nset, &oset);
+ sel->el_signal->sig_no = signo;
+
switch (signo) {
case SIGCONT:
tty_rawmode(sel);
if (ed_redisplay(sel, 0) == CC_REFRESH)
re_refresh(sel);
- term__flush();
+ term__flush(sel);
break;
case SIGWINCH:
@@ -90,7 +92,10 @@ sig_handler(int signo)
if (signo == sighdl[i])
break;
- (void) signal(signo, sel->el_signal[i]);
+ (void) sigaction(signo, &sel->el_signal->sig_action[i], NULL);
+ sel->el_signal->sig_action[i].sa_handler = SIG_ERR;
+ sel->el_signal->sig_action[i].sa_flags = 0;
+ sigemptyset(&sel->el_signal->sig_action[i].sa_mask);
(void) sigprocmask(SIG_SETMASK, &oset, NULL);
(void) kill(0, signo);
}
@@ -102,26 +107,29 @@ sig_handler(int signo)
protected int
sig_init(EditLine *el)
{
- int i;
- sigset_t nset, oset;
+ size_t i;
+ sigset_t *nset, oset;
- (void) sigemptyset(&nset);
-#define _DO(a) (void) sigaddset(&nset, a);
+ el->el_signal = el_malloc(sizeof(*el->el_signal));
+ if (el->el_signal == NULL)
+ return -1;
+
+ nset = &el->el_signal->sig_set;
+ (void) sigemptyset(nset);
+#define _DO(a) (void) sigaddset(nset, a);
ALLSIGS
#undef _DO
- (void) sigprocmask(SIG_BLOCK, &nset, &oset);
+ (void) sigprocmask(SIG_BLOCK, nset, &oset);
-#define SIGSIZE (sizeof(sighdl) / sizeof(sighdl[0]) * sizeof(el_signalhandler_t))
-
- el->el_signal = (el_signalhandler_t *) el_malloc(SIGSIZE);
- if (el->el_signal == NULL)
- return (-1);
- for (i = 0; sighdl[i] != -1; i++)
- el->el_signal[i] = SIG_ERR;
+ for (i = 0; sighdl[i] != -1; i++) {
+ el->el_signal->sig_action[i].sa_handler = SIG_ERR;
+ el->el_signal->sig_action[i].sa_flags = 0;
+ sigemptyset(&el->el_signal->sig_action[i].sa_mask);
+ }
(void) sigprocmask(SIG_SETMASK, &oset, NULL);
- return (0);
+ return 0;
}
@@ -143,20 +151,21 @@ sig_end(EditLine *el)
protected void
sig_set(EditLine *el)
{
- int i;
- sigset_t nset, oset;
+ size_t i;
+ sigset_t oset;
+ struct sigaction osa, nsa;
- (void) sigemptyset(&nset);
-#define _DO(a) (void) sigaddset(&nset, a);
- ALLSIGS
-#undef _DO
- (void) sigprocmask(SIG_BLOCK, &nset, &oset);
+ nsa.sa_handler = sig_handler;
+ nsa.sa_flags = 0;
+ sigemptyset(&nsa.sa_mask);
+
+ (void) sigprocmask(SIG_BLOCK, &el->el_signal->sig_set, &oset);
for (i = 0; sighdl[i] != -1; i++) {
- el_signalhandler_t s;
/* This could happen if we get interrupted */
- if ((s = signal(sighdl[i], sig_handler)) != sig_handler)
- el->el_signal[i] = s;
+ if (sigaction(sighdl[i], &nsa, &osa) != -1 &&
+ osa.sa_handler != sig_handler)
+ el->el_signal->sig_action[i] = osa;
}
sel = el;
(void) sigprocmask(SIG_SETMASK, &oset, NULL);
@@ -169,20 +178,17 @@ sig_set(EditLine *el)
protected void
sig_clr(EditLine *el)
{
- int i;
- sigset_t nset, oset;
+ size_t i;
+ sigset_t oset;
- (void) sigemptyset(&nset);
-#define _DO(a) (void) sigaddset(&nset, a);
- ALLSIGS
-#undef _DO
- (void) sigprocmask(SIG_BLOCK, &nset, &oset);
+ (void) sigprocmask(SIG_BLOCK, &el->el_signal->sig_set, &oset);
for (i = 0; sighdl[i] != -1; i++)
- if (el->el_signal[i] != SIG_ERR)
- (void) signal(sighdl[i], el->el_signal[i]);
+ if (el->el_signal->sig_action[i].sa_handler != SIG_ERR)
+ (void)sigaction(sighdl[i],
+ &el->el_signal->sig_action[i], NULL);
sel = NULL; /* we are going to die if the handler is
* called */
- (void) sigprocmask(SIG_SETMASK, &oset, NULL);
+ (void)sigprocmask(SIG_SETMASK, &oset, NULL);
}
diff --git a/lib/libedit/sig.h b/lib/libedit/sig.h
index 34251f817a4..ac1b1b917be 100644
--- a/lib/libedit/sig.h
+++ b/lib/libedit/sig.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: sig.h,v 1.6 2003/10/31 08:42:24 otto Exp $ */
-/* $NetBSD: sig.h,v 1.5 2003/08/07 16:44:33 agc Exp $ */
+/* $OpenBSD: sig.h,v 1.7 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: sig.h,v 1.8 2009/02/19 15:20:22 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -52,15 +52,18 @@
#define ALLSIGS \
_DO(SIGINT) \
_DO(SIGTSTP) \
- _DO(SIGSTOP) \
_DO(SIGQUIT) \
_DO(SIGHUP) \
_DO(SIGTERM) \
_DO(SIGCONT) \
_DO(SIGWINCH)
+#define ALLSIGSNO 7
-typedef void (*el_signalhandler_t)(int);
-typedef el_signalhandler_t *el_signal_t;
+typedef struct {
+ struct sigaction sig_action[ALLSIGSNO];
+ sigset_t sig_set;
+ volatile sig_atomic_t sig_no;
+} *el_signal_t;
protected void sig_end(EditLine*);
protected int sig_init(EditLine*);
diff --git a/lib/libedit/sys.h b/lib/libedit/sys.h
index 1335d61c12b..cb01859112a 100644
--- a/lib/libedit/sys.h
+++ b/lib/libedit/sys.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: sys.h,v 1.8 2003/10/31 08:42:24 otto Exp $ */
-/* $NetBSD: sys.h,v 1.8 2003/08/07 16:44:33 agc Exp $ */
+/* $OpenBSD: sys.h,v 1.9 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: sys.h,v 1.13 2009/12/30 22:37:40 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -49,6 +49,16 @@
# define __attribute__(A)
#endif
+#ifndef __BEGIN_DECLS
+# ifdef __cplusplus
+# define __BEGIN_DECLS extern "C" {
+# define __END_DECLS }
+# else
+# define __BEGIN_DECLS
+# define __END_DECLS
+# endif
+#endif
+
#ifndef public
# define public /* Externally visible functions/variables */
#endif
@@ -62,6 +72,10 @@
/* When we want to hide everything */
#endif
+#ifndef __arraycount
+# define __arraycount(a) (sizeof(a) / sizeof(*(a)))
+#endif
+
#ifndef _PTR_T
# define _PTR_T
typedef void *ptr_t;
@@ -92,6 +106,15 @@ char *fgetln(FILE *fp, size_t *len);
#define REGEX /* Use POSIX.2 regular expression functions */
#undef REGEXP /* Use UNIX V8 regular expression functions */
+#if defined(__sun)
+extern int tgetent(char *, const char *);
+extern int tgetflag(char *);
+extern int tgetnum(char *);
+extern int tputs(const char *, int, int (*)(int));
+extern char* tgoto(const char*, int, int);
+extern char* tgetstr(char*, char**);
+#endif
+
#ifdef notdef
# undef REGEX
# undef REGEXP
diff --git a/lib/libedit/term.c b/lib/libedit/term.c
index 0f14a967e8e..2e7467747ee 100644
--- a/lib/libedit/term.c
+++ b/lib/libedit/term.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: term.c,v 1.13 2009/12/11 18:58:59 jacekm Exp $ */
-/* $NetBSD: term.c,v 1.38 2003/09/14 21:48:55 christos Exp $ */
+/* $OpenBSD: term.c,v 1.14 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: term.c,v 1.57 2009/12/30 22:37:40 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -45,27 +45,32 @@
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
+#include <limits.h>
#ifdef HAVE_TERMCAP_H
#include <termcap.h>
#endif
#ifdef HAVE_CURSES_H
#include <curses.h>
-#endif
-#ifdef HAVE_NCURSES_H
+#elif HAVE_NCURSES_H
#include <ncurses.h>
#endif
/* Solaris's term.h does horrid things. */
-#if (defined(HAVE_TERM_H) && !defined(SUNOS))
+
+#if defined(HAVE_TERM_H) && !defined(__sun)
#include <term.h>
#endif
#include <sys/types.h>
#include <sys/ioctl.h>
+#ifdef _REENTRANT
+#include <pthread.h>
+#endif
+
#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
+ * and the current position assuming that it is correct. If this is not
* true, then the update will be WRONG! This is (should be) a valid
* assumption...
*/
@@ -265,9 +270,13 @@ private int term_alloc_display(EditLine *);
private void term_alloc(EditLine *, const struct termcapstr *, const char *);
private void term_init_arrow(EditLine *);
private void term_reset_arrow(EditLine *);
+private int term_putc(int);
+private void term_tputs(EditLine *, const char *, int);
-
-private FILE *term_outfile = NULL; /* XXX: How do we fix that? */
+#ifdef _REENTRANT
+private pthread_mutex_t term_mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
+private FILE *term_outfile = NULL;
/* term_setflags():
@@ -315,7 +324,6 @@ term_setflags(EditLine *el)
#endif /* DEBUG_SCREEN */
}
-
/* term_init():
* Initialize the terminal stuff
*/
@@ -341,7 +349,6 @@ term_init(EditLine *el)
if (el->el_term.t_val == NULL)
goto fail5;
(void) memset(el->el_term.t_val, 0, T_val * sizeof(int));
- term_outfile = el->el_outfile;
(void) term_set(el, NULL);
term_init_arrow(el);
return (0);
@@ -377,6 +384,8 @@ term_end(EditLine *el)
el->el_term.t_str = NULL;
el_free((ptr_t) el->el_term.t_val);
el->el_term.t_val = NULL;
+ el_free((ptr_t) el->el_term.t_fkey);
+ el->el_term.t_fkey = NULL;
term_free_display(el);
}
@@ -388,7 +397,7 @@ private void
term_alloc(EditLine *el, const struct termcapstr *t, const char *cap)
{
char termbuf[TC_BUFSIZE];
- int tlen, clen;
+ size_t tlen, clen;
char **tlist = el->el_term.t_str;
char **tmp, **str = &tlist[t - tstr];
@@ -404,7 +413,8 @@ term_alloc(EditLine *el, const struct termcapstr *t, const char *cap)
* New string is shorter; no need to allocate space
*/
if (clen <= tlen) {
- (void) strlcpy(*str, cap, tlen + 1);
+ if (*str)
+ (void) strlcpy(*str, cap, tlen + 1);
return;
}
/*
@@ -414,7 +424,7 @@ term_alloc(EditLine *el, const struct termcapstr *t, const char *cap)
tlen = TC_BUFSIZE - el->el_term.t_loc;
(void) strlcpy(*str = &el->el_term.t_buf[el->el_term.t_loc],
cap, tlen);
- el->el_term.t_loc += clen + 1; /* one for \0 */
+ el->el_term.t_loc += (int)clen + 1; /* one for \0 */
return;
}
/*
@@ -431,7 +441,7 @@ term_alloc(EditLine *el, const struct termcapstr *t, const char *cap)
termbuf[tlen++] = '\0';
}
memcpy(el->el_term.t_buf, termbuf, TC_BUFSIZE);
- el->el_term.t_loc = tlen;
+ el->el_term.t_loc = (int)tlen;
if (el->el_term.t_loc + 3 >= TC_BUFSIZE) {
(void) fprintf(el->el_errfile,
"Out of termcap string space.\n");
@@ -439,7 +449,7 @@ term_alloc(EditLine *el, const struct termcapstr *t, const char *cap)
}
tlen = TC_BUFSIZE - el->el_term.t_loc;
(void) strlcpy(*str = &el->el_term.t_buf[el->el_term.t_loc], cap, tlen);
- el->el_term.t_loc += clen + 1; /* one for \0 */
+ el->el_term.t_loc += (int)clen + 1; /* one for \0 */
return;
}
@@ -469,39 +479,40 @@ term_rebuffer_display(EditLine *el)
private int
term_alloc_display(EditLine *el)
{
- int i, rv = -1;
- char **b;
+ int i;
+ Char **b;
coord_t *c = &el->el_term.t_size;
- b = (char **) el_malloc((size_t) (sizeof(char *) * (c->v + 1)));
+ b = el_malloc(sizeof(*b) * (c->v + 1));
if (b == NULL)
- goto done;
- b[0] = NULL;
+ return (-1);
for (i = 0; i < c->v; i++) {
- b[i] = (char *) el_malloc((size_t) (sizeof(char) * (c->h + 1)));
- if (b[i] == NULL)
- goto done;
- b[i + 1] = NULL;
+ b[i] = el_malloc(sizeof(**b) * (c->h + 1));
+ if (b[i] == NULL) {
+ while (--i >= 0)
+ el_free((ptr_t) b[i]);
+ el_free((ptr_t) b);
+ return (-1);
+ }
}
+ b[c->v] = NULL;
el->el_display = b;
- b = (char **) el_malloc((size_t) (sizeof(char *) * (c->v + 1)));
+ b = el_malloc(sizeof(*b) * (c->v + 1));
if (b == NULL)
- goto done;
- b[0] = NULL;
+ return (-1);
for (i = 0; i < c->v; i++) {
- b[i] = (char *) el_malloc((size_t) (sizeof(char) * (c->h + 1)));
- if (b[i] == NULL)
- goto done;
- b[i + 1] = NULL;
+ b[i] = el_malloc(sizeof(**b) * (c->h + 1));
+ if (b[i] == NULL) {
+ while (--i >= 0)
+ el_free((ptr_t) b[i]);
+ el_free((ptr_t) b);
+ return (-1);
+ }
}
+ b[c->v] = NULL;
el->el_vdisplay = b;
-
- rv = 0;
-done:
- if (rv)
- term_free_display(el);
- return (rv);
+ return (0);
}
@@ -511,21 +522,21 @@ done:
private void
term_free_display(EditLine *el)
{
- char **b;
- char **bufp;
+ 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) *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) *bufp);
el_free((ptr_t) b);
}
}
@@ -554,21 +565,30 @@ term_move_to_line(EditLine *el, int where)
while (del > 0) {
if (EL_HAS_AUTO_MARGINS &&
el->el_display[el->el_cursor.v][0] != '\0') {
+ size_t h = el->el_term.t_size.h - 1;
+#ifdef WIDECHAR
+ for (; h > 0 &&
+ el->el_display[el->el_cursor.v][h] ==
+ MB_FILL_CHAR;
+ h--)
+ continue;
+#endif
/* move without newline */
- term_move_to_char(el, el->el_term.t_size.h - 1);
- term_overwrite(el,
- &el->el_display[el->el_cursor.v][el->el_cursor.h],
- 1);
+ term_move_to_char(el, (int)h);
+ term_overwrite(el, &el->el_display
+ [el->el_cursor.v][el->el_cursor.h],
+ (size_t)(el->el_term.t_size.h -
+ el->el_cursor.h));
/* updates Cursor */
del--;
} else {
if ((del > 1) && GoodStr(T_DO)) {
- (void) tputs(tgoto(Str(T_DO), del, del),
- del, term__putc);
+ term_tputs(el, tgoto(Str(T_DO), del,
+ del), del);
del = 0;
} else {
for (; del > 0; del--)
- term__putc('\n');
+ term__putc(el, '\n');
/* because the \n will become \r\n */
el->el_cursor.h = 0;
}
@@ -576,12 +596,11 @@ term_move_to_line(EditLine *el, int where)
}
} else { /* del < 0 */
if (GoodStr(T_UP) && (-del > 1 || !GoodStr(T_up)))
- (void) tputs(tgoto(Str(T_UP), -del, -del), -del,
- term__putc);
+ term_tputs(el, tgoto(Str(T_UP), -del, -del), -del);
else {
if (GoodStr(T_up))
for (; del < 0; del++)
- (void) tputs(Str(T_up), 1, term__putc);
+ term_tputs(el, Str(T_up), 1);
}
}
el->el_cursor.v = where;/* now where is here */
@@ -608,7 +627,7 @@ mc_again:
return;
}
if (!where) { /* if where is first column */
- term__putc('\r'); /* do a CR */
+ term__putc(el, '\r'); /* do a CR */
el->el_cursor.h = 0;
return;
}
@@ -616,25 +635,30 @@ mc_again:
if ((del < -4 || del > 4) && GoodStr(T_ch))
/* go there directly */
- (void) tputs(tgoto(Str(T_ch), where, where), where, term__putc);
+ term_tputs(el, tgoto(Str(T_ch), where, where), where);
else {
if (del > 0) { /* moving forward */
if ((del > 4) && GoodStr(T_RI))
- (void) tputs(tgoto(Str(T_RI), del, del),
- del, term__putc);
+ term_tputs(el, tgoto(Str(T_RI), del, del), del);
else {
/* if I can do tabs, use them */
if (EL_CAN_TAB) {
if ((el->el_cursor.h & 0370) !=
- (where & 0370)) {
+ (where & ~0x7)
+#ifdef WIDECHAR
+ && (el->el_display[
+ el->el_cursor.v][where & 0370] !=
+ MB_FILL_CHAR)
+#endif
+ ) {
/* if not within tab stop */
for (i =
(el->el_cursor.h & 0370);
- i < (where & 0370);
+ i < (where & ~0x7);
i += 8)
- term__putc('\t');
+ term__putc(el, '\t');
/* then tab over */
- el->el_cursor.h = where & 0370;
+ el->el_cursor.h = where & ~0x7;
}
}
/*
@@ -645,15 +669,15 @@ mc_again:
* 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);
+ term_overwrite(el, &el->el_display[
+ el->el_cursor.v][el->el_cursor.h],
+ (size_t)(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);
+ term_tputs(el, tgoto(Str(T_LE), -del, -del),
+ -del);
else { /* can't go directly there */
/*
* if the "cost" is greater than the "cost"
@@ -664,12 +688,12 @@ mc_again:
(((unsigned int) where >> 3) +
(where & 07)))
: (-del > where)) {
- term__putc('\r'); /* do a CR */
+ term__putc(el, '\r'); /* do a CR */
el->el_cursor.h = 0;
goto mc_again; /* and try again */
}
for (i = 0; i < -del; i++)
- term__putc('\b');
+ term__putc(el, '\b');
}
}
}
@@ -679,24 +703,27 @@ mc_again:
/* term_overwrite():
* Overstrike num characters
+ * Assumes MB_FILL_CHARs are present to keep the column count correct
*/
protected void
-term_overwrite(EditLine *el, const char *cp, int n)
+term_overwrite(EditLine *el, const Char *cp, size_t n)
{
- if (n <= 0)
- return; /* catch bugs */
+ if (n == 0)
+ return;
- if (n > el->el_term.t_size.h) {
+ if (n > (size_t)el->el_term.t_size.h) {
#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);
+
+ do {
+ /* term__putc() ignores any MB_FILL_CHARs */
+ term__putc(el, *cp++);
+ el->el_cursor.h++;
+ } while (--n);
if (el->el_cursor.h >= el->el_term.t_size.h) { /* wrap? */
if (EL_HAS_AUTO_MARGINS) { /* yes */
@@ -705,16 +732,22 @@ term_overwrite(EditLine *el, const char *cp, int n)
if (EL_HAS_MAGIC_MARGINS) {
/* force the wrap to avoid the "magic"
* situation */
- char c;
- if ((c = el->el_display[el->el_cursor.v][el->el_cursor.h])
- != '\0')
+ Char c;
+ if ((c = el->el_display[el->el_cursor.v]
+ [el->el_cursor.h]) != '\0') {
term_overwrite(el, &c, 1);
- else
- term__putc(' ');
- el->el_cursor.h = 1;
+#ifdef WIDECHAR
+ while (el->el_display[el->el_cursor.v]
+ [el->el_cursor.h] == MB_FILL_CHAR)
+ el->el_cursor.h++;
+#endif
+ } else {
+ term__putc(el, ' ');
+ el->el_cursor.h = 1;
+ }
}
} else /* no wrap, but cursor stays on screen */
- el->el_cursor.h = el->el_term.t_size.h;
+ el->el_cursor.h = el->el_term.t_size.h - 1;
}
}
@@ -744,28 +777,28 @@ term_deletechars(EditLine *el, int num)
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);
+ term_tputs(el, tgoto(Str(T_DC), num, num), num);
return;
}
if (GoodStr(T_dm)) /* if I have delete mode */
- (void) tputs(Str(T_dm), 1, term__putc);
+ term_tputs(el, Str(T_dm), 1);
if (GoodStr(T_dc)) /* else do one at a time */
while (num--)
- (void) tputs(Str(T_dc), 1, term__putc);
+ term_tputs(el, Str(T_dc), 1);
if (GoodStr(T_ed)) /* if I have delete mode */
- (void) tputs(Str(T_ed), 1, term__putc);
+ term_tputs(el, Str(T_ed), 1);
}
/* term_insertwrite():
* Puts terminal in insert character mode or inserts num
* characters in the line
+ * Assumes MB_FILL_CHARs are present to keep column count correct
*/
protected void
-term_insertwrite(EditLine *el, char *cp, int num)
+term_insertwrite(EditLine *el, Char *cp, int num)
{
if (num <= 0)
return;
@@ -785,37 +818,35 @@ term_insertwrite(EditLine *el, char *cp, int num)
if (GoodStr(T_IC)) /* if I have multiple insert */
if ((num > 1) || !GoodStr(T_ic)) {
/* if ic would be more expensive */
- (void) tputs(tgoto(Str(T_IC), num, num),
- num, term__putc);
- term_overwrite(el, cp, num);
+ term_tputs(el, tgoto(Str(T_IC), num, num), num);
+ term_overwrite(el, cp, (size_t)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);
+ term_tputs(el, Str(T_im), 1);
el->el_cursor.h += num;
do
- term__putc(*cp++);
+ term__putc(el, *cp++);
while (--num);
if (GoodStr(T_ip)) /* have to make num chars insert */
- (void) tputs(Str(T_ip), 1, term__putc);
+ term_tputs(el, Str(T_ip), 1);
- (void) tputs(Str(T_ei), 1, term__putc);
+ term_tputs(el, Str(T_ei), 1);
return;
}
do {
if (GoodStr(T_ic)) /* have to make num chars insert */
- (void) tputs(Str(T_ic), 1, term__putc);
- /* insert a char */
+ term_tputs(el, Str(T_ic), 1);
- term__putc(*cp++);
+ term__putc(el, *cp++);
el->el_cursor.h++;
if (GoodStr(T_ip)) /* have to make num chars insert */
- (void) tputs(Str(T_ip), 1, term__putc);
+ term_tputs(el, Str(T_ip), 1);
/* pad the inserted char */
} while (--num);
@@ -831,10 +862,10 @@ term_clear_EOL(EditLine *el, int num)
int i;
if (EL_CAN_CEOL && GoodStr(T_ce))
- (void) tputs(Str(T_ce), 1, term__putc);
+ term_tputs(el, Str(T_ce), 1);
else {
for (i = 0; i < num; i++)
- term__putc(' ');
+ term__putc(el, ' ');
el->el_cursor.h += num; /* have written num spaces */
}
}
@@ -849,14 +880,14 @@ term_clear_screen(EditLine *el)
if (GoodStr(T_cl))
/* send the clear screen code */
- (void) tputs(Str(T_cl), Val(T_li), term__putc);
+ term_tputs(el, Str(T_cl), Val(T_li));
else if (GoodStr(T_ho) && GoodStr(T_cd)) {
- (void) tputs(Str(T_ho), Val(T_li), term__putc); /* home */
+ term_tputs(el, Str(T_ho), Val(T_li)); /* home */
/* clear to bottom of screen */
- (void) tputs(Str(T_cd), Val(T_li), term__putc);
+ term_tputs(el, Str(T_cd), Val(T_li));
} else {
- term__putc('\r');
- term__putc('\n');
+ term__putc(el, '\r');
+ term__putc(el, '\n');
}
}
@@ -869,9 +900,9 @@ term_beep(EditLine *el)
{
if (GoodStr(T_bl))
/* what termcap says we should use */
- (void) tputs(Str(T_bl), 1, term__putc);
+ term_tputs(el, Str(T_bl), 1);
else
- term__putc('\007'); /* an ASCII bell; ^G */
+ term__putc(el, '\007'); /* an ASCII bell; ^G */
}
@@ -883,9 +914,9 @@ protected void
term_clear_to_bottom(EditLine *el)
{
if (GoodStr(T_cd))
- (void) tputs(Str(T_cd), Val(T_li), term__putc);
+ term_tputs(el, Str(T_cd), Val(T_li));
else if (GoodStr(T_ce))
- (void) tputs(Str(T_ce), Val(T_li), term__putc);
+ term_tputs(el, Str(T_ce), Val(T_li));
}
#endif
@@ -956,8 +987,11 @@ term_set(EditLine *el, const char *term)
/* Get the size */
Val(T_co) = tgetnum("co");
Val(T_li) = tgetnum("li");
- for (t = tstr; t->name != NULL; t++)
- term_alloc(el, t, tgetstr((char *)t->name, &area));
+ for (t = tstr; t->name != NULL; t++) {
+ /* XXX: some systems' tgetstr needs non const */
+ term_alloc(el, t, tgetstr(strchr(t->name, *t->name),
+ &area));
+ }
}
if (Val(T_co) < 2)
@@ -1046,32 +1080,32 @@ term_init_arrow(EditLine *el)
{
fkey_t *arrow = el->el_term.t_fkey;
- arrow[A_K_DN].name = "down";
+ arrow[A_K_DN].name = STR("down");
arrow[A_K_DN].key = T_kd;
arrow[A_K_DN].fun.cmd = ED_NEXT_HISTORY;
arrow[A_K_DN].type = XK_CMD;
- arrow[A_K_UP].name = "up";
+ arrow[A_K_UP].name = STR("up");
arrow[A_K_UP].key = T_ku;
arrow[A_K_UP].fun.cmd = ED_PREV_HISTORY;
arrow[A_K_UP].type = XK_CMD;
- arrow[A_K_LT].name = "left";
+ arrow[A_K_LT].name = STR("left");
arrow[A_K_LT].key = T_kl;
arrow[A_K_LT].fun.cmd = ED_PREV_CHAR;
arrow[A_K_LT].type = XK_CMD;
- arrow[A_K_RT].name = "right";
+ arrow[A_K_RT].name = STR("right");
arrow[A_K_RT].key = T_kr;
arrow[A_K_RT].fun.cmd = ED_NEXT_CHAR;
arrow[A_K_RT].type = XK_CMD;
- arrow[A_K_HO].name = "home";
+ arrow[A_K_HO].name = STR("home");
arrow[A_K_HO].key = T_kh;
arrow[A_K_HO].fun.cmd = ED_MOVE_TO_BEG;
arrow[A_K_HO].type = XK_CMD;
- arrow[A_K_EN].name = "end";
+ arrow[A_K_EN].name = STR("end");
arrow[A_K_EN].key = T_at7;
arrow[A_K_EN].fun.cmd = ED_MOVE_TO_END;
arrow[A_K_EN].type = XK_CMD;
@@ -1085,18 +1119,18 @@ private void
term_reset_arrow(EditLine *el)
{
fkey_t *arrow = el->el_term.t_fkey;
- static const char strA[] = {033, '[', 'A', '\0'};
- static const char strB[] = {033, '[', 'B', '\0'};
- static const char strC[] = {033, '[', 'C', '\0'};
- static const char strD[] = {033, '[', 'D', '\0'};
- static const char strH[] = {033, '[', 'H', '\0'};
- static const char strF[] = {033, '[', 'F', '\0'};
- static const char stOA[] = {033, 'O', 'A', '\0'};
- static const char stOB[] = {033, 'O', 'B', '\0'};
- static const char stOC[] = {033, 'O', 'C', '\0'};
- static const char stOD[] = {033, 'O', 'D', '\0'};
- static const char stOH[] = {033, 'O', 'H', '\0'};
- static const char stOF[] = {033, 'O', 'F', '\0'};
+ static const Char strA[] = {033, '[', 'A', '\0'};
+ static const Char strB[] = {033, '[', 'B', '\0'};
+ static const Char strC[] = {033, '[', 'C', '\0'};
+ static const Char strD[] = {033, '[', 'D', '\0'};
+ static const Char strH[] = {033, '[', 'H', '\0'};
+ static const Char strF[] = {033, '[', 'F', '\0'};
+ static const Char stOA[] = {033, 'O', 'A', '\0'};
+ static const Char stOB[] = {033, 'O', 'B', '\0'};
+ static const Char stOC[] = {033, 'O', 'C', '\0'};
+ static const Char stOD[] = {033, 'O', 'D', '\0'};
+ static const Char stOH[] = {033, 'O', 'H', '\0'};
+ static const Char stOF[] = {033, 'O', 'F', '\0'};
key_add(el, strA, &arrow[A_K_UP].fun, arrow[A_K_UP].type);
key_add(el, strB, &arrow[A_K_DN].fun, arrow[A_K_DN].type);
@@ -1132,13 +1166,13 @@ term_reset_arrow(EditLine *el)
* Set an arrow key binding
*/
protected int
-term_set_arrow(EditLine *el, const char *name, key_value_t *fun, int type)
+term_set_arrow(EditLine *el, const Char *name, key_value_t *fun, int type)
{
fkey_t *arrow = el->el_term.t_fkey;
int i;
for (i = 0; i < A_K_NKEYS; i++)
- if (strcmp(name, arrow[i].name) == 0) {
+ if (Strcmp(name, arrow[i].name) == 0) {
arrow[i].fun = *fun;
arrow[i].type = type;
return (0);
@@ -1151,13 +1185,13 @@ term_set_arrow(EditLine *el, const char *name, key_value_t *fun, int type)
* Clear an arrow key binding
*/
protected int
-term_clear_arrow(EditLine *el, const char *name)
+term_clear_arrow(EditLine *el, const 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) {
+ if (Strcmp(name, arrow[i].name) == 0) {
arrow[i].type = XK_NOD;
return (0);
}
@@ -1169,13 +1203,13 @@ term_clear_arrow(EditLine *el, const char *name)
* Print the arrow key bindings
*/
protected void
-term_print_arrow(EditLine *el, const char *name)
+term_print_arrow(EditLine *el, const Char *name)
{
int i;
fkey_t *arrow = el->el_term.t_fkey;
for (i = 0; i < A_K_NKEYS; i++)
- if (*name == '\0' || strcmp(name, arrow[i].name) == 0)
+ if (*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);
@@ -1204,60 +1238,111 @@ term_bind_arrow(EditLine *el)
term_reset_arrow(el);
for (i = 0; i < A_K_NKEYS; i++) {
+ Char wt_str[VISUAL_WIDTH_MAX];
+ Char *px;
+ size_t n;
+
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,
+ if (!p || !*p)
+ continue;
+ for (n = 0; n < VISUAL_WIDTH_MAX && p[n]; ++n)
+ wt_str[n] = p[n];
+ while (n < VISUAL_WIDTH_MAX)
+ wt_str[n++] = '\0';
+ px = wt_str;
+ 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, px);
+ else {
+ if (p[1] && (dmap[j] == map[j] ||
+ map[j] == ED_SEQUENCE_LEAD_IN)) {
+ key_add(el, px, &arrow[i].fun,
+ arrow[i].type);
+ map[j] = ED_SEQUENCE_LEAD_IN;
+ } else if (map[j] == ED_UNASSIGNED) {
+ key_clear(el, map, px);
+ if (arrow[i].type == XK_CMD)
+ map[j] = arrow[i].fun.cmd;
+ else
+ key_add(el, px, &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
+ */
+private int
+term_putc(int c)
+{
+ if (term_outfile == NULL)
+ return -1;
+ return fputc(c, term_outfile);
+}
+
+private void
+term_tputs(EditLine *el, const char *cap, int affcnt)
+{
+#ifdef _REENTRANT
+ pthread_mutex_lock(&term_mutex);
+#endif
+ term_outfile = el->el_outfile;
+ (void)tputs(cap, affcnt, term_putc);
+#ifdef _REENTRANT
+ pthread_mutex_unlock(&term_mutex);
+#endif
+}
/* term__putc():
* Add a character
*/
protected int
-term__putc(int c)
+term__putc(EditLine *el, Int c)
{
-
- return (fputc(c, term_outfile));
+ char buf[MB_LEN_MAX +1];
+ ssize_t i;
+ if (c == MB_FILL_CHAR)
+ return 0;
+ i = ct_encode_char(buf, MB_LEN_MAX, c);
+ if (i <= 0)
+ return (int)i;
+ buf[i] = '\0';
+ return fputs(buf, el->el_outfile);
}
-
/* term__flush():
* Flush output
*/
protected void
-term__flush(void)
+term__flush(EditLine *el)
{
- (void) fflush(term_outfile);
+ (void) fflush(el->el_outfile);
+}
+
+/* term_writec():
+ * Write the given character out, in a human readable form
+ */
+protected void
+term_writec(EditLine *el, Int c)
+{
+ Char visbuf[VISUAL_WIDTH_MAX +1];
+ ssize_t vcnt = ct_visual_char(visbuf, VISUAL_WIDTH_MAX, c);
+ visbuf[vcnt] = '\0';
+ term_overwrite(el, visbuf, (size_t)vcnt);
+ term__flush(el);
}
@@ -1267,11 +1352,10 @@ term__flush(void)
protected int
/*ARGSUSED*/
term_telltc(EditLine *el, int argc __attribute__((__unused__)),
- const char **argv __attribute__((__unused__)))
+ const Char **argv __attribute__((__unused__)))
{
const struct termcapstr *t;
char **ts;
- char upbuf[EL_BUFSIZ];
(void) fprintf(el->el_outfile, "\n\tYour terminal has the\n");
(void) fprintf(el->el_outfile, "\tfollowing characteristics:\n\n");
@@ -1287,11 +1371,18 @@ term_telltc(EditLine *el, int argc __attribute__((__unused__)),
(void) fprintf(el->el_outfile, "\tIt %s magic margins\n",
EL_HAS_MAGIC_MARGINS ? "has" : "does not have");
- for (t = tstr, ts = el->el_term.t_str; t->name != NULL; t++, ts++)
+ for (t = tstr, ts = el->el_term.t_str; t->name != NULL; t++, ts++) {
+ const char *ub;
+ if (*ts && **ts) {
+ ub = ct_encode_string(ct_visual_string(
+ ct_decode_string(*ts, &el->el_scratch)),
+ &el->el_scratch);
+ } else {
+ ub = "(empty)";
+ }
(void) fprintf(el->el_outfile, "\t%25s (%s) == %s\n",
- t->long_name,
- t->name, *ts && **ts ?
- key__decode_str(*ts, upbuf, "") : "(empty)");
+ t->long_name, t->name, ub);
+ }
(void) fputc('\n', el->el_outfile);
return (0);
}
@@ -1303,17 +1394,19 @@ term_telltc(EditLine *el, int argc __attribute__((__unused__)),
protected int
/*ARGSUSED*/
term_settc(EditLine *el, int argc __attribute__((__unused__)),
- const char **argv)
+ const Char **argv)
{
const struct termcapstr *ts;
const struct termcapval *tv;
- const char *what, *how;
+ char what[8], how[8];
if (argv == NULL || argv[1] == NULL || argv[2] == NULL)
- return (-1);
+ return -1;
- what = argv[1];
- how = argv[2];
+ strncpy(what, ct_encode_string(argv[1], &el->el_scratch), sizeof(what));
+ what[sizeof(what) - 1] = '\0';
+ strncpy(how, ct_encode_string(argv[2], &el->el_scratch), sizeof(how));
+ how[sizeof(how) - 1] = '\0';
/*
* Do the strings first
@@ -1325,7 +1418,7 @@ term_settc(EditLine *el, int argc __attribute__((__unused__)),
if (ts->name != NULL) {
term_alloc(el, ts, how);
term_setflags(el);
- return (0);
+ return 0;
}
/*
* Do the numeric ones second
@@ -1334,55 +1427,110 @@ term_settc(EditLine *el, int argc __attribute__((__unused__)),
if (strcmp(tv->name, what) == 0)
break;
- if (tv->name != NULL) {
- if (tv == &tval[T_pt] || tv == &tval[T_km] ||
- tv == &tval[T_am] || tv == &tval[T_xn]) {
- if (strcmp(how, "yes") == 0)
- el->el_term.t_val[tv - tval] = 1;
- else if (strcmp(how, "no") == 0)
- el->el_term.t_val[tv - tval] = 0;
- else {
- (void) fprintf(el->el_errfile,
- "settc: Bad value `%s'.\n", how);
- return (-1);
- }
- term_setflags(el);
- if (term_change_size(el, Val(T_li), Val(T_co)) == -1)
- return (-1);
- return (0);
- } else {
- long i;
- char *ep;
+ if (tv->name != NULL)
+ return -1;
- i = strtol(how, &ep, 10);
- if (*ep != '\0') {
- (void) fprintf(el->el_errfile,
- "settc: Bad value `%s'.\n", how);
- return (-1);
- }
- el->el_term.t_val[tv - tval] = (int) i;
- el->el_term.t_size.v = Val(T_co);
- el->el_term.t_size.h = Val(T_li);
- if (tv == &tval[T_co] || tv == &tval[T_li])
- if (term_change_size(el, Val(T_li), Val(T_co))
- == -1)
- return (-1);
- return (0);
+ if (tv == &tval[T_pt] || tv == &tval[T_km] ||
+ tv == &tval[T_am] || tv == &tval[T_xn]) {
+ if (strcmp(how, "yes") == 0)
+ el->el_term.t_val[tv - tval] = 1;
+ else if (strcmp(how, "no") == 0)
+ el->el_term.t_val[tv - tval] = 0;
+ else {
+ (void) fprintf(el->el_errfile,
+ "" FSTR ": Bad value `%s'.\n", argv[0], how);
+ return -1;
+ }
+ term_setflags(el);
+ if (term_change_size(el, Val(T_li), Val(T_co)) == -1)
+ return -1;
+ return 0;
+ } else {
+ long i;
+ char *ep;
+
+ i = strtol(how, &ep, 10);
+ if (*ep != '\0') {
+ (void) fprintf(el->el_errfile,
+ "" FSTR ": Bad value `%s'.\n", argv[0], how);
+ return -1;
}
+ el->el_term.t_val[tv - tval] = (int) i;
+ el->el_term.t_size.v = Val(T_co);
+ el->el_term.t_size.h = Val(T_li);
+ if (tv == &tval[T_co] || tv == &tval[T_li])
+ if (term_change_size(el, Val(T_li), Val(T_co))
+ == -1)
+ return -1;
+ return 0;
}
- return (-1);
}
+/* term_gettc():
+ * Get the current terminal characteristics
+ */
+protected int
+/*ARGSUSED*/
+term_gettc(EditLine *el, int argc __attribute__((__unused__)), char **argv)
+{
+ const struct termcapstr *ts;
+ const struct termcapval *tv;
+ char *what;
+ void *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) {
+ *(char **)how = el->el_term.t_str[ts - tstr];
+ 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)
+ return -1;
+
+ if (tv == &tval[T_pt] || tv == &tval[T_km] ||
+ tv == &tval[T_am] || tv == &tval[T_xn]) {
+ static char yes[] = "yes";
+ static char no[] = "no";
+ if (el->el_term.t_val[tv - tval])
+ *(char **)how = yes;
+ else
+ *(char **)how = no;
+ return 0;
+ } else {
+ *(int *)how = el->el_term.t_val[tv - tval];
+ return 0;
+ }
+}
+
/* term_echotc():
* Print the termcap string out with variable substitution
*/
protected int
/*ARGSUSED*/
term_echotc(EditLine *el, int argc __attribute__((__unused__)),
- const char **argv)
+ const Char **argv)
{
- char *cap, *scap, *ep;
+ char *cap, *scap;
+ Char *ep;
int arg_need, arg_cols, arg_rows;
int verbose = 0, silent = 0;
char *area;
@@ -1413,21 +1561,21 @@ term_echotc(EditLine *el, int argc __attribute__((__unused__)),
}
if (!*argv || *argv[0] == '\0')
return (0);
- if (strcmp(*argv, "tabs") == 0) {
+ if (Strcmp(*argv, STR("tabs")) == 0) {
(void) fprintf(el->el_outfile, fmts, EL_CAN_TAB ? "yes" : "no");
return (0);
- } else if (strcmp(*argv, "meta") == 0) {
+ } else if (Strcmp(*argv, STR("meta")) == 0) {
(void) fprintf(el->el_outfile, fmts, Val(T_km) ? "yes" : "no");
return (0);
- } else if (strcmp(*argv, "xn") == 0) {
+ } else if (Strcmp(*argv, STR("xn")) == 0) {
(void) fprintf(el->el_outfile, fmts, EL_HAS_MAGIC_MARGINS ?
"yes" : "no");
return (0);
- } else if (strcmp(*argv, "am") == 0) {
+ } else if (Strcmp(*argv, STR("am")) == 0) {
(void) fprintf(el->el_outfile, fmts, EL_HAS_AUTO_MARGINS ?
"yes" : "no");
return (0);
- } else if (strcmp(*argv, "baud") == 0) {
+ } else if (Strcmp(*argv, STR("baud")) == 0) {
#ifdef notdef
int i;
@@ -1439,13 +1587,14 @@ term_echotc(EditLine *el, int argc __attribute__((__unused__)),
}
(void) fprintf(el->el_outfile, fmtd, 0);
#else
- (void) fprintf(el->el_outfile, fmtd, el->el_tty.t_speed);
+ (void) fprintf(el->el_outfile, fmtd, (int)el->el_tty.t_speed);
#endif
return (0);
- } else if (strcmp(*argv, "rows") == 0 || strcmp(*argv, "lines") == 0) {
+ } else if (Strcmp(*argv, STR("rows")) == 0 ||
+ Strcmp(*argv, STR("lines")) == 0) {
(void) fprintf(el->el_outfile, fmtd, Val(T_li));
return (0);
- } else if (strcmp(*argv, "cols") == 0) {
+ } else if (Strcmp(*argv, STR("cols")) == 0) {
(void) fprintf(el->el_outfile, fmtd, Val(T_co));
return (0);
}
@@ -1454,16 +1603,19 @@ term_echotc(EditLine *el, int argc __attribute__((__unused__)),
*/
scap = NULL;
for (t = tstr; t->name != NULL; t++)
- if (strcmp(t->name, *argv) == 0) {
+ if (strcmp(t->name,
+ ct_encode_string(*argv, &el->el_scratch)) == 0) {
scap = el->el_term.t_str[t - tstr];
break;
}
- if (t->name == NULL)
- scap = tgetstr((char *)*argv, &area);
+ if (t->name == NULL) {
+ /* XXX: some systems' tgetstr needs non const */
+ scap = tgetstr(ct_encode_string(*argv, &el->el_scratch), &area);
+ }
if (!scap || scap[0] == '\0') {
if (!silent)
(void) fprintf(el->el_errfile,
- "echotc: Termcap parameter `%s' not found.\n",
+ "echotc: Termcap parameter `" FSTR "' not found.\n",
*argv);
return (-1);
}
@@ -1506,11 +1658,11 @@ term_echotc(EditLine *el, int argc __attribute__((__unused__)),
if (*argv && *argv[0]) {
if (!silent)
(void) fprintf(el->el_errfile,
- "echotc: Warning: Extra argument `%s'.\n",
+ "echotc: Warning: Extra argument `" FSTR "'.\n",
*argv);
return (-1);
}
- (void) tputs(scap, 1, term__putc);
+ term_tputs(el, scap, 1);
break;
case 1:
argv++;
@@ -1521,11 +1673,11 @@ term_echotc(EditLine *el, int argc __attribute__((__unused__)),
return (-1);
}
arg_cols = 0;
- i = strtol(*argv, &ep, 10);
+ i = Strtol(*argv, &ep, 10);
if (*ep != '\0' || i < 0) {
if (!silent)
(void) fprintf(el->el_errfile,
- "echotc: Bad value `%s' for rows.\n",
+ "echotc: Bad value `" FSTR "' for rows.\n",
*argv);
return (-1);
}
@@ -1534,11 +1686,11 @@ term_echotc(EditLine *el, int argc __attribute__((__unused__)),
if (*argv && *argv[0]) {
if (!silent)
(void) fprintf(el->el_errfile,
- "echotc: Warning: Extra argument `%s'.\n",
+ "echotc: Warning: Extra argument `" FSTR "'.\n",
*argv);
return (-1);
}
- (void) tputs(tgoto(scap, arg_cols, arg_rows), 1, term__putc);
+ term_tputs(el, tgoto(scap, arg_cols, arg_rows), 1);
break;
default:
/* This is wrong, but I will ignore it... */
@@ -1555,11 +1707,11 @@ term_echotc(EditLine *el, int argc __attribute__((__unused__)),
"echotc: Warning: Missing argument.\n");
return (-1);
}
- i = strtol(*argv, &ep, 10);
+ i = Strtol(*argv, &ep, 10);
if (*ep != '\0' || i < 0) {
if (!silent)
(void) fprintf(el->el_errfile,
- "echotc: Bad value `%s' for cols.\n",
+ "echotc: Bad value `" FSTR "' for cols.\n",
*argv);
return (-1);
}
@@ -1571,11 +1723,11 @@ term_echotc(EditLine *el, int argc __attribute__((__unused__)),
"echotc: Warning: Missing argument.\n");
return (-1);
}
- i = strtol(*argv, &ep, 10);
+ i = Strtol(*argv, &ep, 10);
if (*ep != '\0' || i < 0) {
if (!silent)
(void) fprintf(el->el_errfile,
- "echotc: Bad value `%s' for rows.\n",
+ "echotc: Bad value `" FSTR "' for rows.\n",
*argv);
return (-1);
}
@@ -1583,19 +1735,18 @@ term_echotc(EditLine *el, int argc __attribute__((__unused__)),
if (*ep != '\0') {
if (!silent)
(void) fprintf(el->el_errfile,
- "echotc: Bad value `%s'.\n", *argv);
+ "echotc: Bad value `" FSTR "'.\n", *argv);
return (-1);
}
argv++;
if (*argv && *argv[0]) {
if (!silent)
(void) fprintf(el->el_errfile,
- "echotc: Warning: Extra argument `%s'.\n",
+ "echotc: Warning: Extra argument `" FSTR "'.\n",
*argv);
return (-1);
}
- (void) tputs(tgoto(scap, arg_cols, arg_rows), arg_rows,
- term__putc);
+ term_tputs(el, tgoto(scap, arg_cols, arg_rows), arg_rows);
break;
}
return (0);
diff --git a/lib/libedit/term.h b/lib/libedit/term.h
index 794cba094a6..9eba12e58f5 100644
--- a/lib/libedit/term.h
+++ b/lib/libedit/term.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: term.h,v 1.7 2003/10/31 08:42:24 otto Exp $ */
-/* $NetBSD: term.h,v 1.15 2003/09/14 21:48:55 christos Exp $ */
+/* $OpenBSD: term.h,v 1.8 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: term.h,v 1.21 2009/12/30 22:37:40 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -44,7 +44,7 @@
#include "histedit.h"
typedef struct { /* Symbolic function key bindings */
- const char *name; /* name of the key */
+ const Char *name; /* name of the key */
int key; /* Index in termcap table */
key_value_t fun; /* Function bound to it */
int type; /* Type of function */
@@ -85,8 +85,8 @@ typedef struct {
protected void term_move_to_line(EditLine *, int);
protected void term_move_to_char(EditLine *, int);
protected void term_clear_EOL(EditLine *, int);
-protected void term_overwrite(EditLine *, const char *, int);
-protected void term_insertwrite(EditLine *, char *, int);
+protected void term_overwrite(EditLine *, const Char *, size_t);
+protected void term_insertwrite(EditLine *, Char *, int);
protected void term_deletechars(EditLine *, int);
protected void term_clear_screen(EditLine *);
protected void term_beep(EditLine *);
@@ -94,17 +94,19 @@ protected int term_change_size(EditLine *, int, int);
protected int term_get_size(EditLine *, int *, int *);
protected int term_init(EditLine *);
protected void term_bind_arrow(EditLine *);
-protected void term_print_arrow(EditLine *, const char *);
-protected int term_clear_arrow(EditLine *, const char *);
-protected int term_set_arrow(EditLine *, const char *, key_value_t *, int);
+protected void term_print_arrow(EditLine *, const Char *);
+protected int term_clear_arrow(EditLine *, const Char *);
+protected int term_set_arrow(EditLine *, const Char *, key_value_t *, int);
protected void term_end(EditLine *);
protected void term_get(EditLine *, const char **);
protected int term_set(EditLine *, const char *);
-protected int term_settc(EditLine *, int, const char **);
-protected int term_telltc(EditLine *, int, const char **);
-protected int term_echotc(EditLine *, int, const char **);
-protected int term__putc(int);
-protected void term__flush(void);
+protected int term_settc(EditLine *, int, const Char **);
+protected int term_gettc(EditLine *, int, char **);
+protected int term_telltc(EditLine *, int, const Char **);
+protected int term_echotc(EditLine *, int, const Char **);
+protected void term_writec(EditLine *, Int);
+protected int term__putc(EditLine *, Int);
+protected void term__flush(EditLine *);
/*
* Easy access macros
@@ -116,6 +118,7 @@ protected void term__flush(void);
#define EL_CAN_CEOL (EL_FLAGS & TERM_CAN_CEOL)
#define EL_CAN_TAB (EL_FLAGS & TERM_CAN_TAB)
#define EL_CAN_ME (EL_FLAGS & TERM_CAN_ME)
+#define EL_CAN_UP (EL_FLAGS & TERM_CAN_UP)
#define EL_HAS_META (EL_FLAGS & TERM_HAS_META)
#define EL_HAS_AUTO_MARGINS (EL_FLAGS & TERM_HAS_AUTO_MARGINS)
#define EL_HAS_MAGIC_MARGINS (EL_FLAGS & TERM_HAS_MAGIC_MARGINS)
diff --git a/lib/libedit/tokenizer.c b/lib/libedit/tokenizer.c
index 972e26923cf..efd72af5e80 100644
--- a/lib/libedit/tokenizer.c
+++ b/lib/libedit/tokenizer.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: tokenizer.c,v 1.11 2009/10/27 23:59:28 deraadt Exp $ */
-/* $NetBSD: tokenizer.c,v 1.13 2003/10/18 23:48:42 christos Exp $ */
+/* $OpenBSD: tokenizer.c,v 1.12 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: tokenizer.c,v 1.18 2010/01/03 18:27:10 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -34,51 +34,54 @@
*/
#include "config.h"
+
+/* We build this file twice, once as NARROW, once as WIDE. */
/*
* tokenize.c: Bourne shell like tokenizer
*/
#include <string.h>
#include <stdlib.h>
-#include "tokenizer.h"
+#include "histedit.h"
+#include "chartype.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_strdup(a) strdup(a)
+#define IFS STR("\t \n")
+
#define tok_malloc(a) malloc(a)
#define tok_free(a) free(a)
#define tok_realloc(a, b) realloc(a, b)
+#define tok_strdup(a) Strdup(a)
-struct tokenizer {
- char *ifs; /* In field separator */
+struct TYPE(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 */
+ 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(Tokenizer *);
+private void FUN(tok,finish)(TYPE(Tokenizer) *);
-/* tok_finish():
+/* FUN(tok,finish)():
* Finish a word in the tokenizer.
*/
private void
-tok_finish(Tokenizer *tok)
+FUN(tok,finish)(TYPE(Tokenizer) *tok)
{
*tok->wptr = '\0';
@@ -91,13 +94,13 @@ tok_finish(Tokenizer *tok)
}
-/* tok_init():
+/* FUN(tok,init)():
* Initialize the tokenizer
*/
-public Tokenizer *
-tok_init(const char *ifs)
+public TYPE(Tokenizer) *
+FUN(tok,init)(const Char *ifs)
{
- Tokenizer *tok = (Tokenizer *) tok_malloc(sizeof(Tokenizer));
+ TYPE(Tokenizer) *tok = tok_malloc(sizeof(TYPE(Tokenizer)));
if (tok == NULL)
return NULL;
@@ -108,14 +111,14 @@ tok_init(const char *ifs)
}
tok->argc = 0;
tok->amax = AINCR;
- tok->argv = (char **) tok_malloc(sizeof(char *) * tok->amax);
+ tok->argv = tok_malloc(sizeof(*tok->argv) * tok->amax);
if (tok->argv == NULL) {
tok_free((ptr_t)tok->ifs);
tok_free((ptr_t)tok);
return NULL;
}
tok->argv[0] = NULL;
- tok->wspace = (char *) tok_malloc(WINCR);
+ tok->wspace = tok_malloc(WINCR * sizeof(*tok->wspace));
if (tok->wspace == NULL) {
tok_free((ptr_t)tok->argv);
tok_free((ptr_t)tok->ifs);
@@ -132,11 +135,11 @@ tok_init(const char *ifs)
}
-/* tok_reset():
+/* FUN(tok,reset)():
* Reset the tokenizer
*/
public void
-tok_reset(Tokenizer *tok)
+FUN(tok,reset)(TYPE(Tokenizer) *tok)
{
tok->argc = 0;
@@ -147,11 +150,11 @@ tok_reset(Tokenizer *tok)
}
-/* tok_end():
+/* FUN(tok,end)():
* Clean up
*/
public void
-tok_end(Tokenizer *tok)
+FUN(tok,end)(TYPE(Tokenizer) *tok)
{
tok_free((ptr_t) tok->ifs);
@@ -162,22 +165,40 @@ tok_end(Tokenizer *tok)
-/* tok_line():
- * Bourne shell like tokenizing
- * Return:
- * -1: Internal error
- * 3: Quoted return
- * 2: Unmatched double quote
- * 1: Unmatched single quote
- * 0: Ok
+/* FUN(tok,line)():
+ * Bourne shell (sh(1)) like tokenizing
+ * Arguments:
+ * tok current tokenizer state (setup with FUN(tok,init)())
+ * line line to parse
+ * Returns:
+ * -1 Internal error
+ * 3 Quoted return
+ * 2 Unmatched double quote
+ * 1 Unmatched single quote
+ * 0 Ok
+ * Modifies (if return value is 0):
+ * argc number of arguments
+ * argv argument array
+ * cursorc if !NULL, argv element containing cursor
+ * cursorv if !NULL, offset in argv[cursorc] of cursor
*/
public int
-tok_line(Tokenizer *tok, const char *line, int *argc, const char ***argv)
+FUN(tok,line)(TYPE(Tokenizer) *tok, const TYPE(LineInfo) *line,
+ int *argc, const Char ***argv, int *cursorc, int *cursoro)
{
- const char *ptr;
-
- for (;;) {
- switch (*(ptr = line++)) {
+ const Char *ptr;
+ int cc, co;
+
+ cc = co = -1;
+ ptr = line->buffer;
+ for (ptr = line->buffer; ;ptr++) {
+ if (ptr >= line->lastchar)
+ ptr = STR("");
+ if (ptr == line->cursor) {
+ cc = tok->argc;
+ co = (int)(tok->wptr - tok->wstart);
+ }
+ switch (*ptr) {
case '\'':
tok->flags |= TOK_KEEP;
tok->flags &= ~TOK_EAT;
@@ -276,10 +297,7 @@ tok_line(Tokenizer *tok, const char *line, int *argc, const char ***argv)
tok->flags &= ~TOK_EAT;
switch (tok->quote) {
case Q_none:
- tok_finish(tok);
- *argv = (const char **)tok->argv;
- *argc = tok->argc;
- return (0);
+ goto tok_line_outok;
case Q_single:
case Q_double:
@@ -309,10 +327,7 @@ tok_line(Tokenizer *tok, const char *line, int *argc, const char ***argv)
tok->flags &= ~TOK_EAT;
return (3);
}
- tok_finish(tok);
- *argv = (const char **)tok->argv;
- *argc = tok->argc;
- return (0);
+ goto tok_line_outok;
case Q_single:
return (1);
@@ -339,8 +354,8 @@ tok_line(Tokenizer *tok, const char *line, int *argc, const char ***argv)
tok->flags &= ~TOK_EAT;
switch (tok->quote) {
case Q_none:
- if (strchr(tok->ifs, *ptr) != NULL)
- tok_finish(tok);
+ if (Strchr(tok->ifs, *ptr) != NULL)
+ FUN(tok,finish)(tok);
else
*tok->wptr++ = *ptr;
break;
@@ -371,7 +386,8 @@ tok_line(Tokenizer *tok, const char *line, int *argc, const char ***argv)
if (tok->wptr >= tok->wmax - 4) {
size_t size = tok->wmax - tok->wspace + WINCR;
- char *s = (char *) tok_realloc(tok->wspace, size);
+ Char *s = tok_realloc(tok->wspace,
+ size * sizeof(*s));
if (s == NULL)
return (-1);
@@ -388,13 +404,41 @@ tok_line(Tokenizer *tok, const char *line, int *argc, const char ***argv)
tok->wmax = s + size;
}
if (tok->argc >= tok->amax - 4) {
- char **p;
+ Char **p;
tok->amax += AINCR;
- p = (char **) tok_realloc(tok->argv,
- tok->amax * sizeof(char *));
+ p = tok_realloc(tok->argv, tok->amax * sizeof(*p));
if (p == NULL)
return (-1);
tok->argv = p;
}
}
+ tok_line_outok:
+ if (cc == -1 && co == -1) {
+ cc = tok->argc;
+ co = (int)(tok->wptr - tok->wstart);
+ }
+ if (cursorc != NULL)
+ *cursorc = cc;
+ if (cursoro != NULL)
+ *cursoro = co;
+ FUN(tok,finish)(tok);
+ *argv = (const Char **)tok->argv;
+ *argc = tok->argc;
+ return (0);
+}
+
+/* FUN(tok,str)():
+ * Simpler version of tok_line, taking a NUL terminated line
+ * and splitting into words, ignoring cursor state.
+ */
+public int
+FUN(tok,str)(TYPE(Tokenizer) *tok, const Char *line, int *argc,
+ const Char ***argv)
+{
+ TYPE(LineInfo) li;
+
+ memset(&li, 0, sizeof(li));
+ li.buffer = line;
+ li.cursor = li.lastchar = Strchr(line, '\0');
+ return (FUN(tok,line)(tok, &li, argc, argv, NULL, NULL));
}
diff --git a/lib/libedit/tty.c b/lib/libedit/tty.c
index f02c44a9b0f..52cd36dba05 100644
--- a/lib/libedit/tty.c
+++ b/lib/libedit/tty.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: tty.c,v 1.11 2009/10/27 23:59:28 deraadt Exp $ */
-/* $NetBSD: tty.c,v 1.20 2003/10/18 22:37:24 christos Exp $ */
+/* $OpenBSD: tty.c,v 1.12 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: tty.c,v 1.33 2010/04/18 21:17:22 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -38,17 +38,20 @@
/*
* tty.c: tty interface stuff
*/
-#include "tty.h"
+#include <assert.h>
+#include <errno.h>
+#include <strings.h> /* for ffs */
#include "el.h"
+#include "tty.h"
typedef struct ttymodes_t {
const char *m_name;
- u_int m_value;
+ unsigned int m_value;
int m_type;
} ttymodes_t;
typedef struct ttymap_t {
- int nch, och; /* Internal and termio rep of chars */
+ Int nch, och; /* Internal and termio rep of chars */
el_action_t bind[3]; /* emacs, vi, and vi-cmd */
} ttymap_t;
@@ -114,11 +117,11 @@ private const ttychar_t ttychar = {
private const ttymap_t tty_map[] = {
#ifdef VERASE
{C_ERASE, VERASE,
- {ED_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
+ {EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
#endif /* VERASE */
#ifdef VERASE2
{C_ERASE2, VERASE2,
- {ED_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
+ {EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
#endif /* VERASE2 */
#ifdef VKILL
{C_KILL, VKILL,
@@ -438,13 +441,12 @@ private const ttymodes_t ttymodes[] = {
-#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 int tty_getty(EditLine *, struct termios *);
+private int tty_setty(EditLine *, int, const struct termios *);
private int tty__getcharindex(int);
private void tty__getchar(struct termios *, unsigned char *);
private void tty__setchar(struct termios *, unsigned char *);
@@ -453,6 +455,29 @@ private int tty_setup(EditLine *);
#define t_qu t_ts
+/* tty_getty():
+ * Wrapper for tcgetattr to handle EINTR
+ */
+private int
+tty_getty(EditLine *el, struct termios *t)
+{
+ int rv;
+ while ((rv = tcgetattr(el->el_infd, t)) == -1 && errno == EINTR)
+ continue;
+ return rv;
+}
+
+/* tty_setty():
+ * Wrapper for tcsetattr to handle EINTR
+ */
+private int
+tty_setty(EditLine *el, int action, const struct termios *t)
+{
+ int rv;
+ while ((rv = tcsetattr(el->el_infd, action, t)) == -1 && errno == EINTR)
+ continue;
+ return rv;
+}
/* tty_setup():
* Get the tty parameters and initialize the editing state
@@ -514,7 +539,7 @@ tty_setup(EditLine *el)
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) {
+ if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) {
#ifdef DEBUG_TTY
(void) fprintf(el->el_errfile,
"tty_setup: tty_setty: %s\n",
@@ -522,8 +547,11 @@ tty_setup(EditLine *el)
#endif /* DEBUG_TTY */
return (-1);
}
- } else
+ }
+#ifdef notdef
+ else
tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
+#endif
el->el_tty.t_ed.c_iflag &= ~el->el_tty.t_t[ED_IO][MD_INP].t_clrmask;
el->el_tty.t_ed.c_iflag |= el->el_tty.t_t[ED_IO][MD_INP].t_setmask;
@@ -860,7 +888,7 @@ tty_bind_char(EditLine *el, int force)
unsigned char *t_n = el->el_tty.t_c[ED_IO];
unsigned char *t_o = el->el_tty.t_ed.c_cc;
- unsigned char new[2], old[2];
+ Char new[2], old[2];
const ttymap_t *tp;
el_action_t *map, *alt;
const el_action_t *dmap, *dalt;
@@ -882,16 +910,16 @@ tty_bind_char(EditLine *el, int force)
if (new[0] == old[0] && !force)
continue;
/* Put the old default binding back, and set the new binding */
- key_clear(el, map, (char *)old);
- map[old[0]] = dmap[old[0]];
- key_clear(el, map, (char *)new);
+ key_clear(el, map, old);
+ map[UC(old[0])] = dmap[UC(old[0])];
+ key_clear(el, map, new);
/* MAP_VI == 1, MAP_EMACS == 0... */
- map[new[0]] = tp->bind[el->el_map.type];
+ map[UC(new[0])] = tp->bind[el->el_map.type];
if (dalt) {
- key_clear(el, alt, (char *)old);
- alt[old[0]] = dalt[old[0]];
- key_clear(el, alt, (char *)new);
- alt[new[0]] = tp->bind[el->el_map.type + 1];
+ key_clear(el, alt, old);
+ alt[UC(old[0])] = dalt[UC(old[0])];
+ key_clear(el, alt, new);
+ alt[UC(new[0])] = tp->bind[el->el_map.type + 1];
}
}
}
@@ -919,7 +947,7 @@ tty_rawmode(EditLine *el)
}
/*
* 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!
+ * tty. But 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);
@@ -1040,7 +1068,7 @@ tty_rawmode(EditLine *el)
}
}
}
- if (tty_setty(el, &el->el_tty.t_ed) == -1) {
+ if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) {
#ifdef DEBUG_TTY
(void) fprintf(el->el_errfile, "tty_rawmode: tty_setty: %s\n",
strerror(errno));
@@ -1065,7 +1093,7 @@ tty_cookedmode(EditLine *el)
if (el->el_flags & EDIT_DISABLED)
return (0);
- if (tty_setty(el, &el->el_tty.t_ex) == -1) {
+ if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) {
#ifdef DEBUG_TTY
(void) fprintf(el->el_errfile,
"tty_cookedmode: tty_setty: %s\n",
@@ -1101,7 +1129,7 @@ tty_quotemode(EditLine *el)
el->el_tty.t_qu.c_lflag &= ~el->el_tty.t_t[QU_IO][MD_LIN].t_clrmask;
el->el_tty.t_qu.c_lflag |= el->el_tty.t_t[QU_IO][MD_LIN].t_setmask;
- if (tty_setty(el, &el->el_tty.t_qu) == -1) {
+ if (tty_setty(el, TCSADRAIN, &el->el_tty.t_qu) == -1) {
#ifdef DEBUG_TTY
(void) fprintf(el->el_errfile, "QuoteModeOn: tty_setty: %s\n",
strerror(errno));
@@ -1122,7 +1150,7 @@ tty_noquotemode(EditLine *el)
if (el->el_tty.t_mode != QU_IO)
return (0);
- if (tty_setty(el, &el->el_tty.t_ed) == -1) {
+ if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) {
#ifdef DEBUG_TTY
(void) fprintf(el->el_errfile, "QuoteModeOff: tty_setty: %s\n",
strerror(errno));
@@ -1139,19 +1167,20 @@ tty_noquotemode(EditLine *el)
*/
protected int
/*ARGSUSED*/
-tty_stty(EditLine *el, int argc __attribute__((__unused__)), const char **argv)
+tty_stty(EditLine *el, int argc __attribute__((__unused__)), const Char **argv)
{
const ttymodes_t *m;
char x;
int aflag = 0;
- const char *s, *d;
- const char *name;
+ const Char *s, *d;
+ char name[EL_BUFSIZ];
struct termios *tios = &el->el_tty.t_ex;
int z = EX_IO;
if (argv == NULL)
return (-1);
- name = *argv++;
+ strncpy(name, ct_encode_string(*argv++, &el->el_scratch), sizeof(name));
+ name[sizeof(name) - 1] = '\0';
while (argv && *argv && argv[0][0] == '-' && argv[0][2] == '\0')
switch (argv[0][1]) {
@@ -1183,7 +1212,7 @@ tty_stty(EditLine *el, int argc __attribute__((__unused__)), const char **argv)
if (!argv || !*argv) {
int i = -1;
- int len = 0, st = 0, cu;
+ size_t len = 0, st = 0, cu;
for (m = ttymodes; m->m_name; m++) {
if (m->m_type != i) {
(void) fprintf(el->el_outfile, "%s%s",
@@ -1193,18 +1222,22 @@ tty_stty(EditLine *el, int argc __attribute__((__unused__)), const char **argv)
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 (i != -1) {
+ 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;
+ } else {
+ x = '\0';
+ }
if (x != '\0' || aflag) {
cu = strlen(m->m_name) + (x != '\0') + 1;
- if (len + cu >= el->el_term.t_size.h) {
+ if (len + cu >= (size_t)el->el_term.t_size.h) {
(void) fprintf(el->el_outfile, "\n%*s",
- st, "");
+ (int)st, "");
len = st + cu;
} else
len += cu;
@@ -1221,7 +1254,7 @@ tty_stty(EditLine *el, int argc __attribute__((__unused__)), const char **argv)
return (0);
}
while (argv && (s = *argv++)) {
- char *p;
+ const Char *p;
switch (*s) {
case '+':
case '-':
@@ -1232,24 +1265,26 @@ tty_stty(EditLine *el, int argc __attribute__((__unused__)), const char **argv)
break;
}
d = s;
- if ((p = strchr(s, '=')) != NULL)
- *p++ = '\0';
+ p = Strchr(s, '=');
for (m = ttymodes; m->m_name; m++)
- if (strcmp(m->m_name, d) == 0 &&
+ if ((p ? strncmp(m->m_name, ct_encode_string(d, &el->el_scratch), (size_t)(p - d)) :
+ strcmp(m->m_name, ct_encode_string(d, &el->el_scratch))) == 0 &&
(p == NULL || m->m_type == MD_CHAR))
break;
if (!m->m_name) {
(void) fprintf(el->el_errfile,
- "%s: Invalid argument `%s'.\n", name, d);
+ "%s: Invalid argument `" FSTR "'.\n", name, d);
return (-1);
}
if (p) {
int c = ffs((int)m->m_value);
- int v = *p ? parse__escape((const char **const) &p) :
+ int v = *++p ? parse__escape(&p) :
el->el_tty.t_vdisable;
+ assert(c != 0);
c--;
c = tty__getcharindex(c);
+ assert(c != -1);
tios->c_cc[c] = v;
continue;
}
@@ -1268,6 +1303,17 @@ tty_stty(EditLine *el, int argc __attribute__((__unused__)), const char **argv)
break;
}
}
+
+ if (el->el_tty.t_mode == z) {
+ if (tty_setty(el, TCSADRAIN, tios) == -1) {
+#ifdef DEBUG_TTY
+ (void) fprintf(el->el_errfile,
+ "tty_stty: tty_setty: %s\n", strerror(errno));
+#endif /* DEBUG_TTY */
+ return (-1);
+ }
+ }
+
return (0);
}
diff --git a/lib/libedit/tty.h b/lib/libedit/tty.h
index 0ab2dd1c9a8..a80f4eea7c0 100644
--- a/lib/libedit/tty.h
+++ b/lib/libedit/tty.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: tty.h,v 1.7 2003/10/31 08:42:24 otto Exp $ */
-/* $NetBSD: tty.h,v 1.10 2003/08/07 16:44:34 agc Exp $ */
+/* $OpenBSD: tty.h,v 1.8 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: tty.h,v 1.12 2009/12/30 22:37:40 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -41,6 +41,7 @@
#ifndef _h_el_tty
#define _h_el_tty
+#include "sys.h"
#include "histedit.h"
#include <termios.h>
#include <unistd.h>
@@ -451,15 +452,15 @@
typedef struct {
const char *t_name;
- u_int t_setmask;
- u_int t_clrmask;
+ unsigned int t_setmask;
+ unsigned int t_clrmask;
} ttyperm_t[NN_IO][MD_NN];
typedef unsigned char ttychar_t[NN_IO][C_NCC];
protected int tty_init(EditLine *);
protected void tty_end(EditLine *);
-protected int tty_stty(EditLine *, int, const char **);
+protected int tty_stty(EditLine *, int, const Char **);
protected int tty_rawmode(EditLine *);
protected int tty_cookedmode(EditLine *);
protected int tty_quotemode(EditLine *);
diff --git a/lib/libedit/vi.c b/lib/libedit/vi.c
index 7282fcbee10..85155df9711 100644
--- a/lib/libedit/vi.c
+++ b/lib/libedit/vi.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: vi.c,v 1.8 2009/10/27 23:59:28 deraadt Exp $ */
-/* $NetBSD: vi.c,v 1.19 2003/08/07 16:44:35 agc Exp $ */
+/* $OpenBSD: vi.c,v 1.9 2010/06/30 00:05:35 nicm Exp $ */
+/* $NetBSD: vi.c,v 1.31 2009/12/30 22:37:40 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -36,6 +36,7 @@
#include "config.h"
#include <stdlib.h>
#include <unistd.h>
+#include <limits.h>
#include <sys/wait.h>
/*
@@ -43,14 +44,14 @@
*/
#include "el.h"
-private el_action_t cv_action(EditLine *, int);
-private el_action_t cv_paste(EditLine *, int);
+private el_action_t cv_action(EditLine *, Int);
+private el_action_t cv_paste(EditLine *, Int);
/* cv_action():
* Handle vi actions.
*/
private el_action_t
-cv_action(EditLine *el, int c)
+cv_action(EditLine *el, Int c)
{
if (el->el_chared.c_vcmd.action != NOP) {
@@ -61,11 +62,13 @@ cv_action(EditLine *el, int c)
if (!(c & YANK))
cv_undo(el);
cv_yank(el, el->el_line.buffer,
- el->el_line.lastchar - el->el_line.buffer);
+ (int)(el->el_line.lastchar - el->el_line.buffer));
el->el_chared.c_vcmd.action = NOP;
el->el_chared.c_vcmd.pos = 0;
- el->el_line.lastchar = el->el_line.buffer;
- el->el_line.cursor = el->el_line.buffer;
+ if (!(c & YANK)) {
+ 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;
@@ -80,28 +83,28 @@ cv_action(EditLine *el, int c)
* Paste previous deletion before or after the cursor
*/
private el_action_t
-cv_paste(EditLine *el, int c)
+cv_paste(EditLine *el, Int c)
{
- char *ptr;
c_kill_t *k = &el->el_chared.c_kill;
- int len = k->last - k->buf;
+ size_t len = (size_t)(k->last - k->buf);
if (k->buf == NULL || len == 0)
return (CC_ERROR);
#ifdef DEBUG_PASTE
- (void) fprintf(el->el_errfile, "Paste: \"%.*s\"\n", len, k->buf);
+ (void) fprintf(el->el_errfile, "Paste: \"%.*s\"\n", (int)len, k->buf);
#endif
cv_undo(el);
if (!c && el->el_line.cursor < el->el_line.lastchar)
el->el_line.cursor++;
- ptr = el->el_line.cursor;
- c_insert(el, len);
+ c_insert(el, (int)len);
if (el->el_line.cursor + len > el->el_line.lastchar)
return (CC_ERROR);
- (void) memcpy(ptr, k->buf, len +0u);
+ (void) memcpy(el->el_line.cursor, k->buf, len *
+ sizeof(*el->el_line.cursor));
+
return (CC_REFRESH);
}
@@ -112,7 +115,7 @@ cv_paste(EditLine *el, int c)
*/
protected el_action_t
/*ARGSUSED*/
-vi_paste_next(EditLine *el, int c __attribute__((__unused__)))
+vi_paste_next(EditLine *el, Int c __attribute__((__unused__)))
{
return (cv_paste(el, 0));
@@ -125,7 +128,7 @@ vi_paste_next(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-vi_paste_prev(EditLine *el, int c __attribute__((__unused__)))
+vi_paste_prev(EditLine *el, Int c __attribute__((__unused__)))
{
return (cv_paste(el, 1));
@@ -138,7 +141,7 @@ vi_paste_prev(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-vi_prev_big_word(EditLine *el, int c)
+vi_prev_big_word(EditLine *el, Int c __attribute__((__unused__)))
{
if (el->el_line.cursor == el->el_line.buffer)
@@ -163,7 +166,7 @@ vi_prev_big_word(EditLine *el, int c)
*/
protected el_action_t
/*ARGSUSED*/
-vi_prev_word(EditLine *el, int c __attribute__((__unused__)))
+vi_prev_word(EditLine *el, Int c __attribute__((__unused__)))
{
if (el->el_line.cursor == el->el_line.buffer)
@@ -188,7 +191,7 @@ vi_prev_word(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-vi_next_big_word(EditLine *el, int c)
+vi_next_big_word(EditLine *el, Int c __attribute__((__unused__)))
{
if (el->el_line.cursor >= el->el_line.lastchar - 1)
@@ -212,7 +215,7 @@ vi_next_big_word(EditLine *el, int c)
*/
protected el_action_t
/*ARGSUSED*/
-vi_next_word(EditLine *el, int c __attribute__((__unused__)))
+vi_next_word(EditLine *el, Int c __attribute__((__unused__)))
{
if (el->el_line.cursor >= el->el_line.lastchar - 1)
@@ -235,7 +238,7 @@ vi_next_word(EditLine *el, int c __attribute__((__unused__)))
* [~]
*/
protected el_action_t
-vi_change_case(EditLine *el, int c)
+vi_change_case(EditLine *el, Int c)
{
int i;
@@ -244,11 +247,11 @@ vi_change_case(EditLine *el, int c)
cv_undo(el);
for (i = 0; i < el->el_state.argument; i++) {
- c = *(unsigned char *)el->el_line.cursor;
- if (isupper(c))
- *el->el_line.cursor = tolower(c);
- else if (islower(c))
- *el->el_line.cursor = toupper(c);
+ c = *el->el_line.cursor;
+ if (Isupper(c))
+ *el->el_line.cursor = Tolower(c);
+ else if (Islower(c))
+ *el->el_line.cursor = Toupper(c);
if (++el->el_line.cursor >= el->el_line.lastchar) {
el->el_line.cursor--;
@@ -267,7 +270,7 @@ vi_change_case(EditLine *el, int c)
*/
protected el_action_t
/*ARGSUSED*/
-vi_change_meta(EditLine *el, int c __attribute__((__unused__)))
+vi_change_meta(EditLine *el, Int c __attribute__((__unused__)))
{
/*
@@ -284,7 +287,7 @@ vi_change_meta(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-vi_insert_at_bol(EditLine *el, int c __attribute__((__unused__)))
+vi_insert_at_bol(EditLine *el, Int c __attribute__((__unused__)))
{
el->el_line.cursor = el->el_line.buffer;
@@ -300,7 +303,7 @@ vi_insert_at_bol(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-vi_replace_char(EditLine *el, int c __attribute__((__unused__)))
+vi_replace_char(EditLine *el, Int c __attribute__((__unused__)))
{
if (el->el_line.cursor >= el->el_line.lastchar)
@@ -319,7 +322,7 @@ vi_replace_char(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-vi_replace_mode(EditLine *el, int c __attribute__((__unused__)))
+vi_replace_mode(EditLine *el, Int c __attribute__((__unused__)))
{
el->el_map.current = el->el_map.key;
@@ -335,7 +338,7 @@ vi_replace_mode(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-vi_substitute_char(EditLine *el, int c __attribute__((__unused__)))
+vi_substitute_char(EditLine *el, Int c __attribute__((__unused__)))
{
c_delafter(el, el->el_state.argument);
@@ -350,12 +353,12 @@ vi_substitute_char(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-vi_substitute_line(EditLine *el, int c __attribute__((__unused__)))
+vi_substitute_line(EditLine *el, Int c __attribute__((__unused__)))
{
cv_undo(el);
cv_yank(el, el->el_line.buffer,
- el->el_line.lastchar - el->el_line.buffer);
+ (int)(el->el_line.lastchar - el->el_line.buffer));
(void) em_kill_line(el, 0);
el->el_map.current = el->el_map.key;
return (CC_REFRESH);
@@ -368,12 +371,12 @@ vi_substitute_line(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-vi_change_to_eol(EditLine *el, int c __attribute__((__unused__)))
+vi_change_to_eol(EditLine *el, Int c __attribute__((__unused__)))
{
cv_undo(el);
cv_yank(el, el->el_line.cursor,
- el->el_line.lastchar - el->el_line.cursor);
+ (int)(el->el_line.lastchar - el->el_line.cursor));
(void) ed_kill_line(el, 0);
el->el_map.current = el->el_map.key;
return (CC_REFRESH);
@@ -386,7 +389,7 @@ vi_change_to_eol(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-vi_insert(EditLine *el, int c __attribute__((__unused__)))
+vi_insert(EditLine *el, Int c __attribute__((__unused__)))
{
el->el_map.current = el->el_map.key;
@@ -401,7 +404,7 @@ vi_insert(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-vi_add(EditLine *el, int c __attribute__((__unused__)))
+vi_add(EditLine *el, Int c __attribute__((__unused__)))
{
int ret;
@@ -426,7 +429,7 @@ vi_add(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-vi_add_at_eol(EditLine *el, int c __attribute__((__unused__)))
+vi_add_at_eol(EditLine *el, Int c __attribute__((__unused__)))
{
el->el_map.current = el->el_map.key;
@@ -442,7 +445,7 @@ vi_add_at_eol(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-vi_delete_meta(EditLine *el, int c __attribute__((__unused__)))
+vi_delete_meta(EditLine *el, Int c __attribute__((__unused__)))
{
return (cv_action(el, DELETE));
@@ -455,7 +458,7 @@ vi_delete_meta(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-vi_end_big_word(EditLine *el, int c)
+vi_end_big_word(EditLine *el, Int c)
{
if (el->el_line.cursor == el->el_line.lastchar)
@@ -479,7 +482,7 @@ vi_end_big_word(EditLine *el, int c)
*/
protected el_action_t
/*ARGSUSED*/
-vi_end_word(EditLine *el, int c __attribute__((__unused__)))
+vi_end_word(EditLine *el, Int c __attribute__((__unused__)))
{
if (el->el_line.cursor == el->el_line.lastchar)
@@ -503,7 +506,7 @@ vi_end_word(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-vi_undo(EditLine *el, int c __attribute__((__unused__)))
+vi_undo(EditLine *el, Int c __attribute__((__unused__)))
{
c_undo_t un = el->el_chared.c_undo;
@@ -513,7 +516,8 @@ vi_undo(EditLine *el, int c __attribute__((__unused__)))
/* switch line buffer and undo buffer */
el->el_chared.c_undo.buf = el->el_line.buffer;
el->el_chared.c_undo.len = el->el_line.lastchar - el->el_line.buffer;
- el->el_chared.c_undo.cursor = el->el_line.cursor - el->el_line.buffer;
+ el->el_chared.c_undo.cursor =
+ (int)(el->el_line.cursor - el->el_line.buffer);
el->el_line.limit = un.buf + (el->el_line.limit - el->el_line.buffer);
el->el_line.buffer = un.buf;
el->el_line.cursor = un.buf + un.cursor;
@@ -529,7 +533,7 @@ vi_undo(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-vi_command_mode(EditLine *el, int c __attribute__((__unused__)))
+vi_command_mode(EditLine *el, Int c __attribute__((__unused__)))
{
/* [Esc] cancels pending action */
@@ -553,7 +557,7 @@ vi_command_mode(EditLine *el, int c __attribute__((__unused__)))
* [0]
*/
protected el_action_t
-vi_zero(EditLine *el, int c)
+vi_zero(EditLine *el, Int c)
{
if (el->el_state.doingarg)
@@ -574,20 +578,14 @@ vi_zero(EditLine *el, int c)
*/
protected el_action_t
/*ARGSUSED*/
-vi_delete_prev_char(EditLine *el, int c __attribute__((__unused__)))
+vi_delete_prev_char(EditLine *el, Int c __attribute__((__unused__)))
{
- char *cp;
- cp = el->el_line.cursor;
- if (cp <= el->el_line.buffer)
+ if (el->el_line.cursor <= el->el_line.buffer)
return (CC_ERROR);
- /* do the delete here so we dont mess up the undo and paste buffers */
- el->el_line.cursor = --cp;
- for (; cp < el->el_line.lastchar; cp++)
- cp[0] = cp[1];
- el->el_line.lastchar = cp - 1;
-
+ c_delbefore1(el);
+ el->el_line.cursor--;
return (CC_REFRESH);
}
@@ -598,13 +596,12 @@ vi_delete_prev_char(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-vi_list_or_eof(EditLine *el, int c __attribute__((__unused__)))
+vi_list_or_eof(EditLine *el, Int c)
{
if (el->el_line.cursor == el->el_line.lastchar) {
if (el->el_line.cursor == el->el_line.buffer) {
- term_overwrite(el, STReof, 4); /* then do a EOF */
- term__flush();
+ term_writec(el, c); /* then do a EOF */
return (CC_EOF);
} else {
/*
@@ -636,16 +633,16 @@ vi_list_or_eof(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-vi_kill_line_prev(EditLine *el, int c __attribute__((__unused__)))
+vi_kill_line_prev(EditLine *el, Int c __attribute__((__unused__)))
{
- char *kp, *cp;
+ 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);
+ c_delbefore(el, (int)(el->el_line.cursor - el->el_line.buffer));
el->el_line.cursor = el->el_line.buffer; /* zap! */
return (CC_REFRESH);
}
@@ -657,7 +654,7 @@ vi_kill_line_prev(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-vi_search_prev(EditLine *el, int c __attribute__((__unused__)))
+vi_search_prev(EditLine *el, Int c __attribute__((__unused__)))
{
return (cv_search(el, ED_SEARCH_PREV_HISTORY));
@@ -670,7 +667,7 @@ vi_search_prev(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-vi_search_next(EditLine *el, int c __attribute__((__unused__)))
+vi_search_next(EditLine *el, Int c __attribute__((__unused__)))
{
return (cv_search(el, ED_SEARCH_NEXT_HISTORY));
@@ -683,7 +680,7 @@ vi_search_next(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-vi_repeat_search_next(EditLine *el, int c __attribute__((__unused__)))
+vi_repeat_search_next(EditLine *el, Int c __attribute__((__unused__)))
{
if (el->el_search.patlen == 0)
@@ -699,7 +696,7 @@ vi_repeat_search_next(EditLine *el, int c __attribute__((__unused__)))
*/
/*ARGSUSED*/
protected el_action_t
-vi_repeat_search_prev(EditLine *el, int c __attribute__((__unused__)))
+vi_repeat_search_prev(EditLine *el, Int c __attribute__((__unused__)))
{
if (el->el_search.patlen == 0)
@@ -717,7 +714,7 @@ vi_repeat_search_prev(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-vi_next_char(EditLine *el, int c __attribute__((__unused__)))
+vi_next_char(EditLine *el, Int c __attribute__((__unused__)))
{
return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 0);
}
@@ -729,7 +726,7 @@ vi_next_char(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-vi_prev_char(EditLine *el, int c __attribute__((__unused__)))
+vi_prev_char(EditLine *el, Int c __attribute__((__unused__)))
{
return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 0);
}
@@ -741,7 +738,7 @@ vi_prev_char(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-vi_to_next_char(EditLine *el, int c __attribute__((__unused__)))
+vi_to_next_char(EditLine *el, Int c __attribute__((__unused__)))
{
return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 1);
}
@@ -753,7 +750,7 @@ vi_to_next_char(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-vi_to_prev_char(EditLine *el, int c __attribute__((__unused__)))
+vi_to_prev_char(EditLine *el, Int c __attribute__((__unused__)))
{
return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 1);
}
@@ -765,7 +762,7 @@ vi_to_prev_char(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-vi_repeat_next_char(EditLine *el, int c __attribute__((__unused__)))
+vi_repeat_next_char(EditLine *el, Int c __attribute__((__unused__)))
{
return cv_csearch(el, el->el_search.chadir, el->el_search.chacha,
@@ -779,7 +776,7 @@ vi_repeat_next_char(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-vi_repeat_prev_char(EditLine *el, int c __attribute__((__unused__)))
+vi_repeat_prev_char(EditLine *el, Int c __attribute__((__unused__)))
{
el_action_t r;
int dir = el->el_search.chadir;
@@ -797,20 +794,20 @@ vi_repeat_prev_char(EditLine *el, int c __attribute__((__unused__)))
*/
protected el_action_t
/*ARGSUSED*/
-vi_match(EditLine *el, int c)
+vi_match(EditLine *el, Int c)
{
- const char match_chars[] = "()[]{}";
- char *cp;
- int delta, i, count;
- char o_ch, c_ch;
+ const Char match_chars[] = STR("()[]{}");
+ Char *cp;
+ size_t delta, i, count;
+ Char o_ch, c_ch;
*el->el_line.lastchar = '\0'; /* just in case */
- i = strcspn(el->el_line.cursor, match_chars);
+ i = Strcspn(el->el_line.cursor, match_chars);
o_ch = el->el_line.cursor[i];
if (o_ch == 0)
return CC_ERROR;
- delta = strchr(match_chars, o_ch) - match_chars;
+ delta = Strchr(match_chars, o_ch) - match_chars;
c_ch = match_chars[delta ^ 1];
count = 1;
delta = 1 - (delta & 1) * 2;
@@ -844,7 +841,7 @@ vi_match(EditLine *el, int c)
*/
protected el_action_t
/*ARGSUSED*/
-vi_undo_line(EditLine *el, int c)
+vi_undo_line(EditLine *el, Int c)
{
cv_undo(el);
@@ -858,7 +855,7 @@ vi_undo_line(EditLine *el, int c)
*/
protected el_action_t
/*ARGSUSED*/
-vi_to_column(EditLine *el, int c)
+vi_to_column(EditLine *el, Int c)
{
el->el_line.cursor = el->el_line.buffer;
@@ -872,11 +869,11 @@ vi_to_column(EditLine *el, int c)
*/
protected el_action_t
/*ARGSUSED*/
-vi_yank_end(EditLine *el, int c)
+vi_yank_end(EditLine *el, Int c)
{
cv_yank(el, el->el_line.cursor,
- el->el_line.lastchar - el->el_line.cursor);
+ (int)(el->el_line.lastchar - el->el_line.cursor));
return CC_REFRESH;
}
@@ -886,7 +883,7 @@ vi_yank_end(EditLine *el, int c)
*/
protected el_action_t
/*ARGSUSED*/
-vi_yank(EditLine *el, int c)
+vi_yank(EditLine *el, Int c)
{
return cv_action(el, YANK);
@@ -894,11 +891,11 @@ vi_yank(EditLine *el, int c)
/* vi_comment_out():
* Vi comment out current command
- * [c]
+ * [#]
*/
protected el_action_t
/*ARGSUSED*/
-vi_comment_out(EditLine *el, int c)
+vi_comment_out(EditLine *el, Int c)
{
el->el_line.cursor = el->el_line.buffer;
@@ -911,18 +908,19 @@ vi_comment_out(EditLine *el, int c)
/* vi_alias():
* Vi include shell alias
* [@]
- * NB: posix impiles that we should enter insert mode, however
+ * NB: posix implies that we should enter insert mode, however
* this is against historical precedent...
*/
+#ifdef __weak_reference
+extern char *get_alias_text(const char *) __weak_reference(get_alias_text);
+#endif
protected el_action_t
/*ARGSUSED*/
-vi_alias(EditLine *el, int c)
+vi_alias(EditLine *el, Int c)
{
-#ifdef __weak_extern
+#ifdef __weak_reference
char alias_name[3];
char *alias_text;
- extern char *get_alias_text(const char *);
- __weak_extern(get_alias_text);
if (get_alias_text == 0) {
return CC_ERROR;
@@ -935,7 +933,7 @@ vi_alias(EditLine *el, int c)
alias_text = get_alias_text(alias_name);
if (alias_text != NULL)
- el_push(el, alias_text);
+ FUN(el,push)(el, ct_decode_string(alias_text, &el->el_scratch));
return CC_NORM;
#else
return CC_ERROR;
@@ -948,14 +946,14 @@ vi_alias(EditLine *el, int c)
*/
protected el_action_t
/*ARGSUSED*/
-vi_to_history_line(EditLine *el, int c)
+vi_to_history_line(EditLine *el, Int c)
{
int sv_event_no = el->el_history.eventno;
el_action_t rval;
if (el->el_history.eventno == 0) {
- (void) strncpy(el->el_history.buf, el->el_line.buffer,
+ (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);
@@ -993,13 +991,16 @@ vi_to_history_line(EditLine *el, int c)
*/
protected el_action_t
/*ARGSUSED*/
-vi_histedit(EditLine *el, int c)
+vi_histedit(EditLine *el, Int c)
{
int fd;
pid_t pid;
- int st;
+ ssize_t st;
+ int status;
char tempfile[] = "/tmp/histedit.XXXXXXXXXX";
char *cp;
+ size_t len;
+ Char *line;
if (el->el_state.doingarg) {
if (vi_to_history_line(el, 0) == CC_ERROR)
@@ -1009,29 +1010,54 @@ vi_histedit(EditLine *el, int c)
fd = mkstemp(tempfile);
if (fd < 0)
return CC_ERROR;
- cp = el->el_line.buffer;
- write(fd, cp, el->el_line.lastchar - cp +0u);
+ len = (size_t)(el->el_line.lastchar - el->el_line.buffer);
+#define TMP_BUFSIZ (EL_BUFSIZ * MB_LEN_MAX)
+ cp = el_malloc(TMP_BUFSIZ);
+ if (cp == NULL)
+ return CC_ERROR;
+ line = el_malloc(len * sizeof(*line));
+ if (line == NULL) {
+ el_free((ptr_t)cp);
+ return CC_ERROR;
+ }
+ Strncpy(line, el->el_line.buffer, len);
+ line[len] = '\0';
+ ct_wcstombs(cp, line, TMP_BUFSIZ - 1);
+ cp[TMP_BUFSIZ - 1] = '\0';
+ len = strlen(cp);
+ write(fd, cp, len);
write(fd, "\n", 1);
pid = fork();
switch (pid) {
case -1:
close(fd);
unlink(tempfile);
+ el_free(cp);
+ el_free(line);
return CC_ERROR;
case 0:
close(fd);
- execlp("vi", "vi", tempfile, (char*)NULL);
+ execlp("vi", "vi", tempfile, (char *)NULL);
exit(0);
/*NOTREACHED*/
default:
- while (waitpid(pid, &st, 0) != pid)
+ while (waitpid(pid, &status, 0) != pid)
continue;
- lseek(fd, 0ll, SEEK_SET);
- st = read(fd, cp, el->el_line.limit - cp +0u);
- if (st > 0 && cp[st - 1] == '\n')
- st--;
- el->el_line.cursor = cp;
- el->el_line.lastchar = cp + st;
+ lseek(fd, (off_t)0, SEEK_SET);
+ st = read(fd, cp, TMP_BUFSIZ);
+ if (st > 0) {
+ len = (size_t)(el->el_line.lastchar -
+ el->el_line.buffer);
+ len = ct_mbstowcs(el->el_line.buffer, cp, len);
+ if (len > 0 && el->el_line.buffer[len -1] == '\n')
+ --len;
+ }
+ else
+ len = 0;
+ el->el_line.cursor = el->el_line.buffer;
+ el->el_line.lastchar = el->el_line.buffer + len;
+ el_free(cp);
+ el_free(line);
break;
}
@@ -1049,34 +1075,35 @@ vi_histedit(EditLine *el, int c)
*/
protected el_action_t
/*ARGSUSED*/
-vi_history_word(EditLine *el, int c)
+vi_history_word(EditLine *el, Int c)
{
- const char *wp = HIST_FIRST(el);
- const char *wep, *wsp;
+ const Char *wp = HIST_FIRST(el);
+ const Char *wep, *wsp;
int len;
- char *cp;
- const char *lim;
+ Char *cp;
+ const Char *lim;
if (wp == NULL)
return CC_ERROR;
wep = wsp = 0;
do {
- while (isspace((unsigned char)*wp))
+ while (Isspace(*wp))
wp++;
if (*wp == 0)
break;
wsp = wp;
- while (*wp && !isspace((unsigned char)*wp))
+ while (*wp && !Isspace(*wp))
wp++;
wep = wp;
- } while ((!el->el_state.doingarg || --el->el_state.argument > 0) && *wp != 0);
+ } while ((!el->el_state.doingarg || --el->el_state.argument > 0)
+ && *wp != 0);
if (wsp == 0 || (el->el_state.doingarg && el->el_state.argument != 0))
return CC_ERROR;
cv_undo(el);
- len = wep - wsp;
+ len = (int)(wep - wsp);
if (el->el_line.cursor < el->el_line.lastchar)
el->el_line.cursor++;
c_insert(el, len + 1);
@@ -1098,7 +1125,7 @@ vi_history_word(EditLine *el, int c)
*/
protected el_action_t
/*ARGSUSED*/
-vi_redo(EditLine *el, int c)
+vi_redo(EditLine *el, Int c)
{
c_redo_t *r = &el->el_chared.c_redo;
@@ -1114,7 +1141,7 @@ vi_redo(EditLine *el, int c)
/* sanity */
r->pos = r->lim - 1;
r->pos[0] = 0;
- el_push(el, r->buf);
+ FUN(el,push)(el, r->buf);
}
el->el_state.thiscmd = r->cmd;
diff --git a/lib/libedit/vi.h b/lib/libedit/vi.h
new file mode 100644
index 00000000000..69b07dc8167
--- /dev/null
+++ b/lib/libedit/vi.h
@@ -0,0 +1,51 @@
+/* Automatically generated file, do not edit */
+#ifndef _h_vi_c
+#define _h_vi_c
+protected el_action_t vi_paste_next (EditLine *, Int);
+protected el_action_t vi_paste_prev (EditLine *, Int);
+protected el_action_t vi_prev_big_word (EditLine *, Int);
+protected el_action_t vi_prev_word (EditLine *, Int);
+protected el_action_t vi_next_big_word (EditLine *, Int);
+protected el_action_t vi_next_word (EditLine *, Int);
+protected el_action_t vi_change_case (EditLine *, Int);
+protected el_action_t vi_change_meta (EditLine *, Int);
+protected el_action_t vi_insert_at_bol (EditLine *, Int);
+protected el_action_t vi_replace_char (EditLine *, Int);
+protected el_action_t vi_replace_mode (EditLine *, Int);
+protected el_action_t vi_substitute_char (EditLine *, Int);
+protected el_action_t vi_substitute_line (EditLine *, Int);
+protected el_action_t vi_change_to_eol (EditLine *, Int);
+protected el_action_t vi_insert (EditLine *, Int);
+protected el_action_t vi_add (EditLine *, Int);
+protected el_action_t vi_add_at_eol (EditLine *, Int);
+protected el_action_t vi_delete_meta (EditLine *, Int);
+protected el_action_t vi_end_big_word (EditLine *, Int);
+protected el_action_t vi_end_word (EditLine *, Int);
+protected el_action_t vi_undo (EditLine *, Int);
+protected el_action_t vi_command_mode (EditLine *, Int);
+protected el_action_t vi_zero (EditLine *, Int);
+protected el_action_t vi_delete_prev_char (EditLine *, Int);
+protected el_action_t vi_list_or_eof (EditLine *, Int);
+protected el_action_t vi_kill_line_prev (EditLine *, Int);
+protected el_action_t vi_search_prev (EditLine *, Int);
+protected el_action_t vi_search_next (EditLine *, Int);
+protected el_action_t vi_repeat_search_next (EditLine *, Int);
+protected el_action_t vi_repeat_search_prev (EditLine *, Int);
+protected el_action_t vi_next_char (EditLine *, Int);
+protected el_action_t vi_prev_char (EditLine *, Int);
+protected el_action_t vi_to_next_char (EditLine *, Int);
+protected el_action_t vi_to_prev_char (EditLine *, Int);
+protected el_action_t vi_repeat_next_char (EditLine *, Int);
+protected el_action_t vi_repeat_prev_char (EditLine *, Int);
+protected el_action_t vi_match (EditLine *, Int);
+protected el_action_t vi_undo_line (EditLine *, Int);
+protected el_action_t vi_to_column (EditLine *, Int);
+protected el_action_t vi_yank_end (EditLine *, Int);
+protected el_action_t vi_yank (EditLine *, Int);
+protected el_action_t vi_comment_out (EditLine *, Int);
+protected el_action_t vi_alias (EditLine *, Int);
+protected el_action_t vi_to_history_line (EditLine *, Int);
+protected el_action_t vi_histedit (EditLine *, Int);
+protected el_action_t vi_history_word (EditLine *, Int);
+protected el_action_t vi_redo (EditLine *, Int);
+#endif /* _h_vi_c */