diff options
author | David E. O'Brien <obrien@FreeBSD.org> | 2011-03-31 18:34:50 +0000 |
---|---|---|
committer | David E. O'Brien <obrien@FreeBSD.org> | 2011-03-31 18:34:50 +0000 |
commit | 703cb6130cc6bd2fc0b0eba9cf05b5f483673ef4 (patch) | |
tree | 75d1413f2d85aff18799bc1b708f14ace12aaf47 | |
parent | 8dfe73baa31e01bec909d4aa794df323b0876a9d (diff) |
Vendor import NetBSD's libedit of "2010/06/01 18:20:26 UTC".vendor/NetBSD/libedit/2010-06-01
Obtained from: NetBSD
Notes
Notes:
svn path=/vendor/NetBSD/libedit/dist/; revision=220220
svn path=/vendor/NetBSD/libedit/2010-06-01/; revision=220221; tag=vendor/NetBSD/libedit/2010-06-01
-rw-r--r-- | Makefile | 38 | ||||
-rw-r--r-- | TEST/Makefile | 8 | ||||
-rw-r--r-- | TEST/tc1.c | 19 | ||||
-rw-r--r-- | TEST/wtc1.c | 269 | ||||
-rw-r--r-- | chared.c | 183 | ||||
-rw-r--r-- | chared.h | 45 | ||||
-rw-r--r-- | chartype.c | 360 | ||||
-rw-r--r-- | chartype.h | 245 | ||||
-rw-r--r-- | common.c | 126 | ||||
-rw-r--r-- | config.h | 2 | ||||
-rw-r--r-- | editline.3 | 176 | ||||
-rw-r--r-- | editrc.5 | 39 | ||||
-rw-r--r-- | el.c | 149 | ||||
-rw-r--r-- | el.h | 33 | ||||
-rw-r--r-- | eln.c | 365 | ||||
-rw-r--r-- | emacs.c | 93 | ||||
-rw-r--r-- | filecomplete.c | 107 | ||||
-rw-r--r-- | filecomplete.h | 9 | ||||
-rw-r--r-- | hist.c | 47 | ||||
-rw-r--r-- | hist.h | 25 | ||||
-rw-r--r-- | histedit.h | 153 | ||||
-rw-r--r-- | history.c | 339 | ||||
-rw-r--r-- | key.c | 181 | ||||
-rw-r--r-- | key.h | 23 | ||||
-rw-r--r-- | makelist | 27 | ||||
-rw-r--r-- | map.c | 71 | ||||
-rw-r--r-- | map.h | 16 | ||||
-rw-r--r-- | parse.c | 92 | ||||
-rw-r--r-- | parse.h | 10 | ||||
-rw-r--r-- | prompt.c | 81 | ||||
-rw-r--r-- | prompt.h | 14 | ||||
-rw-r--r-- | read.c | 214 | ||||
-rw-r--r-- | read.h | 7 | ||||
-rw-r--r-- | readline.c | 628 | ||||
-rw-r--r-- | readline/readline.h | 39 | ||||
-rw-r--r-- | refresh.c | 400 | ||||
-rw-r--r-- | refresh.h | 4 | ||||
-rw-r--r-- | search.c | 83 | ||||
-rw-r--r-- | search.h | 14 | ||||
-rw-r--r-- | shlib_version | 6 | ||||
-rw-r--r-- | sig.c | 80 | ||||
-rw-r--r-- | sig.h | 11 | ||||
-rw-r--r-- | sys.h | 15 | ||||
-rw-r--r-- | term.c | 451 | ||||
-rw-r--r-- | term.h | 26 | ||||
-rw-r--r-- | tokenizer.c | 93 | ||||
-rw-r--r-- | tty.c | 109 | ||||
-rw-r--r-- | tty.h | 5 | ||||
-rw-r--r-- | vi.c | 226 |
49 files changed, 4017 insertions, 1739 deletions
@@ -1,15 +1,16 @@ -# $NetBSD: Makefile,v 1.35 2006/08/31 20:20:38 rpaulo Exp $ +# $NetBSD: Makefile,v 1.41 2010/02/03 15:34:43 roy Exp $ # @(#)Makefile 8.1 (Berkeley) 6/4/93 USE_SHLIBDIR= yes -WARNS= 3 +WIDECHAR ?= yes +WARNS= 4 LIB= edit -LIBDPLIBS= termcap ${.CURDIR}/../libterm +LIBDPLIBS+= terminfo ${.CURDIR}/../libterminfo -OSRCS= chared.c common.c el.c emacs.c fcns.c filecomplete.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 @@ -25,9 +26,16 @@ MLINKS= editline.3 el_init.3 editline.3 el_end.3 editline.3 el_reset.3 \ editline.3 tok_line.3 editline.3 tok_str.3 # For speed and debugging -#SRCS= ${OSRCS} tokenizer.c history.c readline.c +#SRCS= ${OSRCS} readline.c tokenizer.c history.c # For protection -SRCS= editline.c tokenizer.c history.c readline.c +SRCS= editline.c readline.c tokenizer.c history.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} @@ -36,8 +44,8 @@ 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+=tc1.o tc1 +CLEANFILES+=help.c.tmp help.h.tmp vi.h.tmp tc1.o tc1 +CLEANFILES+=tokenizern.c.tmp tokenizern.c tokenizerw.c.tmp tokenizerw.c CPPFLAGS+=-I. -I${LIBEDITDIR} CPPFLAGS+=-I. -I${.CURDIR} CPPFLAGS+=#-DDEBUG_TTY -DDEBUG_KEY -DDEBUG_READ -DDEBUG -DDEBUG_REFRESH @@ -94,11 +102,21 @@ editline.c: ${OSRCS} makelist Makefile ${HOST_SH} ${LIBEDITDIR}/makelist -e ${OSRCS:T} > ${.TARGET}.tmp && \ mv ${.TARGET}.tmp ${.TARGET} +tokenizern.c: makelist Makefile + ${_MKTARGET_CREATE} + ${HOST_SH} ${LIBEDITDIR}/makelist -n tokenizer.c > ${.TARGET}.tmp && \ + mv ${.TARGET}.tmp ${.TARGET} + +historyn.c: makelist Makefile + ${_MKTARGET_CREATE} + ${HOST_SH} ${LIBEDITDIR}/makelist -n history.c > ${.TARGET}.tmp && \ + mv ${.TARGET}.tmp ${.TARGET} + tc1.o: ${LIBEDITDIR}/TEST/tc1.c tc1: libedit.a tc1.o ${_MKTARGET_LINK} - ${CC} ${LDFLAGS} ${.ALLSRC} -o ${.TARGET} libedit.a ${LDADD} -ltermcap + ${CC} ${LDFLAGS} ${.ALLSRC} -o ${.TARGET} libedit.a ${LDADD} -ltermlib .include <bsd.lib.mk> .include <bsd.subdir.mk> diff --git a/TEST/Makefile b/TEST/Makefile index 91ef1194a825..e06fcebff070 100644 --- a/TEST/Makefile +++ b/TEST/Makefile @@ -1,10 +1,10 @@ -# $NetBSD: Makefile,v 1.3 2006/08/31 20:20:38 rpaulo Exp $ +# $NetBSD: Makefile,v 1.5 2010/02/03 15:34:43 roy Exp $ NOMAN=1 -PROG=tc1 +PROG=wtc1 CPPFLAGS=-I${.CURDIR}/.. -LDADD+=-ledit -ltermcap -DPADD+=${LIBEDIT} ${LIBTERMCAP} +LDADD+=-ledit -ltermlib +DPADD+=${LIBEDIT} ${LIBTERMLIB} .ifdef DEBUG CPPFLAGS+=-DDEBUG diff --git a/TEST/tc1.c b/TEST/tc1.c index ee0b1a940a7f..77f8a515373c 100644 --- a/TEST/tc1.c +++ b/TEST/tc1.c @@ -1,4 +1,4 @@ -/* $NetBSD: tc1.c,v 1.1 2006/08/31 20:20:38 rpaulo Exp $ */ +/* $NetBSD: tc1.c,v 1.5 2010/04/18 21:17:47 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -42,7 +42,7 @@ __COPYRIGHT("@(#) Copyright (c) 1992, 1993\n\ #if 0 static char sccsid[] = "@(#)test.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: tc1.c,v 1.1 2006/08/31 20:20:38 rpaulo Exp $"); +__RCSID("$NetBSD: tc1.c,v 1.5 2010/04/18 21:17:47 christos Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -57,6 +57,7 @@ __RCSID("$NetBSD: tc1.c,v 1.1 2006/08/31 20:20:38 rpaulo Exp $"); #include <stdlib.h> #include <unistd.h> #include <dirent.h> +#include <locale.h> #include "histedit.h" @@ -71,7 +72,7 @@ static void sig(int); static char * prompt(EditLine *el) { - static char a[] = "Edit$ "; + static char a[] = "\1\033[7m\1Edit$\1\033[0m\1 "; static char b[] = "Edit> "; return (continuation ? b : a); @@ -91,6 +92,7 @@ complete(EditLine *el, int ch) const char* ptr; const LineInfo *lf = el_line(el); int len; + int res = CC_ERROR; /* * Find the last word @@ -104,16 +106,16 @@ complete(EditLine *el, int ch) 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 @@ -130,6 +132,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); @@ -146,7 +149,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); diff --git a/TEST/wtc1.c b/TEST/wtc1.c new file mode 100644 index 000000000000..b1f22a57287f --- /dev/null +++ b/TEST/wtc1.c @@ -0,0 +1,269 @@ +#include <stdio.h> +#include <string.h> +#include <signal.h> +#include <sys/wait.h> +#include <ctype.h> +#include <stdlib.h> +#include <unistd.h> +#include <dirent.h> +#include <limits.h> +#include <locale.h> + +#include "../histedit.h" + + +static int continuation; +volatile sig_atomic_t gotsig; + +static wchar_t * +prompt(EditLine *el) +{ + static wchar_t a[] = L"\1\033[7m\1Edit$\1\033[0m\1 "; + static wchar_t b[] = L"Edit> "; + + return continuation ? b : a; +} + + +static void +sig(int i) +{ + gotsig = i; +} + +const char * +my_wcstombs(const wchar_t *wstr) +{ + static struct { + char *str; + int len; + } buf; + + int needed = wcstombs(0, wstr, 0) + 1; + if (needed > buf.len) { + buf.str = malloc(needed); + buf.len = needed; + } + wcstombs(buf.str, wstr, needed); + buf.str[needed - 1] = 0; + + return buf.str; +} + + +static unsigned char +complete(EditLine *el, int ch) +{ + DIR *dd = opendir("."); + struct dirent *dp; + const wchar_t *ptr; + char *buf, *bptr; + const LineInfoW *lf = el_wline(el); + int len, mblen, i; + unsigned char res; + + /* Find the last word */ + for (ptr = lf->cursor -1; !iswspace(*ptr) && ptr > lf->buffer; --ptr) + continue; + len = lf->cursor - ++ptr; + + /* Convert last word to multibyte encoding, so we can compare to it */ + wctomb(NULL, 0); /* Reset shift state */ + mblen = MB_LEN_MAX * len + 1; + buf = bptr =(char *)malloc(mblen); + for (i = 0; i < len; ++i) { + /* Note: really should test for -1 return from wctomb */ + bptr += wctomb(bptr, ptr[i]); + } + *bptr = 0; /* Terminate multibyte string */ + mblen = bptr - buf; + + /* Scan directory for matching name */ + for (dp = readdir(dd); dp != NULL; dp = readdir(dd)) { + if (mblen > strlen(dp->d_name)) + continue; + if (strncmp(dp->d_name, buf, mblen) == 0) { + if (el_insertstr(el, &dp->d_name[mblen]) == -1) + res = CC_ERROR; + else + res = CC_REFRESH; + break; + } + } + + closedir(dd); + free(buf); + return res; +} + + +int +main(int argc, char *argv[]) +{ + EditLine *el = NULL; + int numc, ncontinuation; + const wchar_t *line; + TokenizerW *tok; + HistoryW *hist; + HistEventW ev; +#ifdef DEBUG + int i; +#endif + + setlocale(LC_ALL, ""); + + (void)signal(SIGINT, sig); + (void)signal(SIGQUIT, sig); + (void)signal(SIGHUP, sig); + (void)signal(SIGTERM, sig); + + hist = history_winit(); /* Init built-in history */ + history_w(hist, &ev, H_SETSIZE, 100); /* Remember 100 events */ + + tok = tok_winit(NULL); /* Init the tokenizer */ + + el = el_init(argv[0], stdin, stdout, stderr); + + el_wset(el, EL_EDITOR, L"vi"); /* Default editor is vi */ + el_wset(el, EL_SIGNAL, 1); /* Handle signals gracefully */ + el_wset(el, EL_PROMPT_ESC, prompt, '\1'); /* Set the prompt function */ + + el_wset(el, EL_HIST, history_w, hist); /* FIXME - history_w? */ + + /* Add a user-defined function */ + el_wset(el, EL_ADDFN, L"ed-complete", L"Complete argument", complete); + + /* Bind <tab> to it */ + el_wset(el, EL_BIND, L"^I", L"ed-complete", NULL); + + /* + * Bind j, k in vi command mode to previous and next line, instead + * of previous and next history. + */ + el_wset(el, EL_BIND, L"-a", L"k", L"ed-prev-line", NULL); + el_wset(el, EL_BIND, L"-a", L"j", L"ed-next-line", NULL); + + /* Source the user's defaults file. */ + el_source(el, NULL); + + while((line = el_wgets(el, &numc)) != NULL && numc != 0) { + int ac, cc, co, rc; + const wchar_t **av; + + const LineInfoW *li; + li = el_wline(el); + +#ifdef DEBUG + (void)fwprintf(stderr, L"==> got %d %ls", numc, line); + (void)fwprintf(stderr, L" > li `%.*ls_%.*ls'\n", + (li->cursor - li->buffer), li->buffer, + (li->lastchar - 1 - li->cursor), + (li->cursor >= li->lastchar) ? L"" : li->cursor); +#endif + + if (gotsig) { + (void)fprintf(stderr, "Got signal %d.\n", gotsig); + gotsig = 0; + el_reset(el); + } + + if(!continuation && numc == 1) + continue; /* Only got a linefeed */ + + ac = cc = co = 0; + ncontinuation = tok_wline(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 + history_w(hist, &ev, continuation ? H_APPEND : H_ENTER, line); + + continuation = ncontinuation; + ncontinuation = 0; + if(continuation) + continue; + +#ifdef DEBUG + for (i = 0; i < ac; ++i) { + (void)fwprintf(stderr, L" > arg# %2d ", i); + if (i != cc) + (void)fwprintf(stderr, L"`%ls'\n", av[i]); + else + (void)fwprintf(stderr, L"`%.*ls_%ls'\n", + co, av[i], av[i] + co); + } +#endif + + if (wcscmp (av[0], L"history") == 0) { + switch(ac) { + case 1: + for(rc = history_w(hist, &ev, H_LAST); + rc != -1; + rc = history_w(hist, &ev, H_PREV)) + (void)fwprintf(stdout, L"%4d %ls", + ev.num, ev.str); + break; + case 2: + if (wcscmp(av[1], L"clear") == 0) + history_w(hist, &ev, H_CLEAR); + else + goto badhist; + break; + case 3: + if (wcscmp(av[1], L"load") == 0) + history_w(hist, &ev, H_LOAD, + my_wcstombs(av[2])); + else if (wcscmp(av[1], L"save") == 0) + history_w(hist, &ev, H_SAVE, + my_wcstombs(av[2])); + else + goto badhist; + break; + badhist: + default: + (void)fprintf(stderr, + "Bad history arguments\n"); + break; + } + } else if (el_wparse(el, ac, av) == -1) { + switch (fork()) { + case 0: { + Tokenizer *ntok = tok_init(NULL); + int nargc; + const char **nav; + tok_str(ntok, my_wcstombs(line), &nargc, &nav); + execvp(nav[0],(char **)nav); + perror(nav[0]); + _exit(1); + /* NOTREACHED */ + break; + } + case -1: + perror("fork"); + break; + default: + if (wait(&rc) == -1) + perror("wait"); + (void)fprintf(stderr, "Exit %x\n", rc); + break; + } + } + + tok_wreset(tok); + } + + el_end(el); + tok_wend(tok); + history_wend(hist); + + fprintf(stdout, "\n"); + return 0; +} + + @@ -1,4 +1,4 @@ -/* $NetBSD: chared.c,v 1.25 2005/08/08 01:41:30 christos Exp $ */ +/* $NetBSD: chared.c,v 1.28 2009/12/30 22:37:40 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)chared.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: chared.c,v 1.25 2005/08/08 01:41:30 christos Exp $"); +__RCSID("$NetBSD: chared.c,v 1.28 2009/12/30 22:37:40 christos Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -47,7 +47,7 @@ __RCSID("$NetBSD: chared.c,v 1.25 2005/08/08 01:41:30 christos Exp $"); #include <stdlib.h> #include "el.h" -private void ch__clearmacro __P((EditLine *)); +private void ch__clearmacro (EditLine *); /* value to leave unused in line buffer */ #define EL_LEAVE 2 @@ -60,13 +60,13 @@ cv_undo(EditLine *el) { c_undo_t *vu = &el->el_chared.c_undo; c_redo_t *r = &el->el_chared.c_redo; - unsigned int 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; @@ -80,11 +80,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; } @@ -95,10 +95,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 */ } @@ -119,7 +119,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); @@ -127,7 +127,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]; @@ -143,7 +143,7 @@ c_delafter(EditLine *el, int num) protected void c_delafter1(EditLine *el) { - char *cp; + Char *cp; for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++) *cp = cp[1]; @@ -160,7 +160,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); @@ -168,7 +168,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; @@ -186,7 +186,7 @@ c_delbefore(EditLine *el, int num) protected void c_delbefore1(EditLine *el) { - char *cp; + Char *cp; for (cp = el->el_line.cursor - 1; cp <= el->el_line.lastchar; cp++) *cp = cp[1]; @@ -199,9 +199,9 @@ c_delbefore1(EditLine *el) * 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); } @@ -209,11 +209,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; } @@ -223,24 +223,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--; } @@ -256,13 +256,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) @@ -274,21 +274,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++; } @@ -303,17 +303,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++; @@ -332,9 +332,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 */ { @@ -353,7 +353,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); @@ -376,7 +377,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; @@ -402,15 +403,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++; } @@ -423,19 +424,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--; @@ -450,22 +451,27 @@ ch_init(EditLine *el) { c_macro_t *ma = &el->el_chared.c_macro; - el->el_line.buffer = (char *) el_malloc(EL_BUFSIZ); + 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; @@ -475,10 +481,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; @@ -492,7 +500,7 @@ ch_init(EditLine *el) ma->level = -1; ma->offset = 0; - ma->macro = (char **) el_malloc(EL_MAXMACRO * sizeof(char *)); + ma->macro = el_malloc(EL_MAXMACRO * sizeof(*ma->macro)); if (ma->macro == NULL) return (-1); return (0); @@ -530,8 +538,7 @@ ch_reset(EditLine *el, int mclear) } private void -ch__clearmacro(el) - EditLine *el; +ch__clearmacro(EditLine *el) { c_macro_t *ma = &el->el_chared.c_macro; while (ma->level >= 0) @@ -543,12 +550,10 @@ ch__clearmacro(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; @@ -564,12 +569,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; @@ -582,12 +587,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; @@ -600,15 +605,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 + @@ -653,11 +660,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)) @@ -693,15 +700,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; @@ -712,7 +719,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; @@ -722,7 +729,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; } @@ -750,7 +757,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; } @@ -760,7 +767,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. @@ -772,6 +779,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); } } @@ -1,4 +1,4 @@ -/* $NetBSD: chared.h,v 1.17 2006/03/06 21:11:56 christos Exp $ */ +/* $NetBSD: chared.h,v 1.20 2010/04/15 00:57:33 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -63,25 +63,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; @@ -91,16 +91,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; /* @@ -119,7 +119,6 @@ typedef struct el_chared_t { #define STRQQ "\"\"" #define isglob(a) (strchr("*[]?", (a)) != NULL) -#define isword(a) (isprint(a)) #define NOP 0x00 #define DELETE 0x01 @@ -140,23 +139,23 @@ 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 void c_delafter1(EditLine *); -protected int c_gets(EditLine *, char *, const char *); +protected int c_gets(EditLine *, Char *, const Char *); protected int c_hpos(EditLine *); protected int ch_init(EditLine *); diff --git a/chartype.c b/chartype.c new file mode 100644 index 000000000000..3a539d468eb0 --- /dev/null +++ b/chartype.c @@ -0,0 +1,360 @@ +/* $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" +#if !defined(lint) && !defined(SCCSID) +__RCSID("$NetBSD: chartype.c,v 1.4 2010/04/15 00:55:57 christos Exp $"); +#endif /* not lint && not SCCSID */ +#include "el.h" +#include <stdlib.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/chartype.h b/chartype.h new file mode 100644 index 000000000000..f5440b4fd8dc --- /dev/null +++ b/chartype.h @@ -0,0 +1,245 @@ +/* $NetBSD: chartype.h,v 1.6 2010/04/20 02:01:13 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... */ +#if !defined(__NetBSD__) && !defined(__sun) && !(defined(__APPLE__) && defined(__MACH__)) +#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 */ @@ -1,4 +1,4 @@ -/* $NetBSD: common.c,v 1.19 2006/03/06 21:11:56 christos Exp $ */ +/* $NetBSD: common.c,v 1.24 2009/12/30 22:37:40 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)common.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: common.c,v 1.19 2006/03/06 21:11:56 christos Exp $"); +__RCSID("$NetBSD: common.c,v 1.24 2009/12/30 22:37:40 christos Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -52,7 +52,7 @@ __RCSID("$NetBSD: common.c,v 1.19 2006/03/06 21:11:56 christos Exp $"); */ 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); @@ -66,7 +66,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; @@ -109,9 +109,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); @@ -123,7 +123,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 */ @@ -137,7 +137,7 @@ ed_delete_prev_word(EditLine *el, int c __attribute__((__unused__))) */ protected el_action_t /*ARGSUSED*/ -ed_delete_next_char(EditLine *el, int c) +ed_delete_next_char(EditLine *el, Int c) { #ifdef notdef /* XXX */ #define EL el->el_line @@ -155,7 +155,7 @@ ed_delete_next_char(EditLine *el, int c) return (CC_ERROR); #else /* then do an EOF */ - term_writechar(el, c); + term_writec(el, c); return (CC_EOF); #endif } else { @@ -187,9 +187,9 @@ ed_delete_next_char(EditLine *el, int c) */ 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; @@ -208,18 +208,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); } @@ -231,14 +231,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); @@ -254,7 +254,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) { @@ -280,9 +280,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 && @@ -309,7 +309,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) @@ -335,7 +335,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) { @@ -359,14 +359,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)); @@ -379,10 +379,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) { @@ -407,10 +407,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) { @@ -432,7 +432,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); @@ -450,7 +450,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); @@ -464,7 +464,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); @@ -478,7 +478,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); @@ -492,7 +492,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); @@ -506,7 +506,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); @@ -520,7 +520,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); @@ -534,7 +534,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); @@ -547,7 +547,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); @@ -563,7 +563,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) @@ -583,7 +583,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 */ @@ -599,7 +599,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); @@ -612,7 +612,7 @@ 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, 0); @@ -627,7 +627,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); @@ -640,7 +640,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; @@ -650,7 +650,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); @@ -660,7 +660,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 */ @@ -678,7 +678,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; @@ -705,9 +705,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; @@ -723,7 +723,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); @@ -744,7 +744,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)) { @@ -773,9 +773,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; @@ -799,7 +799,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)) @@ -827,9 +827,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); /* @@ -870,9 +870,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); /* @@ -904,13 +904,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); @@ -15,4 +15,6 @@ #define HAVE_STRVIS 1 #define HAVE_STRUNVIS 1 +#define HAVE_STRUCT_DIRENT_D_NAMLEN 1 + #include "sys.h" diff --git a/editline.3 b/editline.3 index a0f32b6a1b8a..e2504107c8b8 100644 --- a/editline.3 +++ b/editline.3 @@ -1,4 +1,4 @@ -.\" $NetBSD: editline.3,v 1.55 2007/01/12 16:31:13 christos Exp $ +.\" $NetBSD: editline.3,v 1.73 2010/01/03 19:05:26 wiz Exp $ .\" .\" Copyright (c) 1997-2003 The NetBSD Foundation, Inc. .\" All rights reserved. @@ -13,9 +13,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of The 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 @@ -29,33 +26,50 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd January 12, 2007 -.Os +.Dd January 3, 2010 .Dt EDITLINE 3 +.Os .Sh NAME .Nm editline , .Nm el_init , .Nm el_end , .Nm el_reset , .Nm el_gets , +.Nm el_wgets , .Nm el_getc , +.Nm el_wgetc , .Nm el_push , +.Nm el_wpush , .Nm el_parse , +.Nm el_wparse , .Nm el_set , +.Nm el_wset , .Nm el_get , +.Nm el_wget , .Nm el_source , .Nm el_resize , .Nm el_line , +.Nm el_wline , .Nm el_insertstr , +.Nm el_winsertstr , .Nm el_deletestr , +.Nm el_wdeletestr , .Nm history_init , +.Nm history_winit , .Nm history_end , +.Nm history_wend , .Nm history , +.Nm history_w , .Nm tok_init , +.Nm tok_winit , .Nm tok_end , +.Nm tok_wend , .Nm tok_reset , +.Nm tok_wreset , .Nm tok_line , +.Nm tok_wline , .Nm tok_str +.Nm tok_wstr .Nd line editor, history and tokenization functions .Sh LIBRARY .Lb libedit @@ -69,17 +83,29 @@ .Fn el_reset "EditLine *e" .Ft const char * .Fn el_gets "EditLine *e" "int *count" +.Ft const wchar_t * +.Fn el_wgets "EditLine *e" "int *count" .Ft int .Fn el_getc "EditLine *e" "char *ch" +.Ft int +.Fn el_wgetc "EditLine *e" "wchar_t *ch" .Ft void .Fn el_push "EditLine *e" "const char *str" +.Ft void +.Fn el_wpush "EditLine *e" "const wchar_t *str" .Ft int .Fn el_parse "EditLine *e" "int argc" "const char *argv[]" .Ft int +.Fn el_wparse "EditLine *e" "int argc" "const wchar_t *argv[]" +.Ft int .Fn el_set "EditLine *e" "int op" "..." .Ft int +.Fn el_wset "EditLine *e" "int op" "..." +.Ft int .Fn el_get "EditLine *e" "int op" "..." .Ft int +.Fn el_wget "EditLine *e" "int op" "..." +.Ft int .Fn el_source "EditLine *e" "const char *file" .Ft void .Fn el_resize "EditLine *e" @@ -87,24 +113,44 @@ .Fn el_line "EditLine *e" .Ft int .Fn el_insertstr "EditLine *e" "const char *str" +.Ft int +.Fn el_winsertstr "EditLine *e" "const wchar_t *str" .Ft void .Fn el_deletestr "EditLine *e" "int count" +.Ft void +.Fn el_wdeletestr "EditLine *e" "int count" .Ft History * .Fn history_init +.Ft HistoryW * +.Fn history_winit .Ft void .Fn history_end "History *h" +.Ft void +.Fn history_wend "HistoryW *h" .Ft int .Fn history "History *h" "HistEvent *ev" "int op" "..." +.Ft int +.Fn history_w "HistoryW *h" "HistEventW *ev" "int op" "..." .Ft Tokenizer * .Fn tok_init "const char *IFS" +.Ft TokenizerW * +.Fn tok_winit "const wchar_t *IFS" .Ft void .Fn tok_end "Tokenizer *t" .Ft void +.Fn tok_wend "TokenizerW *t" +.Ft void .Fn tok_reset "Tokenizer *t" +.Ft void +.Fn tok_wreset "TokenizerW *t" .Ft int .Fn tok_line "Tokenizer *t" "const LineInfo *li" "int *argc" "const char **argv[]" "int *cursorc" "int *cursoro" .Ft int +.Fn tok_wline "TokenizerW *t" "const LineInfoW *li" "int *argc" "const wchar_t **argv[]" "int *cursorc" "int *cursoro" +.Ft int .Fn tok_str "Tokenizer *t" "const char *str" "int *argc" "const char **argv[]" +.Ft int +.Fn tok_wstr "TokenizerW *t" "const wchar_t *str" "int *argc" "const wchar_t **argv[]" .Sh DESCRIPTION The .Nm @@ -127,6 +173,9 @@ which is created by and freed by .Fn el_end . .Pp +The wide character functions behave the same way as their narrow +counterparts. +.Pp The following functions are available: .Bl -tag -width 4n .It Fn el_init @@ -160,6 +209,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 @@ -220,10 +277,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 , @@ -257,66 +334,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 @@ -358,10 +412,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 @@ -390,7 +442,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 @@ -432,10 +485,22 @@ 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 @@ -460,7 +525,8 @@ above). Return non-zero if editing is enabled. .It Dv EL_GETCFN , Fa "int (**f)(EditLine *, char *)" Return a pointer to the function that read characters, which is equal to -``EL_BUILTIN_GETCFN'' in the case of the default builtin function. +.Dq Dv EL_BUILTIN_GETCFN +in the case of the default builtin function. .It Dv EL_CLIENTDATA , Fa "void **data" Retrieve .Fa data @@ -599,18 +665,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. @@ -802,6 +861,7 @@ 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 At this time, it is the responsibility of the caller to check the result of the @@ -1,4 +1,4 @@ -.\" $NetBSD: editrc.5,v 1.20 2006/08/21 12:45:30 christos 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. @@ -13,9 +13,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of The 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 @@ -30,8 +27,8 @@ .\" POSSIBILITY OF SUCH DAMAGE. .\" .Dd October 18, 2003 -.Os .Dt EDITRC 5 +.Os .Sh NAME .Nm editrc .Nd configuration file for editline library @@ -90,16 +87,8 @@ shell. .Pp The following builtin commands are available: .Bl -tag -width 4n -.It Ic bind Xo -.Op Fl a -.Op Fl e -.Op Fl k -.Op Fl l -.Op Fl r -.Op Fl s -.Op Fl v -.Op Ar key Op Ar command -.Xc +.It Ic bind Oo Fl a Oc Oo Fl e Oc Oo Fl k Oc Oo Fl l Oc Oo Fl r Oc \ +Oo Fl s Oc Oo Fl v Oc Oo Ar key Op Ar command Oc Without options, list all bound keys, and the editor command to which each is bound. If @@ -195,11 +184,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 Ar ... . If @@ -227,7 +212,7 @@ Enable or disable the .Nm editline functionality in a program. .It Ic history Ar list | Ar size Dv n | Ar unique Dv n -The +The .Ar list command lists all entries in the history. The @@ -255,16 +240,8 @@ to as defined in .Xr termcap 5 . No sanity checking is done. -.It Ic setty Xo -.Op Fl a -.Op Fl d -.Op Fl q -.Op Fl x -.Op Ar +mode -.Op Ar -mode -.Op Ar mode -.Op Ar char=c -.Xc +.It Ic setty Oo Fl a Oc Oo Fl d Oc Oo Fl q Oc Oo Fl x Oc Oo Ar +mode Oc \ +Oo Ar -mode Oc Oo Ar mode Oc Oo Ar char=c Oc Control which tty modes that .Nm won't allow the user to change. @@ -1,4 +1,4 @@ -/* $NetBSD: el.c,v 1.44 2006/12/15 22:13:33 christos Exp $ */ +/* $NetBSD: el.c,v 1.59 2010/04/15 00:56:40 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)el.c 8.2 (Berkeley) 1/3/94"; #else -__RCSID("$NetBSD: el.c,v 1.44 2006/12/15 22:13:33 christos Exp $"); +__RCSID("$NetBSD: el.c,v 1.59 2010/04/15 00:56:40 christos Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -49,6 +49,9 @@ __RCSID("$NetBSD: el.c,v 1.44 2006/12/15 22:13:33 christos Exp $"); #include <string.h> #include <stdlib.h> #include <stdarg.h> +#include <ctype.h> +#include <locale.h> +#include <langinfo.h> #include "el.h" /* el_init(): @@ -57,7 +60,6 @@ __RCSID("$NetBSD: el.c,v 1.44 2006/12/15 22:13:33 christos Exp $"); public EditLine * el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr) { - EditLine *el = (EditLine *) el_malloc(sizeof(EditLine)); if (el == NULL) @@ -71,7 +73,8 @@ el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr) el->el_infd = fileno(fin); - if ((el->el_prog = el_strdup(prog)) == NULL) { + el->el_prog = Strdup(ct_decode_string(prog, &el->el_scratch)); + if (el->el_prog == NULL) { el_free(el); return NULL; } @@ -80,6 +83,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); @@ -125,6 +134,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 } @@ -144,7 +159,7 @@ 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 ap; int rv = 0; @@ -155,16 +170,28 @@ el_set(EditLine *el, int op, ...) switch (op) { case EL_PROMPT: - case EL_RPROMPT: - rv = prompt_set(el, va_arg(ap, 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(ap, char *)); break; case EL_EDITOR: - rv = map_set_editor(el, va_arg(ap, char *)); + rv = map_set_editor(el, va_arg(ap, Char *)); break; case EL_SIGNAL: @@ -177,40 +204,39 @@ el_set(EditLine *el, int op, ...) case EL_BIND: case EL_TELLTC: case EL_SETTC: - case EL_GETTC: 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(ap, 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; @@ -224,8 +250,8 @@ el_set(EditLine *el, int op, ...) case EL_ADDFN: { - char *name = va_arg(ap, char *); - char *help = va_arg(ap, char *); + 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); @@ -235,9 +261,11 @@ el_set(EditLine *el, int op, ...) case EL_HIST: { hist_fun_t func = va_arg(ap, hist_fun_t); - ptr_t ptr = va_arg(ap, char *); + 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; } @@ -253,6 +281,7 @@ el_set(EditLine *el, int op, ...) { el_rfunc_t rc = va_arg(ap, el_rfunc_t); rv = el_read_setfn(el, rc); + el->el_flags &= ~NARROW_READ; break; } @@ -308,6 +337,12 @@ el_set(EditLine *el, int op, ...) break; } + case EL_REFRESH: + re_clear_display(el); + re_refresh(el); + term__flush(el); + break; + default: rv = -1; break; @@ -322,7 +357,7 @@ el_set(EditLine *el, int op, ...) * retrieve the editline parameters */ public int -el_get(EditLine *el, int op, ...) +FUN(el,get)(EditLine *el, int op, ...) { va_list ap; int rv; @@ -334,12 +369,22 @@ el_get(EditLine *el, int op, ...) switch (op) { case EL_PROMPT: - case EL_RPROMPT: - rv = prompt_get(el, va_arg(ap, el_pfunc_t *), 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, va_arg(ap, const char **)); + rv = map_get_editor(el, va_arg(ap, const Char **)); break; case EL_SIGNAL: @@ -363,7 +408,7 @@ el_get(EditLine *el, int op, ...) char *argv[20]; int i; - for (i = 1; i < sizeof(argv) / sizeof(argv[0]); i++) + for (i = 1; i < (int)(sizeof(argv) / sizeof(argv[0])); i++) if ((argv[i] = va_arg(ap, char *)) == NULL) break; @@ -381,26 +426,6 @@ el_get(EditLine *el, int op, ...) break; } -#if 0 /* XXX */ - case EL_ADDFN: - { - 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; - } - - case EL_HIST: - { - hist_fun_t func = va_arg(ap, hist_fun_t); - ptr_t ptr = va_arg(ap, char *); - rv = hist_set(el, func, ptr); - } - break; -#endif /* XXX */ - case EL_GETCFN: *va_arg(ap, el_rfunc_t *) = el_read_getfn(el); rv = 0; @@ -453,11 +478,11 @@ el_get(EditLine *el, int op, ...) /* 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; } @@ -470,12 +495,15 @@ el_source(EditLine *el, const char *fname) FILE *fp; size_t len; char *ptr; +#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); @@ -501,10 +529,18 @@ el_source(EditLine *el, const char *fname) return (-1); while ((ptr = fgetln(fp, &len)) != NULL) { - if (len > 0 && ptr[len - 1] == '\n') + dptr = ct_decode_string(ptr, &el->el_scratch); + if (!dptr) + continue; + if (len > 0 && dptr[len - 1] == '\n') --len; - ptr[len] = '\0'; - if (parse_line(el, ptr) == -1) { + + /* 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) { (void) fclose(fp); return (-1); } @@ -552,23 +588,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; tty_rawmode(el); - } else if (strcmp(how, "off") == 0) { + } 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); @@ -1,4 +1,4 @@ -/* $NetBSD: el.h,v 1.17 2006/12/15 22:13:33 christos Exp $ */ +/* $NetBSD: el.h,v 1.21 2009/12/31 15:58:26 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -46,6 +46,8 @@ #define VIDEFAULT #define ANCHOR +#include "histedit.h" +#include "chartype.h" #include <stdio.h> #include <sys/types.h> @@ -55,6 +57,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 */ @@ -66,10 +72,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; /* @@ -82,13 +88,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) @@ -109,15 +114,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 +139,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/eln.c b/eln.c new file mode 100644 index 000000000000..072a034b7a7b --- /dev/null +++ b/eln.c @@ -0,0 +1,365 @@ +/* $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" +#if !defined(lint) && !defined(SCCSID) +__RCSID("$NetBSD: eln.c,v 1.7 2010/04/15 00:52:48 christos Exp $"); +#endif /* not lint && not SCCSID */ + +#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)); +} @@ -1,4 +1,4 @@ -/* $NetBSD: emacs.c,v 1.21 2006/03/06 21:11:56 christos Exp $ */ +/* $NetBSD: emacs.c,v 1.23 2009/12/30 22:37:40 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)emacs.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: emacs.c,v 1.21 2006/03/06 21:11:56 christos Exp $"); +__RCSID("$NetBSD: emacs.c,v 1.23 2009/12/30 22:37:40 christos Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -52,7 +52,7 @@ __RCSID("$NetBSD: emacs.c,v 1.21 2006/03/06 21:11:56 christos Exp $"); */ protected el_action_t /*ARGSUSED*/ -em_delete_or_list(EditLine *el, int c) +em_delete_or_list(EditLine *el, Int c) { if (el->el_line.cursor == el->el_line.lastchar) { @@ -88,9 +88,9 @@ em_delete_or_list(EditLine *el, int c) */ 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); @@ -103,7 +103,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 */ @@ -117,9 +117,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); @@ -133,7 +133,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; @@ -152,9 +153,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; @@ -174,9 +175,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); @@ -187,14 +188,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); @@ -207,9 +208,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); @@ -236,7 +237,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]) { @@ -256,7 +257,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); @@ -281,16 +282,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((unsigned char)*cp); + if (Islower(*cp)) + *cp = Toupper(*cp); el->el_line.cursor = ep; if (el->el_line.cursor > el->el_line.lastchar) @@ -305,24 +306,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((unsigned char)*cp); + if (Isalpha(*cp)) { + if (Islower(*cp)) + *cp = Toupper(*cp); cp++; break; } } for (; cp < ep; cp++) - if (isupper((unsigned char)*cp)) - *cp = tolower((unsigned char)*cp); + if (Isupper(*cp)) + *cp = Tolower(*cp); el->el_line.cursor = ep; if (el->el_line.cursor > el->el_line.lastchar) @@ -337,16 +338,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((unsigned char)*cp); + if (Isupper(*cp)) + *cp = Tolower(*cp); el->el_line.cursor = ep; if (el->el_line.cursor > el->el_line.lastchar) @@ -361,7 +362,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; @@ -375,9 +376,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; @@ -392,7 +393,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) @@ -409,7 +410,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; @@ -422,7 +423,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) ? @@ -436,9 +437,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); @@ -448,7 +449,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; @@ -463,7 +464,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; @@ -476,7 +477,7 @@ 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; @@ -490,7 +491,7 @@ em_inc_search_prev(EditLine *el, int c __attribute__((__unused__))) */ protected el_action_t /*ARGSUSED*/ -em_delete_prev_char(EditLine *el, int c __attribute__((__unused__))) +em_delete_prev_char(EditLine *el, Int c __attribute__((__unused__))) { if (el->el_line.cursor <= el->el_line.buffer) diff --git a/filecomplete.c b/filecomplete.c index 78982c37ee4e..c97b9f206c07 100644 --- a/filecomplete.c +++ b/filecomplete.c @@ -1,4 +1,4 @@ -/* $NetBSD: filecomplete.c,v 1.10 2006/11/09 16:58:38 christos Exp $ */ +/* $NetBSD: filecomplete.c,v 1.19 2010/06/01 18:20:26 christos Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -15,9 +15,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of The 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 @@ -34,7 +31,7 @@ #include "config.h" #if !defined(lint) && !defined(SCCSID) -__RCSID("$NetBSD: filecomplete.c,v 1.10 2006/11/09 16:58:38 christos Exp $"); +__RCSID("$NetBSD: filecomplete.c,v 1.19 2010/06/01 18:20:26 christos Exp $"); #endif /* not lint && not SCCSID */ #include <sys/types.h> @@ -62,8 +59,8 @@ __RCSID("$NetBSD: filecomplete.c,v 1.10 2006/11/09 16:58:38 christos Exp $"); #include "histedit.h" #include "filecomplete.h" -static char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', '$', - '>', '<', '=', ';', '|', '&', '{', '(', '\0' }; +static Char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', + '$', '>', '<', '=', ';', '|', '&', '{', '(', '\0' }; /********************************/ @@ -149,20 +146,24 @@ fn_filename_completion_function(const char *text, int state) nptr = realloc(filename, strlen(temp) + 1); if (nptr == NULL) { free(filename); + filename = NULL; return NULL; } filename = nptr; (void)strcpy(filename, temp); len = temp - text; /* including last slash */ + nptr = realloc(dirname, len + 1); if (nptr == NULL) { - free(filename); + free(dirname); + dirname = NULL; return NULL; } dirname = nptr; (void)strncpy(dirname, text, len); dirname[len] = '\0'; } else { + free(filename); if (*text == 0) filename = NULL; else { @@ -170,6 +171,7 @@ fn_filename_completion_function(const char *text, int state) if (filename == NULL) return NULL; } + free(dirname); dirname = NULL; } @@ -179,12 +181,14 @@ fn_filename_completion_function(const char *text, int state) } /* support for ``~user'' syntax */ - free(dirpath); - if (dirname == NULL && (dirname = strdup("./")) == NULL) - return NULL; - - if (*dirname == '~') + free(dirpath); + dirpath = NULL; + if (dirname == NULL) { + if ((dirname = strdup("")) == NULL) + return NULL; + dirpath = strdup("./"); + } else if (*dirname == '~') dirpath = fn_tilde_expand(dirname); else dirpath = strdup(dirname); @@ -211,10 +215,10 @@ fn_filename_completion_function(const char *text, int state) /* 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 +#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) @@ -223,10 +227,10 @@ fn_filename_completion_function(const char *text, int state) if (entry) { /* match found */ -#if defined(__SVR4) || defined(__linux__) - len = strlen(entry->d_name); -#else +#if HAVE_STRUCT_DIRENT_D_NAMLEN len = entry->d_namlen; +#else + len = strlen(entry->d_name); #endif temp = malloc(strlen(dirname) + len + 1); @@ -248,7 +252,7 @@ append_char_function(const char *name) { struct stat stbuf; char *expname = *name == '~' ? fn_tilde_expand(name) : NULL; - const char *rs = ""; + const char *rs = " "; if (stat(expname ? expname : name, &stbuf) == -1) goto out; @@ -338,9 +342,9 @@ _fn_qsort_string_compare(const void *i1, const void *i2) * 'max' is maximum length of string in 'matches'. */ void -fn_display_match_list (EditLine *el, char **matches, int len, int max) +fn_display_match_list (EditLine *el, char **matches, size_t len, size_t max) { - int i, idx, limit, count; + size_t i, idx, limit, count; int screenwidth = el->el_term.t_size.h; /* @@ -362,9 +366,12 @@ fn_display_match_list (EditLine *el, char **matches, int len, int max) idx = 1; for(; count > 0; count--) { - for(i = 0; i < limit && matches[idx]; i++, idx++) - (void)fprintf(el->el_outfile, "%-*s ", max, - matches[idx]); + 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"); } } @@ -385,13 +392,14 @@ 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 *), int query_items, + 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 LineInfo *li; - char *temp, **matches; - const char *ctemp; + const TYPE(LineInfo) *li; + Char *temp; + char **matches; + const Char *ctemp; size_t len; int what_to_do = '\t'; int retval = CC_NORM; @@ -409,45 +417,45 @@ fn_complete(EditLine *el, app_func = append_char_function; /* We now look backwards for the start of a filename/variable word */ - li = el_line(el); - ctemp = (const char *) li->cursor; + li = FUN(el,line)(el); + ctemp = li->cursor; while (ctemp > li->buffer - && !strchr(word_break, ctemp[-1]) - && (!special_prefixes || !strchr(special_prefixes, ctemp[-1]) ) ) + && !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(len + 1); + temp = malloc(sizeof(*temp) * (len + 1)); #else - temp = alloca(len + 1); + temp = alloca(sizeof(*temp) * (len + 1)); #endif - (void)strncpy(temp, ctemp, len); + (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 = li->cursor - li->buffer; + *point = (int)(li->cursor - li->buffer); if (end != NULL) - *end = li->lastchar - li->buffer; + *end = (int)(li->lastchar - li->buffer); if (attempted_completion_function) { - int cur_off = li->cursor - li->buffer; - matches = (*attempted_completion_function) (temp, + 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(temp, complet_func); + matches = completion_matches(ct_encode_string(temp, &el->el_scratch), complet_func); if (over != NULL) *over = 0; if (matches) { int i; - int matches_num, maxlen, match_len, match_display=1; + size_t matches_num, maxlen, match_len, match_display=1; retval = CC_REFRESH; /* @@ -456,7 +464,8 @@ fn_complete(EditLine *el, */ if (matches[0][0] != '\0') { el_deletestr(el, (int) len); - el_insertstr(el, matches[0]); + FUN(el,insertstr)(el, + ct_decode_string(matches[0], &el->el_scratch)); } if (what_to_do == '?') @@ -468,7 +477,9 @@ fn_complete(EditLine *el, * it, unless we do filename completion and the * object is a directory. */ - el_insertstr(el, (*append_char_function)(matches[0])); + FUN(el,insertstr)(el, + ct_decode_string((*app_func)(matches[0]), + &el->el_scratch)); } else if (what_to_do == '!') { display_matches: /* @@ -476,7 +487,7 @@ fn_complete(EditLine *el, * matches. */ - for(i=1, maxlen=0; matches[i]; i++) { + for(i = 1, maxlen = 0; matches[i]; i++) { match_len = strlen(matches[i]); if (match_len > maxlen) maxlen = match_len; @@ -492,7 +503,7 @@ fn_complete(EditLine *el, */ if (matches_num > query_items) { (void)fprintf(el->el_outfile, - "Display all %d possibilities? (y or n) ", + "Display all %zu possibilities? (y or n) ", matches_num); (void)fflush(el->el_outfile); if (getc(stdin) != 'y') @@ -502,7 +513,7 @@ fn_complete(EditLine *el, if (match_display) fn_display_match_list(el, matches, matches_num, - maxlen); + maxlen); retval = CC_REDISPLAY; } else if (matches[0][0]) { /* diff --git a/filecomplete.h b/filecomplete.h index f7253785c70a..971e6e059391 100644 --- a/filecomplete.h +++ b/filecomplete.h @@ -1,4 +1,4 @@ -/* $NetBSD: filecomplete.h,v 1.5 2006/08/21 12:45:30 christos Exp $ */ +/* $NetBSD: filecomplete.h,v 1.9 2009/12/30 22:37:40 christos Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -15,9 +15,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of The 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 @@ -37,10 +34,10 @@ int fn_complete(EditLine *, char *(*)(const char *, int), char **(*)(const char *, int, int), - const char *, const char *, const char *(*)(const char *), int, + const Char *, const Char *, const char *(*)(const char *), size_t, int *, int *, int *, int *); -void fn_display_match_list(EditLine *, char **, 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); @@ -1,4 +1,4 @@ -/* $NetBSD: hist.c,v 1.15 2003/11/01 23:36:39 christos Exp $ */ +/* $NetBSD: hist.c,v 1.17 2009/12/30 23:54:52 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)hist.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: hist.c,v 1.15 2003/11/01 23:36:39 christos Exp $"); +__RCSID("$NetBSD: hist.c,v 1.17 2009/12/30 23:54:52 christos Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -56,7 +56,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); @@ -97,11 +97,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); @@ -128,9 +128,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') @@ -153,33 +154,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; @@ -193,13 +194,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); @@ -208,3 +209,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 @@ -1,4 +1,4 @@ -/* $NetBSD: hist.h,v 1.10 2003/08/07 16:44:31 agc Exp $ */ +/* $NetBSD: hist.h,v 1.12 2009/12/30 23:54:52 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -42,21 +42,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) @@ -70,7 +78,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/histedit.h b/histedit.h index bb54567c5713..5a0bb69db242 100644 --- a/histedit.h +++ b/histedit.h @@ -1,4 +1,4 @@ -/* $NetBSD: histedit.h,v 1.31 2006/12/15 22:13:33 christos Exp $ */ +/* $NetBSD: histedit.h,v 1.46 2010/04/15 00:50:03 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -41,7 +41,9 @@ #define _HISTEDIT_H_ #define LIBEDIT_MAJOR 2 -#define LIBEDIT_MINOR 10 +#define LIBEDIT_MINOR 11 + +#include <stdint.h> #include <sys/types.h> #include <stdio.h> @@ -92,7 +94,7 @@ void el_reset(EditLine *); */ const char *el_gets(EditLine *, int *); int el_getc(EditLine *, char *); -void el_push(EditLine *, char *); +void el_push(EditLine *, const char *); /* * Beep! @@ -114,30 +116,47 @@ 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_GETTC 17 /* , const char *, ..., NULL); */ -#define EL_GETFP 18 /* , int, FILE **) */ -#define EL_SETFP 19 /* , int, FILE *) */ - -#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 @@ -187,12 +206,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 *); */ @@ -201,6 +220,10 @@ int history(History *, HistEvent *, int, ...); #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); */ + /* @@ -220,6 +243,74 @@ int tok_line(Tokenizer *, const LineInfo *, 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 diff --git a/history.c b/history.c index 3ab53df3d0d2..aa593b2db2f6 100644 --- a/history.c +++ b/history.c @@ -1,4 +1,4 @@ -/* $NetBSD: history.c,v 1.32 2006/09/28 13:52:51 christos Exp $ */ +/* $NetBSD: history.c,v 1.37 2010/01/03 18:27:10 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,12 +37,12 @@ #if 0 static char sccsid[] = "@(#)history.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: history.c,v 1.32 2006/09/28 13:52:51 christos Exp $"); +__RCSID("$NetBSD: history.c,v 1.37 2010/01/03 18:27:10 christos Exp $"); #endif #endif /* not lint && not SCCSID */ /* - * hist.c: History access functions + * hist.c: TYPE(History) access functions */ #include <string.h> #include <stdlib.h> @@ -57,13 +57,14 @@ __RCSID("$NetBSD: history.c,v 1.32 2006/09/28 13:52:51 christos Exp $"); 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 */ @@ -89,29 +90,29 @@ struct history { #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 *); /***********************************************************************/ @@ -120,7 +121,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; @@ -131,24 +133,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_next(ptr_t, HistEvent *); -private int history_def_first(ptr_t, HistEvent *); -private int history_def_prev(ptr_t, HistEvent *); -private int history_def_last(ptr_t, HistEvent *); -private int history_def_curr(ptr_t, HistEvent *); -private int history_def_set(ptr_t, HistEvent *, const int); -private void history_def_clear(ptr_t, HistEvent *); -private int history_def_enter(ptr_t, HistEvent *, const char *); -private int history_def_add(ptr_t, HistEvent *, const char *); -private int history_def_del(ptr_t, HistEvent *, const int); - -private int history_def_init(ptr_t *, HistEvent *, int); -private int history_def_insert(history_t *, HistEvent *, const char *); -private void history_def_delete(history_t *, HistEvent *, hentry_t *); +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) @@ -166,23 +171,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 @@ -206,7 +211,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; @@ -226,7 +231,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; @@ -246,7 +251,7 @@ 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; @@ -271,7 +276,7 @@ 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; @@ -297,7 +302,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; @@ -318,7 +323,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; @@ -340,27 +345,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; @@ -368,18 +399,36 @@ 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, HistEvent *ev __attribute__((__unused__)), +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->str = Strdup(h->cursor->ev.str); ev->num = h->cursor->ev.num; history_def_delete(h, ev, h->cursor); return (0); @@ -392,13 +441,16 @@ history_def_del(ptr_t p, HistEvent *ev __attribute__((__unused__)), /* 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) + 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); @@ -411,7 +463,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)); @@ -421,6 +473,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; @@ -440,12 +493,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) @@ -467,7 +520,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) @@ -492,7 +545,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; @@ -510,11 +563,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; @@ -542,9 +595,9 @@ 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); @@ -558,7 +611,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) { @@ -578,7 +631,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); @@ -597,7 +650,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) { @@ -613,7 +666,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); @@ -628,9 +681,9 @@ 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 || @@ -671,17 +724,20 @@ history_set_fun(History *h, History *nh) /* 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; size_t sz, max_size; char *ptr; int i = -1; - HistEvent ev; + TYPE(HistEvent) ev; +#ifdef WIDECHAR + static ct_buffer_t conv; +#endif if ((fp = fopen(fname, "r")) == NULL) return (i); @@ -715,9 +771,9 @@ history_load(History *h, const char *fname) } (void) strunvis(ptr, line); line[sz] = c; - 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: @@ -729,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); @@ -753,7 +812,7 @@ 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; + len = Strlen(ev.str) * 4; if (len >= max_size) { char *nptr; max_size = (len + 1024) & ~1023; @@ -764,7 +823,7 @@ history_save(History *h, const char *fname) } ptr = nptr; } - (void) strvis(ptr, ev.str, VIS_WHITE); + (void) strvis(ptr, ct_encode_string(ev.str, &conv), VIS_WHITE); (void) fprintf(fp, "%s\n", ptr); } oomem: @@ -779,7 +838,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; @@ -792,11 +851,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; @@ -813,13 +889,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); @@ -831,13 +907,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); @@ -849,10 +925,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); @@ -877,7 +953,7 @@ 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; @@ -886,13 +962,13 @@ history(History *h, HistEvent *ev, int fun, ...) 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; @@ -947,16 +1023,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; @@ -977,15 +1053,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; } @@ -1,4 +1,4 @@ -/* $NetBSD: key.c,v 1.19 2006/03/23 20:22:51 christos Exp $ */ +/* $NetBSD: key.c,v 1.23 2009/12/30 22:37:40 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)key.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: key.c,v 1.19 2006/03/23 20:22:51 christos Exp $"); +__RCSID("$NetBSD: key.c,v 1.23 2009/12/30 22:37:40 christos Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -72,7 +72,7 @@ __RCSID("$NetBSD: key.c,v 1.19 2006/03/23 20:22:51 christos Exp $"); * 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 */ @@ -80,17 +80,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 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 @@ -102,7 +102,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; @@ -139,7 +139,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; @@ -171,7 +171,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)); @@ -185,7 +185,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') { @@ -213,9 +213,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) || @@ -230,7 +233,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') { @@ -251,7 +254,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 */ @@ -261,7 +264,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; } @@ -272,14 +275,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 */ @@ -309,7 +312,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) { @@ -350,7 +353,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: @@ -371,7 +374,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; @@ -451,7 +454,7 @@ node__put(EditLine *el, key_node_t *ptr) * 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; @@ -481,14 +484,14 @@ node__free(key_node_t *k) * 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); @@ -496,17 +499,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, KEY_BUFSIZ, 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); @@ -530,16 +535,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) { @@ -550,15 +555,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, KEY_BUFSIZ, 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) @@ -572,7 +576,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]; @@ -585,13 +589,16 @@ key_kprint(EditLine *el, const char *key, key_value_t *val, int ntype) (void) key__decode_str(val->str, unparsbuf, sizeof(unparsbuf), ntype == XK_STR ? "\"\"" : "[]"); - (void) fprintf(el->el_outfile, fmt, key, unparsbuf); + (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 @@ -606,7 +613,8 @@ key_kprint(EditLine *el, const char *key, key_value_t *val, int ntype) break; } else - (void) fprintf(el->el_outfile, fmt, key, "no input"); + (void) fprintf(el->el_outfile, fmt, ct_encode_string(key, + &el->el_scratch), "no input"); } @@ -615,52 +623,14 @@ key_kprint(EditLine *el, const char *key, key_value_t *val, int ntype) *b++ = c; \ else \ b++ -/* key__decode_char(): - * Put a printable form of char in buf. - */ -protected int -key__decode_char(char *buf, int cnt, int off, int ch) -{ - char *sb = buf + off; - char *eb = buf + cnt; - char *b = sb; - if (ch == 0) { - ADDC('^'); - ADDC('@'); - return b - sb; - } - if (iscntrl(ch)) { - ADDC('^'); - if (ch == '\177') - ADDC('?'); - else - ADDC(ch | 0100); - } else if (ch == '^') { - ADDC('\\'); - ADDC('^'); - } else if (ch == '\\') { - ADDC('\\'); - ADDC('\\'); - } else if (ch == ' ' || (isprint(ch) && !isspace(ch))) { - ADDC(ch); - } else { - ADDC('\\'); - ADDC((((unsigned int) ch >> 6) & 7) + '0'); - ADDC((((unsigned int) ch >> 3) & 7) + '0'); - ADDC((ch & 7) + '0'); - } - return b - sb; -} - - /* key__decode_str(): * Make a printable version of the ey */ -protected int -key__decode_str(const char *str, char *buf, int len, const char *sep) +protected size_t +key__decode_str(const Char *str, char *buf, size_t len, const char *sep) { char *b = buf, *eb = b + len; - const char *p; + const Char *p; b = buf; if (sep[0] != '\0') { @@ -669,38 +639,27 @@ key__decode_str(const char *str, char *buf, int len, const char *sep) if (*str == '\0') { ADDC('^'); ADDC('@'); - if (sep[0] != '\0' && sep[1] != '\0') { - ADDC(sep[1]); - } - goto done; + goto add_endsep; } for (p = str; *p != 0; p++) { - if (iscntrl((unsigned char) *p)) { - ADDC('^'); - if (*p == '\177') { - ADDC('?'); - } else { - ADDC(*p | 0100); - } - } else if (*p == '^' || *p == '\\') { - ADDC('\\'); - ADDC(*p); - } else if (*p == ' ' || (isprint((unsigned char) *p) && - !isspace((unsigned char) *p))) { - ADDC(*p); - } else { - ADDC('\\'); - ADDC((((unsigned int) *p >> 6) & 7) + '0'); - ADDC((((unsigned int) *p >> 3) & 7) + '0'); - ADDC((*p & 7) + '0'); + 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 += n; } } +add_endsep: if (sep[0] != '\0' && sep[1] != '\0') { ADDC(sep[1]); } -done: ADDC('\0'); - if (b - buf >= len) + if ((size_t)(b - buf) >= len) buf[len - 1] = '\0'; - return b - buf; + return (size_t)(b - buf); } + @@ -1,4 +1,4 @@ -/* $NetBSD: key.h,v 1.10 2006/03/23 20:22:51 christos Exp $ */ +/* $NetBSD: key.h,v 1.13 2009/12/30 22:37:40 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -42,13 +42,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; @@ -65,17 +65,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 int key__decode_str(const char *, char *, int, +protected size_t key__decode_str(const Char *, char *, size_t, const char *); -protected int key__decode_char(char *, int, int, int); #endif /* _h_el_key */ @@ -1,5 +1,5 @@ #!/bin/sh - -# $NetBSD: makelist,v 1.11 2005/10/22 16:45:03 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. @@ -36,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 @@ -53,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`" @@ -69,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 { @@ -83,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_"; @@ -104,16 +113,16 @@ 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; } } @@ -152,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"); }' @@ -164,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; @@ -1,4 +1,4 @@ -/* $NetBSD: map.c,v 1.24 2006/04/09 01:36:51 christos Exp $ */ +/* $NetBSD: map.c,v 1.25 2009/12/30 22:37:40 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)map.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: map.c,v 1.24 2006/04/09 01:36:51 christos Exp $"); +__RCSID("$NetBSD: map.c,v 1.25 2009/12/30 22:37:40 christos Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -47,10 +47,8 @@ __RCSID("$NetBSD: map.c,v 1.24 2006/04/09 01:36:51 christos Exp $"); #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 *); @@ -968,7 +966,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; } @@ -979,7 +977,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; @@ -997,7 +995,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]) { @@ -1051,7 +1049,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; @@ -1082,14 +1080,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); } @@ -1101,17 +1099,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); @@ -1122,7 +1120,7 @@ map_get_editor(EditLine *el, const char **editor) * Print the function description for 1 key */ private void -map_print_key(EditLine *el, el_action_t *map, const char *in) +map_print_key(EditLine *el, el_action_t *map, const Char *in) { char outbuf[EL_BUFSIZ]; el_bindings_t *bp, *ep; @@ -1133,7 +1131,7 @@ map_print_key(EditLine *el, el_action_t *map, const char *in) 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 @@ -1145,10 +1143,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, *ep; - char firstbuf[2], lastbuf[2]; + Char firstbuf[2], lastbuf[2]; char unparsbuf[EL_BUFSIZ], extrabuf[EL_BUFSIZ]; firstbuf[0] = first; @@ -1170,7 +1168,7 @@ map_print_some_keys(EditLine *el, el_action_t *map, int first, int last) if (first == last) { (void) key__decode_str(firstbuf, unparsbuf, sizeof(unparsbuf), STRQQ); - (void) fprintf(el->el_outfile, "%-15s-> %s\n", + (void) fprintf(el->el_outfile, "%-15s-> " FSTR "\n", unparsbuf, bp->name); } else { (void) key__decode_str(firstbuf, unparsbuf, @@ -1178,7 +1176,7 @@ map_print_some_keys(EditLine *el, el_action_t *map, int first, int last) (void) key__decode_str(lastbuf, extrabuf, sizeof(extrabuf), STRQQ); (void) fprintf(el->el_outfile, - "%-4s to %-7s-> %s\n", + "%-4s to %-7s-> " FSTR "\n", unparsbuf, extrabuf, bp->name); } return; @@ -1234,9 +1232,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("")); } @@ -1244,15 +1242,15 @@ 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; + 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; @@ -1298,12 +1296,12 @@ map_bind(EditLine *el, int argc, const char **argv) 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 @@ -1317,7 +1315,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); } @@ -1353,7 +1351,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) @@ -1366,7 +1364,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) @@ -1394,7 +1393,7 @@ 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 + 1; @@ -1,4 +1,4 @@ -/* $NetBSD: map.h,v 1.8 2003/08/07 16:44:32 agc Exp $ */ +/* $NetBSD: map.h,v 1.9 2009/12/30 22:37:40 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -41,9 +41,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; @@ -63,13 +63,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 */ @@ -1,4 +1,4 @@ -/* $NetBSD: parse.c,v 1.22 2005/05/29 04:58:15 lukem Exp $ */ +/* $NetBSD: parse.c,v 1.23 2009/12/30 22:37:40 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: parse.c,v 1.22 2005/05/29 04:58:15 lukem Exp $"); +__RCSID("$NetBSD: parse.c,v 1.23 2009/12/30 22:37:40 christos Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -58,17 +58,17 @@ __RCSID("$NetBSD: parse.c,v 1.22 2005/05/29 04:58:15 lukem Exp $"); #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 } }; @@ -76,16 +76,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_str(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); } @@ -94,25 +94,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); @@ -123,7 +123,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); } @@ -132,14 +132,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 **ptr) +parse__escape(const Char **ptr) { - const char *p; - int c; + const Char *p; + Int c; p = *ptr; @@ -173,6 +173,28 @@ parse__escape(const char **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': @@ -213,10 +235,10 @@ parse__escape(const char **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 (;;) @@ -252,12 +274,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); } @@ -1,4 +1,4 @@ -/* $NetBSD: parse.h,v 1.6 2005/05/29 04:58:15 lukem Exp $ */ +/* $NetBSD: parse.h,v 1.7 2009/12/30 22:37:40 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -40,9 +40,9 @@ #ifndef _h_el_parse #define _h_el_parse -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 *); +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 */ @@ -1,4 +1,4 @@ -/* $NetBSD: prompt.c,v 1.11 2003/08/07 16:44:32 agc Exp $ */ +/* $NetBSD: prompt.c,v 1.18 2009/12/31 15:58:26 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)prompt.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: prompt.c,v 1.11 2003/08/07 16:44:32 agc Exp $"); +__RCSID("$NetBSD: prompt.c,v 1.18 2009/12/31 15:58:26 christos Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -47,17 +47,17 @@ __RCSID("$NetBSD: prompt.c,v 1.11 2003/08/07 16:44:32 agc Exp $"); #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); } @@ -66,11 +66,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); } @@ -78,23 +78,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; @@ -111,10 +123,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; } @@ -132,24 +146,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; } @@ -157,14 +178,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; } @@ -1,4 +1,4 @@ -/* $NetBSD: prompt.h,v 1.6 2003/08/07 16:44:32 agc Exp $ */ +/* $NetBSD: prompt.h,v 1.10 2009/12/30 22:37:40 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -42,16 +42,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 *); @@ -1,4 +1,4 @@ -/* $NetBSD: read.c,v 1.39 2005/08/02 12:11:14 christos Exp $ */ +/* $NetBSD: read.c,v 1.55 2010/03/22 22:59:06 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)read.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: read.c,v 1.39 2005/08/02 12:11:14 christos Exp $"); +__RCSID("$NetBSD: read.c,v 1.55 2010/03/22 22:59:06 christos Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -49,14 +49,16 @@ __RCSID("$NetBSD: read.c,v 1.39 2005/08/02 12:11:14 christos Exp $"); #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 @@ -190,6 +192,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) { @@ -203,7 +208,7 @@ read_preread(EditLine *el) } } #endif /* FIONREAD */ - +#endif return (chrs > 0); } @@ -212,33 +217,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)) { @@ -252,7 +261,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)) { @@ -260,7 +274,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: @@ -280,57 +294,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); } @@ -344,6 +418,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 */ @@ -368,7 +446,7 @@ read_prepare(EditLine *el) re_refresh(el); /* print the prompt */ if (el->el_flags & UNBUFFERED) - term__flush(); + term__flush(el); } protected void @@ -380,23 +458,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); @@ -410,12 +493,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; } @@ -426,8 +513,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); } } @@ -438,16 +525,17 @@ el_gets(EditLine *el, int *nread) read_prepare(el); if (el->el_flags & EDIT_DISABLED) { - char *cp; + Char *cp; size_t idx; + if ((el->el_flags & UNBUFFERED) == 0) cp = el->el_line.buffer; else cp = el->el_line.lastchar; - term__flush(); + term__flush(el); - while ((*el->el_read.read_char)(el, cp) == 1) { + 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); @@ -455,8 +543,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) @@ -465,11 +551,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 @@ -485,7 +575,13 @@ el_gets(EditLine *el, int *nread) #endif /* DEBUG_READ */ break; } - if ((unsigned int)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); @@ -515,7 +611,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((unsigned char)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; @@ -567,7 +663,7 @@ el_gets(EditLine *el, int *nread) 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 */ @@ -588,7 +684,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; @@ -598,15 +694,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; } @@ -1,4 +1,4 @@ -/* $NetBSD: read.h,v 1.5 2006/08/21 12:45:30 christos Exp $ */ +/* $NetBSD: read.h,v 1.7 2009/12/30 22:37:40 christos Exp $ */ /*- * Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -15,9 +15,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of The 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 @@ -38,7 +35,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/readline.c b/readline.c index e4a3f07b95a6..a0a390cc61f1 100644 --- a/readline.c +++ b/readline.c @@ -1,4 +1,4 @@ -/* $NetBSD: readline.c,v 1.70 2006/11/24 00:01:17 christos Exp $ */ +/* $NetBSD: readline.c,v 1.89 2010/04/15 00:57:33 christos Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -15,9 +15,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of The 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 @@ -34,7 +31,7 @@ #include "config.h" #if !defined(lint) && !defined(SCCSID) -__RCSID("$NetBSD: readline.c,v 1.70 2006/11/24 00:01:17 christos Exp $"); +__RCSID("$NetBSD: readline.c,v 1.89 2010/04/15 00:57:33 christos Exp $"); #endif /* not lint && not SCCSID */ #include <sys/types.h> @@ -55,13 +52,10 @@ __RCSID("$NetBSD: readline.c,v 1.70 2006/11/24 00:01:17 christos Exp $"); #else #include "np/vis.h" #endif -#ifdef HAVE_ALLOCA_H -#include <alloca.h> -#endif +#include "readline/readline.h" #include "el.h" #include "fcns.h" /* for EL_NUM_FCNS */ #include "histedit.h" -#include "readline/readline.h" #include "filecomplete.h" void rl_prep_terminal(int); @@ -76,6 +70,7 @@ void rl_deprep_terminal(void); /* 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', '"', '\\', '\'', '`', '@', '$', @@ -111,7 +106,7 @@ 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; @@ -124,6 +119,11 @@ Function *rl_startup_hook = NULL; VFunction *rl_completion_display_matches_hook = 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. @@ -157,7 +157,7 @@ int rl_completion_append_character = ' '; /* stuff below is used internally by libedit for readline emulation */ -static History *h = NULL; +static TYPE(History) *h = NULL; static EditLine *e = NULL; static Function *map[256]; static jmp_buf topbuf; @@ -191,13 +191,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); @@ -213,25 +213,65 @@ _getc_function(EditLine *el, char *c) { int i; - i = (*rl_getc_function)(NULL, 0); + 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 editmode = 1; struct termios t; @@ -239,7 +279,7 @@ rl_initialize(void) if (e != NULL) el_end(e); if (h != NULL) - history_end(h); + FUN(history,end)(h); if (!rl_instream) rl_instream = stdin; @@ -255,13 +295,13 @@ 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); @@ -271,13 +311,12 @@ rl_initialize(void) 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 */ @@ -331,7 +370,7 @@ rl_initialize(void) char * readline(const char *p) { - HistEvent ev; + TYPE(HistEvent) ev; const char * volatile prompt = p; int count; const char *ret; @@ -346,14 +385,8 @@ readline(const char *p) (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); @@ -385,7 +418,7 @@ readline(const char *p) } else buf = NULL; - history(h, &ev, H_GETSIZE); + FUNW(history)(h, &ev, H_GETSIZE); history_length = ev.num; return buf; @@ -451,7 +484,7 @@ _rl_compat_sub(const char *str, const char *what, const char *with, } else *r++ = *s++; } - *r = 0; + *r = '\0'; return(result); } @@ -465,18 +498,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] == '-') { @@ -531,7 +564,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); @@ -550,7 +583,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); @@ -566,13 +599,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; } @@ -637,9 +670,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); } @@ -694,7 +729,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); } @@ -704,7 +739,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); @@ -713,7 +748,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); @@ -966,52 +1001,52 @@ 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++; 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)strcpy(result + len, arr[i]); 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; } /* @@ -1080,12 +1115,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; } @@ -1096,10 +1131,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 */ @@ -1114,6 +1149,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; + strcpy(template, _history_tmp_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 @@ -1121,11 +1292,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) == -1); + if (filename == NULL && (filename = _default_history_file()) == NULL) + return errno; + return (FUNW(history)(h, &ev, H_LOAD, filename) == -1 ? + (errno ? errno : EINVAL) : 0); } @@ -1135,11 +1309,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) == -1); + if (filename == NULL && (filename = _default_history_file()) == NULL) + return errno; + return (FUNW(history)(h, &ev, H_SAVE, filename) == -1 ? + (errno ? errno : EINVAL) : 0); } @@ -1152,30 +1329,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); } @@ -1187,13 +1363,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 */ @@ -1206,31 +1385,84 @@ add_history(const char *line) HIST_ENTRY * remove_history(int num) { - static HIST_ENTRY she; - HistEvent ev; + HIST_ENTRY *he; + TYPE(HistEvent) ev; if (h == NULL || e == NULL) rl_initialize(); - if (history(h, &ev, H_DEL, num) != 0) + if ((he = malloc(sizeof(*he))) == NULL) return NULL; - she.line = ev.str; - she.data = NULL; + if (FUNW(history)(h, &ev, H_DELDATA, num, &he->data) != 0) { + free(he); + return NULL; + } - return &she; + 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; } @@ -1240,16 +1472,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); @@ -1273,23 +1505,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); } @@ -1299,17 +1532,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); @@ -1344,21 +1581,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); } @@ -1369,9 +1608,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)); } @@ -1384,29 +1624,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); } @@ -1455,9 +1697,9 @@ username_completion_function(const char *text, int state) if (pwd == NULL) { endpwent(); - return (NULL); + return NULL; } - return (strdup(pwd->pw_name)); + return strdup(pwd->pw_name); } @@ -1481,7 +1723,7 @@ void rl_display_match_list(char **matches, int len, int max) { - fn_display_match_list(e, matches, len, max); + fn_display_match_list(e, matches, (size_t)len, (size_t)max); } static const char * @@ -1490,7 +1732,8 @@ _rl_completion_append_character_function(const char *dummy __attribute__((__unused__))) { static char buf[2]; - buf[1] = rl_completion_append_character; + buf[0] = rl_completion_append_character; + buf[1] = '\0'; return buf; } @@ -1502,6 +1745,10 @@ _rl_completion_append_character_function(const char *dummy int 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(); @@ -1517,8 +1764,10 @@ rl_complete(int ignore __attribute__((__unused__)), int invoking_key) return fn_complete(e, (CPFunction *)rl_completion_entry_function, rl_attempted_completion_function, - rl_basic_word_break_characters, rl_special_prefixes, - _rl_completion_append_character_function, rl_completion_query_items, + 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); } @@ -1539,7 +1788,7 @@ _el_rl_complete(EditLine *el __attribute__((__unused__)), int ch) * 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; @@ -1606,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) @@ -1638,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); @@ -1669,19 +1932,17 @@ rl_callback_read_char() } else wbuf = NULL; (*(void (*)(const char *))rl_linefunc)(wbuf); - el_set(e, EL_UNBUFFERED, 1); + //el_set(e, EL_UNBUFFERED, 1); } } void -rl_callback_handler_install (const char *prompt, VCPFunction *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); } @@ -1690,6 +1951,7 @@ void rl_callback_handler_remove(void) { el_set(e, EL_UNBUFFERED, 0); + rl_linefunc = NULL; } void @@ -1768,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)(); @@ -1804,7 +2067,7 @@ _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 @@ -1812,8 +2075,8 @@ _rl_update_pos(void) { const LineInfo *li = el_line(e); - rl_point = li->cursor - li->buffer; - rl_end = li->lastchar - li->buffer; + rl_point = (int)(li->cursor - li->buffer); + rl_end = (int)(li->lastchar - li->buffer); } void @@ -1835,12 +2098,73 @@ rl_set_screen_size(int rows, int 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) { @@ -1855,6 +2179,17 @@ _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) @@ -1889,8 +2224,13 @@ rl_generic_bind(int type, const char * keyseq, const char * data, Keymap k) int /*ARGSUSED*/ -rl_bind_key_in_map(int key, Function *fun, Keymap k) +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/readline/readline.h b/readline/readline.h index 97e81cdc3673..c4a5aa10be0a 100644 --- a/readline/readline.h +++ b/readline/readline.h @@ -1,4 +1,4 @@ -/* $NetBSD: readline.h,v 1.19 2006/11/24 00:01:17 christos Exp $ */ +/* $NetBSD: readline.h,v 1.30 2009/09/07 21:24:34 christos Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -15,9 +15,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of The 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 @@ -35,6 +32,7 @@ #define _READLINE_H_ #include <sys/types.h> +#include <stdio.h> /* list of readline stuff supported by editline library's readline wrapper */ @@ -44,10 +42,19 @@ 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 { @@ -68,7 +75,7 @@ typedef KEYMAP_ENTRY *Keymap; #ifndef CTRL #include <sys/ioctl.h> -#if !defined(__sun__) && !defined(__hpux__) +#if !defined(__sun) && !defined(__hpux) && !defined(_AIX) #include <sys/ttydefaults.h> #endif #ifndef CTRL @@ -81,12 +88,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; @@ -118,7 +129,7 @@ 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; @@ -140,6 +151,8 @@ 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); @@ -149,6 +162,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); @@ -163,8 +177,9 @@ 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 *, VCPFunction *); @@ -178,11 +193,15 @@ 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 @@ -192,7 +211,9 @@ 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/refresh.c b/refresh.c index 3057ca6c15f3..7c128df0fba8 100644 --- a/refresh.c +++ b/refresh.c @@ -1,4 +1,4 @@ -/* $NetBSD: refresh.c,v 1.27 2005/11/09 22:11:10 christos Exp $ */ +/* $NetBSD: refresh.c,v 1.35 2009/12/30 22:37:40 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)refresh.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: refresh.c,v 1.27 2005/11/09 22:11:10 christos Exp $"); +__RCSID("$NetBSD: refresh.c,v 1.35 2009/12/30 22:37:40 christos Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -51,14 +51,15 @@ __RCSID("$NetBSD: refresh.c,v 1.27 2005/11/09 22:11:10 christos Exp $"); #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_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); +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 *); @@ -88,45 +89,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; + } } } @@ -135,43 +161,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)); + + while (shift && (el->el_refresh.r_cursor.h + w > el->el_term.t_size.h)) + re_putc(el, ' ', 1); - ELRE_DEBUG(1, (__F, "printing %3.3o '%c'\r\n", c, c)); + el->el_vdisplay[el->el_refresh.r_cursor.v] + [el->el_refresh.r_cursor.h] = c; + /* 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); } } @@ -186,7 +200,7 @@ protected void re_refresh(EditLine *el) { int i, rhdiff; - char *cp, *st; + Char *cp, *st; coord_t cur; #ifdef notyet size_t termsz; @@ -238,11 +252,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 */ @@ -273,7 +294,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++) { @@ -298,9 +319,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'; } @@ -323,9 +345,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); } @@ -336,9 +358,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; @@ -347,8 +369,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) { @@ -358,19 +380,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)); +#endif } @@ -380,9 +407,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; @@ -392,7 +419,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) { @@ -404,7 +431,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))); } @@ -412,7 +439,7 @@ 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) @@ -423,7 +450,7 @@ re__strncopy(char *a, char *b, size_t n) * 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 - * int the first or second diff, diff is the difference between the + * in the first or second diff, diff is the difference between the * number of characters between the new and old line. */ private void @@ -471,12 +498,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 @@ -603,12 +631,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) { @@ -657,8 +685,8 @@ 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, "fx %d, sx %d\n", fx, sx)); ELRE_DEBUG(1, (__F, "ofd %d, osb %d, ose %d, ols %d, oe %d\n", @@ -741,7 +769,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 */ @@ -754,20 +782,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 */ @@ -779,7 +808,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 */ @@ -793,14 +822,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, @@ -808,8 +838,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)); - re_clear_eol(el, fx, sx, (oe - old) - (ne - new)); + term_overwrite(el, nfd, (size_t)(nsb - nfd)); + re_clear_eol(el, fx, sx, + (int)((oe - old) - (ne - new))); /* * Done */ @@ -828,7 +859,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 */ @@ -845,12 +876,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)); - re_clear_eol(el, fx, sx, (oe - old) - (ne - new)); + term_overwrite(el, nse, (size_t)(nls - nse)); + re_clear_eol(el, fx, sx, + (int)((oe - old) - (ne - new))); } } /* @@ -860,7 +892,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 */ @@ -871,7 +903,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 @@ -879,20 +911,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); } } /* @@ -900,8 +933,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) { @@ -914,10 +947,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 @@ -934,7 +968,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; @@ -957,8 +991,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 @@ -975,43 +1009,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); } @@ -1019,11 +1052,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; @@ -1036,25 +1076,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'); } } } @@ -1067,7 +1107,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]; @@ -1082,19 +1122,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); } @@ -1123,17 +1168,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/refresh.h b/refresh.h index dd2bd02094ba..f80be4635456 100644 --- a/refresh.h +++ b/refresh.h @@ -1,4 +1,4 @@ -/* $NetBSD: refresh.h,v 1.5 2003/08/07 16:44:33 agc Exp $ */ +/* $NetBSD: refresh.h,v 1.6 2009/12/30 22:37:40 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -48,7 +48,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 *); @@ -1,4 +1,4 @@ -/* $NetBSD: search.c,v 1.20 2004/11/04 01:16:03 christos Exp $ */ +/* $NetBSD: search.c,v 1.24 2010/04/15 00:57:33 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)search.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: search.c,v 1.20 2004/11/04 01:16:03 christos Exp $"); +__RCSID("$NetBSD: search.c,v 1.24 2010/04/15 00:57:33 christos Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -66,7 +66,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; @@ -106,8 +107,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; @@ -119,30 +123,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 } @@ -151,7 +155,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", @@ -174,11 +178,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", @@ -199,21 +203,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); @@ -242,7 +247,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]) { @@ -318,7 +323,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 */ @@ -445,8 +450,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 @@ -458,7 +463,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; @@ -477,11 +482,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++] = '.'; @@ -495,7 +500,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 */ @@ -519,9 +524,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; @@ -559,12 +564,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 */ @@ -585,16 +590,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; } @@ -1,4 +1,4 @@ -/* $NetBSD: search.h,v 1.8 2003/10/18 23:27:36 christos Exp $ */ +/* $NetBSD: search.h,v 1.9 2009/12/30 22:37:40 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -43,24 +43,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/shlib_version b/shlib_version index bfa6b7053ffa..778486cf30d9 100644 --- a/shlib_version +++ b/shlib_version @@ -1,5 +1,5 @@ -# $NetBSD: shlib_version,v 1.16 2006/11/24 00:01:17 christos Exp $ +# $NetBSD: shlib_version,v 1.18 2009/01/11 03:07:48 christos Exp $ # Remember to update distrib/sets/lists/base/shl.* when changing # -major=2 -minor=10 +major=3 +minor=0 @@ -1,4 +1,4 @@ -/* $NetBSD: sig.c,v 1.11 2003/08/07 16:44:33 agc Exp $ */ +/* $NetBSD: sig.c,v 1.15 2009/02/19 15:20:22 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)sig.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: sig.c,v 1.11 2003/08/07 16:44:33 agc Exp $"); +__RCSID("$NetBSD: sig.c,v 1.15 2009/02/19 15:20:22 christos Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -75,12 +75,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: @@ -96,7 +98,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); } @@ -108,26 +113,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; } @@ -149,20 +157,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); @@ -175,20 +184,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); } @@ -1,4 +1,4 @@ -/* $NetBSD: sig.h,v 1.5 2003/08/07 16:44:33 agc Exp $ */ +/* $NetBSD: sig.h,v 1.8 2009/02/19 15:20:22 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -51,15 +51,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*); @@ -1,4 +1,4 @@ -/* $NetBSD: sys.h,v 1.9 2004/01/17 17:57:40 christos Exp $ */ +/* $NetBSD: sys.h,v 1.13 2009/12/30 22:37:40 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -71,6 +71,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; @@ -101,6 +105,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 @@ -1,4 +1,4 @@ -/* $NetBSD: term.c,v 1.46 2006/11/24 00:01:17 christos Exp $ */ +/* $NetBSD: term.c,v 1.57 2009/12/30 22:37:40 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)term.c 8.2 (Berkeley) 4/30/95"; #else -__RCSID("$NetBSD: term.c,v 1.46 2006/11/24 00:01:17 christos Exp $"); +__RCSID("$NetBSD: term.c,v 1.57 2009/12/30 22:37:40 christos Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -51,27 +51,32 @@ __RCSID("$NetBSD: term.c,v 1.46 2006/11/24 00:01:17 christos Exp $"); #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... */ @@ -271,9 +276,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(): @@ -321,7 +330,6 @@ term_setflags(EditLine *el) #endif /* DEBUG_SCREEN */ } - /* term_init(): * Initialize the terminal stuff */ @@ -347,7 +355,6 @@ term_init(EditLine *el) if (el->el_term.t_val == NULL) return (-1); (void) memset(el->el_term.t_val, 0, T_val * sizeof(int)); - term_outfile = el->el_outfile; (void) term_set(el, NULL); term_init_arrow(el); return (0); @@ -382,7 +389,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]; @@ -409,7 +416,7 @@ term_alloc(EditLine *el, const struct termcapstr *t, const char *cap) /* XXX strcpy is safe */ (void) strcpy(*str = &el->el_term.t_buf[el->el_term.t_loc], cap); - el->el_term.t_loc += clen + 1; /* one for \0 */ + el->el_term.t_loc += (int)clen + 1; /* one for \0 */ return; } /* @@ -426,7 +433,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"); @@ -434,7 +441,7 @@ term_alloc(EditLine *el, const struct termcapstr *t, const char *cap) } /* XXX strcpy is safe */ (void) strcpy(*str = &el->el_term.t_buf[el->el_term.t_loc], cap); - el->el_term.t_loc += clen + 1; /* one for \0 */ + el->el_term.t_loc += (int)clen + 1; /* one for \0 */ return; } @@ -465,14 +472,14 @@ private int term_alloc_display(EditLine *el) { int i; - char **b; + 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) return (-1); for (i = 0; i < c->v; i++) { - b[i] = (char *) el_malloc((size_t) (sizeof(char) * (c->h + 1))); + b[i] = el_malloc(sizeof(**b) * (c->h + 1)); if (b[i] == NULL) { while (--i >= 0) el_free((ptr_t) b[i]); @@ -483,11 +490,11 @@ term_alloc_display(EditLine *el) 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) return (-1); for (i = 0; i < c->v; i++) { - b[i] = (char *) el_malloc((size_t) (sizeof(char) * (c->h + 1))); + b[i] = el_malloc(sizeof(**b) * (c->h + 1)); if (b[i] == NULL) { while (--i >= 0) el_free((ptr_t) b[i]); @@ -507,21 +514,21 @@ term_alloc_display(EditLine *el) 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); } } @@ -550,21 +557,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; } @@ -572,12 +588,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 */ @@ -604,7 +619,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; } @@ -612,25 +627,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; } } /* @@ -641,15 +661,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" @@ -660,12 +680,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'); } } } @@ -675,24 +695,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 */ @@ -701,16 +724,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; } } @@ -740,28 +769,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; @@ -781,37 +810,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); @@ -827,10 +854,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 */ } } @@ -845,14 +872,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'); } } @@ -865,9 +892,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 */ } @@ -879,9 +906,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 @@ -1045,32 +1072,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; @@ -1084,18 +1111,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); @@ -1131,13 +1158,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); @@ -1150,13 +1177,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); } @@ -1168,13 +1195,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); @@ -1203,73 +1230,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) +term_writec(EditLine *el, Int c) { - char buf[8]; - int cnt = key__decode_char(buf, sizeof(buf), 0, c); - buf[cnt] = '\0'; - term_overwrite(el, buf, cnt); - term__flush(); + 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); } @@ -1279,11 +1344,10 @@ term_writec(EditLine *el, int c) 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"); @@ -1302,10 +1366,11 @@ term_telltc(EditLine *el, int argc __attribute__((__unused__)), for (t = tstr, ts = el->el_term.t_str; t->name != NULL; t++, ts++) { const char *ub; if (*ts && **ts) { - (void) key__decode_str(*ts, upbuf, sizeof(upbuf), ""); - ub = upbuf; + ub = ct_encode_string(ct_visual_string( + ct_decode_string(*ts, &el->el_scratch)), + &el->el_scratch); } else { - ub = "(empty)"; + ub = "(empty)"; } (void) fprintf(el->el_outfile, "\t%25s (%s) == %s\n", t->long_name, t->name, ub); @@ -1321,17 +1386,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; - 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 @@ -1363,7 +1430,7 @@ term_settc(EditLine *el, int argc __attribute__((__unused__)), el->el_term.t_val[tv - tval] = 0; else { (void) fprintf(el->el_errfile, - "%s: Bad value `%s'.\n", argv[0], how); + "" FSTR ": Bad value `%s'.\n", argv[0], how); return -1; } term_setflags(el); @@ -1377,7 +1444,7 @@ term_settc(EditLine *el, int argc __attribute__((__unused__)), i = strtol(how, &ep, 10); if (*ep != '\0') { (void) fprintf(el->el_errfile, - "%s: Bad value `%s'.\n", argv[0], how); + "" FSTR ": Bad value `%s'.\n", argv[0], how); return -1; } el->el_term.t_val[tv - tval] = (int) i; @@ -1452,9 +1519,10 @@ term_gettc(EditLine *el, int argc __attribute__((__unused__)), char **argv) 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; @@ -1485,21 +1553,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; @@ -1514,10 +1582,11 @@ term_echotc(EditLine *el, int argc __attribute__((__unused__)), (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); } @@ -1526,18 +1595,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) { /* XXX: some systems' tgetstr needs non const */ - scap = tgetstr(strchr(*argv, **argv), &area); + 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); } @@ -1580,11 +1650,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++; @@ -1595,11 +1665,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); } @@ -1608,11 +1678,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... */ @@ -1629,11 +1699,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); } @@ -1645,11 +1715,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); } @@ -1657,19 +1727,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); @@ -1,4 +1,4 @@ -/* $NetBSD: term.h,v 1.18 2006/11/24 00:01:17 christos Exp $ */ +/* $NetBSD: term.h,v 1.21 2009/12/30 22:37:40 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -43,7 +43,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 */ @@ -84,8 +84,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 *); @@ -93,19 +93,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_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(int); -protected void term__flush(void); +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 diff --git a/tokenizer.c b/tokenizer.c index b8a263332f8d..90af723d0156 100644 --- a/tokenizer.c +++ b/tokenizer.c @@ -1,4 +1,4 @@ -/* $NetBSD: tokenizer.c,v 1.14 2003/12/05 13:37:48 lukem Exp $ */ +/* $NetBSD: tokenizer.c,v 1.18 2010/01/03 18:27:10 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,55 +37,57 @@ #if 0 static char sccsid[] = "@(#)tokenizer.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: tokenizer.c,v 1.14 2003/12/05 13:37:48 lukem Exp $"); +__RCSID("$NetBSD: tokenizer.c,v 1.18 2010/01/03 18:27:10 christos Exp $"); #endif #endif /* not lint && not SCCSID */ +/* We build this file twice, once as NARROW, once as WIDE. */ /* * tokenize.c: Bourne shell like tokenizer */ #include <string.h> #include <stdlib.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'; @@ -98,13 +100,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; @@ -115,14 +117,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); @@ -139,11 +141,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; @@ -154,11 +156,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); @@ -169,10 +171,10 @@ tok_end(Tokenizer *tok) -/* tok_line(): +/* FUN(tok,line)(): * Bourne shell (sh(1)) like tokenizing * Arguments: - * tok current tokenizer state (setup with tok_init()) + * tok current tokenizer state (setup with FUN(tok,init)()) * line line to parse * Returns: * -1 Internal error @@ -187,20 +189,20 @@ tok_end(Tokenizer *tok) * cursorv if !NULL, offset in argv[cursorc] of cursor */ public int -tok_line(Tokenizer *tok, const LineInfo *line, - int *argc, const char ***argv, int *cursorc, int *cursoro) +FUN(tok,line)(TYPE(Tokenizer) *tok, const TYPE(LineInfo) *line, + int *argc, const Char ***argv, int *cursorc, int *cursoro) { - const char *ptr; + const Char *ptr; int cc, co; cc = co = -1; ptr = line->buffer; for (ptr = line->buffer; ;ptr++) { if (ptr >= line->lastchar) - ptr = ""; + ptr = STR(""); if (ptr == line->cursor) { cc = tok->argc; - co = tok->wptr - tok->wstart; + co = (int)(tok->wptr - tok->wstart); } switch (*ptr) { case '\'': @@ -358,8 +360,8 @@ tok_line(Tokenizer *tok, const LineInfo *line, 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; @@ -390,7 +392,8 @@ tok_line(Tokenizer *tok, const LineInfo *line, 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); @@ -407,10 +410,9 @@ tok_line(Tokenizer *tok, const LineInfo *line, 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; @@ -419,29 +421,30 @@ tok_line(Tokenizer *tok, const LineInfo *line, tok_line_outok: if (cc == -1 && co == -1) { cc = tok->argc; - co = tok->wptr - tok->wstart; + co = (int)(tok->wptr - tok->wstart); } if (cursorc != NULL) *cursorc = cc; if (cursoro != NULL) *cursoro = co; - tok_finish(tok); - *argv = (const char **)tok->argv; + FUN(tok,finish)(tok); + *argv = (const Char **)tok->argv; *argc = tok->argc; return (0); } -/* tok_str(): +/* FUN(tok,str)(): * Simpler version of tok_line, taking a NUL terminated line * and splitting into words, ignoring cursor state. */ public int -tok_str(Tokenizer *tok, const char *line, int *argc, const char ***argv) +FUN(tok,str)(TYPE(Tokenizer) *tok, const Char *line, int *argc, + const Char ***argv) { - LineInfo li; + TYPE(LineInfo) li; memset(&li, 0, sizeof(li)); li.buffer = line; - li.cursor = li.lastchar = strchr(line, '\0'); - return (tok_line(tok, &li, argc, argv, NULL, NULL)); + li.cursor = li.lastchar = Strchr(line, '\0'); + return (FUN(tok,line)(tok, &li, argc, argv, NULL, NULL)); } @@ -1,4 +1,4 @@ -/* $NetBSD: tty.c,v 1.25 2006/03/18 09:09:41 christos Exp $ */ +/* $NetBSD: tty.c,v 1.33 2010/04/18 21:17:22 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)tty.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: tty.c,v 1.25 2006/03/18 09:09:41 christos Exp $"); +__RCSID("$NetBSD: tty.c,v 1.33 2010/04/18 21:17:22 christos Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -45,8 +45,10 @@ __RCSID("$NetBSD: tty.c,v 1.25 2006/03/18 09:09:41 christos Exp $"); * tty.c: tty interface stuff */ #include <assert.h> -#include "tty.h" +#include <errno.h> +#include <strings.h> /* for ffs */ #include "el.h" +#include "tty.h" typedef struct ttymodes_t { const char *m_name; @@ -55,7 +57,7 @@ typedef struct ttymodes_t { } 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; @@ -445,13 +447,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 *); @@ -460,6 +461,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 @@ -521,7 +545,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", @@ -870,7 +894,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; @@ -892,16 +916,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]; } } } @@ -929,7 +953,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); @@ -1050,7 +1074,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)); @@ -1075,7 +1099,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", @@ -1111,7 +1135,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)); @@ -1132,7 +1156,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)); @@ -1149,19 +1173,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]) { @@ -1193,7 +1218,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", @@ -1216,9 +1241,9 @@ tty_stty(EditLine *el, int argc __attribute__((__unused__)), const char **argv) 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; @@ -1235,7 +1260,7 @@ tty_stty(EditLine *el, int argc __attribute__((__unused__)), const char **argv) return (0); } while (argv && (s = *argv++)) { - const char *p; + const Char *p; switch (*s) { case '+': case '-': @@ -1246,23 +1271,24 @@ tty_stty(EditLine *el, int argc __attribute__((__unused__)), const char **argv) break; } d = s; - p = strchr(s, '='); + p = Strchr(s, '='); for (m = ttymodes; m->m_name; m++) - if ((p ? strncmp(m->m_name, d, (size_t)(p - d)) : - 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 **) &p) : + int v = *++p ? parse__escape(&p) : el->el_tty.t_vdisable; - assert(c-- != 0); + assert(c != 0); + c--; c = tty__getcharindex(c); assert(c != -1); tios->c_cc[c] = v; @@ -1283,6 +1309,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); } @@ -1,4 +1,4 @@ -/* $NetBSD: tty.h,v 1.11 2005/06/01 11:37:52 lukem Exp $ */ +/* $NetBSD: tty.h,v 1.12 2009/12/30 22:37:40 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -40,6 +40,7 @@ #ifndef _h_el_tty #define _h_el_tty +#include "sys.h" #include "histedit.h" #include <termios.h> #include <unistd.h> @@ -458,7 +459,7 @@ 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 *); @@ -1,4 +1,4 @@ -/* $NetBSD: vi.c,v 1.27 2006/10/22 07:48:13 mrg Exp $ */ +/* $NetBSD: vi.c,v 1.31 2009/12/30 22:37:40 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -35,13 +35,14 @@ #include "config.h" #include <stdlib.h> #include <unistd.h> +#include <limits.h> #include <sys/wait.h> #if !defined(lint) && !defined(SCCSID) #if 0 static char sccsid[] = "@(#)vi.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: vi.c,v 1.27 2006/10/22 07:48:13 mrg Exp $"); +__RCSID("$NetBSD: vi.c,v 1.31 2009/12/30 22:37:40 christos Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -50,14 +51,14 @@ __RCSID("$NetBSD: vi.c,v 1.27 2006/10/22 07:48:13 mrg Exp $"); */ #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) { @@ -68,7 +69,7 @@ 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; if (!(c & YANK)) { @@ -89,15 +90,15 @@ 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) { 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); @@ -105,10 +106,11 @@ cv_paste(EditLine *el, int c) if (!c && el->el_line.cursor < el->el_line.lastchar) 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(el->el_line.cursor, k->buf, len +0u); + (void) memcpy(el->el_line.cursor, k->buf, len * + sizeof(*el->el_line.cursor)); return (CC_REFRESH); } @@ -120,7 +122,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)); @@ -133,7 +135,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)); @@ -146,7 +148,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) @@ -171,7 +173,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) @@ -196,7 +198,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) @@ -220,7 +222,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) @@ -243,7 +245,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; @@ -252,11 +254,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--; @@ -275,7 +277,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__))) { /* @@ -292,7 +294,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; @@ -308,7 +310,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) @@ -327,7 +329,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; @@ -343,7 +345,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); @@ -358,12 +360,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); @@ -376,12 +378,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); @@ -394,7 +396,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; @@ -409,7 +411,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; @@ -434,7 +436,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; @@ -450,7 +452,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)); @@ -463,7 +465,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) @@ -487,7 +489,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) @@ -511,7 +513,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; @@ -521,7 +523,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; @@ -537,7 +540,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 */ @@ -561,7 +564,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) @@ -582,7 +585,7 @@ 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__))) { if (el->el_line.cursor <= el->el_line.buffer) @@ -600,7 +603,7 @@ vi_delete_prev_char(EditLine *el, int c __attribute__((__unused__))) */ protected el_action_t /*ARGSUSED*/ -vi_list_or_eof(EditLine *el, int c) +vi_list_or_eof(EditLine *el, Int c) { if (el->el_line.cursor == el->el_line.lastchar) { @@ -637,16 +640,16 @@ vi_list_or_eof(EditLine *el, int c) */ 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); } @@ -658,7 +661,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)); @@ -671,7 +674,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)); @@ -684,7 +687,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) @@ -700,7 +703,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) @@ -718,7 +721,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); } @@ -730,7 +733,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); } @@ -742,7 +745,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); } @@ -754,7 +757,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); } @@ -766,7 +769,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, @@ -780,7 +783,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; @@ -798,20 +801,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; @@ -845,7 +848,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); @@ -859,7 +862,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; @@ -873,11 +876,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; } @@ -887,7 +890,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); @@ -899,7 +902,7 @@ vi_yank(EditLine *el, int 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; @@ -920,7 +923,7 @@ 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_reference char alias_name[3]; @@ -937,7 +940,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; @@ -950,14 +953,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); @@ -995,13 +998,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) @@ -1011,29 +1017,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, 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; } @@ -1051,34 +1082,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); @@ -1100,7 +1132,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; @@ -1116,7 +1148,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; |