Index: ObsoleteFiles.inc =================================================================== --- ObsoleteFiles.inc +++ ObsoleteFiles.inc @@ -46,6 +46,8 @@ OLD_FILES+=usr/tests/sys/netpfil/pf/pft_ping.py # 20190816: dir.h removed from POSIX OLD_FILES+=usr/include/sys/dir.h +# 20190802: sync libedit with NetBSD +OLD_LIBS+=lib/libedit.so.7 # 20190729: gzip'ed a.out support removed OLD_FILES+=usr/include/sys/inflate.h # 20190722: cap_random(3) removed Index: bin/sh/histedit.c =================================================================== --- bin/sh/histedit.c +++ bin/sh/histedit.c @@ -122,7 +122,7 @@ el_set(el, EL_PROMPT, getprompt); el_set(el, EL_ADDFN, "sh-complete", "Filename completion", - _el_fn_sh_complete); + _el_fn_complete); } else { bad: out2fmt_flush("sh: can't initialize editing\n"); Index: lib/libedit/Makefile =================================================================== --- lib/libedit/Makefile +++ lib/libedit/Makefile @@ -4,7 +4,7 @@ PACKAGE=clibs -SHLIB_MAJOR= 7 +SHLIB_MAJOR= 8 SHLIBDIR?= /lib WARNS?= 3 @@ -12,11 +12,14 @@ LIBADD= ncursesw -OSRCS= chared.c common.c el.c eln.c emacs.c fcns.c filecomplete.c help.c \ - hist.c keymacro.c map.c chartype.c \ - parse.c prompt.c read.c refresh.c search.c sig.c terminal.c tty.c vi.c +SRCS= chared.c common.c el.c eln.c emacs.c filecomplete.c \ + hist.c keymacro.c literal.c map.c chartype.c \ + parse.c prompt.c read.c refresh.c search.c sig.c terminal.c tty.c vi.c \ + readline.c tokenizer.c history.c \ + tokenizern.c historyn.c \ + common.h emacs.h fcns.h func.h help.h vi.h -MAN= editline.3 editrc.5 +MAN= editline.3 editrc.5 editline.7 MLINKS= editline.3 el_deletestr.3 editline.3 el_end.3 editline.3 el_init.3 \ editline.3 el_get.3 editline.3 el_getc.3 editline.3 el_gets.3 \ @@ -28,20 +31,10 @@ editline.3 tok_init.3 editline.3 tok_end.3 editline.3 tok_reset.3 \ editline.3 tok_line.3 editline.3 tok_str.3 -# For speed and debugging -#SRCS= ${OSRCS} readline.c tokenizer.c history.c -# For protection -SRCS= editline.c readline.c tokenizer.c history.c -SRCS+= common.h emacs.h fcns.h help.h vi.h - -# Widechar -SRCS+= tokenizern.c historyn.c -CLEANFILES+= tokenizern.c historyn.c - INCS= histedit.h -CLEANFILES+= common.h editline.c emacs.h fcns.c fcns.h help.c help.h vi.h -CFLAGS+= -I. -I${.CURDIR} -I${.CURDIR}/edit -DWIDECHAR +CLEANFILES+= common.h emacs.h fcns.c fcns.h help.h vi.h +CFLAGS+= -I. -I${.CURDIR} -I${.CURDIR}/edit #CFLAGS+= -DDEBUG_TTY -DDEBUG_KEY -DDEBUG_READ -DDEBUG -DDEBUG_REFRESH #CFLAGS+= -DDEBUG_PASTE -DDEBUG_EDIT @@ -58,24 +51,12 @@ fcns.h: ${AHDR} makelist sh ${.CURDIR}/makelist -fh ${AHDR} > ${.TARGET} -fcns.c: ${AHDR} fcns.h makelist +func.h: ${AHDR} makelist sh ${.CURDIR}/makelist -fc ${AHDR} > ${.TARGET} -help.c: ${ASRC} makelist - sh ${.CURDIR}/makelist -bc ${ASRC} > ${.TARGET} - help.h: ${ASRC} makelist sh ${.CURDIR}/makelist -bh ${ASRC} > ${.TARGET} -editline.c: ${OSRCS} - sh ${.CURDIR}/makelist -e ${.ALLSRC:T} > ${.TARGET} - -tokenizern.c: makelist Makefile - sh ${.CURDIR}/makelist -n tokenizer.c > ${.TARGET} - -historyn.c: makelist Makefile - sh ${.CURDIR}/makelist -n history.c > ${.TARGET} - # minimal dependency to make "make depend" optional editline.o editline.po editline.pico editline.ln: \ common.h emacs.h fcns.c fcns.h help.c help.h vi.h Index: lib/libedit/TEST/Makefile =================================================================== --- lib/libedit/TEST/Makefile +++ lib/libedit/TEST/Makefile @@ -0,0 +1,16 @@ +# $NetBSD: Makefile,v 1.8 2017/10/15 18:59:00 abhinav Exp $ + +MK_MAN=no +PROG=wtc1 +CFLAGS=-I${.CURDIR}/.. -I.. +LIBADD=edit termcap +CLEANFILES=test_filecompletion + +.ifdef DEBUG +CFLAGS+=-DDEBUG +.endif + +test_filecompletion: test_filecompletion.c + ${CC} ${CFLAGS} ${.ALLSRC} -o ${.TARGET} -ledit -ltermcap + +.include Index: lib/libedit/TEST/tc1.c =================================================================== --- lib/libedit/TEST/tc1.c +++ lib/libedit/TEST/tc1.c @@ -62,6 +62,10 @@ #include "histedit.h" +#ifndef __UNCONST +#define __UNCONST(a) ((void*)(const void*)a) +#endif + static int continuation = 0; volatile sig_atomic_t gotsig = 0; @@ -92,7 +96,7 @@ struct dirent *dp; const char* ptr; const LineInfo *lf = el_line(el); - int len; + size_t len; int res = CC_ERROR; /* @@ -276,7 +280,7 @@ } else if (el_parse(el, ac, av) == -1) { switch (fork()) { case 0: - execvp(av[0], __DECONST(char **, av)); + execvp(av[0], (char *const *)__UNCONST(av)); perror(av[0]); _exit(1); /*NOTREACHED*/ Index: lib/libedit/TEST/test_filecompletion.c =================================================================== --- lib/libedit/TEST/test_filecompletion.c +++ lib/libedit/TEST/test_filecompletion.c @@ -0,0 +1,553 @@ +/* $NetBSD: test_filecompletion.c,v 1.4 2019/03/31 03:04:57 abhinav Exp $ */ + +/*- + * Copyright (c) 2017 Abhinav Upadhyay + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "filecomplete.h" +#include "el.h" + +typedef struct { + const wchar_t *user_typed_text; /* The actual text typed by the user on the terminal */ + const char *completion_function_input ; /*the text received by fn_filename_completion_function */ + const char *expanded_text[2]; /* the value to which completion_function_input should be expanded */ + const wchar_t *escaped_output; /* expected escaped value of expanded_text */ +} test_input; + +static test_input inputs[] = { + { + /* simple test for escaping angular brackets */ + L"ls ang", + "ang", + {"angtest", NULL}, + L"ls ang\\test " + }, + { + /* test angular bracket inside double quotes: ls "dq_ang */ + L"ls \"dq_ang", + "dq_ang", + {"dq_angtest", NULL}, + L"ls \"dq_angtest\" " + }, + { + /* test angular bracket inside singlq quotes: ls "sq_ang */ + L"ls 'sq_ang", + "sq_ang", + {"sq_angtest", NULL}, + L"ls 'sq_angtest' " + }, + { + /* simple test for backslash */ + L"ls back", + "back", + {"backslash\\test", NULL}, + L"ls backslash\\\\test " + }, + { + /* backslash inside single quotes */ + L"ls 'sback", + "sback", + {"sbackslash\\test", NULL}, + L"ls 'sbackslash\\test' " + }, + { + /* backslash inside double quotes */ + L"ls \"dback", + "dback", + {"dbackslash\\test", NULL}, + L"ls \"dbackslash\\\\test\" " + }, + { + /* test braces */ + L"ls br", + "br", + {"braces{test}", NULL}, + L"ls braces\\{test\\} " + }, + { + /* test braces inside single quotes */ + L"ls 'sbr", + "sbr", + {"sbraces{test}", NULL}, + L"ls 'sbraces{test}' " + }, + { + /* test braces inside double quotes */ + L"ls \"dbr", + "dbr", + {"dbraces{test}", NULL}, + L"ls \"dbraces{test}\" " + }, + { + /* test dollar */ + L"ls doll", + "doll", + {"doll$artest", NULL}, + L"ls doll\\$artest " + }, + { + /* test dollar inside single quotes */ + L"ls 'sdoll", + "sdoll", + {"sdoll$artest", NULL}, + L"ls 'sdoll$artest' " + }, + { + /* test dollar inside double quotes */ + L"ls \"ddoll", + "ddoll", + {"ddoll$artest", NULL}, + L"ls \"ddoll\\$artest\" " + }, + { + /* test equals */ + L"ls eq", + "eq", + {"equals==test", NULL}, + L"ls equals\\=\\=test " + }, + { + /* test equals inside sinqle quotes */ + L"ls 'seq", + "seq", + {"sequals==test", NULL}, + L"ls 'sequals==test' " + }, + { + /* test equals inside double quotes */ + L"ls \"deq", + "deq", + {"dequals==test", NULL}, + L"ls \"dequals==test\" " + }, + { + /* test \n */ + L"ls new", + "new", + {"new\\nline", NULL}, + L"ls new\\\\nline " + }, + { + /* test \n inside single quotes */ + L"ls 'snew", + "snew", + {"snew\nline", NULL}, + L"ls 'snew\nline' " + }, + { + /* test \n inside double quotes */ + L"ls \"dnew", + "dnew", + {"dnew\nline", NULL}, + L"ls \"dnew\nline\" " + }, + { + /* test single space */ + L"ls spac", + "spac", + {"space test", NULL}, + L"ls space\\ test " + }, + { + /* test single space inside singlq quotes */ + L"ls 's_spac", + "s_spac", + {"s_space test", NULL}, + L"ls 's_space test' " + }, + { + /* test single space inside double quotes */ + L"ls \"d_spac", + "d_spac", + {"d_space test", NULL}, + L"ls \"d_space test\" " + }, + { + /* test multiple spaces */ + L"ls multi", + "multi", + {"multi space test", NULL}, + L"ls multi\\ space\\ \\ test " + }, + { + /* test multiple spaces inside single quotes */ + L"ls 's_multi", + "s_multi", + {"s_multi space test", NULL}, + L"ls 's_multi space test' " + }, + { + /* test multiple spaces inside double quotes */ + L"ls \"d_multi", + "d_multi", + {"d_multi space test", NULL}, + L"ls \"d_multi space test\" " + }, + { + /* test double quotes */ + L"ls doub", + "doub", + {"doub\"quotes", NULL}, + L"ls doub\\\"quotes " + }, + { + /* test double quotes inside single quotes */ + L"ls 's_doub", + "s_doub", + {"s_doub\"quotes", NULL}, + L"ls 's_doub\"quotes' " + }, + { + /* test double quotes inside double quotes */ + L"ls \"d_doub", + "d_doub", + {"d_doub\"quotes", NULL}, + L"ls \"d_doub\\\"quotes\" " + }, + { + /* test multiple double quotes */ + L"ls mud", + "mud", + {"mud\"qu\"otes\"", NULL}, + L"ls mud\\\"qu\\\"otes\\\" " + }, + { + /* test multiple double quotes inside single quotes */ + L"ls 'smud", + "smud", + {"smud\"qu\"otes\"", NULL}, + L"ls 'smud\"qu\"otes\"' " + }, + { + /* test multiple double quotes inside double quotes */ + L"ls \"dmud", + "dmud", + {"dmud\"qu\"otes\"", NULL}, + L"ls \"dmud\\\"qu\\\"otes\\\"\" " + }, + { + /* test one single quote */ + L"ls sing", + "sing", + {"single'quote", NULL}, + L"ls single\\'quote " + }, + { + /* test one single quote inside single quote */ + L"ls 'ssing", + "ssing", + {"ssingle'quote", NULL}, + L"ls 'ssingle'\\''quote' " + }, + { + /* test one single quote inside double quote */ + L"ls \"dsing", + "dsing", + {"dsingle'quote", NULL}, + L"ls \"dsingle'quote\" " + }, + { + /* test multiple single quotes */ + L"ls mu_sing", + "mu_sing", + {"mu_single''quotes''", NULL}, + L"ls mu_single\\'\\'quotes\\'\\' " + }, + { + /* test multiple single quotes inside single quote */ + L"ls 'smu_sing", + "smu_sing", + {"smu_single''quotes''", NULL}, + L"ls 'smu_single'\\'''\\''quotes'\\\'''\\''' " + }, + { + /* test multiple single quotes inside double quote */ + L"ls \"dmu_sing", + "dmu_sing", + {"dmu_single''quotes''", NULL}, + L"ls \"dmu_single''quotes''\" " + }, + { + /* test parenthesis */ + L"ls paren", + "paren", + {"paren(test)", NULL}, + L"ls paren\\(test\\) " + }, + { + /* test parenthesis inside single quote */ + L"ls 'sparen", + "sparen", + {"sparen(test)", NULL}, + L"ls 'sparen(test)' " + }, + { + /* test parenthesis inside double quote */ + L"ls \"dparen", + "dparen", + {"dparen(test)", NULL}, + L"ls \"dparen(test)\" " + }, + { + /* test pipe */ + L"ls pip", + "pip", + {"pipe|test", NULL}, + L"ls pipe\\|test " + }, + { + /* test pipe inside single quote */ + L"ls 'spip", + "spip", + {"spipe|test", NULL}, + L"ls 'spipe|test' ", + }, + { + /* test pipe inside double quote */ + L"ls \"dpip", + "dpip", + {"dpipe|test", NULL}, + L"ls \"dpipe|test\" " + }, + { + /* test tab */ + L"ls ta", + "ta", + {"tab\ttest", NULL}, + L"ls tab\\\ttest " + }, + { + /* test tab inside single quote */ + L"ls 'sta", + "sta", + {"stab\ttest", NULL}, + L"ls 'stab\ttest' " + }, + { + /* test tab inside double quote */ + L"ls \"dta", + "dta", + {"dtab\ttest", NULL}, + L"ls \"dtab\ttest\" " + }, + { + /* test back tick */ + L"ls tic", + "tic", + {"tick`test`", NULL}, + L"ls tick\\`test\\` " + }, + { + /* test back tick inside single quote */ + L"ls 'stic", + "stic", + {"stick`test`", NULL}, + L"ls 'stick`test`' " + }, + { + /* test back tick inside double quote */ + L"ls \"dtic", + "dtic", + {"dtick`test`", NULL}, + L"ls \"dtick\\`test\\`\" " + }, + { + /* test for @ */ + L"ls at", + "at", + {"atthe@rate", NULL}, + L"ls atthe\\@rate " + }, + { + /* test for @ inside single quote */ + L"ls 'sat", + "sat", + {"satthe@rate", NULL}, + L"ls 'satthe@rate' " + }, + { + /* test for @ inside double quote */ + L"ls \"dat", + "dat", + {"datthe@rate", NULL}, + L"ls \"datthe@rate\" " + }, + { + /* test ; */ + L"ls semi", + "semi", + {"semi;colon;test", NULL}, + L"ls semi\\;colon\\;test " + }, + { + /* test ; inside single quote */ + L"ls 'ssemi", + "ssemi", + {"ssemi;colon;test", NULL}, + L"ls 'ssemi;colon;test' " + }, + { + /* test ; inside double quote */ + L"ls \"dsemi", + "dsemi", + {"dsemi;colon;test", NULL}, + L"ls \"dsemi;colon;test\" " + }, + { + /* test & */ + L"ls amp", + "amp", + {"ampers&and", NULL}, + L"ls ampers\\&and " + }, + { + /* test & inside single quote */ + L"ls 'samp", + "samp", + {"sampers&and", NULL}, + L"ls 'sampers&and' " + }, + { + /* test & inside double quote */ + L"ls \"damp", + "damp", + {"dampers&and", NULL}, + L"ls \"dampers&and\" " + }, + { + /* test completion when cursor at \ */ + L"ls foo\\", + "foo", + {"foo bar", NULL}, + L"ls foo\\ bar " + }, + { + /* test completion when cursor at single quote */ + L"ls foo'", + "foo'", + {"foo bar", NULL}, + L"ls foo\\ bar " + }, + { + /* test completion when cursor at double quote */ + L"ls foo\"", + "foo\"", + {"foo bar", NULL}, + L"ls foo\\ bar " + }, + { + /* test multiple completion matches */ + L"ls fo", + "fo", + {"foo bar", "foo baz"}, + L"ls foo\\ ba" + }, + { + L"ls ba", + "ba", + {"bar ", "bar "}, + L"ls bar\\ \\<=;|&{("; + +/* + * Custom completion function passed to fn_complet, NULLe. + * The function returns hardcoded completion matches + * based on the test cases present in inputs[] (above) + */ +static char * +mycomplet_func(const char *text, int index) +{ + static int last_index = 0; + size_t i = 0; + if (last_index == 2) { + last_index = 0; + return NULL; + } + + for (i = 0; i < sizeof(inputs)/sizeof(inputs[0]); i++) { + if (strcmp(text, inputs[i].completion_function_input) == 0) { + if (inputs[i].expanded_text[last_index] != NULL) + return strdup(inputs[i].expanded_text[last_index++]); + else { + last_index = 0; + return NULL; + } + } + } + + return NULL; +} + +int +main(int argc, char **argv) +{ + EditLine *el = el_init(argv[0], stdin, stdout, stderr); + size_t i; + size_t input_len; + el_line_t line; + wchar_t *buffer = malloc(64 * sizeof(*buffer)); + if (buffer == NULL) + err(EXIT_FAILURE, "malloc failed"); + + for (i = 0; i < sizeof(inputs)/sizeof(inputs[0]); i++) { + memset(buffer, 0, 64 * sizeof(*buffer)); + input_len = wcslen(inputs[i].user_typed_text); + wmemcpy(buffer, inputs[i].user_typed_text, input_len); + buffer[input_len] = 0; + line.buffer = buffer; + line.cursor = line.buffer + input_len ; + line.lastchar = line.cursor - 1; + line.limit = line.buffer + 64 * sizeof(*buffer); + el->el_line = line; + fn_complete(el, mycomplet_func, NULL, break_chars, NULL, NULL, 10, NULL, NULL, NULL, NULL); + + /* + * fn_complete would have expanded and escaped the input in el->el_line.buffer. + * We need to assert that it matches with the expected value in our test data + */ + printf("User input: %ls\t Expected output: %ls\t Generated output: %ls\n", + inputs[i].user_typed_text, inputs[i].escaped_output, el->el_line.buffer); + assert(wcscmp(el->el_line.buffer, inputs[i].escaped_output) == 0); + } + el_end(el); + return 0; + +} Index: lib/libedit/chared.h =================================================================== --- lib/libedit/chared.h +++ lib/libedit/chared.h @@ -1,4 +1,4 @@ -/* $NetBSD: chared.h,v 1.27 2016/02/16 22:53:14 christos Exp $ */ +/* $NetBSD: chared.h,v 1.30 2016/05/22 19:44:26 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -41,8 +41,6 @@ #ifndef _h_el_chared #define _h_el_chared -#define EL_MAXMACRO 10 - /* * This is an issue of basic "vi" look-and-feel. Defining VI_MOVE works * like real vi: i.e. the transition from command<->insert modes moves @@ -55,29 +53,22 @@ */ #define VI_MOVE - -typedef struct c_macro_t { - int level; - int offset; - Char **macro; -} c_macro_t; - /* * Undo information for vi - no undo in emacs (yet) */ typedef struct c_undo_t { ssize_t len; /* length of saved line */ int cursor; /* position of saved cursor */ - Char *buf; /* full saved text */ + wchar_t *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; + wchar_t *buf; /* redo insert key sequence */ + wchar_t *pos; + wchar_t *lim; el_action_t cmd; /* command to redo */ - Char ch; /* char that invoked it */ + wchar_t ch; /* char that invoked it */ int count; int action; /* from cv_action() */ } c_redo_t; @@ -87,16 +78,16 @@ */ typedef struct c_vcmd_t { int action; - Char *pos; + wchar_t *pos; } c_vcmd_t; /* * Kill buffer for emacs */ typedef struct c_kill_t { - Char *buf; - Char *last; - Char *mark; + wchar_t *buf; + wchar_t *last; + wchar_t *mark; } c_kill_t; typedef void (*el_zfunc_t)(EditLine *, void *); @@ -111,7 +102,6 @@ c_kill_t c_kill; c_redo_t c_redo; c_vcmd_t c_vcmd; - c_macro_t c_macro; el_zfunc_t c_resizefun; el_afunc_t c_aliasfun; void * c_resizearg; @@ -136,30 +126,31 @@ #define MODE_REPLACE_1 2 -protected int cv__isword(wint_t); -protected int cv__isWord(wint_t); -protected void cv_delfini(EditLine *); -protected Char *cv__endword(Char *, Char *, int, int (*)(wint_t)); -protected int ce__isword(wint_t); -protected void cv_undo(EditLine *); -protected void cv_yank(EditLine *, const Char *, int); -protected Char *cv_next_word(EditLine*, Char *, Char *, int, int (*)(wint_t)); -protected Char *cv_prev_word(Char *, Char *, int, int (*)(wint_t)); -protected Char *c__next_word(Char *, Char *, int, int (*)(wint_t)); -protected Char *c__prev_word(Char *, Char *, int, int (*)(wint_t)); -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_hpos(EditLine *); +libedit_private int cv__isword(wint_t); +libedit_private int cv__isWord(wint_t); +libedit_private void cv_delfini(EditLine *); +libedit_private wchar_t *cv__endword(wchar_t *, wchar_t *, int, int (*)(wint_t)); +libedit_private int ce__isword(wint_t); +libedit_private void cv_undo(EditLine *); +libedit_private void cv_yank(EditLine *, const wchar_t *, int); +libedit_private wchar_t *cv_next_word(EditLine*, wchar_t *, wchar_t *, int, + int (*)(wint_t)); +libedit_private wchar_t *cv_prev_word(wchar_t *, wchar_t *, int, int (*)(wint_t)); +libedit_private wchar_t *c__next_word(wchar_t *, wchar_t *, int, int (*)(wint_t)); +libedit_private wchar_t *c__prev_word(wchar_t *, wchar_t *, int, int (*)(wint_t)); +libedit_private void c_insert(EditLine *, int); +libedit_private void c_delbefore(EditLine *, int); +libedit_private void c_delbefore1(EditLine *); +libedit_private void c_delafter(EditLine *, int); +libedit_private void c_delafter1(EditLine *); +libedit_private int c_gets(EditLine *, wchar_t *, const wchar_t *); +libedit_private int c_hpos(EditLine *); -protected int ch_init(EditLine *); -protected void ch_reset(EditLine *, int); -protected int ch_resizefun(EditLine *, el_zfunc_t, void *); -protected int ch_aliasfun(EditLine *, el_afunc_t, void *); -protected int ch_enlargebufs(EditLine *, size_t); -protected void ch_end(EditLine *); +libedit_private int ch_init(EditLine *); +libedit_private void ch_reset(EditLine *); +libedit_private int ch_resizefun(EditLine *, el_zfunc_t, void *); +libedit_private int ch_aliasfun(EditLine *, el_afunc_t, void *); +libedit_private int ch_enlargebufs(EditLine *, size_t); +libedit_private void ch_end(EditLine *); #endif /* _h_el_chared */ Index: lib/libedit/chared.c =================================================================== --- lib/libedit/chared.c +++ lib/libedit/chared.c @@ -1,4 +1,4 @@ -/* $NetBSD: chared.c,v 1.49 2016/02/24 14:29:21 christos Exp $ */ +/* $NetBSD: chared.c,v 1.59 2019/07/23 10:18:52 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.49 2016/02/24 14:29:21 christos Exp $"); +__RCSID("$NetBSD: chared.c,v 1.59 2019/07/23 10:18:52 christos Exp $"); #endif #endif /* not lint && not SCCSID */ #include @@ -52,16 +52,15 @@ #include "el.h" #include "common.h" +#include "fcns.h" -private void ch__clearmacro (EditLine *); - /* value to leave unused in line buffer */ #define EL_LEAVE 2 /* cv_undo(): * Handle state for the vi undo command */ -protected void +libedit_private void cv_undo(EditLine *el) { c_undo_t *vu = &el->el_chared.c_undo; @@ -85,8 +84,8 @@ /* cv_yank(): * Save yank/delete data for paste */ -protected void -cv_yank(EditLine *el, const Char *ptr, int size) +libedit_private void +cv_yank(EditLine *el, const wchar_t *ptr, int size) { c_kill_t *k = &el->el_chared.c_kill; @@ -98,10 +97,10 @@ /* c_insert(): * Insert num characters */ -protected void +libedit_private void c_insert(EditLine *el, int num) { - Char *cp; + wchar_t *cp; if (el->el_line.lastchar + num >= el->el_line.limit) { if (!ch_enlargebufs(el, (size_t)num)) @@ -120,7 +119,7 @@ /* c_delafter(): * Delete num characters after the cursor */ -protected void +libedit_private void c_delafter(EditLine *el, int num) { @@ -133,7 +132,7 @@ } if (num > 0) { - Char *cp; + wchar_t *cp; for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++) *cp = cp[num]; @@ -146,10 +145,10 @@ /* c_delafter1(): * Delete the character after the cursor, do not yank */ -protected void +libedit_private void c_delafter1(EditLine *el) { - Char *cp; + wchar_t *cp; for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++) *cp = cp[1]; @@ -161,7 +160,7 @@ /* c_delbefore(): * Delete num characters before the cursor */ -protected void +libedit_private void c_delbefore(EditLine *el, int num) { @@ -174,10 +173,10 @@ } if (num > 0) { - Char *cp; + wchar_t *cp; for (cp = el->el_line.cursor - num; - cp <= el->el_line.lastchar; + &cp[num] <= el->el_line.lastchar; cp++) *cp = cp[num]; @@ -189,10 +188,10 @@ /* c_delbefore1(): * Delete the character before the cursor, do not yank */ -protected void +libedit_private void c_delbefore1(EditLine *el) { - Char *cp; + wchar_t *cp; for (cp = el->el_line.cursor - 1; cp <= el->el_line.lastchar; cp++) *cp = cp[1]; @@ -204,22 +203,22 @@ /* ce__isword(): * Return if p is part of a word according to emacs */ -protected int +libedit_private int ce__isword(wint_t p) { - return Isalnum(p) || Strchr(STR("*?_-.[]~="), p) != NULL; + return iswalnum(p) || wcschr(L"*?_-.[]~=", p) != NULL; } /* cv__isword(): * Return if p is part of a word according to vi */ -protected int +libedit_private int cv__isword(wint_t p) { - if (Isalnum(p) || p == '_') + if (iswalnum(p) || p == L'_') return 1; - if (Isgraph(p)) + if (iswgraph(p)) return 2; return 0; } @@ -228,18 +227,18 @@ /* cv__isWord(): * Return if p is part of a big word according to vi */ -protected int +libedit_private int cv__isWord(wint_t p) { - return !Isspace(p); + return !iswspace(p); } /* c__prev_word(): * Find the previous word */ -protected Char * -c__prev_word(Char *p, Char *low, int n, int (*wtest)(wint_t)) +libedit_private wchar_t * +c__prev_word(wchar_t *p, wchar_t *low, int n, int (*wtest)(wint_t)) { p--; @@ -262,8 +261,8 @@ /* c__next_word(): * Find the next word */ -protected Char * -c__next_word(Char *p, Char *high, int n, int (*wtest)(wint_t)) +libedit_private wchar_t * +c__next_word(wchar_t *p, wchar_t *high, int n, int (*wtest)(wint_t)) { while (n--) { while ((p < high) && !(*wtest)(*p)) @@ -280,8 +279,9 @@ /* cv_next_word(): * Find the next word vi style */ -protected Char * -cv_next_word(EditLine *el, Char *p, Char *high, int n, int (*wtest)(wint_t)) +libedit_private wchar_t * +cv_next_word(EditLine *el, wchar_t *p, wchar_t *high, int n, + int (*wtest)(wint_t)) { int test; @@ -294,7 +294,7 @@ * trailing whitespace! This is not what 'w' does.. */ if (n || el->el_chared.c_vcmd.action != (DELETE|INSERT)) - while ((p < high) && Isspace(*p)) + while ((p < high) && iswspace(*p)) p++; } @@ -309,14 +309,14 @@ /* cv_prev_word(): * Find the previous word vi style */ -protected Char * -cv_prev_word(Char *p, Char *low, int n, int (*wtest)(wint_t)) +libedit_private wchar_t * +cv_prev_word(wchar_t *p, wchar_t *low, int n, int (*wtest)(wint_t)) { int test; p--; while (n--) { - while ((p > low) && Isspace(*p)) + while ((p > low) && iswspace(*p)) p--; test = (*wtest)(*p); while ((p >= low) && (*wtest)(*p) == test) @@ -335,7 +335,7 @@ /* cv_delfini(): * Finish vi delete action */ -protected void +libedit_private void cv_delfini(EditLine *el) { int size; @@ -373,15 +373,15 @@ /* cv__endword(): * Go to the end of this word according to vi */ -protected Char * -cv__endword(Char *p, Char *high, int n, int (*wtest)(wint_t)) +libedit_private wchar_t * +cv__endword(wchar_t *p, wchar_t *high, int n, int (*wtest)(wint_t)) { int test; p++; while (n--) { - while ((p < high) && Isspace(*p)) + while ((p < high) && iswspace(*p)) p++; test = (*wtest)(*p); @@ -395,31 +395,25 @@ /* ch_init(): * Initialize the character editor */ -protected int +libedit_private int ch_init(EditLine *el) { - c_macro_t *ma = &el->el_chared.c_macro; - - el->el_line.buffer = el_malloc(EL_BUFSIZ * + el->el_line.buffer = el_calloc(EL_BUFSIZ, sizeof(*el->el_line.buffer)); if (el->el_line.buffer == NULL) return -1; - (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 = el_malloc(EL_BUFSIZ * + el->el_chared.c_undo.buf = el_calloc(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 * - 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 = el_malloc(EL_BUFSIZ * + el->el_chared.c_redo.buf = el_calloc(EL_BUFSIZ, sizeof(*el->el_chared.c_redo.buf)); if (el->el_chared.c_redo.buf == NULL) return -1; @@ -430,12 +424,10 @@ el->el_chared.c_vcmd.action = NOP; el->el_chared.c_vcmd.pos = el->el_line.buffer; - el->el_chared.c_kill.buf = el_malloc(EL_BUFSIZ * + el->el_chared.c_kill.buf = el_calloc(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 * - 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; el->el_chared.c_resizefun = NULL; @@ -451,19 +443,14 @@ el->el_state.argument = 1; el->el_state.lastcmd = ED_UNASSIGNED; - ma->level = -1; - ma->offset = 0; - ma->macro = el_malloc(EL_MAXMACRO * sizeof(*ma->macro)); - if (ma->macro == NULL) - return -1; return 0; } /* ch_reset(): * Reset the character editor */ -protected void -ch_reset(EditLine *el, int mclear) +libedit_private void +ch_reset(EditLine *el) { el->el_line.cursor = el->el_line.buffer; el->el_line.lastchar = el->el_line.buffer; @@ -485,28 +472,17 @@ el->el_state.lastcmd = ED_UNASSIGNED; el->el_history.eventno = 0; - - if (mclear) - ch__clearmacro(el); } -private void -ch__clearmacro(EditLine *el) -{ - c_macro_t *ma = &el->el_chared.c_macro; - while (ma->level >= 0) - el_free(ma->macro[ma->level--]); -} - /* ch_enlargebufs(): * Enlarge line buffer to be able to hold twice as much characters. * Returns 1 if successful, 0 if not. */ -protected int +libedit_private int ch_enlargebufs(EditLine *el, size_t addlen) { size_t sz, newsz; - Char *newbuffer, *oldbuf, *oldkbuf; + wchar_t *newbuffer, *oldbuf, *oldkbuf; sz = (size_t)(el->el_line.limit - el->el_line.buffer + EL_LEAVE); newsz = sz * 2; @@ -591,7 +567,7 @@ /* ch_end(): * Free the data structures used by the editor */ -protected void +libedit_private void ch_end(EditLine *el) { el_free(el->el_line.buffer); @@ -606,21 +582,19 @@ el->el_chared.c_redo.cmd = ED_UNASSIGNED; el_free(el->el_chared.c_kill.buf); el->el_chared.c_kill.buf = NULL; - ch_reset(el, 1); - el_free(el->el_chared.c_macro.macro); - el->el_chared.c_macro.macro = NULL; + ch_reset(el); } /* el_insertstr(): - * Insert string at cursorI + * Insert string at cursor */ -public int -FUN(el,insertstr)(EditLine *el, const Char *s) +int +el_winsertstr(EditLine *el, const wchar_t *s) { size_t len; - if (s == NULL || (len = Strlen(s)) == 0) + if (s == NULL || (len = wcslen(s)) == 0) return -1; if (el->el_line.lastchar + len >= el->el_line.limit) { if (!ch_enlargebufs(el, len)) @@ -637,7 +611,7 @@ /* el_deletestr(): * Delete num characters before the cursor */ -public void +void el_deletestr(EditLine *el, int n) { if (n <= 0) @@ -655,7 +629,7 @@ /* el_cursor(): * Move the cursor to the left or the right of the current position */ -public int +int el_cursor(EditLine *el, int n) { if (n == 0) @@ -674,15 +648,14 @@ /* c_gets(): * Get a string */ -protected int -c_gets(EditLine *el, Char *buf, const Char *prompt) +libedit_private int +c_gets(EditLine *el, wchar_t *buf, const wchar_t *prompt) { - wchar_t wch; ssize_t len; - Char *cp = el->el_line.buffer, ch; + wchar_t *cp = el->el_line.buffer, ch; if (prompt) { - len = (ssize_t)Strlen(prompt); + len = (ssize_t)wcslen(prompt); (void)memcpy(cp, prompt, (size_t)len * sizeof(*cp)); cp += len; } @@ -694,12 +667,11 @@ el->el_line.lastchar = cp + 1; re_refresh(el); - if (el_wgetc(el, &wch) != 1) { + if (el_wgetc(el, &ch) != 1) { ed_end_of_file(el, 0); len = -1; break; } - ch = (Char)wch; switch (ch) { @@ -741,10 +713,10 @@ /* c_hpos(): * Return the current horizontal position of the cursor */ -protected int +libedit_private int c_hpos(EditLine *el) { - Char *ptr; + wchar_t *ptr; /* * Find how many characters till the beginning of this line. @@ -760,7 +732,7 @@ } } -protected int +libedit_private int ch_resizefun(EditLine *el, el_zfunc_t f, void *a) { el->el_chared.c_resizefun = f; @@ -768,7 +740,7 @@ return 0; } -protected int +libedit_private int ch_aliasfun(EditLine *el, el_afunc_t f, void *a) { el->el_chared.c_aliasfun = f; Index: lib/libedit/chartype.h =================================================================== --- lib/libedit/chartype.h +++ lib/libedit/chartype.h @@ -1,4 +1,4 @@ -/* $NetBSD: chartype.h,v 1.25 2016/03/07 00:05:20 christos Exp $ */ +/* $NetBSD: chartype.h,v 1.35 2017/05/22 19:16:25 christos Exp $ */ /*- * Copyright (c) 2009 The NetBSD Foundation, Inc. @@ -31,14 +31,16 @@ #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__)) && !defined(__OpenBSD__) && !defined(__FreeBSD__) +#if !defined(__NetBSD__) && \ + !defined(__sun) && \ + !(defined(__APPLE__) && defined(__MACH__)) && \ + !defined(__OpenBSD__) && \ + !defined(__FreeBSD__) && \ + !defined(__DragonFly__) #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 @@ -54,156 +56,31 @@ #warning Build environment does not support non-BMP characters #endif -#define ct_wctob wctob -#define ct_wctomb wctomb -#define ct_wcrtomb wcrtomb -#define ct_wctomb_reset wctomb(0,0) -#define ct_wcstombs wcstombs -#define ct_mbstowcs mbstowcs - -#define Char wchar_t -#define FUN(prefix,rest) prefix ## _w ## rest -#define FUNW(type) type ## _w -#define TYPE(type) type ## W -#define FSTR "%ls" -#define FSTARSTR "%.*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) - -static inline int -Width(wchar_t c) -{ - int w = wcwidth(c); - return w < 0 ? 0 : w; -} - -#else /* NARROW */ - -#define ct_wctob(w) ((int)(w)) -#define ct_wctomb error -#define ct_wcrtomb 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 FUN(prefix,rest) prefix ## _ ## rest -#define FUNW(type) type -#define TYPE(type) type -#define FSTR "%s" -#define FSTARSTR "%.*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; + wchar_t *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 *); +char *ct_encode_string(const wchar_t *, 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 *); +wchar_t *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 *); +libedit_private wchar_t **ct_decode_argv(int, const char *[], ct_buffer_t *); -/* Resizes the conversion buffer(s) if needed. */ -protected int ct_conv_cbuff_resize(ct_buffer_t *, size_t); -protected int ct_conv_wbuff_resize(ct_buffer_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_cbuff_resize(b, s) ((s) == (0)) -#define ct_conv_wbuff_resize(b, s) ((s) == (0)) -#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 sufficient +/* Encode a character into the destination buffer, provided there is sufficient * 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). */ +libedit_private ssize_t ct_encode_char(char *, size_t, wchar_t); +libedit_private size_t ct_enc_width(wchar_t); /* The maximum buffer size to hold the most unwieldy visual representation, * in this case \U+nnnnn. */ @@ -212,20 +89,20 @@ /* 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) +#define MB_FILL_CHAR ((wchar_t)-1) /* Visual width of character c, taking into account ^? , \0177 and \U+nnnnn * style visual expansions. */ -protected int ct_visual_width(Char); +libedit_private int ct_visual_width(wchar_t); /* 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); + * up, or -1 if insufficient space. Buffer length is in count of wchar_t's. */ +libedit_private ssize_t ct_visual_char(wchar_t *, size_t, wchar_t); /* 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 *); +libedit_private const wchar_t *ct_visual_string(const wchar_t *, ct_buffer_t *); /* printable character, use ct_visual_width() to find out display width */ @@ -239,10 +116,6 @@ /* 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 +libedit_private int ct_chr_class(wchar_t c); -size_t ct_mbrtowc(wchar_t *, const char *, size_t); - - #endif /* _chartype_f */ Index: lib/libedit/chartype.c =================================================================== --- lib/libedit/chartype.c +++ lib/libedit/chartype.c @@ -1,4 +1,4 @@ -/* $NetBSD: chartype.c,v 1.23 2016/02/28 23:02:24 christos Exp $ */ +/* $NetBSD: chartype.c,v 1.35 2019/07/23 10:18:52 christos Exp $ */ /*- * Copyright (c) 2009 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ */ #include "config.h" #if !defined(lint) && !defined(SCCSID) -__RCSID("$NetBSD: chartype.c,v 1.23 2016/02/28 23:02:24 christos Exp $"); +__RCSID("$NetBSD: chartype.c,v 1.35 2019/07/23 10:18:52 christos Exp $"); #endif /* not lint && not SCCSID */ #include __FBSDID("$FreeBSD$"); @@ -45,8 +45,10 @@ #define CT_BUFSIZ ((size_t)1024) -#ifdef WIDECHAR -protected int +static int ct_conv_cbuff_resize(ct_buffer_t *, size_t); +static int ct_conv_wbuff_resize(ct_buffer_t *, size_t); + +static int ct_conv_cbuff_resize(ct_buffer_t *conv, size_t csize) { void *p; @@ -67,7 +69,7 @@ return 0; } -protected int +static int ct_conv_wbuff_resize(ct_buffer_t *conv, size_t wsize) { void *p; @@ -89,8 +91,8 @@ } -public char * -ct_encode_string(const Char *s, ct_buffer_t *conv) +char * +ct_encode_string(const wchar_t *s, ct_buffer_t *conv) { char *dst; ssize_t used; @@ -119,7 +121,7 @@ return conv->cbuff; } -public Char * +wchar_t * ct_decode_string(const char *s, ct_buffer_t *conv) { size_t len; @@ -127,7 +129,7 @@ if (!s) return NULL; - len = ct_mbstowcs(NULL, s, (size_t)0); + len = mbstowcs(NULL, s, (size_t)0); if (len == (size_t)-1) return NULL; @@ -135,18 +137,18 @@ if (ct_conv_wbuff_resize(conv, len + CT_BUFSIZ) == -1) return NULL; - ct_mbstowcs(conv->wbuff, s, conv->wsize); + mbstowcs(conv->wbuff, s, conv->wsize); return conv->wbuff; } -protected Char ** +libedit_private wchar_t ** ct_decode_argv(int argc, const char *argv[], ct_buffer_t *conv) { size_t bufspace; int i; - Char *p; - Char **wargv; + wchar_t *p; + wchar_t **wargv; ssize_t bytes; /* Make sure we have enough space in the conversion buffer to store all @@ -157,7 +159,7 @@ if (ct_conv_wbuff_resize(conv, bufspace + CT_BUFSIZ) == -1) return NULL; - wargv = el_malloc((size_t)(argc + 1) * sizeof(*wargv)); + wargv = el_calloc((size_t)(argc + 1), sizeof(*wargv)); for (i = 0, p = conv->wbuff; i < argc; ++i) { if (!argv[i]) { /* don't pass null pointers to mbstowcs */ @@ -181,109 +183,79 @@ } -protected size_t -ct_enc_width(Char c) +libedit_private size_t +ct_enc_width(wchar_t c) { - mbstate_t ps = (mbstate_t){{0}}; - size_t len; - char cbuf[MB_LEN_MAX]; - len = ct_wcrtomb(cbuf, c, &ps); - if (len == (size_t)-1) - return (0); - return (len); + mbstate_t mbs; + char buf[MB_LEN_MAX]; + size_t size; + memset(&mbs, 0, sizeof(mbs)); + + if ((size = wcrtomb(buf, c, &mbs)) == (size_t)-1) + return 0; + return size; } -protected ssize_t -ct_encode_char(char *dst, size_t len, Char c) +libedit_private ssize_t +ct_encode_char(char *dst, size_t len, wchar_t c) { ssize_t l = 0; if (len < ct_enc_width(c)) return -1; - l = ct_wctomb(dst, c); + l = wctomb(dst, c); if (l < 0) { - ct_wctomb_reset; + wctomb(NULL, L'\0'); l = 0; } return l; } -size_t -ct_mbrtowc(wchar_t *wc, const char *s, size_t n) +libedit_private const wchar_t * +ct_visual_string(const wchar_t *s, ct_buffer_t *conv) { - mbstate_t mbs; - /* This only works because UTF-8 is stateless */ - memset(&mbs, 0, sizeof(mbs)); - return mbrtowc(wc, s, n, &mbs); -} + wchar_t *dst; + ssize_t used; -#else + if (!s) + return NULL; -size_t -ct_mbrtowc(wchar_t *wc, const char *s, size_t n) -{ - if (s == NULL) - return 0; - if (n == 0) - return (size_t)-2; - if (wc != NULL) - *wc = *s; - return *s != '\0'; -} -#endif + if (ct_conv_wbuff_resize(conv, CT_BUFSIZ) == -1) + return NULL; -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; + used = 0; + dst = conv->wbuff; while (*s) { - used = ct_visual_char(dst, buffsize - (size_t)(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! */ + used = ct_visual_char(dst, + conv->wsize - (size_t)(dst - conv->wbuff), *s); + if (used != -1) { + ++s; + dst += used; + continue; } - else - ++s; - dst += used; + + /* failed to encode, need more buffer space */ + used = dst - conv->wbuff; + if (ct_conv_wbuff_resize(conv, conv->wsize + CT_BUFSIZ) == -1) + return NULL; + dst = conv->wbuff + 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; + + if (dst >= (conv->wbuff + conv->wsize)) { /* sigh */ + used = dst - conv->wbuff; + if (ct_conv_wbuff_resize(conv, conv->wsize + CT_BUFSIZ) == -1) + return NULL; + dst = conv->wbuff + used; } - *dst = 0; - return buff; -out: - el_free(buff); - buffsize = 0; - return NULL; + + *dst = L'\0'; + return conv->wbuff; } -protected int -ct_visual_width(Char c) +libedit_private int +ct_visual_width(wchar_t c) { int t = ct_chr_class(c); switch (t) { @@ -293,7 +265,6 @@ 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: @@ -301,20 +272,14 @@ 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) +libedit_private ssize_t +ct_visual_char(wchar_t *dst, size_t len, wchar_t c) { int t = ct_chr_class(c); switch (t) { @@ -339,7 +304,6 @@ * so this is right */ if ((ssize_t)len < ct_visual_width(c)) return -1; /* insufficient space */ -#ifdef WIDECHAR *dst++ = '\\'; *dst++ = 'U'; *dst++ = '+'; @@ -351,13 +315,6 @@ *dst++ = tohexdigit(((unsigned int) c >> 4) & 0xf); *dst = tohexdigit(((unsigned int) c ) & 0xf); return c > 0xffff ? 8 : 7; -#else - *dst++ = '\\'; -#define tooctaldigit(v) (Char)((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 */ @@ -368,16 +325,16 @@ -protected int -ct_chr_class(Char c) +libedit_private int +ct_chr_class(wchar_t c) { if (c == '\t') return CHTYPE_TAB; else if (c == '\n') return CHTYPE_NL; - else if (IsASCII(c) && Iscntrl(c)) + else if (c < 0x100 && iswcntrl(c)) return CHTYPE_ASCIICTL; - else if (Isprint(c)) + else if (iswprint(c)) return CHTYPE_PRINT; else return CHTYPE_NONPRINT; Index: lib/libedit/common.c =================================================================== --- lib/libedit/common.c +++ lib/libedit/common.c @@ -1,4 +1,4 @@ -/* $NetBSD: common.c,v 1.40 2016/03/02 19:24:20 christos Exp $ */ +/* $NetBSD: common.c,v 1.48 2018/02/26 17:36:14 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -51,6 +51,7 @@ #include "el.h" #include "common.h" +#include "fcns.h" #include "parse.h" #include "vi.h" @@ -58,7 +59,7 @@ * Indicate end of file * [^D] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ ed_end_of_file(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -73,7 +74,7 @@ * Add character to the line * Insert a character [bound to all insert keys] */ -protected el_action_t +libedit_private el_action_t ed_insert(EditLine *el, wint_t c) { int count = el->el_state.argument; @@ -93,14 +94,14 @@ || el->el_line.cursor >= el->el_line.lastchar) c_insert(el, 1); - *el->el_line.cursor++ = (Char)c; + *el->el_line.cursor++ = c; re_fastaddc(el); /* fast refresh for one char. */ } else { if (el->el_state.inputmode != MODE_REPLACE_1) c_insert(el, el->el_state.argument); while (count-- && el->el_line.cursor < el->el_line.lastchar) - *el->el_line.cursor++ = (Char)c; + *el->el_line.cursor++ = c; re_refresh(el); } @@ -115,11 +116,11 @@ * Delete from beginning of current word to cursor * [M-^?] [^W] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ ed_delete_prev_word(EditLine *el, wint_t c __attribute__((__unused__))) { - Char *cp, *p, *kp; + wchar_t *cp, *p, *kp; if (el->el_line.cursor == el->el_line.buffer) return CC_ERROR; @@ -143,15 +144,14 @@ * Delete character under cursor * [^D] [x] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ ed_delete_next_char(EditLine *el, wint_t c __attribute__((__unused__))) { #ifdef DEBUG_EDIT #define EL el->el_line (void) fprintf(el->el_errfile, - "\nD(b: %p(" FSTR ") c: %p(" FSTR ") last: %p(" FSTR - ") limit: %p(" FSTR ")\n", + "\nD(b: %p(%ls) c: %p(%ls) last: %p(%ls) limit: %p(%ls)\n", EL.buffer, EL.buffer, EL.cursor, EL.cursor, EL.lastchar, EL.lastchar, EL.limit, EL.limit); #endif @@ -191,11 +191,11 @@ * Cut to the end of line * [^K] [^K] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ ed_kill_line(EditLine *el, wint_t c __attribute__((__unused__))) { - Char *kp, *cp; + wchar_t *kp, *cp; cp = el->el_line.cursor; kp = el->el_chared.c_kill.buf; @@ -212,7 +212,7 @@ * Move cursor to the end of line * [^E] [^E] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ ed_move_to_end(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -235,7 +235,7 @@ * Move cursor to the beginning of line * [^A] [^A] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ ed_move_to_beg(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -244,7 +244,7 @@ if (el->el_map.type == MAP_VI) { /* We want FIRST non space character */ - while (Isspace(*el->el_line.cursor)) + while (iswspace(*el->el_line.cursor)) el->el_line.cursor++; if (el->el_chared.c_vcmd.action != NOP) { cv_delfini(el); @@ -259,7 +259,7 @@ * Exchange the character to the left of the cursor with the one under it * [^T] [^T] */ -protected el_action_t +libedit_private el_action_t ed_transpose_chars(EditLine *el, wint_t c) { @@ -273,7 +273,7 @@ /* must have at least two chars entered */ c = el->el_line.cursor[-2]; el->el_line.cursor[-2] = el->el_line.cursor[-1]; - el->el_line.cursor[-1] = (Char)c; + el->el_line.cursor[-1] = c; return CC_REFRESH; } else return CC_ERROR; @@ -284,11 +284,11 @@ * Move to the right one character * [^F] [^F] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ ed_next_char(EditLine *el, wint_t c __attribute__((__unused__))) { - Char *lim = el->el_line.lastchar; + wchar_t *lim = el->el_line.lastchar; if (el->el_line.cursor >= lim || (el->el_line.cursor == lim - 1 && @@ -313,7 +313,7 @@ * Move to the beginning of the current word * [M-b] [b] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ ed_prev_word(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -339,7 +339,7 @@ * Move to the left one character * [^B] [^B] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ ed_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -364,16 +364,18 @@ * Add the next character typed verbatim * [^V] [^V] */ -protected el_action_t -ed_quoted_insert(EditLine *el, wint_t c) +libedit_private el_action_t +/*ARGSUSED*/ +ed_quoted_insert(EditLine *el, wint_t c __attribute__((__unused__))) { int num; + wchar_t ch; tty_quotemode(el); - num = el_wgetc(el, &c); + num = el_wgetc(el, &ch); tty_noquotemode(el); if (num == 1) - return ed_insert(el, c); + return ed_insert(el, ch); else return ed_end_of_file(el, 0); } @@ -382,11 +384,11 @@ /* ed_digit(): * Adds to argument or enters a digit */ -protected el_action_t +libedit_private el_action_t ed_digit(EditLine *el, wint_t c) { - if (!Isdigit(c)) + if (!iswdigit(c)) return CC_ERROR; if (el->el_state.doingarg) { @@ -410,11 +412,11 @@ * Digit that starts argument * For ESC-n */ -protected el_action_t +libedit_private el_action_t ed_argument_digit(EditLine *el, wint_t c) { - if (!Isdigit(c)) + if (!iswdigit(c)) return CC_ERROR; if (el->el_state.doingarg) { @@ -434,7 +436,7 @@ * Indicates unbound character * Bound to keys that are not assigned */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ ed_unassigned(EditLine *el __attribute__((__unused__)), wint_t c __attribute__((__unused__))) @@ -444,17 +446,13 @@ } -/** - ** TTY key handling. - **/ - -/* ed_tty_sigint(): - * Tty interrupt character - * [^C] +/* ed_ignore(): + * Input characters that have no effect + * [^C ^O ^Q ^S ^Z ^\ ^]] [^C ^O ^Q ^S ^\] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ -ed_tty_sigint(EditLine *el __attribute__((__unused__)), +ed_ignore(EditLine *el __attribute__((__unused__)), wint_t c __attribute__((__unused__))) { @@ -462,95 +460,11 @@ } -/* ed_tty_dsusp(): - * Tty delayed suspend character - * [^Y] - */ -protected el_action_t -/*ARGSUSED*/ -ed_tty_dsusp(EditLine *el __attribute__((__unused__)), - wint_t c __attribute__((__unused__))) -{ - - return CC_NORM; -} - - -/* ed_tty_flush_output(): - * Tty flush output characters - * [^O] - */ -protected el_action_t -/*ARGSUSED*/ -ed_tty_flush_output(EditLine *el __attribute__((__unused__)), - wint_t c __attribute__((__unused__))) -{ - - return CC_NORM; -} - - -/* ed_tty_sigquit(): - * Tty quit character - * [^\] - */ -protected el_action_t -/*ARGSUSED*/ -ed_tty_sigquit(EditLine *el __attribute__((__unused__)), - wint_t c __attribute__((__unused__))) -{ - - return CC_NORM; -} - - -/* ed_tty_sigtstp(): - * Tty suspend character - * [^Z] - */ -protected el_action_t -/*ARGSUSED*/ -ed_tty_sigtstp(EditLine *el __attribute__((__unused__)), - wint_t c __attribute__((__unused__))) -{ - - return CC_NORM; -} - - -/* ed_tty_stop_output(): - * Tty disallow output characters - * [^S] - */ -protected el_action_t -/*ARGSUSED*/ -ed_tty_stop_output(EditLine *el __attribute__((__unused__)), - wint_t c __attribute__((__unused__))) -{ - - return CC_NORM; -} - - -/* ed_tty_start_output(): - * Tty allow output characters - * [^Q] - */ -protected el_action_t -/*ARGSUSED*/ -ed_tty_start_output(EditLine *el __attribute__((__unused__)), - wint_t c __attribute__((__unused__))) -{ - - return CC_NORM; -} - - /* ed_newline(): * Execute command * [^J] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ ed_newline(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -566,7 +480,7 @@ * Delete the character to the left of the cursor * [^?] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ ed_delete_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -586,7 +500,7 @@ * Clear screen leaving current line at the top * [^L] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ ed_clear_screen(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -601,7 +515,7 @@ * Redisplay everything * ^R */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ ed_redisplay(EditLine *el __attribute__((__unused__)), wint_t c __attribute__((__unused__))) @@ -615,12 +529,12 @@ * Erase current line and start from scratch * [^G] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ ed_start_over(EditLine *el, wint_t c __attribute__((__unused__))) { - ch_reset(el, 0); + ch_reset(el); return CC_REFRESH; } @@ -629,7 +543,7 @@ * First character in a bound sequence * Placeholder for external keys */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ ed_sequence_lead_in(EditLine *el __attribute__((__unused__)), wint_t c __attribute__((__unused__))) @@ -643,7 +557,7 @@ * Move to the previous history line * [^P] [k] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ ed_prev_history(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -655,7 +569,7 @@ if (el->el_history.eventno == 0) { /* save the current buffer * away */ - (void) Strncpy(el->el_history.buf, el->el_line.buffer, + (void) wcsncpy(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); @@ -680,7 +594,7 @@ * Move to the next history line * [^N] [j] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ ed_next_history(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -707,11 +621,11 @@ * Search previous in history for a line matching the current * next search history [M-P] [K] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ ed_search_prev_history(EditLine *el, wint_t c __attribute__((__unused__))) { - const Char *hp; + const wchar_t *hp; int h; int found = 0; @@ -727,7 +641,7 @@ return CC_ERROR; } if (el->el_history.eventno == 0) { - (void) Strncpy(el->el_history.buf, el->el_line.buffer, + (void) wcsncpy(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); @@ -748,7 +662,7 @@ #ifdef SDEBUG (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp); #endif - if ((Strncmp(hp, el->el_line.buffer, (size_t) + if ((wcsncmp(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)) { @@ -775,11 +689,11 @@ * Search next in history for a line matching the current * [M-N] [J] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ ed_search_next_history(EditLine *el, wint_t c __attribute__((__unused__))) { - const Char *hp; + const wchar_t *hp; int h; int found = 0; @@ -803,7 +717,7 @@ #ifdef SDEBUG (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp); #endif - if ((Strncmp(hp, el->el_line.buffer, (size_t) + if ((wcsncmp(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)) @@ -829,11 +743,11 @@ * Move up one line * Could be [k] [^p] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ ed_prev_line(EditLine *el, wint_t c __attribute__((__unused__))) { - Char *ptr; + wchar_t *ptr; int nchars = c_hpos(el); /* @@ -872,11 +786,11 @@ * Move down one line * Could be [j] [^n] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ ed_next_line(EditLine *el, wint_t c __attribute__((__unused__))) { - Char *ptr; + wchar_t *ptr; int nchars = c_hpos(el); /* @@ -906,14 +820,14 @@ * Editline extended command * [M-X] [:] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ ed_command(EditLine *el, wint_t c __attribute__((__unused__))) { - Char tmpbuf[EL_BUFSIZ]; + wchar_t tmpbuf[EL_BUFSIZ]; int tmplen; - tmplen = c_gets(el, tmpbuf, STR("\n: ")); + tmplen = c_gets(el, tmpbuf, L"\n: "); terminal__putc(el, '\n'); if (tmplen < 0 || (tmpbuf[tmplen] = 0, parse_line(el, tmpbuf)) == -1) Index: lib/libedit/config.h =================================================================== --- lib/libedit/config.h +++ lib/libedit/config.h @@ -48,13 +48,13 @@ /* #undef HAVE_LIBCURSES */ /* Define to 1 if you have the `ncurses' library (-lncurses). */ -#define HAVE_LIBNCURSES 1 +/* #undef HAVE_LIBNCURSES */ /* Define to 1 if you have the `termcap' library (-ltermcap). */ /* #undef HAVE_LIBTERMCAP */ /* Define to 1 if you have the `terminfo' library (-lterminfo). */ -/* #undef HAVE_LIBTERMINFO */ +#define HAVE_LIBTERMINFO 1 /* Define to 1 if you have the `termlib' library (-ltermlib). */ /* #undef HAVE_LIBTERMLIB */ @@ -75,7 +75,7 @@ #define HAVE_MEMSET 1 /* Define to 1 if you have the header file. */ -#define HAVE_NCURSES_H 1 +/* #undef HAVE_NCURSES_H */ /* Define to 1 if you have the header file, and it defines `DIR'. */ /* #undef HAVE_NDIR_H */ @@ -257,9 +257,6 @@ /* Define to 1 if the system provides the SIZE_MAX constant */ #define HAVE_SIZE_MAX 1 -/* Define to 1 if you want wide-character code */ -/* #undef WIDECHAR */ - /* Define to 1 if on MINIX. */ /* #undef _MINIX */ @@ -284,7 +281,7 @@ #include "sys.h" -#undef SCCSID -#undef LIBC_SCCS -#undef lint -#undef SIZE_T_MAX +/* #undef SCCSID */ +/* #undef LIBC_SCCS */ +/* #undef lint */ + Index: lib/libedit/edit/readline/readline.h =================================================================== --- lib/libedit/edit/readline/readline.h +++ lib/libedit/edit/readline/readline.h @@ -1,4 +1,4 @@ -/* $NetBSD: readline.h,v 1.39 2016/02/17 19:47:49 christos Exp $ */ +/* $NetBSD: readline.h,v 1.46 2019/06/07 15:19:29 christos Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -40,11 +40,13 @@ /* typedefs */ typedef int Function(const char *, int); +typedef char *CPFunction(const char *, int); typedef void VFunction(void); typedef void rl_vcpfunc_t(char *); typedef char **rl_completion_func_t(const char *, int, int); typedef char *rl_compentry_func_t(const char *, int); typedef int rl_command_func_t(int, int); +typedef int rl_hook_func_t(void); /* only supports length */ typedef struct { @@ -99,23 +101,23 @@ #endif extern const char *rl_library_version; extern int rl_readline_version; -extern char *rl_readline_name; +extern const char *rl_readline_name; extern FILE *rl_instream; extern FILE *rl_outstream; extern char *rl_line_buffer; extern int rl_point, rl_end; extern int history_base, history_length; extern int max_input_history; -extern char *rl_basic_word_break_characters; +extern const char *rl_basic_word_break_characters; extern char *rl_completer_word_break_characters; -extern char *rl_completer_quote_characters; +extern const char *rl_completer_quote_characters; extern rl_compentry_func_t *rl_completion_entry_function; extern char *(*rl_completion_word_break_hook)(void); extern rl_completion_func_t *rl_attempted_completion_function; extern int rl_attempted_completion_over; extern int rl_completion_type; extern int rl_completion_query_items; -extern char *rl_special_prefixes; +extern const char *rl_special_prefixes; extern int rl_completion_append_character; extern int rl_inhibit_completion; extern Function *rl_pre_input_hook; @@ -123,6 +125,7 @@ extern char *rl_terminal_name; extern int rl_already_prompted; extern char *rl_prompt; +extern int rl_done; /* * The following is not implemented */ @@ -138,6 +141,7 @@ extern VFunction *rl_completion_display_matches_hook; extern VFunction *rl_prep_term_function; extern VFunction *rl_deprep_term_function; +extern rl_hook_func_t *rl_event_hook; extern int readline_echoing_p; extern int _rl_print_completions_horizontally; @@ -148,6 +152,7 @@ void using_history(void); int add_history(const char *); void clear_history(void); +int append_history(int, const char *); void stifle_history(int); int unstifle_history(void); int history_is_stifled(void); @@ -160,6 +165,7 @@ int history_set_pos(int); HIST_ENTRY *previous_history(void); HIST_ENTRY *next_history(void); +HIST_ENTRY **history_list(void); int history_search(const char *, int); int history_search_prefix(const char *, int); int history_search_pos(const char *, int, int); @@ -176,12 +182,13 @@ char *username_completion_function(const char *, int); int rl_complete(int, int); int rl_read_key(void); -char **completion_matches(const char *, rl_compentry_func_t *); +char **completion_matches(/* const */ char *, rl_compentry_func_t *); 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_reset_terminal(const char *); +void rl_resize_terminal(void); int rl_bind_key(int, rl_command_func_t *); int rl_newline(int, int); void rl_callback_read_char(void); @@ -194,7 +201,7 @@ int rl_read_init_file(const char *); int rl_parse_and_bind(const char *); int rl_variable_bind(const char *, const char *); -void rl_stuff_char(int); +int rl_stuff_char(int); int rl_add_defun(const char *, rl_command_func_t *, int); HISTORY_STATE *history_get_history_state(void); void rl_get_screen_size(int *, int *); @@ -206,6 +213,8 @@ void rl_forced_update_display(void); int rl_set_prompt(const char *); int rl_on_new_line(void); +void rl_reset_after_signal(void); +void rl_echo_signal_char(int); /* * The following are not implemented Index: lib/libedit/editline.3 =================================================================== --- lib/libedit/editline.3 +++ lib/libedit/editline.3 @@ -1,4 +1,4 @@ -.\" $NetBSD: editline.3,v 1.88 2016/02/25 14:59:22 wiz Exp $ +.\" $NetBSD: editline.3,v 1.99 2018/11/18 17:09:39 christos Exp $ .\" .\" Copyright (c) 1997-2014 The NetBSD Foundation, Inc. .\" All rights reserved. @@ -28,7 +28,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 28, 2017 +.Dd November 9, 2018 .Dt EDITLINE 3 .Os .Sh NAME @@ -94,11 +94,11 @@ .Ft int .Fn el_getc "EditLine *e" "char *ch" .Ft int -.Fn el_wgetc "EditLine *e" "wchar_t *ch" +.Fn el_wgetc "EditLine *e" "wchar_t *wc" .Ft void -.Fn el_push "EditLine *e" "const char *str" +.Fn el_push "EditLine *e" "const char *mbs" .Ft void -.Fn el_wpush "EditLine *e" "const wchar_t *str" +.Fn el_wpush "EditLine *e" "const wchar_t *wcs" .Ft int .Fn el_parse "EditLine *e" "int argc" "const char *argv[]" .Ft int @@ -115,7 +115,7 @@ .Fn el_source "EditLine *e" "const char *file" .Ft void .Fn el_resize "EditLine *e" -.Fn int +.Ft int .Fn el_cursor "EditLine *e" "int count" .Ft const LineInfo * .Fn el_line "EditLine *e" @@ -183,8 +183,6 @@ locale set by the application program and never uses .Xr setlocale 3 to change the locale. -The only locales supported are UTF-8 and the default C or POSIX locale. -If any other locale is set, behaviour is undefined. .Sh LINE EDITING FUNCTIONS The line editing functions use a common data structure, .Fa EditLine , @@ -252,18 +250,16 @@ and must be copied if the data is to be retained. .It Fn el_wgetc Read a wide character from the tty, respecting the current locale, -or from the input stream written by -.Fn el_wpush -and -.Fn el_push +or from the input queue described in +.Xr editline 7 if that is not empty, and store it in -.Fa ch . +.Fa wc . If an invalid or incomplete character is found, it is discarded, .Va errno is set to .Er EILSEQ , and the next character is read and stored in -.Fa ch . +.Fa wc . Returns 1 if a valid character was read, 0 on end of file, or \-1 on .Xr read 2 failure. @@ -286,17 +282,23 @@ and return \-1. In the C or POSIX locale, this simply reads a byte, but for any other locale, including UTF-8, this is rarely useful. +.It Fn el_wpush +Push the wide character string +.Fa wcs +back onto the input queue described in +.Xr editline 7 . +If the queue overflows, for example due to a recursive macro, +or if an error occurs, for example because +.Fa wcs +is +.Dv NULL +or memory allocation fails, the function beeps at the user, +but does not report the problem to the caller. .It Fn el_push -Pushes -.Fa str -back onto the input stream. -This is used by the macro expansion mechanism. -Refer to the description of -.Ic bind -.Fl s -in -.Xr editrc 5 -for more information. +Use the current locale to convert the multibyte string +.Fa mbs +to a wide character string, and pass the result to +.Fn el_wpush . .It Fn el_parse Parses the .Fa argv @@ -356,6 +358,8 @@ 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. +Note that the literal escape character cannot be the last character in the +prompt, as the escape sequence is attached to the next character in the prompt. .Dv 0 unsets it. .It Dv EL_REFRESH @@ -505,18 +509,31 @@ In unbuffered mode, .Fn el_gets will return immediately after processing a single character. -.It Dv EL_GETCFN , Fa "int (*f)(EditLine *, char *c)" -Define the character reading function as -.Fa f , -which is to return the number of characters read and store them in -.Fa c . -This function is called internally by -.Fn el_gets +.It Dv EL_GETCFN , Fa "el_rfunc_t f" +Whenever reading a character, use the function +.Bd -ragged -offset indent -compact +.Ft int +.Fo f +.Fa "EditLine *e" +.Fa "wchar_t *wc" +.Fc +.Ed +which stores the character in +.Fa wc +and returns 1 on success, 0 on end of file, or \-1 on I/O or encoding +errors. +Functions internally using it include +.Fn el_wgets , +.Fn el_wgetc , +.Fn el_gets , and .Fn el_getc . -The builtin function can be set or restored with the special function -name -.Dq Dv EL_BUILTIN_GETCFN . +Initially, a builtin function is installed, and replacing it +is discouraged because writing such a function is very error prone. +The builtin function can be restored at any time by passing the +special value +.Dv EL_BUILTIN_GETCFN +instead of a function pointer. .It Dv EL_CLIENTDATA , Fa "void *data" Register .Fa data @@ -560,7 +577,7 @@ .Bl -tag -width 4n .It Dv EL_PROMPT , Fa "char *(*f)(EditLine *)" , Fa "char *c" Set -.Fa f . +.Fa f to a pointer to the function that displays the prompt. If .Fa c @@ -569,7 +586,7 @@ set it to the start/stop literal prompt character. .It Dv EL_RPROMPT , Fa "char *(*f)(EditLine *)" , Fa "char *c" Set -.Fa f . +.Fa f to a pointer to the function that displays the prompt. If .Fa c @@ -594,7 +611,7 @@ .It Dv EL_SIGNAL , Fa "int *s" Set .Fa s -to non zero if +to non-zero if .Nm has installed private signal handlers (see .Fn el_get @@ -603,10 +620,12 @@ Set .Fa c to 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 -.Dq Dv EL_BUILTIN_GETCFN -in the case of the default builtin function. +.It Dv EL_GETCFN , Fa "el_rfunc_t *f" +Set +.Fa f +to a pointer to the function that reads characters, or to +.Dv EL_BUILTIN_GETCFN +if the builtin function is in use. .It Dv EL_CLIENTDATA , Fa "void **data" Set .Fa data @@ -650,6 +669,8 @@ is .Dv NULL , try +.Pa $EDITRC +and if that is not set .Pa $HOME/.editrc . Refer to .Xr editrc 5 @@ -763,8 +784,10 @@ Return the last element in the history. .It Dv H_PREV Return the previous element in the history. +It is newer than the current one. .It Dv H_NEXT Return the next element in the history. +It is older than the current one. .It Dv H_CURR Return the current element in the history. .It Dv H_SET , Fa "int position" @@ -820,6 +843,13 @@ .Ft FILE pointer .Fa fp . +.It Dv H_NSAVE_FP , Fa "size_t n" , Fa "FILE *fp" +Save the last +.Ft n +history entries to the opened +.Ft FILE +pointer +.Fa fp . .It Dv H_SETUNIQUE , Fa "int unique" Set flag that adjacent identical event strings should not be entered into the history. @@ -830,14 +860,14 @@ Delete the event numbered .Fa e . This function is only provided for -.Xr readline 3 +.Nm readline compatibility. The caller is responsible for free'ing the string in the returned .Fa HistEvent . .El .Pp .Fn history -returns \*[Gt]= 0 if the operation +returns >= 0 if the operation .Fa op succeeds. Otherwise, \-1 is returned and @@ -923,7 +953,8 @@ .Xr signal 3 , .Xr termcap 3 , .Xr editrc 5 , -.Xr termcap 5 +.Xr termcap 5 , +.Xr editline 7 .Sh HISTORY The .Nm Index: lib/libedit/editline.7 =================================================================== --- lib/libedit/editline.7 +++ lib/libedit/editline.7 @@ -0,0 +1,937 @@ +.\" $NetBSD: editline.7,v 1.5 2016/05/09 21:27:55 christos Exp $ +.\" $OpenBSD: editline.7,v 1.1 2016/04/20 01:11:45 schwarze Exp $ +.\" +.\" Copyright (c) 2016 Ingo Schwarze +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.\" $FreeBSD$ +.\" +.Dd May 7, 2016 +.Dt EDITLINE 7 +.Os +.Sh NAME +.Nm editline +.Nd line editing user interface +.Sh DESCRIPTION +When a program using the +.Xr editline 3 +library prompts for an input string using the function +.Xr el_wgets 3 , +it reads characters from the terminal. +Invalid input bytes that do not form characters are silently +discarded. +For each character read, one editor command is executed. +The mapping of input characters to editor commands depends on the +editing mode. +There are three editing modes: vi insert mode, vi command mode, +and emacs mode. +The default is vi insert mode. +The program can switch the default to emacs mode by using the +.Xr el_set 3 +or +.Xr el_parse 3 +functions, and the user can switch to emacs mode either in the +.Xr editrc 5 +configuration file or interactively with the +.Ic ed-command +editor command, in all three cases executing the +.Ic bind Fl e +builtin command. +.Pp +If trying to read from the terminal results in end of file or an +error, the library signals end of file to the program and does not +return a string. +.Ss Input character bindings +All default bindings described below can be overridden by individual +programs and can be changed with the +.Xr editrc 5 +.Ic bind +builtin command. +.Pp +In the following tables, +.Sq Ctrl- +indicates a character with the bit 0x40 flipped, and +.Sq Meta- +indicates a character with the bit 0x80 set. +In vi insert mode and in emacs mode, all Meta-characters considered +printable by the current +.Xr locale 1 +are bound to +.Ic ed-insert +instead of to the editor command listed below. +Consequently, in UTF-8 mode, most of the Meta-characters are not +directly accessible because their code points are occupied by +printable Unicode characters, and Meta-characters are usually input +using the +.Ic em-meta-next +editor command. +For example, to enter +.Sq Meta-B +in order to call the +.Ic ed-prev-word +editor command in emacs mode, call +.Ic em-meta-next +by pressing and releasing the escape key (or equivalently, Ctrl-[), +then press and release the +.Sq B +key. +If you have configured a Meta-key on your keyboard, for example +with +.Ql setxkbmap -option altwin:left_meta_win , +the Ctrl-Meta-characters are directly accessible. +For example, to enter +.Sq Ctrl-Meta-H +in order to call the +.Ic ed-delete-prev-word +editor command in emacs mode, hold down the keys +.Sq Ctrl , +.Sq Meta , +and +.Sq H +at the same time. +Alternatively, press and release the escape key, then press and +release +.Sq Ctrl-H . +.Pp +In vi input mode, input characters are bound to the following editor +commands by default: +.Bl -column -offset indent "Ctrl-Z, TSTP" "ed-search-next-history" +.It Ctrl-D, EOF Ta Ic vi-list-or-eof +.It Ctrl-H, BS Ta Ic vi-delete-prev-char +.It Ctrl-J, LF Ta Ic ed-newline +.It Ctrl-M, CR Ta Ic ed-newline +.It Ctrl-Q Ta Ic ed-tty-start-output +.It Ctrl-S Ta Ic ed-tty-stop-output +.It Ctrl-U Ta Ic vi-kill-line-prev +.It Ctrl-V Ta Ic ed-quoted-insert +.It Ctrl-W Ta Ic ed-delete-prev-word +.It Ctrl-[, ESC Ta Ic vi-command-mode +.It Ctrl-\e, QUIT Ta Ic ed-tty-sigquit +.It Ctrl-?, DEL Ta Ic vi-delete-prev-char +.El +.Pp +All other input characters except the NUL character (Ctrl-@) are +bound to +.Ic ed-insert . +.Pp +In vi command mode, input characters are bound to the following +editor commands by default: +.Bl -column -offset indent "Ctrl-Z, TSTP" "ed-search-next-history" +.It Ctrl-A Ta Ic ed-move-to-beg +.It Ctrl-C, INT Ta Ic ed-tty-sigint +.It Ctrl-E Ta Ic ed-move-to-end +.It Ctrl-H, BS Ta Ic ed-delete-prev-char +.It Ctrl-J, LF Ta Ic ed-newline +.It Ctrl-K Ta Ic ed-kill-line +.It Ctrl-L, FF Ta Ic ed-clear-screen +.It Ctrl-M, CR Ta Ic ed-newline +.It Ctrl-N Ta Ic ed-next-history +.It Ctrl-O Ta Ic ed-tty-flush-output +.It Ctrl-P Ta Ic ed-prev-history +.It Ctrl-Q Ta Ic ed-tty-start-output +.It Ctrl-R Ta Ic ed-redisplay +.It Ctrl-S Ta Ic ed-tty-stop-output +.It Ctrl-U Ta Ic vi-kill-line-prev +.It Ctrl-W Ta Ic ed-delete-prev-word +.It Ctrl-[, ESC Ta Ic em-meta-next +.It Ctrl-\e, QUIT Ta Ic ed-tty-sigquit +.It Space Ta Ic ed-next-char +.It # Ta Ic vi-comment-out +.It $ Ta Ic ed-move-to-end +.It % Ta Ic vi-match +.It + Ta Ic ed-next-history +.It \&, Ta Ic vi-repeat-prev-char +.It - Ta Ic ed-prev-history +.It \&. Ta Ic vi-redo +.It / Ta Ic vi-search-prev +.It 0 Ta Ic vi-zero +.It 1 to 9 Ta Ic ed-argument-digit +.It \&: Ta Ic ed-command +.It \&; Ta Ic vi-repeat-next-char +.It \&? Ta Ic vi-search-next +.It @ Ta Ic vi-alias +.It A Ta Ic vi-add-at-eol +.It B Ta Ic vi-prev-big-word +.It C Ta Ic vi-change-to-eol +.It D Ta Ic ed-kill-line +.It E Ta Ic vi-end-big-word +.It F Ta Ic vi-prev-char +.It G Ta Ic vi-to-history-line +.It I Ta Ic vi-insert-at-bol +.It J Ta Ic ed-search-next-history +.It K Ta Ic ed-search-prev-history +.It N Ta Ic vi-repeat-search-prev +.It O Ta Ic ed-sequence-lead-in +.It P Ta Ic vi-paste-prev +.It R Ta Ic vi-replace-mode +.It S Ta Ic vi-substitute-line +.It T Ta Ic vi-to-prev-char +.It U Ta Ic vi-undo-line +.It W Ta Ic vi-next-big-word +.It X Ta Ic ed-delete-prev-char +.It Y Ta Ic vi-yank-end +.It \&[ Ta Ic ed-sequence-lead-in +.It ^ Ta Ic ed-move-to-beg +.It _ Ta Ic vi-history-word +.It a Ta Ic vi-add +.It b Ta Ic vi-prev-word +.It c Ta Ic vi-change-meta +.It d Ta Ic vi-delete-meta +.It e Ta Ic vi-end-word +.It f Ta Ic vi-next-char +.It h Ta Ic ed-prev-char +.It i Ta Ic vi-insert +.It j Ta Ic ed-next-history +.It k Ta Ic ed-prev-history +.It l Ta Ic ed-next-char +.It n Ta Ic vi-repeat-search-next +.It p Ta Ic vi-paste-next +.It r Ta Ic vi-replace-char +.It s Ta Ic vi-substitute-char +.It t Ta Ic vi-to-next-char +.It u Ta Ic vi-undo +.It v Ta Ic vi-histedit +.It w Ta Ic vi-next-word +.It x Ta Ic ed-delete-next-char +.It y Ta Ic vi-yank +.It \&| Ta Ic vi-to-column +.It ~ Ta Ic vi-change-case +.It Ctrl-?, DEL Ta Ic ed-delete-prev-char +.It Meta-O Ta Ic ed-sequence-lead-in +.It Meta-[ Ta Ic ed-sequence-lead-in +.El +.Pp +In emacs mode, input characters are bound to the following editor +commands by default: +.Bl -column -offset indent "Ctrl-Z, TSTP" "ed-search-next-history" +.It 0 to 9 Ta Ic ed-digit +.It Ctrl-@, NUL Ta Ic em-set-mark +.It Ctrl-A Ta Ic ed-move-to-beg +.It Ctrl-B Ta Ic ed-prev-char +.It Ctrl-C, INT Ta Ic ed-tty-sigint +.It Ctrl-D, EOF Ta Ic em-delete-or-list +.It Ctrl-E Ta Ic ed-move-to-end +.It Ctrl-F Ta Ic ed-next-char +.It Ctrl-H, BS Ta Ic em-delete-prev-char +.It Ctrl-J, LF Ta Ic ed-newline +.It Ctrl-K Ta Ic ed-kill-line +.It Ctrl-L, FF Ta Ic ed-clear-screen +.It Ctrl-M, CR Ta Ic ed-newline +.It Ctrl-N Ta Ic ed-next-history +.It Ctrl-O Ta Ic ed-tty-flush-output +.It Ctrl-P Ta Ic ed-prev-history +.It Ctrl-Q Ta Ic ed-tty-start-output +.It Ctrl-R Ta Ic ed-redisplay +.It Ctrl-S Ta Ic ed-tty-stop-output +.It Ctrl-T Ta Ic ed-transpose-chars +.It Ctrl-U Ta Ic ed-kill-line +.It Ctrl-V Ta Ic ed-quoted-insert +.It Ctrl-W Ta Ic em-kill-region +.It Ctrl-X Ta Ic ed-sequence-lead-in +.It Ctrl-Y Ta Ic em-yank +.It Ctrl-Z, TSTP Ta Ic ed-tty-sigtstp +.It Ctrl-[, ESC Ta Ic em-meta-next +.It Ctrl-\e, QUIT Ta Ic ed-tty-sigquit +.It Ctrl-] Ta Ic ed-tty-dsusp +.It Ctrl-?, DEL Ta Ic em-delete-prev-char +.It Ctrl-Meta-H Ta Ic ed-delete-prev-word +.It Ctrl-Meta-L Ta Ic ed-clear-screen +.It Ctrl-Meta-_ Ta Ic em-copy-prev-word +.It Meta-0 to 9 Ta Ic ed-argument-digit +.It Meta-B Ta Ic ed-prev-word +.It Meta-C Ta Ic em-capitol-case +.It Meta-D Ta Ic em-delete-next-word +.It Meta-F Ta Ic em-next-word +.It Meta-L Ta Ic em-lower-case +.It Meta-N Ta Ic ed-search-next-history +.It Meta-O Ta Ic ed-sequence-lead-in +.It Meta-P Ta Ic ed-search-prev-history +.It Meta-U Ta Ic em-upper-case +.It Meta-W Ta Ic em-copy-region +.It Meta-X Ta Ic ed-command +.It Meta-[ Ta Ic ed-sequence-lead-in +.It Meta-b Ta Ic ed-prev-word +.It Meta-c Ta Ic em-capitol-case +.It Meta-d Ta Ic em-delete-next-word +.It Meta-f Ta Ic em-next-word +.It Meta-l Ta Ic em-lower-case +.It Meta-n Ta Ic ed-search-next-history +.It Meta-p Ta Ic ed-search-prev-history +.It Meta-u Ta Ic em-upper-case +.It Meta-w Ta Ic em-copy-region +.It Meta-x Ta Ic ed-command +.It Ctrl-Meta-? Ta Ic ed-delete-prev-word +.El +.Pp +The remaining +.Xr ascii 7 +characters in the range 0x20 to 0x7e are bound to +.Ic ed-insert . +.Pp +If standard output is not connected to a terminal device +or +.Xr el_set 3 +was used to set +.Dv EL_EDITMODE +to 0, all input character bindings are disabled and all characters +typed are appended to the edit buffer. +In that case, the edit buffer is returned to the program after a +newline or carriage return character is typed, or after the first +character typed if +.Xr el_set 3 +was used to set +.Dv EL_UNBUFFERED +to non-zero. +.Ss Editor commands +Most editor commands accept an optional argument. +The argument is entered by prefixing the editor command with one +or more of the editor commands +.Ic ed-argument-digit , +.Ic ed-digit , +.Ic em-universal-argument , +or +.Ic vi-zero . +When an argument is not provided, it defaults to 1. +For most editor commands, the effect of an argument is to repeatedly +execute the command that number of times. +.Pp +When talking about a character string from a left character to a +right character, the left character is included in the string, while +the right character is not included. +.Pp +If an editor command causes an error, the input character is discarded, +no action occurs, and the terminal bell is rung. +In case of a non-fatal error, the terminal bell is also rung, +but the editor command takes effect anyway. +.Pp +In the following list, the default key bindings are listed after +each editor command. +.Bl -tag -width 4n +.It Ic ed-argument-digit Pq vi command: 1 to 9; emacs: Meta-0 to Meta-9 +If in argument input mode, append the input digit to the argument +being read. +Otherwise, switch to argument input mode and use the input digit +as the most significant digit of the argument. +It is an error if the input character is not a digit or if the +existing argument is already greater than a million. +.It Ic ed-clear-screen Pq vi command: Ctrl-L; emacs: Ctrl-L, Ctrl-Meta-L +Clear the screen and display the edit buffer at the top. +Ignore any argument. +.It Ic ed-command Pq vi command: So \&: Sc ; emacs: Meta-X, Meta-x +Read a line from the terminal bypassing the normal line editing +functionality and execute that line as an +.Xr editrc 5 +builtin command. +If in vi command mode, also switch back to vi insert mode. +Ignore any argument. +.It Ic ed-delete-next-char Pq vi command: x +Delete the character at the cursor position. +With an argument, delete that number of characters. +In emacs mode, it is an error if the cursor is at the end of the +edit buffer. +In vi mode, the last character in the edit buffer is deleted in +that case, and it is an error if the buffer is empty. +.It Ic ed-delete-prev-char Pq vi command: X, Ctrl-H, BS, Ctrl-?, DEL +Delete the character to the left of the cursor position. +With an argument, delete that number of characters. +It is an error if the cursor is at the beginning of the edit buffer. +.It Ic ed-delete-prev-word Pq vi: Ctrl-W; emacs: Ctrl-Meta-H, Ctrl-Meta-? +Move to the left to the closest beginning of a word, delete the +string from that position to the cursor, and save it to the cut +buffer. +With an argument, delete that number of words. +It is an error if the cursor is at the beginning of the edit buffer. +.It Ic ed-digit Pq emacs: 0 to 9 +If in argument input mode, append the input digit to the argument +being read. +Otherwise, call +.Ic ed-insert . +It is an error if the input character is not a digit or if the +existing argument is already greater than a million. +.It Ic ed-end-of-file Pq not bound by default +Discard the edit buffer and indicate end of file to the program. +Ignore any argument. +.It Ic ed-ignore Pq various +Discard the input character and do nothing. +.It Ic ed-insert Pq vi input: almost all; emacs: printable characters +In insert mode, insert the input character left of the cursor +position. +In replace mode, overwrite the character at the cursor and move the +cursor to the right by one character position. +Accept an argument to do this repeatedly. +It is an error if the input character is the NUL character (Ctrl-@). +Failure to enlarge the edit buffer also results in an error. +.It Ic ed-kill-line Pq vi command: D, Ctrl-K; emacs: Ctrl-K, Ctrl-U +Delete the string from the cursor position to the end of the line +and save it to the cut buffer. +Ignore any argument. +.It Ic ed-move-to-beg Pq vi command: ^, Ctrl-A; emacs: Ctrl-A +In vi mode, move the cursor to the first non-space character in the +edit buffer. +In emacs mode, move the cursor to the beginning of the edit buffer. +Ignore any argument. +Can be used as a movement command after +.Ic vi_change_meta , +.Ic vi_delete_meta , +or +.Ic vi_yank . +.It Ic ed-move-to-end Pq vi command: $, Ctrl-E; emacs: Ctrl-E +Move the cursor to the end of the edit buffer. +Ignore any argument. +Can be used as a movement command after +.Ic vi_change_meta , +.Ic vi_delete_meta , +or +.Ic vi_yank . +.It Ic ed-newline Pq all modes: Ctrl-J, LF, Ctrl-M, CR +Append a newline character to the edit buffer and return the edit +buffer to the program. +Ignore any argument. +.It Ic ed-next-char Pq vi command: Space, l; emacs: Ctrl-F +Move the cursor one character position to the right. +With an argument, move by that number of characters. +Can be used as a movement command after +.Ic vi_change_meta , +.Ic vi_delete_meta , +or +.Ic vi_yank . +It is an error if the cursor is already at the end of the edit +buffer. +.It Ic ed-next-history Pq vi command: j, +, Ctrl-N; emacs: Ctrl-N +Replace the edit buffer with the next history line. +That line is older than the current line. +With an argument, go forward by that number of history lines. +It is a non-fatal error to advance by more lines than are available. +.It Ic ed-next-line Pq not bound by default +Move the cursor down one line. +With an argument, move down by that number of lines. +It is an error if the edit buffer does not contain enough newline +characters to the right of the cursor position. +.It Ic ed-prev-char Pq vi command: h; emacs: Ctrl-B +Move the cursor one character position to the left. +With an argument, move by that number of characters. +Can be used as a movement command after +.Ic vi_change_meta , +.Ic vi_delete_meta , +or +.Ic vi_yank . +It is an error if the cursor is already at the beginning of the +edit buffer. +.It Ic ed-prev-history Pq vi command: k, -, Ctrl-P; emacs: Ctrl-P +Replace the edit buffer with the previous history line. +That line is newer than the current line. +With an argument, go back by that number of lines. +It is a non-fatal error to back up by more lines than are available. +.It Ic ed-prev-line Pq not bound by default +Move the cursor up one line. +With an argument, move up by that number of lines. +It is an error if the edit buffer does not contain enough newline +characters to the left of the cursor position. +.It Ic ed-prev-word Pq emacs: Meta-B, Meta-b +Move the cursor to the left to the closest beginning of a word. +With an argument, repeat that number of times. +Can be used as a movement command after +.Ic vi_change_meta , +.Ic vi_delete_meta , +or +.Ic vi_yank . +It is an error if the cursor is already at the beginning of the +edit buffer. +.It Ic ed-quoted-insert Pq vi insert, emacs: Ctrl-V +Read one character from the terminal bypassing the normal line +editing functionality and call +.Ic ed-insert +on it. +If trying to read the character returns end of file or an error, +call +.Ic ed-end-of-file +instead. +.It Ic ed-redisplay Pq vi command, emacs: Ctrl-R +Redisplay everything. +Ignore any argument. +.It Ic ed-search-next-history Pq vi command: J; emacs: Meta-N, Meta-n +Replace the edit buffer with the next matching history entry. +.It Ic ed-search-prev-history Pq vi command: K; emacs: Meta-P, Meta-p +Replace the edit buffer with the previous matching history entry. +.It Ic ed-sequence-lead-in Pq vi cmd: O, \&[; emacs: Ctrl-X;\ + both: Meta-O, Meta-[ +Call a macro. +See the section about +.Sx Macros +below for details. +.It Ic ed-start-over Pq not bound by default +Discard the contents of the edit buffer and start from scratch. +Ignore any argument. +.It Ic ed-transpose-chars Pq emacs: Ctrl-T +Exchange the character at the cursor position with the one to the +left of it and move the cursor to the character to the right of the +two exchanged characters. +Ignore any argument. +It is an error if the cursor is at the beginning of the edit buffer +or if the edit buffer contains less than two characters. +.It Ic ed-unassigned Pq all characters not listed +This editor command always results in an error. +.It Ic em-capitol-case Pq emacs: Meta-C, Meta-c +Capitalize the string from the cursor to the end of the current +word. +That is, if it contains at least one alphabetic character, convert +the first alphabetic character to upper case, and convert all +characters to the right of it to lower case. +In any case, move the cursor to the next character after the end +of the current word. +.It Ic em-copy-prev-word Pq emacs: Ctrl-Meta-_ +Copy the string from the beginning of the current word to the cursor +and insert it to the left of the cursor. +Move the cursor to the character after the inserted string. +It is an error if the cursor is at the beginning of the edit buffer. +.It Ic em-copy-region Pq emacs: Meta-W, Meta-w +Copy the string from the cursor to the mark to the cut buffer. +It is an error if the mark is not set. +.It Ic em-delete-next-word Pq emacs: Meta-D, Meta-d +Delete the string from the cursor to the end of the current word +and save it to the cut buffer. +It is an error if the cursor is at the end of the edit buffer. +.It Ic em-delete-or-list Pq emacs: Ctrl-D, EOF +If the cursor is not at the end of the line, delete the character +at the cursor. +If the edit buffer is empty, indicate end of file to the program. +It is an error if the cursor is at the end of the edit buffer and +the edit buffer is not empty. +.It Ic em-delete-prev-char Pq emacs: Ctrl-H, BS, Ctrl-?, DEL +Delete the character to the left of the cursor. +It is an error if the cursor is at the beginning of the edit buffer. +.It Ic em-exchange-mark Pq not bound by default +Exchange the cursor and the mark. +.It Ic em-gosmacs-transpose Pq not bound by default +Exchange the two characters to the left of the cursor. +It is an error if the cursor is on the first or second character +of the edit buffer. +.It Ic em-inc-search-next Pq not bound by default +Emacs incremental next search. +.It Ic em-inc-search-prev Pq not bound by default +Emacs incremental reverse search. +.It Ic em-kill-line Pq not bound by default +Delete the entire contents of the edit buffer and save it to the +cut buffer. +.It Ic em-kill-region Pq emacs: Ctrl-W +Delete the string from the cursor to the mark and save it to the +cut buffer. +It is an error if the mark is not set. +.It Ic em-lower-case Pq emacs: Meta-L, Meta-l +Convert the characters from the cursor to the end of the current +word to lower case. +.It Ic em-meta-next Pq vi command, emacs: Ctrl-[, ESC +Set the bit 0x80 on the next character typed. +Unless the resulting code point is printable, holding down the +.Sq Meta- +key while typing that character is a simpler way to achieve the +same effect. +.It Ic em-next-word Pq Meta-F, Meta-f +Move the cursor to the end of the current word. +Can be used as a movement command after +.Ic vi_change_meta , +.Ic vi_delete_meta , +or +.Ic vi_yank . +It is an error if the cursor is already at the end of the edit +buffer. +.It Ic em-set-mark Pq emacs: Ctrl-Q, NUL +Set the mark at the current cursor position. +.It Ic em-toggle-overwrite Pq not bound by default +Switch from insert to overwrite mode or vice versa. +.It Ic em-universal-argument Pq not bound by default +If in argument input mode, multiply the argument by 4. +Otherwise, switch to argument input mode and set the argument to 4. +It is an error if the existing argument is already greater than a +million. +.It Ic em-upper-case Pq emacs: Meta-U, Meta-u +Convert the characters from the cursor to the end of the current +word to upper case. +.It Ic em-yank Pq emacs: Ctrl-Y +Paste the cut buffer to the left of the cursor. +.It Ic vi-add Pq vi command: a +Switch to vi insert mode. +Unless the cursor is already at the end of the edit buffer, move +it one character position to the right. +.It Ic vi-add-at-eol Pq vi command: A +Switch to vi insert mode and move the cursor to the end of the edit +buffer. +.It Ic vi-alias Pq vi command: @ +If an alias function was defined by calling the +.Xr el_set 3 +or +.Xr el_wset 3 +function with the argument +.Dv EL_ALIAS_TEXT , +read one character from the terminal bypassing the normal line +editing functionality, call the alias function passing the argument that was specified with +.Dv EL_ALIAS_TEXT +as the first argument and the character read, with an underscore +prepended, as the second argument, and pass the string returned +from the alias function to +.Xr el_wpush 3 . +It is an error if no alias function is defined or if trying to read +the character results in end of file or an error. +.It Ic vi-change-case Pq vi command: ~ +Change the case of the character at the cursor and move the cursor +one character position to the right. +It is an error if the cursor is already at the end of the edit +buffer. +.It Ic vi-change-meta Pq vi command: c +Delete the string from the cursor to the position specified by the +following movement command and save a copy of it to the cut buffer. +When given twice in a row, instead delete the whole contents of the +edit buffer and save a copy of it to the cut buffer. +In either case, switch to vi insert mode after that. +.It Ic vi-change-to-eol Pq vi command: C +Delete the string from the cursor position to the end of the line +and save it to the cut buffer, then switch to vi insert mode. +.It Ic vi-command-mode Pq vi insert: Ctrl-[, ESC +Discard pending actions and arguments and switch to vi command mode. +Unless the cursor is already at the beginning of the edit buffer, +move it to the left by one character position. +.It Ic vi-comment-out Pq vi command: # +Insert a +.Sq # +character at the beginning of the edit buffer and return the edit +buffer to the program. +.It Ic vi-delete-meta Pq vi command: d +Delete the string from the cursor to the position specified by the +following movement command and save a copy of it to the cut buffer. +When given twice in a row, instead delete the whole contents of the +edit buffer and save a copy of it to the cut buffer. +.It Ic vi-delete-prev-char Pq vi insert: Ctrl-H, BS, Ctrl-?, DEL +Delete the character to the left of the cursor. +It is an error if the cursor is already at the beginning of the +edit buffer. +.It Ic vi-end-big-word Pq vi command: E +Move the cursor to the end of the current space delimited word. +Can be used as a movement command after +.Ic vi_change_meta , +.Ic vi_delete_meta , +or +.Ic vi_yank . +It is an error if the cursor is already at the end of the edit +buffer. +.It Ic vi-end-word Pq vi command: e +Move the cursor to the end of the current word. +Can be used as a movement command after +.Ic vi_change_meta , +.Ic vi_delete_meta , +or +.Ic vi_yank . +It is an error if the cursor is already at the end of the edit +buffer. +.It Ic vi-history-word Pq vi command: _ +Insert the first word from the most recent history entry after the +cursor, move the cursor after to the character after the inserted +word, and switch to vi insert mode. +It is an error if there is no history entry or the most recent +history entry is empty. +.It Ic vi-insert Pq vi command: i +Enter insert mode. +.It Ic vi-insert-at-bol Pq vi command: I +Move the cursor to the beginning of the edit buffer and switch to +vi insert mode. +.It Ic vi-kill-line-prev Pq vi: Ctrl-U +Delete the string from the beginning of the edit buffer to the +cursor and save it to the cut buffer. +.It Ic vi-list-or-eof Pq vi insert: Ctrl-D, EOF +If the edit buffer is empty, indicate end of file to the program. +It is an error if the edit buffer is not empty. +.It Ic vi-match Pq vi command: % +Consider opening and closing parentheses, braces, and brackets as +delimiters. +If the cursor is not at a delimiter, move it to the right until it +gets to one, then move it to the matching delimiter. +Can be used as a movement command after +.Ic vi_change_meta , +.Ic vi_delete_meta , +or +.Ic vi_yank . +It is an error if there is no delimiter at the cursor or in the +string to the right of the cursor, or if the first such delimiter +has no matching delimiter. +.It Ic vi-next-big-word Pq vi command: W +Move the cursor to the right to the beginning of the next space +delimited word. +Can be used as a movement command after +.Ic vi_change_meta , +.Ic vi_delete_meta , +or +.Ic vi_yank . +It is an error if the cursor is already at the end of the edit +buffer or on its last character. +.It Ic vi-next-char Pq vi command: f +Read one character from the terminal bypassing the normal line +editing functionality and move the cursor to the right to the next +instance of that character in the edit buffer. +Can be used as a movement command after +.Ic vi_change_meta , +.Ic vi_delete_meta , +or +.Ic vi_yank . +If trying to read the character results in end of file or an error, +call +.Ic ed-end-of-file +instead. +It is an error if the character is not found searching to the right +in the edit buffer. +.It Ic vi-next-word Pq vi command: w +Move the cursor to the right to the beginning of the next word. +Can be used as a movement command after +.Ic vi_change_meta , +.Ic vi_delete_meta , +or +.Ic vi_yank . +It is an error if the cursor is already at the end of the edit +buffer or on its last character. +.It Ic vi-paste-next Pq vi command: p +Insert a copy of the cut buffer to the right of the cursor. +It is an error if the cut buffer is empty. +.It Ic vi-paste-prev Pq vi command: P +Insert a copy of the cut buffer to the left of the cursor. +It is an error if the cut buffer is empty. +.It Ic vi-prev-big-word Pq vi command: B +Move the cursor to the left to the next beginning of a space delimited +word. +Can be used as a movement command after +.Ic vi_change_meta , +.Ic vi_delete_meta , +or +.Ic vi_yank . +It is an error if the cursor is already at the beginning of the +edit buffer. +.It Ic vi-prev-char Pq vi command: F +Read one character from the terminal bypassing the normal line +editing functionality and move the cursor to the left to the next +instance of that character in the edit buffer. +Can be used as a movement command after +.Ic vi_change_meta , +.Ic vi_delete_meta , +or +.Ic vi_yank . +If trying to read the character results in end of file or an error, +call +.Ic ed-end-of-file +instead. +It is an error if the character is not found searching to the left +in the edit buffer. +.It Ic vi-prev-word Pq vi command: b +Move the cursor to the left to the next beginning of a word. +Can be used as a movement command after +.Ic vi_change_meta , +.Ic vi_delete_meta , +or +.Ic vi_yank . +It is an error if the cursor is already at the beginning of the +edit buffer. +.It Ic vi-redo Pq vi command: Sq \&. +Redo the last non-motion command. +.It Ic vi-repeat-next-char Pq vi command: Sq \&; +Repeat the most recent character search in the same search direction. +Can be used as a movement command after +.Ic vi_change_meta , +.Ic vi_delete_meta , +or +.Ic vi_yank . +.It Ic vi-repeat-prev-char Pq vi command: Sq \&, +Repeat the most recent character search in the opposite search +direction. +Can be used as a movement command after +.Ic vi_change_meta , +.Ic vi_delete_meta , +or +.Ic vi_yank . +.It Ic vi-repeat-search-next Pq vi command: n +Repeat the most recent history search in the same search direction. +.It Ic vi-repeat-search-prev Pq vi command: N +Repeat the most recent history search in the opposite search +direction. +.It Ic vi-replace-char Pq vi command: r +Switch to vi replace mode, and automatically switch back to vi +command mode after the next character typed. +See +.Ic ed-insert +for a description of replace mode. +It is an error if the cursor is at the end of the edit buffer. +.It Ic vi-replace-mode Pq vi command: R +Switch to vi replace mode. +This is a variant of vi insert mode; see +.Ic ed-insert +for the difference. +.It Ic vi-search-next Pq vi command: \&? +Replace the edit buffer with the next matching history entry. +.It Ic vi-search-prev Pq vi command: / +Replace the edit buffer with the previous matching history entry. +.It Ic vi-substitute-char Pq vi command: s +Delete the character at the cursor and switch to vi insert mode. +.It Ic vi-substitute-line Pq vi command: S +Delete the entire contents of the edit buffer, save a copy of it +in the cut buffer, and enter vi insert mode. +.It Ic vi-to-column Pq vi command: \&| +Move the cursor to the column specified as the argument. +Can be used as a movement command after +.Ic vi_change_meta , +.Ic vi_delete_meta , +or +.Ic vi_yank . +.It Ic vi-to-history-line Pq vi command: G +Replace the edit buffer with the specified history entry. +.It Ic vi-to-next-char Pq vi command: t +Read one character from the terminal bypassing the normal line +editing functionality and move the cursor to the right to the +character before the next instance of that character in the edit +buffer. +Can be used as a movement command after +.Ic vi_change_meta , +.Ic vi_delete_meta , +or +.Ic vi_yank . +If trying to read the character results in end of file or an error, +call +.Ic ed-end-of-file +instead. +It is an error if the character is not found searching to the right +in the edit buffer. +.It Ic vi-to-prev-char Pq vi command: T +Read one character from the terminal bypassing the normal line +editing functionality and move the cursor to the left to the character +after the next instance of that character in the edit buffer. +Can be used as a movement command after +.Ic vi_change_meta , +.Ic vi_delete_meta , +or +.Ic vi_yank . +If trying to read the character results in end of file or an error, +call +.Ic ed-end-of-file +instead. +It is an error if the character is not found searching to the left +in the edit buffer. +.It Ic vi-undo Pq vi command: u +Undo the last change. +.It Ic vi-undo-line Pq vi command: U +Undo all changes to the edit buffer. +.It Ic vi-yank Pq vi command: y +Copy the string from the cursor to the position specified by the +following movement command to the cut buffer. +When given twice in a row, instead copy the whole contents of the +edit buffer to the cut buffer. +.It Ic vi-yank-end Pq vi command: Y +Copy the string from the cursor to the end of the edit buffer to +the cut buffer. +.It Ic vi-zero Pq vi command: 0 +If in argument input mode, multiply the argument by ten. +Otherwise, move the cursor to the beginning of the edit buffer. +Can be used as a movement command after +.Ic vi_change_meta , +.Ic vi_delete_meta , +or +.Ic vi_yank . +.El +.Ss Macros +If an input character is bound to the editor command +.Ic ed-sequence-lead-in , +.Nm +attempts to call a macro. +If the input character by itself forms the name of a macro, that +macro is executed. +Otherwise, additional input characters are read until the string +read forms the name of a macro, in which case that macro is executed, +or until the string read matches the beginning of none of the existing +macro names, in which case the string including the final, mismatching +character is discarded and the terminal bell is rung. +.Pp +There are two kinds of macros. +Command macros execute a single editor command. +Keyboard macros return a string of characters that is appended +as a new line to the +.Sx Input Queue . +.Pp +The following command macros are defined by default in vi command +mode and in emacs mode: +.Bl -column -offset indent "Esc O A, Esc O A" "em-exchange-mark" +.It Esc \&[ A, Esc O A Ta Ic ed-prev-history +.It Esc \&[ B, Esc O B Ta Ic ed-next-history +.It Esc \&[ C, Esc O C Ta Ic ed-next-char +.It Esc \&[ D, Esc O D Ta Ic ed-prev-char +.It Esc \&[ F, Esc O F Ta Ic ed-move-to-end +.It Esc \&[ H, Esc O H Ta Ic ed-move-to-beg +.El +.Pp +In vi command mode, they are also defined by default without the +initial escape character. +.Pp +In addition, the +.Nm +library tries to bind the strings generated by the arrow keys +as reported by the +.Xr terminfo 5 +database to these editor commands, unless that would clobber +user settings. +.Pp +In emacs mode, the two-character string +.Dq Ctrl-X Ctrl-X +is bound to the +.Ic em-exchange-mark +editor command. +.Ss Input Queue +The +.Nm +library maintains an input queue operated in FIFO mode. +Whenever it needs an input character, it takes the first character +from the first line of the input queue. +When the queue is empty, it reads from the terminal. +.Pp +A line can be appended to the end of the input queue in several ways: +.Bl -dash -offset indent +.It +By calling one of the keyboard +.Sx Macros . +.It +By calling the editor command +.Ic vi-redo . +.It +By calling the editor command +.Ic vi-alias . +.It +By pressing a key in emacs incremental search mode that doesn't +have a special meaning in that mode but returns to normal emacs +mode. +.It +If an application program directly calls the functions +.Xr el_push 3 +or +.Xr el_wpush 3 , +it can provide additional, program-specific ways +of appending to the input queue. +.El +.Sh SEE ALSO +.Xr mg 1 , +.Xr vi 1 , +.Xr editline 3 , +.Xr el_wgets 3 , +.Xr el_wpush 3 , +.Xr el_wset 3 , +.Xr editrc 5 +.Sh HISTORY +This manual page first appeared in +.Ox 6.0 +and +.Nx 8 . +.Sh AUTHORS +.An -nosplit +This manual page was written by +.An Ingo Schwarze Aq Mt schwarze@openbsd.org . Index: lib/libedit/editrc.5 =================================================================== --- lib/libedit/editrc.5 +++ lib/libedit/editrc.5 @@ -1,4 +1,4 @@ -.\" $NetBSD: editrc.5,v 1.29 2014/12/25 13:39:41 wiz Exp $ +.\" $NetBSD: editrc.5,v 1.33 2017/06/27 01:22:58 kre Exp $ .\" .\" Copyright (c) 1997-2000 The NetBSD Foundation, Inc. .\" All rights reserved. @@ -28,7 +28,7 @@ .\" .\" $FreeBSD$ .\" -.Dd December 25, 2014 +.Dd May 22, 2016 .Dt EDITRC 5 .Os .Sh NAME @@ -90,21 +90,19 @@ .Pp The following builtin commands are available: .Bl -tag -width 4n -.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 Oo Ar command Oc Oc -Without options, list all bound keys, and the editor command to which -each is bound. -If +.It Ic bind Oo Fl aeklrsv Oc Op Ar key Op Ar command +Without options and arguments, list all bound keys and macros, and +the editor command or input string to which each one is bound. +If only .Ar key -is supplied, show the bindings for -.Ar key . +is supplied, show the binding for that key or macro. If .Ar key command -is supplied, bind +is supplied, bind the editor .Ar command -to -.Ar key . -Options include: +to that key or macro. +.Pp +The options are as follows: .Bl -tag -width 4n .It Fl a List or change key bindings in the @@ -123,13 +121,15 @@ .It Fl l List all editor commands and a short description of each. .It Fl r -Remove a key's binding. +Remove the binding of the key or macro +.Ar key . .It Fl s +Define a keyboard macro rather than a key binding or command macro: .Ar command -is taken as a literal string and treated as terminal input when +is taken as a literal string and appended to the input queue whenever .Ar key is typed. -Bound keys in +Bound keys and macros in .Ar command are themselves reinterpreted, and this continues for ten levels of interpretation. @@ -139,10 +139,10 @@ bindings. .El .Pp -.Ar command -may be one of the commands documented in -.Sx "EDITOR COMMANDS" -below, or another key. +The +.Xr editline 7 +manual documents all editor commands and contains more information +about macros and the input queue. .Pp .Ar key and @@ -245,7 +245,7 @@ Oo Ar -mode Oc Oo Ar mode Oc Oo Ar char=c Oc Control which tty modes that .Nm -will not allow the user to change. +won't allow the user to change. .Fl d , .Fl q or @@ -295,225 +295,26 @@ List the values of all the terminal capabilities (see .Xr termcap 5 ) . .El -.Sh EDITOR COMMANDS -The following editor commands are available for use in key bindings: -.\" Section automatically generated with makelist -.Bl -tag -width 4n -.It Ic vi-paste-next -Vi paste previous deletion to the right of the cursor. -.It Ic vi-paste-prev -Vi paste previous deletion to the left of the cursor. -.It Ic vi-prev-big-word -Vi move to the previous space delimited word. -.It Ic vi-prev-word -Vi move to the previous word. -.It Ic vi-next-big-word -Vi move to the next space delimited word. -.It Ic vi-next-word -Vi move to the next word. -.It Ic vi-change-case -Vi change case of character under the cursor and advance one character. -.It Ic vi-change-meta -Vi change prefix command. -.It Ic vi-insert-at-bol -Vi enter insert mode at the beginning of line. -.It Ic vi-replace-char -Vi replace character under the cursor with the next character typed. -.It Ic vi-replace-mode -Vi enter replace mode. -.It Ic vi-substitute-char -Vi replace character under the cursor and enter insert mode. -.It Ic vi-substitute-line -Vi substitute entire line. -.It Ic vi-change-to-eol -Vi change to end of line. -.It Ic vi-insert -Vi enter insert mode. -.It Ic vi-add -Vi enter insert mode after the cursor. -.It Ic vi-add-at-eol -Vi enter insert mode at end of line. -.It Ic vi-delete-meta -Vi delete prefix command. -.It Ic vi-end-big-word -Vi move to the end of the current space delimited word. -.It Ic vi-end-word -Vi move to the end of the current word. -.It Ic vi-undo -Vi undo last change. -.It Ic vi-command-mode -Vi enter command mode (use alternative key bindings). -.It Ic vi-zero -Vi move to the beginning of line. -.It Ic vi-delete-prev-char -Vi move to previous character (backspace). -.It Ic vi-list-or-eof -Vi list choices for completion or indicate end of file if empty line. -.It Ic vi-kill-line-prev -Vi cut from beginning of line to cursor. -.It Ic vi-search-prev -Vi search history previous. -.It Ic vi-search-next -Vi search history next. -.It Ic vi-repeat-search-next -Vi repeat current search in the same search direction. -.It Ic vi-repeat-search-prev -Vi repeat current search in the opposite search direction. -.It Ic vi-next-char -Vi move to the character specified next. -.It Ic vi-prev-char -Vi move to the character specified previous. -.It Ic vi-to-next-char -Vi move up to the character specified next. -.It Ic vi-to-prev-char -Vi move up to the character specified previous. -.It Ic vi-repeat-next-char -Vi repeat current character search in the same search direction. -.It Ic vi-repeat-prev-char -Vi repeat current character search in the opposite search direction. -.It Ic vi-match -Vi go to matching () {} or []. -.It Ic vi-undo-line -Vi undo all changes to line. -.It Ic vi-to-column -Vi go to specified column. -.It Ic vi-yank-end -Vi yank to end of line. -.It Ic vi-yank -Vi yank. -.It Ic vi-comment-out -Vi comment out current command. -.It Ic vi-alias -Vi include shell alias. -.It Ic vi-to-history-line -Vi go to specified history file line.. -.It Ic vi-histedit -Vi edit history line with vi. -.It Ic vi-history-word -Vi append word from previous input line. -.It Ic vi-redo -Vi redo last non-motion command. -.It Ic em-delete-or-list -Delete character under cursor or list completions if at end of line. -.It Ic em-delete-next-word -Cut from cursor to end of current word. -.It Ic em-yank -Paste cut buffer at cursor position. -.It Ic em-kill-line -Cut the entire line and save in cut buffer. -.It Ic em-kill-region -Cut area between mark and cursor and save in cut buffer. -.It Ic em-copy-region -Copy area between mark and cursor to cut buffer. -.It Ic em-gosmacs-transpose -Exchange the two characters before the cursor. -.It Ic em-next-word -Move next to end of current word. -.It Ic em-upper-case -Uppercase the characters from cursor to end of current word. -.It Ic em-capitol-case -Capitalize the characters from cursor to end of current word. -.It Ic em-lower-case -Lowercase the characters from cursor to end of current word. -.It Ic em-set-mark -Set the mark at cursor. -.It Ic em-exchange-mark -Exchange the cursor and mark. -.It Ic em-universal-argument -Universal argument (argument times 4). -.It Ic em-meta-next -Add 8th bit to next character typed. -.It Ic em-toggle-overwrite -Switch from insert to overwrite mode or vice versa. -.It Ic em-copy-prev-word -Copy current word to cursor. -.It Ic em-inc-search-next -Emacs incremental next search. -.It Ic em-inc-search-prev -Emacs incremental reverse search. -.It Ic ed-end-of-file -Indicate end of file. -.It Ic ed-insert -Add character to the line. -.It Ic ed-delete-prev-word -Delete from beginning of current word to cursor. -.It Ic ed-delete-next-char -Delete character under cursor. -.It Ic ed-kill-line -Cut to the end of line. -.It Ic ed-move-to-end -Move cursor to the end of line. -.It Ic ed-move-to-beg -Move cursor to the beginning of line. -.It Ic ed-transpose-chars -Exchange the character to the left of the cursor with the one under it. -.It Ic ed-next-char -Move to the right one character. -.It Ic ed-prev-word -Move to the beginning of the current word. -.It Ic ed-prev-char -Move to the left one character. -.It Ic ed-quoted-insert -Add the next character typed verbatim. -.It Ic ed-digit -Adds to argument or enters a digit. -.It Ic ed-argument-digit -Digit that starts argument. -.It Ic ed-unassigned -Indicates unbound character. -.It Ic ed-tty-sigint -Tty interrupt character. -.It Ic ed-tty-dsusp -Tty delayed suspend character. -.It Ic ed-tty-flush-output -Tty flush output characters. -.It Ic ed-tty-sigquit -Tty quit character. -.It Ic ed-tty-sigtstp -Tty suspend character. -.It Ic ed-tty-stop-output -Tty disallow output characters. -.It Ic ed-tty-start-output -Tty allow output characters. -.It Ic ed-newline -Execute command. -.It Ic ed-delete-prev-char -Delete the character to the left of the cursor. -.It Ic ed-clear-screen -Clear screen leaving current line at the top. -.It Ic ed-redisplay -Redisplay everything. -.It Ic ed-start-over -Erase current line and start from scratch. -.It Ic ed-sequence-lead-in -First character in a bound sequence. -.It Ic ed-prev-history -Move to the previous history line. -.It Ic ed-next-history -Move to the next history line. -.It Ic ed-search-prev-history -Search previous in history for a line matching the current. -.It Ic ed-search-next-history -Search next in history for a line matching the current. -.It Ic ed-prev-line -Move up one line. -.It Ic ed-next-line -Move down one line. -.It Ic ed-command -Editline extended command. +.Sh ENVIRONMENT +.Bl -tag -width "~/.editrcXXX" +.It Ev EDITRC +Names the default configuration file for the +.Xr editline 3 +library. .El -.\" End of section automatically generated with makelist .Sh FILES .Bl -tag -width "~/.editrcXXX" .It Pa ~/.editrc -User configuration file for the +Last resort, if no other file is specified, +user configuration file for the .Xr editline 3 library. .El .Sh SEE ALSO .Xr editline 3 , .Xr regex 3 , -.Xr termcap 5 +.Xr termcap 5 , +.Xr editline 7 .Sh AUTHORS .An -nosplit The Index: lib/libedit/el.h =================================================================== --- lib/libedit/el.h +++ lib/libedit/el.h @@ -1,4 +1,4 @@ -/* $NetBSD: el.h,v 1.34 2016/02/24 17:13:22 christos Exp $ */ +/* $NetBSD: el.h,v 1.45 2019/07/23 10:18:52 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -57,6 +57,7 @@ #define EDIT_DISABLED 0x04 #define UNBUFFERED 0x08 #define NARROW_HISTORY 0x40 +#define NO_RESET 0x80 typedef unsigned char el_action_t; /* Index to command array */ @@ -66,10 +67,10 @@ } coord_t; typedef struct el_line_t { - Char *buffer; /* Input line */ - Char *cursor; /* Cursor position */ - Char *lastchar; /* Last character */ - const Char *limit; /* Max position */ + wchar_t *buffer; /* Input line */ + wchar_t *cursor; /* Cursor position */ + wchar_t *lastchar; /* Last character */ + const wchar_t *limit; /* Max position */ } el_line_t; /* @@ -82,31 +83,34 @@ 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 */ + wchar_t thisch; /* char that generated it */ } el_state_t; /* * Until we come up with something better... */ #define el_malloc(a) malloc(a) +#define el_calloc(a,b) calloc(a, b) #define el_realloc(a,b) realloc(a, b) #define el_free(a) free(a) #include "tty.h" #include "prompt.h" +#include "literal.h" #include "keymacro.h" #include "terminal.h" #include "refresh.h" #include "chared.h" #include "search.h" #include "hist.h" -#include "fcns.h" /* el_func_t is needed for map.h */ +#include "fcns.h" /* el_func_t is needed for map.h */ #include "map.h" #include "sig.h" -#include "read.h" +struct el_read_t; + struct editline { - Char *el_prog; /* the program name */ + wchar_t *el_prog; /* the program name */ FILE *el_infile; /* Stdio stuff */ FILE *el_outfile; /* Stdio stuff */ FILE *el_errfile; /* Stdio stuff */ @@ -114,10 +118,9 @@ int el_outfd; /* Output file descriptor */ int el_errfd; /* Error 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 */ + wint_t **el_display; /* Real screen image = what is there */ + wint_t **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 */ @@ -126,21 +129,23 @@ el_refresh_t el_refresh; /* Refresh stuff */ el_prompt_t el_prompt; /* Prompt stuff */ el_prompt_t el_rprompt; /* Prompt stuff */ + el_literal_t el_literal; /* prompt literal bits */ el_chared_t el_chared; /* Characted editor stuff */ el_map_t el_map; /* Key mapping stuff */ el_keymacro_t el_keymacro; /* Key binding stuff */ el_history_t el_history; /* History stuff */ el_search_t el_search; /* Search stuff */ el_signal_t el_signal; /* Signal handling stuff */ - el_read_t el_read; /* Character reading stuff */ -#ifdef WIDECHAR + struct el_read_t *el_read; /* Character reading stuff */ + ct_buffer_t el_visual; /* Buffer for displayable str */ 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 **); +libedit_private int el_editmode(EditLine *, int, const wchar_t **); +libedit_private EditLine *el_init_internal(const char *, FILE *, FILE *, + FILE *, int, int, int, int); #ifdef DEBUG #define EL_ABORT(a) do { \ Index: lib/libedit/el.c =================================================================== --- lib/libedit/el.c +++ lib/libedit/el.c @@ -1,4 +1,4 @@ -/* $NetBSD: el.c,v 1.83 2016/02/24 17:13:22 christos Exp $ */ +/* $NetBSD: el.c,v 1.99 2019/07/23 10:18:52 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.83 2016/02/24 17:13:22 christos Exp $"); +__RCSID("$NetBSD: el.c,v 1.99 2019/07/23 10:18:52 christos Exp $"); #endif #endif /* not lint && not SCCSID */ #include @@ -49,38 +49,35 @@ #include #include #include +#include +#include #include #include #include -#ifdef WIDECHAR -#include -#include -#endif #include "el.h" #include "parse.h" +#include "read.h" /* el_init(): * Initialize editline and set default parameters. */ -public EditLine * +EditLine * el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr) { return el_init_fd(prog, fin, fout, ferr, fileno(fin), fileno(fout), fileno(ferr)); } -public EditLine * -el_init_fd(const char *prog, FILE *fin, FILE *fout, FILE *ferr, - int fdin, int fdout, int fderr) +libedit_private EditLine * +el_init_internal(const char *prog, FILE *fin, FILE *fout, FILE *ferr, + int fdin, int fdout, int fderr, int flags) { - EditLine *el = el_malloc(sizeof(*el)); + EditLine *el = el_calloc(1, sizeof(*el)); if (el == NULL) return NULL; - memset(el, 0, sizeof(EditLine)); - el->el_infile = fin; el->el_outfile = fout; el->el_errfile = ferr; @@ -89,7 +86,7 @@ el->el_outfd = fdout; el->el_errfd = fderr; - el->el_prog = Strdup(ct_decode_string(prog, &el->el_scratch)); + el->el_prog = wcsdup(ct_decode_string(prog, &el->el_scratch)); if (el->el_prog == NULL) { el_free(el); return NULL; @@ -98,7 +95,7 @@ /* * Initialize all the modules. Order is important!!! */ - el->el_flags = 0; + el->el_flags = flags; if (terminal_init(el) == -1) { el_free(el->el_prog); @@ -114,16 +111,25 @@ (void) hist_init(el); (void) prompt_init(el); (void) sig_init(el); - (void) read_init(el); - + (void) literal_init(el); + if (read_init(el) == -1) { + el_end(el); + return NULL; + } return el; } +EditLine * +el_init_fd(const char *prog, FILE *fin, FILE *fout, FILE *ferr, + int fdin, int fdout, int fderr) +{ + return el_init_internal(prog, fin, fout, ferr, fdin, fdout, fderr, 0); +} /* el_end(): * Clean up. */ -public void +void el_end(EditLine *el) { @@ -136,20 +142,22 @@ keymacro_end(el); map_end(el); if (!(el->el_flags & NO_TTY)) - tty_end(el); + tty_end(el, TCSAFLUSH); ch_end(el); + read_end(el->el_read); search_end(el); hist_end(el); prompt_end(el); sig_end(el); + literal_end(el); el_free(el->el_prog); -#ifdef WIDECHAR + el_free(el->el_visual.cbuff); + el_free(el->el_visual.wbuff); el_free(el->el_scratch.cbuff); el_free(el->el_scratch.wbuff); el_free(el->el_lgcyconv.cbuff); el_free(el->el_lgcyconv.wbuff); -#endif el_free(el); } @@ -157,20 +165,20 @@ /* el_reset(): * Reset the tty and the parser */ -public void +void el_reset(EditLine *el) { tty_cookedmode(el); - ch_reset(el, 0); /* XXX: Do we want that? */ + ch_reset(el); /* XXX: Do we want that? */ } /* el_set(): * set the editline parameters */ -public int -FUN(el,set)(EditLine *el, int op, ...) +int +el_wset(EditLine *el, int op, ...) { va_list ap; int rv = 0; @@ -207,7 +215,7 @@ el_pfunc_t p = va_arg(ap, el_pfunc_t); int c = va_arg(ap, int); - rv = prompt_set(el, p, (Char)c, op, 1); + rv = prompt_set(el, p, (wchar_t)c, op, 1); break; } @@ -216,7 +224,7 @@ break; case EL_EDITOR: - rv = map_set_editor(el, va_arg(ap, Char *)); + rv = map_set_editor(el, va_arg(ap, wchar_t *)); break; case EL_SIGNAL: @@ -232,36 +240,36 @@ case EL_ECHOTC: case EL_SETTY: { - const Char *argv[20]; + const wchar_t *argv[20]; int i; for (i = 1; i < (int)__arraycount(argv); i++) - if ((argv[i] = va_arg(ap, Char *)) == NULL) + if ((argv[i] = va_arg(ap, wchar_t *)) == NULL) break; switch (op) { case EL_BIND: - argv[0] = STR("bind"); + argv[0] = L"bind"; rv = map_bind(el, i, argv); break; case EL_TELLTC: - argv[0] = STR("telltc"); + argv[0] = L"telltc"; rv = terminal_telltc(el, i, argv); break; case EL_SETTC: - argv[0] = STR("settc"); + argv[0] = L"settc"; rv = terminal_settc(el, i, argv); break; case EL_ECHOTC: - argv[0] = STR("echotc"); + argv[0] = L"echotc"; rv = terminal_echotc(el, i, argv); break; case EL_SETTY: - argv[0] = STR("setty"); + argv[0] = L"setty"; rv = tty_stty(el, i, argv); break; @@ -275,8 +283,8 @@ case EL_ADDFN: { - Char *name = va_arg(ap, Char *); - Char *help = va_arg(ap, Char *); + wchar_t *name = va_arg(ap, wchar_t *); + wchar_t *help = va_arg(ap, wchar_t *); el_func_t func = va_arg(ap, el_func_t); rv = map_addfunc(el, name, help, func); @@ -305,7 +313,7 @@ case EL_GETCFN: { el_rfunc_t rc = va_arg(ap, el_rfunc_t); - rv = el_read_setfn(el, rc); + rv = el_read_setfn(el->el_read, rc); break; } @@ -382,8 +390,8 @@ /* el_get(): * retrieve the editline parameters */ -public int -FUN(el,get)(EditLine *el, int op, ...) +int +el_wget(EditLine *el, int op, ...) { va_list ap; int rv; @@ -403,14 +411,14 @@ case EL_PROMPT_ESC: case EL_RPROMPT_ESC: { el_pfunc_t *p = va_arg(ap, el_pfunc_t *); - Char *c = va_arg(ap, Char *); + wchar_t *c = va_arg(ap, wchar_t *); 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 wchar_t **)); break; case EL_SIGNAL: @@ -431,20 +439,16 @@ case EL_GETTC: { static char name[] = "gettc"; - char *argv[20]; - int i; - - for (i = 1; i < (int)__arraycount(argv); i++) - if ((argv[i] = va_arg(ap, char *)) == NULL) - break; - + char *argv[3]; argv[0] = name; - rv = terminal_gettc(el, i, argv); + argv[1] = va_arg(ap, char *); + argv[2] = va_arg(ap, void *); + rv = terminal_gettc(el, 3, argv); break; } case EL_GETCFN: - *va_arg(ap, el_rfunc_t *) = el_read_getfn(el); + *va_arg(ap, el_rfunc_t *) = el_read_getfn(el->el_read); rv = 0; break; @@ -495,18 +499,18 @@ /* el_line(): * Return editing info */ -public const TYPE(LineInfo) * -FUN(el,line)(EditLine *el) +const LineInfoW * +el_wline(EditLine *el) { - return (const TYPE(LineInfo) *)(void *)&el->el_line; + return (const LineInfoW *)(void *)&el->el_line; } /* el_source(): * Source a file */ -public int +int el_source(EditLine *el, const char *fname) { FILE *fp; @@ -514,24 +518,28 @@ ssize_t slen; char *ptr; char *path = NULL; - const Char *dptr; + const wchar_t *dptr; int error = 0; fp = NULL; if (fname == NULL) { #ifdef HAVE_ISSETUGID - static const char elpath[] = "/.editrc"; - size_t plen = sizeof(elpath); - if (issetugid()) return -1; - if ((ptr = getenv("HOME")) == NULL) - return -1; - plen += strlen(ptr); - if ((path = el_malloc(plen * sizeof(*path))) == NULL) - return -1; - (void)snprintf(path, plen, "%s%s", ptr, elpath); - fname = path; + + if ((fname = getenv("EDITRC")) == NULL) { + static const char elpath[] = "/.editrc"; + size_t plen = sizeof(elpath); + + if ((ptr = getenv("HOME")) == NULL) + return -1; + plen += strlen(ptr); + if ((path = el_calloc(plen, sizeof(*path))) == NULL) + return -1; + (void)snprintf(path, plen, "%s%s", ptr, + elpath + (*ptr == '\0')); + fname = path; + } #else /* * If issetugid() is missing, always return an error, in order @@ -541,6 +549,9 @@ return -1; #endif } + if (fname[0] == '\0') + return -1; + if (fp == NULL) fp = fopen(fname, "r"); if (fp == NULL) { @@ -560,7 +571,7 @@ if (!dptr) continue; /* loop until first non-space char or EOL */ - while (*dptr != '\0' && Isspace(*dptr)) + while (*dptr != '\0' && iswspace(*dptr)) dptr++; if (*dptr == '#') continue; /* ignore, this is a comment line */ @@ -578,7 +589,7 @@ /* el_resize(): * Called from program when terminal is resized */ -public void +void el_resize(EditLine *el) { int lins, cols; @@ -599,7 +610,7 @@ /* el_beep(): * Called from the program to beep */ -public void +void el_beep(EditLine *el) { @@ -610,25 +621,25 @@ /* el_editmode() * Set the state of EDIT_DISABLED from the `edit' command. */ -protected int +libedit_private int /*ARGSUSED*/ -el_editmode(EditLine *el, int argc, const Char **argv) +el_editmode(EditLine *el, int argc, const wchar_t **argv) { - const Char *how; + const wchar_t *how; if (argv == NULL || argc != 2 || argv[1] == NULL) return -1; how = argv[1]; - if (Strcmp(how, STR("on")) == 0) { + if (wcscmp(how, L"on") == 0) { el->el_flags &= ~EDIT_DISABLED; tty_rawmode(el); - } else if (Strcmp(how, STR("off")) == 0) { + } else if (wcscmp(how, L"off") == 0) { tty_cookedmode(el); el->el_flags |= EDIT_DISABLED; } else { - (void) fprintf(el->el_errfile, "edit: Bad value `" FSTR "'.\n", + (void) fprintf(el->el_errfile, "edit: Bad value `%ls'.\n", how); return -1; } Index: lib/libedit/eln.c =================================================================== --- lib/libedit/eln.c +++ lib/libedit/eln.c @@ -1,4 +1,4 @@ -/* $NetBSD: eln.c,v 1.28 2016/02/28 23:02:24 christos Exp $ */ +/* $NetBSD: eln.c,v 1.35 2019/04/26 16:56:57 christos Exp $ */ /*- * Copyright (c) 2009 The NetBSD Foundation, Inc. @@ -27,7 +27,7 @@ */ #include "config.h" #if !defined(lint) && !defined(SCCSID) -__RCSID("$NetBSD: eln.c,v 1.28 2016/02/28 23:02:24 christos Exp $"); +__RCSID("$NetBSD: eln.c,v 1.35 2019/04/26 16:56:57 christos Exp $"); #endif /* not lint && not SCCSID */ #include __FBSDID("$FreeBSD$"); @@ -39,7 +39,7 @@ #include "el.h" -public int +int el_getc(EditLine *el, char *cp) { int num_read; @@ -49,7 +49,7 @@ *cp = '\0'; if (num_read <= 0) return num_read; - num_read = ct_wctob(wc); + num_read = wctob(wc); if (num_read == EOF) { errno = ERANGE; return -1; @@ -60,8 +60,7 @@ } -#ifdef WIDECHAR -public void +void el_push(EditLine *el, const char *str) { /* Using multibyte->wide string decoding works fine under single-byte @@ -70,7 +69,7 @@ } -public const char * +const char * el_gets(EditLine *el, int *nread) { const wchar_t *tmp; @@ -88,24 +87,23 @@ } -public int +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); + wargv = (void *)ct_decode_argv(argc, argv, &el->el_lgcyconv); if (!wargv) return -1; ret = el_wparse(el, argc, wargv); - ct_free_argv(wargv); + el_free(wargv); return ret; } -public int +int el_set(EditLine *el, int op, ...) { va_list ap; @@ -174,8 +172,7 @@ if ((argv[i] = va_arg(ap, const char *)) == NULL) break; argv[0] = argv[i] = NULL; - wargv = (const wchar_t **) - ct_decode_argv(i + 1, argv, &el->el_lgcyconv); + wargv = (void *)ct_decode_argv(i + 1, argv, &el->el_lgcyconv); if (!wargv) { ret = -1; goto out; @@ -187,29 +184,29 @@ */ switch (op) { case EL_BIND: - wargv[0] = STR("bind"); + wargv[0] = L"bind"; ret = map_bind(el, i, wargv); break; case EL_TELLTC: - wargv[0] = STR("telltc"); + wargv[0] = L"telltc"; ret = terminal_telltc(el, i, wargv); break; case EL_SETTC: - wargv[0] = STR("settc"); + wargv[0] = L"settc"; ret = terminal_settc(el, i, wargv); break; case EL_ECHOTC: - wargv[0] = STR("echotc"); + wargv[0] = L"echotc"; ret = terminal_echotc(el, i, wargv); break; case EL_SETTY: - wargv[0] = STR("setty"); + wargv[0] = L"setty"; ret = tty_stty(el, i, wargv); break; default: ret = -1; } - ct_free_argv(wargv); + el_free(wargv); break; } @@ -229,9 +226,9 @@ goto out; } /* XXX: The two strdup's leak */ - ret = map_addfunc(el, Strdup(wargv[0]), Strdup(wargv[1]), + ret = map_addfunc(el, wcsdup(wargv[0]), wcsdup(wargv[1]), func); - ct_free_argv(wargv); + el_free(wargv); break; } case EL_HIST: { /* hist_fun_t, const char * */ @@ -275,7 +272,7 @@ } -public int +int el_get(EditLine *el, int op, ...) { va_list ap; @@ -326,14 +323,12 @@ break; case EL_GETTC: { - char *argv[20]; + char *argv[3]; 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 = terminal_gettc(el, i, argv); + argv[1] = va_arg(ap, char *); + argv[2] = va_arg(ap, void *); + ret = terminal_gettc(el, 3, argv); break; } @@ -368,7 +363,7 @@ const LineInfoW *winfo = el_wline(el); LineInfo *info = &el->el_lgcylinfo; size_t offset; - const Char *p; + const wchar_t *p; info->buffer = ct_encode_string(winfo->buffer, &el->el_lgcyconv); @@ -391,4 +386,3 @@ { return el_winsertstr(el, ct_decode_string(str, &el->el_lgcyconv)); } -#endif /* WIDECHAR */ Index: lib/libedit/emacs.c =================================================================== --- lib/libedit/emacs.c +++ lib/libedit/emacs.c @@ -1,4 +1,4 @@ -/* $NetBSD: emacs.c,v 1.32 2016/02/16 22:53:14 christos Exp $ */ +/* $NetBSD: emacs.c,v 1.36 2016/05/09 21:46:56 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.32 2016/02/16 22:53:14 christos Exp $"); +__RCSID("$NetBSD: emacs.c,v 1.36 2016/05/09 21:46:56 christos Exp $"); #endif #endif /* not lint && not SCCSID */ #include @@ -50,12 +50,13 @@ #include "el.h" #include "emacs.h" +#include "fcns.h" /* em_delete_or_list(): * Delete character under cursor or list completions if at end of line * [^D] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ em_delete_or_list(EditLine *el, wint_t c) { @@ -91,11 +92,11 @@ * Cut from cursor to end of current word * [M-d] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ em_delete_next_word(EditLine *el, wint_t c __attribute__((__unused__))) { - Char *cp, *p, *kp; + wchar_t *cp, *p, *kp; if (el->el_line.cursor == el->el_line.lastchar) return CC_ERROR; @@ -120,11 +121,11 @@ * Paste cut buffer at cursor position * [^Y] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ em_yank(EditLine *el, wint_t c __attribute__((__unused__))) { - Char *kp, *cp; + wchar_t *kp, *cp; if (el->el_chared.c_kill.last == el->el_chared.c_kill.buf) return CC_NORM; @@ -156,11 +157,11 @@ * Cut the entire line and save in cut buffer * [^U] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ em_kill_line(EditLine *el, wint_t c __attribute__((__unused__))) { - Char *kp, *cp; + wchar_t *kp, *cp; cp = el->el_line.buffer; kp = el->el_chared.c_kill.buf; @@ -178,11 +179,11 @@ * Cut area between mark and cursor and save in cut buffer * [^W] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ em_kill_region(EditLine *el, wint_t c __attribute__((__unused__))) { - Char *kp, *cp; + wchar_t *kp, *cp; if (!el->el_chared.c_kill.mark) return CC_ERROR; @@ -211,11 +212,11 @@ * Copy area between mark and cursor to cut buffer * [M-W] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ em_copy_region(EditLine *el, wint_t c __attribute__((__unused__))) { - Char *kp, *cp; + wchar_t *kp, *cp; if (!el->el_chared.c_kill.mark) return CC_ERROR; @@ -241,7 +242,7 @@ * Exchange the two characters before the cursor * Gosling emacs transpose chars [^T] */ -protected el_action_t +libedit_private el_action_t em_gosmacs_transpose(EditLine *el, wint_t c) { @@ -249,7 +250,7 @@ /* must have at least two chars entered */ c = el->el_line.cursor[-2]; el->el_line.cursor[-2] = el->el_line.cursor[-1]; - el->el_line.cursor[-1] = (Char)c; + el->el_line.cursor[-1] = c; return CC_REFRESH; } else return CC_ERROR; @@ -260,7 +261,7 @@ * Move next to end of current word * [M-f] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ em_next_word(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -285,18 +286,18 @@ * Uppercase the characters from cursor to end of current word * [M-u] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ em_upper_case(EditLine *el, wint_t c __attribute__((__unused__))) { - Char *cp, *ep; + wchar_t *cp, *ep; ep = c__next_word(el->el_line.cursor, el->el_line.lastchar, el->el_state.argument, ce__isword); for (cp = el->el_line.cursor; cp < ep; cp++) - if (Islower(*cp)) - *cp = Toupper(*cp); + if (iswlower(*cp)) + *cp = towupper(*cp); el->el_line.cursor = ep; if (el->el_line.cursor > el->el_line.lastchar) @@ -309,26 +310,26 @@ * Capitalize the characters from cursor to end of current word * [M-c] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ em_capitol_case(EditLine *el, wint_t c __attribute__((__unused__))) { - Char *cp, *ep; + wchar_t *cp, *ep; ep = c__next_word(el->el_line.cursor, el->el_line.lastchar, el->el_state.argument, ce__isword); for (cp = el->el_line.cursor; cp < ep; cp++) { - if (Isalpha(*cp)) { - if (Islower(*cp)) - *cp = Toupper(*cp); + if (iswalpha(*cp)) { + if (iswlower(*cp)) + *cp = towupper(*cp); cp++; break; } } for (; cp < ep; cp++) - if (Isupper(*cp)) - *cp = Tolower(*cp); + if (iswupper(*cp)) + *cp = towlower(*cp); el->el_line.cursor = ep; if (el->el_line.cursor > el->el_line.lastchar) @@ -341,18 +342,18 @@ * Lowercase the characters from cursor to end of current word * [M-l] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ em_lower_case(EditLine *el, wint_t c __attribute__((__unused__))) { - Char *cp, *ep; + wchar_t *cp, *ep; ep = c__next_word(el->el_line.cursor, el->el_line.lastchar, el->el_state.argument, ce__isword); for (cp = el->el_line.cursor; cp < ep; cp++) - if (Isupper(*cp)) - *cp = Tolower(*cp); + if (iswupper(*cp)) + *cp = towlower(*cp); el->el_line.cursor = ep; if (el->el_line.cursor > el->el_line.lastchar) @@ -365,7 +366,7 @@ * Set the mark at cursor * [^@] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ em_set_mark(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -379,11 +380,11 @@ * Exchange the cursor and mark * [^X^X] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ em_exchange_mark(EditLine *el, wint_t c __attribute__((__unused__))) { - Char *cp; + wchar_t *cp; cp = el->el_line.cursor; el->el_line.cursor = el->el_chared.c_kill.mark; @@ -396,7 +397,7 @@ * Universal argument (argument times 4) * [^U] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ em_universal_argument(EditLine *el, wint_t c __attribute__((__unused__))) { /* multiply current argument by 4 */ @@ -413,7 +414,7 @@ * Add 8th bit to next character typed * [] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ em_meta_next(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -426,7 +427,7 @@ /* em_toggle_overwrite(): * Switch from insert to overwrite mode or vice versa */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ em_toggle_overwrite(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -440,11 +441,11 @@ /* em_copy_prev_word(): * Copy current word to cursor */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ em_copy_prev_word(EditLine *el, wint_t c __attribute__((__unused__))) { - Char *cp, *oldc, *dp; + wchar_t *cp, *oldc, *dp; if (el->el_line.cursor == el->el_line.buffer) return CC_ERROR; @@ -467,7 +468,7 @@ /* em_inc_search_next(): * Emacs incremental next search */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ em_inc_search_next(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -480,7 +481,7 @@ /* em_inc_search_prev(): * Emacs incremental reverse search */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ em_inc_search_prev(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -494,7 +495,7 @@ * Delete the character to the left of the cursor * [^?] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ em_delete_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) { Index: lib/libedit/filecomplete.h =================================================================== --- lib/libedit/filecomplete.h +++ lib/libedit/filecomplete.h @@ -1,4 +1,4 @@ -/* $NetBSD: filecomplete.h,v 1.9 2009/12/30 22:37:40 christos Exp $ */ +/* $NetBSD: filecomplete.h,v 1.11 2017/04/21 05:38:03 abhinav Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -36,13 +36,11 @@ int fn_complete(EditLine *, char *(*)(const char *, int), char **(*)(const char *, int, int), - const Char *, const Char *, const char *(*)(const char *), size_t, - int *, int *, int *, int *, - const Char *(*)(const Char *, const Char *), - Char *(*)(const Char *), - char *(*)(const char *)); + const wchar_t *, const wchar_t *, const char *(*)(const char *), size_t, + int *, int *, int *, int *); -void fn_display_match_list(EditLine *, char **, size_t, size_t); +void fn_display_match_list(EditLine *, char **, size_t, size_t, + const char *(*)(const char *)); char *fn_tilde_expand(const char *); char *fn_filename_completion_function(const char *, int); Index: lib/libedit/filecomplete.c =================================================================== --- lib/libedit/filecomplete.c +++ lib/libedit/filecomplete.c @@ -1,4 +1,4 @@ -/* $NetBSD: filecomplete.c,v 1.40 2016/02/17 19:47:49 christos Exp $ */ +/* $NetBSD: filecomplete.c,v 1.57 2019/07/28 09:27:29 christos Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ #include "config.h" #if !defined(lint) && !defined(SCCSID) -__RCSID("$NetBSD: filecomplete.c,v 1.40 2016/02/17 19:47:49 christos Exp $"); +__RCSID("$NetBSD: filecomplete.c,v 1.57 2019/07/28 09:27:29 christos Exp $"); #endif /* not lint && not SCCSID */ #include __FBSDID("$FreeBSD$"); @@ -51,12 +51,8 @@ #include "el.h" #include "filecomplete.h" -static const Char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', - '$', '>', '<', '=', ';', '|', '&', '{', '(', '\0' }; -/* Tilde is deliberately omitted here, we treat it specially. */ -static const Char extra_quote_chars[] = { ')', '}', '*', '?', '[', '$', '\0' }; +static const wchar_t break_chars[] = L" \t\n\"\\'`@$><=;|&{("; - /********************************/ /* completion functions */ @@ -89,7 +85,7 @@ } else { /* text until string after slash */ len = (size_t)(temp - txt + 1); - temp = el_malloc(len * sizeof(*temp)); + temp = el_calloc(len, sizeof(*temp)); if (temp == NULL) return NULL; (void)strncpy(temp, txt + 1, len - 2); @@ -124,7 +120,7 @@ txt += len; len = strlen(pass->pw_dir) + 1 + strlen(txt) + 1; - temp = el_malloc(len * sizeof(*temp)); + temp = el_calloc(len, sizeof(*temp)); if (temp == NULL) return NULL; (void)snprintf(temp, len, "%s/%s", pass->pw_dir, txt); @@ -132,7 +128,175 @@ return temp; } +static int +needs_escaping(char c) +{ + switch (c) { + case '\'': + case '"': + case '(': + case ')': + case '\\': + case '<': + case '>': + case '$': + case '#': + case ' ': + case '\n': + case '\t': + case '?': + case ';': + case '`': + case '@': + case '=': + case '|': + case '{': + case '}': + case '&': + case '*': + case '[': + return 1; + default: + return 0; + } +} +static int +needs_dquote_escaping(char c) +{ + switch (c) { + case '"': + case '\\': + case '`': + case '$': + return 1; + default: + return 0; + } +} + + +static wchar_t * +unescape_string(const wchar_t *string, size_t length) +{ + size_t i; + size_t j = 0; + wchar_t *unescaped = el_calloc(length + 1, sizeof(*string)); + if (unescaped == NULL) + return NULL; + for (i = 0; i < length ; i++) { + if (string[i] == '\\') + continue; + unescaped[j++] = string[i]; + } + unescaped[j] = 0; + return unescaped; +} + +static char * +escape_filename(EditLine * el, const char *filename) +{ + size_t original_len = 0; + size_t escaped_character_count = 0; + size_t offset = 0; + size_t newlen; + const char *s; + char c; + size_t s_quoted = 0; /* does the input contain a single quote */ + size_t d_quoted = 0; /* does the input contain a double quote */ + char *escaped_str; + wchar_t *temp = el->el_line.buffer; + + if (filename == NULL) + return NULL; + + while (temp != el->el_line.cursor) { + /* + * If we see a single quote but have not seen a double quote + * so far set/unset s_quote + */ + if (temp[0] == '\'' && !d_quoted) + s_quoted = !s_quoted; + /* + * vice versa to the above condition + */ + else if (temp[0] == '"' && !s_quoted) + d_quoted = !d_quoted; + temp++; + } + + /* Count number of special characters so that we can calculate + * number of extra bytes needed in the new string + */ + for (s = filename; *s; s++, original_len++) { + c = *s; + /* Inside a single quote only single quotes need escaping */ + if (s_quoted && c == '\'') { + escaped_character_count += 3; + continue; + } + /* Inside double quotes only ", \, ` and $ need escaping */ + if (d_quoted && needs_dquote_escaping(c)) { + escaped_character_count++; + continue; + } + if (!s_quoted && !d_quoted && needs_escaping(c)) + escaped_character_count++; + } + + newlen = original_len + escaped_character_count + 1; + if (s_quoted || d_quoted) + newlen++; + + if ((escaped_str = el_malloc(newlen)) == NULL) + return NULL; + + for (s = filename; *s; s++) { + c = *s; + if (!needs_escaping(c)) { + /* no escaping is required continue as usual */ + escaped_str[offset++] = c; + continue; + } + + /* single quotes inside single quotes require special handling */ + if (c == '\'' && s_quoted) { + escaped_str[offset++] = '\''; + escaped_str[offset++] = '\\'; + escaped_str[offset++] = '\''; + escaped_str[offset++] = '\''; + continue; + } + + /* Otherwise no escaping needed inside single quotes */ + if (s_quoted) { + escaped_str[offset++] = c; + continue; + } + + /* No escaping needed inside a double quoted string either + * unless we see a '$', '\', '`', or '"' (itself) + */ + if (d_quoted && !needs_dquote_escaping(c)) { + escaped_str[offset++] = c; + continue; + } + + /* If we reach here that means escaping is actually needed */ + escaped_str[offset++] = '\\'; + escaped_str[offset++] = c; + } + + /* close the quotes */ + if (s_quoted) + escaped_str[offset++] = '\''; + else if (d_quoted) + escaped_str[offset++] = '"'; + + escaped_str[offset] = 0; + return escaped_str; +} + /* * return first found file name starting by the ``text'' or NULL if no * such file can be found @@ -248,7 +412,7 @@ #endif len = strlen(dirname) + len + 1; - temp = el_malloc(len * sizeof(*temp)); + temp = el_calloc(len, sizeof(*temp)); if (temp == NULL) return NULL; (void)snprintf(temp, len, "%s%s", dirname, entry->d_name); @@ -324,7 +488,7 @@ max_equal = i; } - retstr = el_malloc((max_equal + 1) * sizeof(*retstr)); + retstr = el_calloc(max_equal + 1, sizeof(*retstr)); if (retstr == NULL) { el_free(match_list); return NULL; @@ -360,10 +524,13 @@ * num, so the strings are matches[1] *through* matches[num-1]. */ void -fn_display_match_list (EditLine *el, char **matches, size_t num, size_t width) +fn_display_match_list(EditLine * el, char **matches, size_t num, size_t width, + const char *(*app_func) (const char *)) { size_t line, lines, col, cols, thisguy; int screenwidth = el->el_terminal.t_size.h; + if (app_func == NULL) + app_func = append_char_function; /* Ignore matches[0]. Avoid 1-based array logic below. */ matches++; @@ -373,7 +540,7 @@ * Find out how many entries can be put on one line; count * with one space between strings the same way it's printed. */ - cols = (size_t)screenwidth / (width + 1); + cols = (size_t)screenwidth / (width + 2); if (cols == 0) cols = 1; @@ -391,13 +558,62 @@ thisguy = line + col * lines; if (thisguy >= num) break; - (void)fprintf(el->el_outfile, "%s%-*s", - col == 0 ? "" : " ", (int)width, matches[thisguy]); + (void)fprintf(el->el_outfile, "%s%s%s", + col == 0 ? "" : " ", matches[thisguy], + (*app_func)(matches[thisguy])); + (void)fprintf(el->el_outfile, "%-*s", + (int) (width - strlen(matches[thisguy])), ""); } (void)fprintf(el->el_outfile, "\n"); } } +static wchar_t * +find_word_to_complete(const wchar_t * cursor, const wchar_t * buffer, + const wchar_t * word_break, const wchar_t * special_prefixes, size_t * length) +{ + /* We now look backwards for the start of a filename/variable word */ + const wchar_t *ctemp = cursor; + size_t len; + + /* if the cursor is placed at a slash or a quote, we need to find the + * word before it + */ + if (ctemp > buffer) { + switch (ctemp[-1]) { + case '\\': + case '\'': + case '"': + ctemp--; + break; + default: + break; + } + } + + for (;;) { + if (ctemp <= buffer) + break; + if (wcschr(word_break, ctemp[-1])) { + if (ctemp - buffer >= 2 && ctemp[-2] == '\\') { + ctemp -= 2; + continue; + } else + break; + } + if (special_prefixes && wcschr(special_prefixes, ctemp[-1])) + break; + ctemp--; + } + + len = (size_t) (cursor - ctemp); + *length = len; + wchar_t *unescaped_word = unescape_string(ctemp, len); + if (unescaped_word == NULL) + return NULL; + return unescaped_word; +} + /* * Complete the word at or before point, * 'what_to_do' says what to do with the completion. @@ -414,18 +630,14 @@ 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 wchar_t *word_break, const wchar_t *special_prefixes, const char *(*app_func)(const char *), size_t query_items, - int *completion_type, int *over, int *point, int *end, - const Char *(*find_word_start_func)(const Char *, const Char *), - Char *(*dequoting_func)(const Char *), - char *(*quoting_func)(const char *)) + int *completion_type, int *over, int *point, int *end) { - const TYPE(LineInfo) *li; - Char *temp; - Char *dequoted_temp; - char **matches; - const Char *ctemp; + const LineInfoW *li; + wchar_t *temp; + char **matches; + char *completion; size_t len; int what_to_do = '\t'; int retval = CC_NORM; @@ -442,30 +654,12 @@ if (!app_func) app_func = append_char_function; - /* We now look backwards for the start of a filename/variable word */ - li = FUN(el,line)(el); - if (find_word_start_func) - ctemp = find_word_start_func(li->buffer, li->cursor); - else { - ctemp = li->cursor; - while (ctemp > li->buffer - && !Strchr(word_break, ctemp[-1]) - && (!special_prefixes || !Strchr(special_prefixes, ctemp[-1]) ) ) - ctemp--; - } + li = el_wline(el); + temp = find_word_to_complete(li->cursor, + li->buffer, word_break, special_prefixes, &len); + if (temp == NULL) + goto out; - len = (size_t)(li->cursor - ctemp); - temp = el_malloc((len + 1) * sizeof(*temp)); - (void)Strncpy(temp, ctemp, len); - temp[len] = '\0'; - - if (dequoting_func) { - dequoted_temp = dequoting_func(temp); - if (dequoted_temp == NULL) - return retval; - } else - dequoted_temp = NULL; - /* these can be used by function called in completion_matches() */ /* or (*attempted_completion_function)() */ if (point != NULL) @@ -476,16 +670,14 @@ if (attempted_completion_function) { int cur_off = (int)(li->cursor - li->buffer); matches = (*attempted_completion_function)( - ct_encode_string(dequoted_temp ? dequoted_temp : temp, - &el->el_scratch), + ct_encode_string(temp, &el->el_scratch), cur_off - (int)len, cur_off); } else matches = NULL; if (!attempted_completion_function || (over != NULL && !*over && !matches)) matches = completion_matches( - ct_encode_string(dequoted_temp ? dequoted_temp : temp, - &el->el_scratch), complet_func); + ct_encode_string(temp, &el->el_scratch), complet_func); if (over != NULL) *over = 0; @@ -493,42 +685,44 @@ if (matches) { int i; size_t matches_num, maxlen, match_len, match_display=1; + int single_match = matches[2] == NULL && + (matches[1] == NULL || strcmp(matches[0], matches[1]) == 0); retval = CC_REFRESH; - /* - * Only replace the completed string with common part of - * possible matches if there is possible completion. - */ + if (matches[0][0] != '\0') { - char *quoted_match; - if (quoting_func) { - quoted_match = quoting_func(matches[0]); - if (quoted_match == NULL) - goto free_matches; - } else - quoted_match = NULL; el_deletestr(el, (int) len); - FUN(el,insertstr)(el, - ct_decode_string(quoted_match ? quoted_match : - matches[0] , &el->el_scratch)); + if (!attempted_completion_function) + completion = escape_filename(el, matches[0]); + else + completion = strdup(matches[0]); + if (completion == NULL) + goto out; + if (single_match) { + /* + * We found exact match. Add a space after + * it, unless we do filename completion and the + * object is a directory. Also do necessary escape quoting + */ + el_winsertstr(el, + ct_decode_string(completion, &el->el_scratch)); + el_winsertstr(el, + ct_decode_string((*app_func)(completion), + &el->el_scratch)); + } else { + /* + * Only replace the completed string with common part of + * possible matches if there is possible completion. + */ + el_winsertstr(el, + ct_decode_string(completion, &el->el_scratch)); + } + free(completion); } - if (what_to_do == '?') - goto display_matches; - if (matches[2] == NULL && - (matches[1] == NULL || strcmp(matches[0], matches[1]) == 0)) { + if (!single_match && (what_to_do == '!' || what_to_do == '?')) { /* - * We found exact match. Add a space after - * it, unless we do filename completion and the - * object is a directory. - */ - FUN(el,insertstr)(el, - ct_decode_string((*app_func)(matches[0]), - &el->el_scratch)); - } else if (what_to_do == '!') { - display_matches: - /* * More than one match and requested to list possible * matches. */ @@ -567,7 +761,7 @@ * add 1 to matches_num for the call. */ fn_display_match_list(el, matches, - matches_num+1, maxlen); + matches_num+1, maxlen, app_func); } retval = CC_REDISPLAY; } else if (matches[0][0]) { @@ -584,14 +778,14 @@ retval = CC_NORM; } -free_matches: /* free elements of array and the array itself */ for (i = 0; matches[i]; i++) el_free(matches[i]); el_free(matches); matches = NULL; } - free(dequoted_temp); + +out: el_free(temp); return retval; } @@ -605,93 +799,5 @@ { return (unsigned char)fn_complete(el, NULL, NULL, break_chars, NULL, NULL, (size_t)100, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL); + NULL, NULL, NULL, NULL); } - -static const Char * -sh_find_word_start(const Char *buffer, const Char *cursor) -{ - const Char *word_start = buffer; - - while (buffer < cursor) { - if (*buffer == '\\') - buffer++; - else if (Strchr(break_chars, *buffer)) - word_start = buffer + 1; - buffer++; - } - return word_start; -} - -static char * -sh_quote(const char *str) -{ - const char *src; - int extra_len = 0; - char *quoted_str, *dst; - - for (src = str; *src != '\0'; src++) - if (Strchr(break_chars, *src) || - Strchr(extra_quote_chars, *src)) - extra_len++; - - quoted_str = malloc(sizeof(*quoted_str) * - (strlen(str) + extra_len + 1)); - if (quoted_str == NULL) - return NULL; - - dst = quoted_str; - for (src = str; *src != '\0'; src++) { - if (Strchr(break_chars, *src) || - Strchr(extra_quote_chars, *src)) - *dst++ = '\\'; - *dst++ = *src; - } - *dst = '\0'; - - return quoted_str; -} - -static Char * -sh_dequote(const Char *str) -{ - Char *dequoted_str, *dst; - - /* save extra space to replace \~ with ./~ */ - dequoted_str = malloc(sizeof(*dequoted_str) * (Strlen(str) + 1 + 1)); - if (dequoted_str == NULL) - return NULL; - - dst = dequoted_str; - - /* dequote \~ at start as ./~ */ - if (*str == '\\' && str[1] == '~') { - str++; - *dst++ = '.'; - *dst++ = '/'; - } - - while (*str) { - if (*str == '\\') - str++; - if (*str) - *dst++ = *str++; - } - *dst = '\0'; - - return dequoted_str; -} - -/* - * completion function using sh quoting rules; for key binding - */ -/* ARGSUSED */ -unsigned char -_el_fn_sh_complete(EditLine *el, int ch __attribute__((__unused__))) -{ - return (unsigned char)fn_complete(el, NULL, NULL, - break_chars, NULL, NULL, 100, - NULL, NULL, NULL, NULL, - sh_find_word_start, sh_dequote, sh_quote); -} Index: lib/libedit/hist.h =================================================================== --- lib/libedit/hist.h +++ lib/libedit/hist.h @@ -1,4 +1,4 @@ -/* $NetBSD: hist.h,v 1.18 2016/02/17 19:47:49 christos Exp $ */ +/* $NetBSD: hist.h,v 1.23 2017/09/01 10:19:10 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -41,47 +41,41 @@ #ifndef _h_el_hist #define _h_el_hist -typedef int (*hist_fun_t)(void *, TYPE(HistEvent) *, int, ...); +typedef int (*hist_fun_t)(void *, HistEventW *, int, ...); typedef struct el_history_t { - Char *buf; /* The history buffer */ + wchar_t *buf; /* The history buffer */ size_t sz; /* Size of history buffer */ - Char *last; /* The last character */ + wchar_t *last; /* The last character */ int eventno; /* Event we are looking for */ void *ref; /* Argument for history fcns */ hist_fun_t fun; /* Event access */ - TYPE(HistEvent) ev; /* Event cookie */ + HistEventW ev; /* Event cookie */ } el_history_t; #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) +#define HIST_LAST(el) HIST_FUN(el, H_LAST, NULL) +#define HIST_PREV(el) HIST_FUN(el, H_PREV, NULL) +#define HIST_SET(el, num) HIST_FUN(el, H_SET, num) +#define HIST_LOAD(el, fname) HIST_FUN(el, H_LOAD fname) +#define HIST_SAVE(el, fname) HIST_FUN(el, H_SAVE fname) +#define HIST_SAVE_FP(el, fp) HIST_FUN(el, H_SAVE_FP, fp) +#define HIST_NSAVE_FP(el, n, fp) HIST_FUN(el, H_NSAVE_FP, n, fp) -#define HIST_NEXT(el) HIST_FUN(el, H_NEXT, NULL) -#define HIST_FIRST(el) HIST_FUN(el, H_FIRST, NULL) -#define HIST_LAST(el) HIST_FUN(el, H_LAST, NULL) -#define HIST_PREV(el) HIST_FUN(el, H_PREV, NULL) -#define HIST_SET(el, num) HIST_FUN(el, H_SET, num) -#define HIST_LOAD(el, fname) HIST_FUN(el, H_LOAD fname) -#define HIST_SAVE(el, fname) HIST_FUN(el, H_SAVE fname) -#define HIST_SAVE_FP(el, fp) HIST_FUN(el, H_SAVE_FP fp) +libedit_private int hist_init(EditLine *); +libedit_private void hist_end(EditLine *); +libedit_private el_action_t hist_get(EditLine *); +libedit_private int hist_set(EditLine *, hist_fun_t, void *); +libedit_private int hist_command(EditLine *, int, const wchar_t **); +libedit_private int hist_enlargebuf(EditLine *, size_t, size_t); +libedit_private wchar_t *hist_convert(EditLine *, int, void *); -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, void *); -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, void *); -#endif - #endif /* _h_el_hist */ Index: lib/libedit/hist.c =================================================================== --- lib/libedit/hist.c +++ lib/libedit/hist.c @@ -1,4 +1,4 @@ -/* $NetBSD: hist.c,v 1.24 2016/02/16 22:53:14 christos Exp $ */ +/* $NetBSD: hist.c,v 1.34 2019/07/23 10:19:35 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.24 2016/02/16 22:53:14 christos Exp $"); +__RCSID("$NetBSD: hist.c,v 1.34 2019/07/23 10:19:35 christos Exp $"); #endif #endif /* not lint && not SCCSID */ #include @@ -48,22 +48,23 @@ */ #include #include +#include #include "el.h" /* hist_init(): * Initialization function. */ -protected int +libedit_private int hist_init(EditLine *el) { el->el_history.fun = NULL; el->el_history.ref = NULL; - el->el_history.buf = el_malloc(EL_BUFSIZ * sizeof(*el->el_history.buf)); - el->el_history.sz = EL_BUFSIZ; + el->el_history.buf = el_calloc(EL_BUFSIZ, sizeof(*el->el_history.buf)); if (el->el_history.buf == NULL) return -1; + el->el_history.sz = EL_BUFSIZ; el->el_history.last = el->el_history.buf; return 0; } @@ -72,7 +73,7 @@ /* hist_end(): * clean up history; */ -protected void +libedit_private void hist_end(EditLine *el) { @@ -84,7 +85,7 @@ /* hist_set(): * Set new history interface */ -protected int +libedit_private int hist_set(EditLine *el, hist_fun_t fun, void *ptr) { @@ -98,14 +99,15 @@ * Get a history line and update it in the buffer. * eventno tells us the event to get. */ -protected el_action_t +libedit_private el_action_t hist_get(EditLine *el) { - const Char *hp; + const wchar_t *hp; int h; + size_t blen, hlen; if (el->el_history.eventno == 0) { /* if really the current line */ - (void) Strncpy(el->el_line.buffer, el->el_history.buf, + (void) wcsncpy(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,15 +130,17 @@ return CC_ERROR; for (h = 1; h < el->el_history.eventno; h++) - if ((hp = HIST_NEXT(el)) == NULL) { - el->el_history.eventno = h; - return CC_ERROR; - } - (void) Strncpy(el->el_line.buffer, hp, - (size_t)(el->el_line.limit - 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 ((hp = HIST_NEXT(el)) == NULL) + goto out; + hlen = wcslen(hp) + 1; + blen = (size_t)(el->el_line.limit - el->el_line.buffer); + if (hlen > blen && !ch_enlargebufs(el, hlen)) + goto out; + + memcpy(el->el_line.buffer, hp, hlen * sizeof(*hp)); + el->el_line.lastchar = el->el_line.buffer + hlen - 1; + if (el->el_line.lastchar > el->el_line.buffer && el->el_line.lastchar[-1] == '\n') el->el_line.lastchar--; @@ -151,41 +155,66 @@ el->el_line.cursor = el->el_line.lastchar; return CC_REFRESH; +out: + el->el_history.eventno = h; + return CC_ERROR; + } /* hist_command() * process a history command */ -protected int -hist_command(EditLine *el, int argc, const Char **argv) +libedit_private int +hist_command(EditLine *el, int argc, const wchar_t **argv) { - const Char *str; + const wchar_t *str; int num; - TYPE(HistEvent) ev; + HistEventW ev; if (el->el_history.ref == NULL) return -1; - if (argc == 1 || Strcmp(argv[1], STR("list")) == 0) { + if (argc == 1 || wcscmp(argv[1], L"list") == 0) { + size_t maxlen = 0; + char *buf = NULL; + int hno = 1; /* 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, ct_encode_string(str, &el->el_scratch)); + for (str = HIST_LAST(el); str != NULL; str = HIST_PREV(el)) { + char *ptr = + ct_encode_string(str, &el->el_scratch); + size_t len = strlen(ptr); + if (len > 0 && ptr[len - 1] == '\n') + ptr[--len] = '\0'; + len = len * 4 + 1; + if (len >= maxlen) { + maxlen = len + 1024; + char *nbuf = el_realloc(buf, maxlen); + if (nbuf == NULL) { + el_free(buf); + return -1; + } + buf = nbuf; + } + strvis(buf, ptr, VIS_NL); + (void) fprintf(el->el_outfile, "%d\t%s\n", + hno++, buf); + } + el_free(buf); return 0; } if (argc != 3) return -1; - num = (int)Strtol(argv[2], NULL, 0); + num = (int)wcstol(argv[2], NULL, 0); - if (Strcmp(argv[1], STR("size")) == 0) - return FUNW(history)(el->el_history.ref, &ev, H_SETSIZE, num); + if (wcscmp(argv[1], L"size") == 0) + return history_w(el->el_history.ref, &ev, H_SETSIZE, num); - if (Strcmp(argv[1], STR("unique")) == 0) - return FUNW(history)(el->el_history.ref, &ev, H_SETUNIQUE, num); + if (wcscmp(argv[1], L"unique") == 0) + return history_w(el->el_history.ref, &ev, H_SETUNIQUE, num); return -1; } @@ -194,11 +223,11 @@ * Enlarge history buffer to specified value. Called from el_enlargebufs(). * Return 0 for failure, 1 for success. */ -protected int +libedit_private int /*ARGSUSED*/ hist_enlargebuf(EditLine *el, size_t oldsz, size_t newsz) { - Char *newbuf; + wchar_t *newbuf; newbuf = el_realloc(el->el_history.buf, newsz * sizeof(*newbuf)); if (!newbuf) @@ -214,8 +243,7 @@ return 1; } -#ifdef WIDECHAR -protected wchar_t * +libedit_private wchar_t * hist_convert(EditLine *el, int fn, void *arg) { HistEventW ev; @@ -224,4 +252,3 @@ return ct_decode_string((const char *)(const void *)ev.str, &el->el_scratch); } -#endif Index: lib/libedit/histedit.h =================================================================== --- lib/libedit/histedit.h +++ lib/libedit/histedit.h @@ -1,4 +1,4 @@ -/* $NetBSD: histedit.h,v 1.55 2016/02/17 19:47:49 christos Exp $ */ +/* $NetBSD: histedit.h,v 1.57 2017/09/01 10:19:10 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -114,7 +114,6 @@ int el_set(EditLine *, int, ...); int el_get(EditLine *, int, ...); unsigned char _el_fn_complete(EditLine *, int); -unsigned char _el_fn_sh_complete(EditLine *, int); /* * el_set/el_get parameters @@ -228,6 +227,7 @@ #define H_DELDATA 24 /* , int, histdata_t *);*/ #define H_REPLACE 25 /* , const char *, histdata_t); */ #define H_SAVE_FP 26 /* , FILE *); */ +#define H_NSAVE_FP 27 /* , size_t, FILE *); */ @@ -263,6 +263,8 @@ const wchar_t *lastchar; } LineInfoW; +typedef int (*el_rfunc_t)(EditLine *, wchar_t *); + const wchar_t *el_wgets(EditLine *, int *); int el_wgetc(EditLine *, wchar_t *); void el_wpush(EditLine *, const wchar_t *); Index: lib/libedit/history.c =================================================================== --- lib/libedit/history.c +++ lib/libedit/history.c @@ -1,4 +1,4 @@ -/* $NetBSD: history.c,v 1.52 2016/02/17 19:47:49 christos Exp $ */ +/* $NetBSD: history.c,v 1.62 2018/09/13 09:03:40 kre Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)history.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: history.c,v 1.52 2016/02/17 19:47:49 christos Exp $"); +__RCSID("$NetBSD: history.c,v 1.62 2018/09/13 09:03:40 kre Exp $"); #endif #endif /* not lint && not SCCSID */ #include @@ -55,8 +55,44 @@ static const char hist_cookie[] = "_HiStOrY_V2_\n"; #include "histedit.h" + + +#ifdef NARROWCHAR + +#define Char char +#define FUN(prefix, rest) prefix ## _ ## rest +#define FUNW(type) type +#define TYPE(type) type +#define STR(x) x + +#define Strlen(s) strlen(s) +#define Strdup(s) strdup(s) +#define Strcmp(d, s) strcmp(d, s) +#define Strncmp(d, s, n) strncmp(d, s, n) +#define Strncpy(d, s, n) strncpy(d, s, n) +#define Strncat(d, s, n) strncat(d, s, n) +#define ct_decode_string(s, b) (s) +#define ct_encode_string(s, b) (s) + +#else #include "chartype.h" +#define Char wchar_t +#define FUN(prefix, rest) prefix ## _w ## rest +#define FUNW(type) type ## _w +#define TYPE(type) type ## W +#define STR(x) L ## x + +#define Strlen(s) wcslen(s) +#define Strdup(s) wcsdup(s) +#define Strcmp(d, s) wcscmp(d, s) +#define Strncmp(d, s, n) wcsncmp(d, s, n) +#define Strncpy(d, s, n) wcsncpy(d, s, n) +#define Strncat(d, s, n) wcsncat(d, s, n) + +#endif + + typedef int (*history_gfun_t)(void *, TYPE(HistEvent) *); typedef int (*history_efun_t)(void *, TYPE(HistEvent) *, const Char *); typedef void (*history_vfun_t)(void *, TYPE(HistEvent) *); @@ -99,21 +135,22 @@ } HistEventPrivate; +static int history_setsize(TYPE(History) *, TYPE(HistEvent) *, int); +static int history_getsize(TYPE(History) *, TYPE(HistEvent) *); +static int history_setunique(TYPE(History) *, TYPE(HistEvent) *, int); +static int history_getunique(TYPE(History) *, TYPE(HistEvent) *); +static int history_set_fun(TYPE(History) *, TYPE(History) *); +static int history_load(TYPE(History) *, const char *); +static int history_save(TYPE(History) *, const char *); +static int history_save_fp(TYPE(History) *, size_t, FILE *); +static int history_prev_event(TYPE(History) *, TYPE(HistEvent) *, int); +static int history_next_event(TYPE(History) *, TYPE(HistEvent) *, int); +static int history_next_string(TYPE(History) *, TYPE(HistEvent) *, + const Char *); +static int history_prev_string(TYPE(History) *, TYPE(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_save_fp(TYPE(History) *, FILE *); -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 *); - /***********************************************************************/ /* @@ -136,23 +173,23 @@ #define H_UNIQUE 1 /* Store only unique elements */ } history_t; -private int history_def_next(void *, TYPE(HistEvent) *); -private int history_def_first(void *, TYPE(HistEvent) *); -private int history_def_prev(void *, TYPE(HistEvent) *); -private int history_def_last(void *, TYPE(HistEvent) *); -private int history_def_curr(void *, TYPE(HistEvent) *); -private int history_def_set(void *, TYPE(HistEvent) *, const int); -private void history_def_clear(void *, TYPE(HistEvent) *); -private int history_def_enter(void *, TYPE(HistEvent) *, const Char *); -private int history_def_add(void *, TYPE(HistEvent) *, const Char *); -private int history_def_del(void *, TYPE(HistEvent) *, const int); +static int history_def_next(void *, TYPE(HistEvent) *); +static int history_def_first(void *, TYPE(HistEvent) *); +static int history_def_prev(void *, TYPE(HistEvent) *); +static int history_def_last(void *, TYPE(HistEvent) *); +static int history_def_curr(void *, TYPE(HistEvent) *); +static int history_def_set(void *, TYPE(HistEvent) *, const int); +static void history_def_clear(void *, TYPE(HistEvent) *); +static int history_def_enter(void *, TYPE(HistEvent) *, const Char *); +static int history_def_add(void *, TYPE(HistEvent) *, const Char *); +static int history_def_del(void *, TYPE(HistEvent) *, const int); -private int history_def_init(void **, 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 *); +static int history_def_init(void **, TYPE(HistEvent) *, int); +static int history_def_insert(history_t *, TYPE(HistEvent) *, const Char *); +static 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(void *, TYPE(HistEvent) *, int); +static int history_deldata_nth(history_t *, TYPE(HistEvent) *, int, void **); +static int history_set_nth(void *, TYPE(HistEvent) *, int); #define history_def_setsize(p, num)(void) (((history_t *)p)->max = (num)) #define history_def_getsize(p) (((history_t *)p)->cur) @@ -209,7 +246,7 @@ /* history_def_first(): * Default function to return the first event in the history. */ -private int +static int history_def_first(void *p, TYPE(HistEvent) *ev) { history_t *h = (history_t *) p; @@ -229,7 +266,7 @@ /* history_def_last(): * Default function to return the last event in the history. */ -private int +static int history_def_last(void *p, TYPE(HistEvent) *ev) { history_t *h = (history_t *) p; @@ -249,7 +286,7 @@ /* history_def_next(): * Default function to return the next event in the history. */ -private int +static int history_def_next(void *p, TYPE(HistEvent) *ev) { history_t *h = (history_t *) p; @@ -274,7 +311,7 @@ /* history_def_prev(): * Default function to return the previous event in the history. */ -private int +static int history_def_prev(void *p, TYPE(HistEvent) *ev) { history_t *h = (history_t *) p; @@ -300,7 +337,7 @@ /* history_def_curr(): * Default function to return the current event in the history. */ -private int +static int history_def_curr(void *p, TYPE(HistEvent) *ev) { history_t *h = (history_t *) p; @@ -321,7 +358,7 @@ * Default function to set the current event in the history to the * given one. */ -private int +static int history_def_set(void *p, TYPE(HistEvent) *ev, const int n) { history_t *h = (history_t *) p; @@ -348,7 +385,7 @@ * Default function to set the current event in the history to the * n-th one. */ -private int +static int history_set_nth(void *p, TYPE(HistEvent) *ev, int n) { history_t *h = (history_t *) p; @@ -372,7 +409,7 @@ /* history_def_add(): * Append string to element */ -private int +static int history_def_add(void *p, TYPE(HistEvent) *ev, const Char *str) { history_t *h = (history_t *) p; @@ -398,7 +435,7 @@ } -private int +static int history_deldata_nth(history_t *h, TYPE(HistEvent) *ev, int num, void **data) { @@ -420,7 +457,7 @@ * Delete element hp of the h list */ /* ARGSUSED */ -private int +static int history_def_del(void *p, TYPE(HistEvent) *ev __attribute__((__unused__)), const int num) { @@ -438,7 +475,7 @@ * Delete element hp of the h list */ /* ARGSUSED */ -private void +static void history_def_delete(history_t *h, TYPE(HistEvent) *ev __attribute__((__unused__)), hentry_t *hp) { @@ -461,7 +498,7 @@ /* history_def_insert(): * Insert element with string str in the h list */ -private int +static int history_def_insert(history_t *h, TYPE(HistEvent) *ev, const Char *str) { hentry_t *c; @@ -493,7 +530,7 @@ /* history_def_enter(): * Default function to enter an item in the history */ -private int +static int history_def_enter(void *p, TYPE(HistEvent) *ev, const Char *str) { history_t *h = (history_t *) p; @@ -520,7 +557,7 @@ * Default history initialization function */ /* ARGSUSED */ -private int +static int history_def_init(void **p, TYPE(HistEvent) *ev __attribute__((__unused__)), int n) { history_t *h = (history_t *) h_malloc(sizeof(*h)); @@ -545,7 +582,7 @@ /* history_def_clear(): * Default history cleanup function */ -private void +static void history_def_clear(void *p, TYPE(HistEvent) *ev) { history_t *h = (history_t *) p; @@ -565,7 +602,7 @@ /* history_init(): * Initialization function. */ -public TYPE(History) * +TYPE(History) * FUN(history,init)(void) { TYPE(HistEvent) ev; @@ -596,7 +633,7 @@ /* history_end(): * clean up history; */ -public void +void FUN(history,end)(TYPE(History) *h) { TYPE(HistEvent) ev; @@ -612,7 +649,7 @@ /* history_setsize(): * Set history number of events */ -private int +static int history_setsize(TYPE(History) *h, TYPE(HistEvent) *ev, int num) { @@ -632,7 +669,7 @@ /* history_getsize(): * Get number of events currently in history */ -private int +static int history_getsize(TYPE(History) *h, TYPE(HistEvent) *ev) { if (h->h_next != history_def_next) { @@ -651,7 +688,7 @@ /* history_setunique(): * Set if adjacent equal events should not be entered in history. */ -private int +static int history_setunique(TYPE(History) *h, TYPE(HistEvent) *ev, int uni) { @@ -667,7 +704,7 @@ /* history_getunique(): * Get if adjacent equal events should not be entered in history. */ -private int +static int history_getunique(TYPE(History) *h, TYPE(HistEvent) *ev) { if (h->h_next != history_def_next) { @@ -682,7 +719,7 @@ /* history_set_fun(): * Set history functions */ -private int +static int history_set_fun(TYPE(History) *h, TYPE(History) *nh) { TYPE(HistEvent) ev; @@ -729,7 +766,7 @@ /* history_load(): * TYPE(History) load function */ -private int +static int history_load(TYPE(History) *h, const char *fname) { FILE *fp; @@ -740,7 +777,8 @@ char *ptr; int i = -1; TYPE(HistEvent) ev; -#ifdef WIDECHAR + Char *decode_result; +#ifndef NARROWCHAR static ct_buffer_t conv; #endif @@ -772,7 +810,10 @@ ptr = nptr; } (void) strunvis(ptr, line); - if (HENTER(h, &ev, ct_decode_string(ptr, &conv)) == -1) { + decode_result = ct_decode_string(ptr, &conv); + if (decode_result == NULL) + continue; + if (HENTER(h, &ev, decode_result) == -1) { i = -1; goto oomem; } @@ -789,28 +830,36 @@ /* history_save_fp(): * TYPE(History) save function */ -private int -history_save_fp(TYPE(History) *h, FILE *fp) +static int +history_save_fp(TYPE(History) *h, size_t nelem, FILE *fp) { TYPE(HistEvent) ev; int i = -1, retval; size_t len, max_size; char *ptr; const char *str; -#ifdef WIDECHAR +#ifndef NARROWCHAR static ct_buffer_t conv; #endif if (fchmod(fileno(fp), S_IRUSR|S_IWUSR) == -1) goto done; - if (fputs(hist_cookie, fp) == EOF) + if (ftell(fp) == 0 && fputs(hist_cookie, fp) == EOF) goto done; ptr = h_malloc((max_size = 1024) * sizeof(*ptr)); if (ptr == NULL) goto done; - for (i = 0, retval = HLAST(h, &ev); - retval != -1; - retval = HPREV(h, &ev), i++) { + if (nelem != (size_t)-1) { + for (retval = HFIRST(h, &ev); retval != -1 && nelem-- > 0; + retval = HNEXT(h, &ev)) + continue; + } else + retval = -1; + + if (retval == -1) + retval = HLAST(h, &ev); + + for (i = 0; retval != -1; retval = HPREV(h, &ev), i++) { str = ct_encode_string(ev.str, &conv); len = strlen(str) * 4 + 1; if (len > max_size) { @@ -836,7 +885,7 @@ /* history_save(): * History save function */ -private int +static int history_save(TYPE(History) *h, const char *fname) { FILE *fp; @@ -845,7 +894,7 @@ if ((fp = fopen(fname, "w")) == NULL) return -1; - i = history_save_fp(h, fp); + i = history_save_fp(h, (size_t)-1, fp); (void) fclose(fp); return i; @@ -855,7 +904,7 @@ /* history_prev_event(): * Find the previous event, with number given */ -private int +static int history_prev_event(TYPE(History) *h, TYPE(HistEvent) *ev, int num) { int retval; @@ -869,7 +918,7 @@ } -private int +static int history_next_evdata(TYPE(History) *h, TYPE(HistEvent) *ev, int num, void **d) { int retval; @@ -889,7 +938,7 @@ /* history_next_event(): * Find the next event, with number given */ -private int +static int history_next_event(TYPE(History) *h, TYPE(HistEvent) *ev, int num) { int retval; @@ -906,7 +955,7 @@ /* history_prev_string(): * Find the previous event beginning with string */ -private int +static int history_prev_string(TYPE(History) *h, TYPE(HistEvent) *ev, const Char *str) { size_t len = Strlen(str); @@ -924,7 +973,7 @@ /* history_next_string(): * Find the next event beginning with string */ -private int +static int history_next_string(TYPE(History) *h, TYPE(HistEvent) *ev, const Char *str) { size_t len = Strlen(str); @@ -1033,11 +1082,20 @@ break; case H_SAVE_FP: - retval = history_save_fp(h, va_arg(va, FILE *)); + retval = history_save_fp(h, (size_t)-1, va_arg(va, FILE *)); if (retval == -1) he_seterrev(ev, _HE_HIST_WRITE); break; + case H_NSAVE_FP: + { + size_t sz = va_arg(va, size_t); + retval = history_save_fp(h, sz, va_arg(va, FILE *)); + if (retval == -1) + he_seterrev(ev, _HE_HIST_WRITE); + break; + } + case H_PREV_EVENT: retval = history_prev_event(h, ev, va_arg(va, int)); break; Index: lib/libedit/historyn.c =================================================================== --- lib/libedit/historyn.c +++ lib/libedit/historyn.c @@ -0,0 +1,3 @@ +#include "config.h" +#define NARROWCHAR +#include "history.c" Index: lib/libedit/keymacro.h =================================================================== --- lib/libedit/keymacro.h +++ lib/libedit/keymacro.h @@ -1,4 +1,4 @@ -/* $NetBSD: keymacro.h,v 1.3 2016/01/29 19:59:11 christos Exp $ */ +/* $NetBSD: keymacro.h,v 1.6 2016/05/09 21:46:56 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -43,13 +43,13 @@ typedef union keymacro_value_t { el_action_t cmd; /* If it is a command the # */ - Char *str; /* If it is a string... */ + wchar_t *str; /* If it is a string... */ } keymacro_value_t; typedef struct keymacro_node_t keymacro_node_t; typedef struct el_keymacro_t { - Char *buf; /* Key print buffer */ + wchar_t *buf; /* Key print buffer */ keymacro_node_t *map; /* Key map */ keymacro_value_t val; /* Local conversion buffer */ } el_keymacro_t; @@ -57,21 +57,21 @@ #define XK_CMD 0 #define XK_STR 1 #define XK_NOD 2 -#define XK_EXE 3 -protected int keymacro_init(EditLine *); -protected void keymacro_end(EditLine *); -protected keymacro_value_t *keymacro_map_cmd(EditLine *, int); -protected keymacro_value_t *keymacro_map_str(EditLine *, Char *); -protected void keymacro_reset(EditLine *); -protected int keymacro_get(EditLine *, Char *, keymacro_value_t *); -protected void keymacro_add(EditLine *, const Char *, keymacro_value_t *, int); -protected void keymacro_clear(EditLine *, el_action_t *, const Char *); -protected int keymacro_delete(EditLine *, const Char *); -protected void keymacro_print(EditLine *, const Char *); -protected void keymacro_kprint(EditLine *, const Char *, keymacro_value_t *, - int); -protected size_t keymacro__decode_str(const Char *, char *, size_t, +libedit_private int keymacro_init(EditLine *); +libedit_private void keymacro_end(EditLine *); +libedit_private keymacro_value_t *keymacro_map_cmd(EditLine *, int); +libedit_private keymacro_value_t *keymacro_map_str(EditLine *, wchar_t *); +libedit_private void keymacro_reset(EditLine *); +libedit_private int keymacro_get(EditLine *, wchar_t *, keymacro_value_t *); +libedit_private void keymacro_add(EditLine *, const wchar_t *, + keymacro_value_t *, int); +libedit_private void keymacro_clear(EditLine *, el_action_t *, const wchar_t *); +libedit_private int keymacro_delete(EditLine *, const wchar_t *); +libedit_private void keymacro_print(EditLine *, const wchar_t *); +libedit_private void keymacro_kprint(EditLine *, const wchar_t *, + keymacro_value_t *, int); +libedit_private size_t keymacro__decode_str(const wchar_t *, char *, size_t, const char *); #endif /* _h_el_keymacro */ Index: lib/libedit/keymacro.c =================================================================== --- lib/libedit/keymacro.c +++ lib/libedit/keymacro.c @@ -1,4 +1,4 @@ -/* $NetBSD: keymacro.c,v 1.14 2016/02/24 14:25:38 christos Exp $ */ +/* $NetBSD: keymacro.c,v 1.24 2019/07/23 10:18:52 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: keymacro.c,v 1.14 2016/02/24 14:25:38 christos Exp $"); +__RCSID("$NetBSD: keymacro.c,v 1.24 2019/07/23 10:18:52 christos Exp $"); #endif #endif /* not lint && not SCCSID */ #include @@ -52,7 +52,7 @@ * number of characters. This module maintains a map (the * el->el_keymacro.map) * to convert these extended-key sequences into input strs - * (XK_STR), editor functions (XK_CMD), or unix commands (XK_EXE). + * (XK_STR) or editor functions (XK_CMD). * * Warning: * If key is a substr of some other keys, then the longer @@ -69,13 +69,14 @@ #include #include "el.h" +#include "fcns.h" /* * The Nodes of the el->el_keymacro.map. The el->el_keymacro.map is a * linked list of these node elements */ struct keymacro_node_t { - Char ch; /* single character of key */ + wchar_t ch; /* single character of key */ int type; /* node type */ keymacro_value_t val; /* command code or pointer to str, */ /* if this is a leaf */ @@ -83,18 +84,18 @@ struct keymacro_node_t *sibling;/* ptr to another key with same prefix*/ }; -private int node_trav(EditLine *, keymacro_node_t *, Char *, +static int node_trav(EditLine *, keymacro_node_t *, wchar_t *, keymacro_value_t *); -private int node__try(EditLine *, keymacro_node_t *, const Char *, - keymacro_value_t *, int); -private keymacro_node_t *node__get(wint_t); -private void node__free(keymacro_node_t *); -private void node__put(EditLine *, keymacro_node_t *); -private int node__delete(EditLine *, keymacro_node_t **, - const Char *); -private int node_lookup(EditLine *, const Char *, +static int node__try(EditLine *, keymacro_node_t *, + const wchar_t *, keymacro_value_t *, int); +static keymacro_node_t *node__get(wint_t); +static void node__free(keymacro_node_t *); +static void node__put(EditLine *, keymacro_node_t *); +static int node__delete(EditLine *, keymacro_node_t **, + const wchar_t *); +static int node_lookup(EditLine *, const wchar_t *, keymacro_node_t *, size_t); -private int node_enum(EditLine *, keymacro_node_t *, size_t); +static int node_enum(EditLine *, keymacro_node_t *, size_t); #define KEY_BUFSIZ EL_BUFSIZ @@ -102,11 +103,11 @@ /* keymacro_init(): * Initialize the key maps */ -protected int +libedit_private int keymacro_init(EditLine *el) { - el->el_keymacro.buf = el_malloc(KEY_BUFSIZ * + el->el_keymacro.buf = el_calloc(KEY_BUFSIZ, sizeof(*el->el_keymacro.buf)); if (el->el_keymacro.buf == NULL) return -1; @@ -118,7 +119,7 @@ /* keymacro_end(): * Free the key maps */ -protected void +libedit_private void keymacro_end(EditLine *el) { @@ -131,7 +132,7 @@ /* keymacro_map_cmd(): * Associate cmd with a key value */ -protected keymacro_value_t * +libedit_private keymacro_value_t * keymacro_map_cmd(EditLine *el, int cmd) { @@ -143,8 +144,8 @@ /* keymacro_map_str(): * Associate str with a key value */ -protected keymacro_value_t * -keymacro_map_str(EditLine *el, Char *str) +libedit_private keymacro_value_t * +keymacro_map_str(EditLine *el, wchar_t *str) { el->el_keymacro.val.str = str; @@ -157,7 +158,7 @@ * Then initializes el->el_keymacro.map with arrow keys * [Always bind the ansi arrow keys?] */ -protected void +libedit_private void keymacro_reset(EditLine *el) { @@ -171,12 +172,13 @@ * Calls the recursive function with entry point el->el_keymacro.map * Looks up *ch in map and then reads characters until a * complete match is found or a mismatch occurs. Returns the - * type of the match found (XK_STR, XK_CMD, or XK_EXE). + * type of the match found (XK_STR or XK_CMD). * Returns NULL in val.str and XK_STR for no match. + * Returns XK_NOD for end of file or read error. * The last character read is returned in *ch. */ -protected int -keymacro_get(EditLine *el, Char *ch, keymacro_value_t *val) +libedit_private int +keymacro_get(EditLine *el, wchar_t *ch, keymacro_value_t *val) { return node_trav(el, el->el_keymacro.map, ch, val); @@ -189,8 +191,9 @@ * code is applied to the existing key. Ntype specifies if code is a * command, an out str or a unix command. */ -protected void -keymacro_add(EditLine *el, const Char *key, keymacro_value_t *val, int ntype) +libedit_private void +keymacro_add(EditLine *el, const wchar_t *key, keymacro_value_t *val, + int ntype) { if (key[0] == '\0') { @@ -217,13 +220,11 @@ /* keymacro_clear(): * */ -protected void -keymacro_clear(EditLine *el, el_action_t *map, const Char *in) +libedit_private void +keymacro_clear(EditLine *el, el_action_t *map, const wchar_t *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) || @@ -237,8 +238,8 @@ * Delete the key and all longer keys staring with key, if * they exists. */ -protected int -keymacro_delete(EditLine *el, const Char *key) +libedit_private int +keymacro_delete(EditLine *el, const wchar_t *key) { if (key[0] == '\0') { @@ -258,8 +259,8 @@ * Print the binding associated with key key. * Print entire el->el_keymacro.map if null */ -protected void -keymacro_print(EditLine *el, const Char *key) +libedit_private void +keymacro_print(EditLine *el, const wchar_t *key) { /* do nothing if el->el_keymacro.map is empty and null key specified */ @@ -269,7 +270,7 @@ el->el_keymacro.buf[0] = '"'; if (node_lookup(el, key, el->el_keymacro.map, (size_t)1) <= -1) /* key is not bound */ - (void) fprintf(el->el_errfile, "Unbound extended key \"" FSTR + (void) fprintf(el->el_errfile, "Unbound extended key \"%ls" "\"\n", key); return; } @@ -279,21 +280,17 @@ * recursively traverses node in tree until match or mismatch is * found. May read in more characters. */ -private int -node_trav(EditLine *el, keymacro_node_t *ptr, Char *ch, keymacro_value_t *val) +static int +node_trav(EditLine *el, keymacro_node_t *ptr, wchar_t *ch, + keymacro_value_t *val) { - wchar_t wc; if (ptr->ch == *ch) { /* match found */ if (ptr->next) { /* key not complete so get next char */ - if (el_wgetc(el, &wc) != 1) {/* if EOF or error */ - val->cmd = ED_END_OF_FILE; - return XK_CMD; - /* PWP: Pretend we just read an end-of-file */ - } - *ch = (Char)wc; + if (el_wgetc(el, ch) != 1) + return XK_NOD; return node_trav(el, ptr->next, ch, val); } else { *val = ptr->val; @@ -318,8 +315,8 @@ /* node__try(): * Find a node that matches *str or allocate a new one */ -private int -node__try(EditLine *el, keymacro_node_t *ptr, const Char *str, +static int +node__try(EditLine *el, keymacro_node_t *ptr, const wchar_t *str, keymacro_value_t *val, int ntype) { @@ -345,7 +342,6 @@ case XK_NOD: break; case XK_STR: - case XK_EXE: if (ptr->val.str) el_free(ptr->val.str); break; @@ -360,8 +356,7 @@ ptr->val = *val; break; case XK_STR: - case XK_EXE: - if ((ptr->val.str = Strdup(val->str)) == NULL) + if ((ptr->val.str = wcsdup(val->str)) == NULL) return -1; break; default: @@ -381,8 +376,8 @@ /* node__delete(): * Delete node that matches str */ -private int -node__delete(EditLine *el, keymacro_node_t **inptr, const Char *str) +static int +node__delete(EditLine *el, keymacro_node_t **inptr, const wchar_t *str) { keymacro_node_t *ptr; keymacro_node_t *prev_ptr = NULL; @@ -429,7 +424,7 @@ /* node__put(): * Puts a tree of nodes onto free list using free(3). */ -private void +static void node__put(EditLine *el, keymacro_node_t *ptr) { if (ptr == NULL) @@ -445,7 +440,6 @@ case XK_CMD: case XK_NOD: break; - case XK_EXE: case XK_STR: if (ptr->val.str != NULL) el_free(ptr->val.str); @@ -461,7 +455,7 @@ /* node__get(): * Returns pointer to a keymacro_node_t for ch. */ -private keymacro_node_t * +static keymacro_node_t * node__get(wint_t ch) { keymacro_node_t *ptr; @@ -469,7 +463,7 @@ ptr = el_malloc(sizeof(*ptr)); if (ptr == NULL) return NULL; - ptr->ch = (Char)ch; + ptr->ch = ch; ptr->type = XK_NOD; ptr->val.str = NULL; ptr->next = NULL; @@ -477,7 +471,7 @@ return ptr; } -private void +static void node__free(keymacro_node_t *k) { if (k == NULL) @@ -491,8 +485,9 @@ * look for the str starting at node ptr. * Print if last node */ -private int -node_lookup(EditLine *el, const Char *str, keymacro_node_t *ptr, size_t cnt) +static int +node_lookup(EditLine *el, const wchar_t *str, keymacro_node_t *ptr, + size_t cnt) { ssize_t used; @@ -543,7 +538,7 @@ /* node_enum(): * Traverse the node printing the characters it is bound in buffer */ -private int +static int node_enum(EditLine *el, keymacro_node_t *ptr, size_t cnt) { ssize_t used; @@ -553,7 +548,7 @@ el->el_keymacro.buf[++cnt] = '\0'; (void) fprintf(el->el_errfile, "Some extended keys too long for internal print buffer"); - (void) fprintf(el->el_errfile, " \"" FSTR "...\"\n", + (void) fprintf(el->el_errfile, " \"%ls...\"\n", el->el_keymacro.buf); return 0; } @@ -586,8 +581,9 @@ * Print the specified key and its associated * function specified by val */ -protected void -keymacro_kprint(EditLine *el, const Char *key, keymacro_value_t *val, int ntype) +libedit_private void +keymacro_kprint(EditLine *el, const wchar_t *key, keymacro_value_t *val, + int ntype) { el_bindings_t *fp; char unparsbuf[EL_BUFSIZ]; @@ -596,7 +592,6 @@ if (val != NULL) switch (ntype) { case XK_STR: - case XK_EXE: (void) keymacro__decode_str(val->str, unparsbuf, sizeof(unparsbuf), ntype == XK_STR ? "\"\"" : "[]"); @@ -606,7 +601,7 @@ case XK_CMD: for (fp = el->el_map.help; fp->name; fp++) if (val->cmd == fp->func) { - ct_wcstombs(unparsbuf, fp->name, sizeof(unparsbuf)); + wcstombs(unparsbuf, fp->name, sizeof(unparsbuf)); unparsbuf[sizeof(unparsbuf) -1] = '\0'; (void) fprintf(el->el_outfile, fmt, ct_encode_string(key, &el->el_scratch), unparsbuf); @@ -637,11 +632,12 @@ /* keymacro__decode_str(): * Make a printable version of the ey */ -protected size_t -keymacro__decode_str(const Char *str, char *buf, size_t len, const char *sep) +libedit_private size_t +keymacro__decode_str(const wchar_t *str, char *buf, size_t len, + const char *sep) { char *b = buf, *eb = b + len; - const Char *p; + const wchar_t *p; b = buf; if (sep[0] != '\0') { @@ -653,8 +649,8 @@ goto add_endsep; } for (p = str; *p != 0; p++) { - Char dbuf[VISUAL_WIDTH_MAX]; - Char *p2 = dbuf; + wchar_t dbuf[VISUAL_WIDTH_MAX]; + wchar_t *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++); Index: lib/libedit/literal.h =================================================================== --- lib/libedit/literal.h +++ lib/libedit/literal.h @@ -0,0 +1,54 @@ +/* $NetBSD: literal.h,v 1.2 2017/06/30 20:26:52 kre Exp $ */ + +/*- + * Copyright (c) 2017 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * $FreeBSD$ + */ + +/* + * el.literal.h: Literal character + */ +#ifndef _h_el_literal +#define _h_el_literal + +#define EL_LITERAL ((wint_t)0x80000000) + +typedef struct el_literal_t { + char **l_buf; /* array of buffers */ + size_t l_idx; /* max in use */ + size_t l_len; /* max allocated */ +} el_literal_t; + +libedit_private void literal_init(EditLine *); +libedit_private void literal_end(EditLine *); +libedit_private void literal_clear(EditLine *); +libedit_private wint_t literal_add(EditLine *, const wchar_t *, + const wchar_t *, int *); +libedit_private const char *literal_get(EditLine *, wint_t); + +#endif /* _h_el_literal */ Index: lib/libedit/literal.c =================================================================== --- lib/libedit/literal.c +++ lib/libedit/literal.c @@ -0,0 +1,138 @@ +/* $NetBSD: literal.c,v 1.5 2019/07/23 13:10:11 christos Exp $ */ + +/*- + * Copyright (c) 2017 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "config.h" +#if !defined(lint) && !defined(SCCSID) +__RCSID("$NetBSD: literal.c,v 1.5 2019/07/23 13:10:11 christos Exp $"); +#endif /* not lint && not SCCSID */ +#include +__FBSDID("$FreeBSD$"); + +/* + * literal.c: Literal sequences handling. + */ +#include +#include +#include +#include +#include "el.h" + +libedit_private void +literal_init(EditLine *el) +{ + el_literal_t *l = &el->el_literal; + + memset(l, 0, sizeof(*l)); +} + +libedit_private void +literal_end(EditLine *el) +{ + literal_clear(el); +} + +libedit_private void +literal_clear(EditLine *el) +{ + el_literal_t *l = &el->el_literal; + size_t i; + + if (l->l_len == 0) + return; + + for (i = 0; i < l->l_idx; i++) + el_free(l->l_buf[i]); + el_free(l->l_buf); + l->l_buf = NULL; + l->l_len = 0; + l->l_idx = 0; +} + +libedit_private wint_t +literal_add(EditLine *el, const wchar_t *buf, const wchar_t *end, int *wp) +{ + el_literal_t *l = &el->el_literal; + size_t i, len; + ssize_t w, n; + char *b; + + w = wcwidth(end[1]); /* column width of the visible char */ + *wp = (int)w; + + if (w <= 0) /* we require something to be printed */ + return 0; + + len = (size_t)(end - buf); + for (w = 0, i = 0; i < len; i++) + w += ct_enc_width(buf[i]); + w += ct_enc_width(end[1]); + + b = el_malloc((size_t)(w + 1)); + if (b == NULL) + return 0; + + for (n = 0, i = 0; i < len; i++) + n += ct_encode_char(b + n, (size_t)(w - n), buf[i]); + n += ct_encode_char(b + n, (size_t)(w - n), end[1]); + b[n] = '\0'; + + /* + * Then save this literal string in the list of such strings, + * and return a "magic character" to put into the terminal buffer. + * When that magic char is 'printed' the saved string (which includes + * the char that belongs in that position) gets sent instead. + */ + if (l->l_idx == l->l_len) { + char **bp; + + l->l_len += 4; + bp = el_realloc(l->l_buf, sizeof(*l->l_buf) * l->l_len); + if (bp == NULL) { + free(b); + l->l_len -= 4; + return 0; + } + l->l_buf = bp; + } + l->l_buf[l->l_idx++] = b; + return EL_LITERAL | (wint_t)(l->l_idx - 1); +} + +libedit_private const char * +literal_get(EditLine *el, wint_t idx) +{ + el_literal_t *l = &el->el_literal; + + assert(idx & EL_LITERAL); + idx &= ~EL_LITERAL; + assert(l->l_idx > (size_t)idx); + return l->l_buf[idx]; +} Index: lib/libedit/makelist =================================================================== --- lib/libedit/makelist +++ lib/libedit/makelist @@ -37,7 +37,7 @@ # makelist.sh: Automatically generate header files... AWK=awk -USAGE="Usage: $0 -n|-h|-e|-fc|-fh|-bc|-bh|-m " +USAGE="Usage: $0 -h|-fc|-fh|-bh " if [ "x$1" = "x" ] then @@ -52,17 +52,6 @@ case $FLAG in -# generate foo.h file from foo.c -# --n) - cat << _EOF -#include "config.h" -#undef WIDECHAR -#define NARROWCHAR -#include "${FILES}" -_EOF - ;; - -h) set - `echo $FILES | sed -e 's/\\./_/g'` hdr="_h_`basename $1`" @@ -79,7 +68,7 @@ # 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 *, wint_t);\n", + printf("libedit_private el_action_t\t%s (EditLine *, wint_t);\n", name); } } @@ -88,15 +77,13 @@ }' ;; -# generate help.c from various .c files +# generate help.h from various .c files # --bc) +-bh) cat $FILES | $AWK ' BEGIN { printf("/* Automatically generated file, do not edit */\n"); - printf("#include \"config.h\"\n#include \"el.h\"\n"); - printf("#include \"help.h\"\n"); - printf("private const struct el_bindings_t el_func_help[] = {\n"); + printf("static const struct el_bindings_t el_func_help[] = {\n"); low = "abcdefghijklmnopqrstuvwxyz_"; high = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_"; for (i = 1; i <= length(low); i++) @@ -116,38 +103,24 @@ fname = fname s; } - printf(" { %-30.30s %-30.30s\n","STR(\"" fname "\"),", uname ","); + printf(" { %-30.30s %-30.30s\n","L\"" fname "\",", uname ","); ok = 1; } } /^ \*/ { if (ok) { - printf(" STR(\""); + printf(" L\""); for (i = 2; i < NF; i++) printf("%s ", $i); - printf("%s\") },\n", $i); + printf("%s\" },\n", $i); ok = 0; } } END { printf("};\n"); - printf("\nprotected const el_bindings_t* help__get(void)"); - printf("{ return el_func_help; }\n"); }' ;; -# generate help.h from various .c files -# --bh) - $AWK ' - BEGIN { - printf("/* Automatically generated file, do not edit */\n"); - printf("#ifndef _h_help_c\n#define _h_help_c\n"); - printf("protected const el_bindings_t *help__get(void);\n"); - printf("#endif /* _h_help_c */\n"); - }' /dev/null - ;; - # generate fcns.h from various .h files # -fh) @@ -155,7 +128,6 @@ sort | tr '[:lower:]' '[:upper:]' | $AWK ' BEGIN { printf("/* Automatically generated file, do not edit */\n"); - printf("#ifndef _h_fcns_c\n#define _h_fcns_c\n"); count = 0; } { @@ -163,24 +135,16 @@ } END { printf("#define\t%-30.30s\t%3d\n", "EL_NUM_FCNS", count); - - printf("typedef el_action_t (*el_func_t)(EditLine *, wint_t);"); - printf("\nprotected const el_func_t* func__get(void);\n"); - printf("#endif /* _h_fcns_c */\n"); }' ;; -# generate fcns.c from various .h files +# generate func.h from various .h files # -fc) cat $FILES | $AWK '/el_action_t/ { print $3 }' | sort | $AWK ' BEGIN { printf("/* Automatically generated file, do not edit */\n"); - printf("#include \"config.h\"\n#include \"el.h\"\n"); - printf("#include \"common.h\"\n"); - printf("#include \"emacs.h\"\n"); - printf("#include \"vi.h\"\n"); - printf("private const el_func_t el_func[] = {"); + printf("static const el_func_t el_func[] = {"); maxlen = 80; needn = 1; len = 0; @@ -200,62 +164,9 @@ } END { printf("\n};\n"); - printf("\nprotected const el_func_t* func__get(void) { return el_func; }\n"); }' ;; -# generate editline.c from various .c files -# --e) - echo "$FILES" | tr ' ' '\012' | $AWK ' - BEGIN { - printf("/* Automatically generated file, do not edit */\n"); - printf("#define protected static\n"); - printf("#define SCCSID\n"); - } - { - printf("#include \"%s\"\n", $1); - }' - ;; - -# generate man page fragment from various .c files -# --m) - cat $FILES | $AWK ' - BEGIN { - printf(".\\\" Section automatically generated with makelist\n"); - printf(".Bl -tag -width 4n\n"); - } - /\(\):/ { - pr = substr($2, 1, 2); - if (pr == "vi" || pr == "em" || pr == "ed") { - name = substr($2, 1, length($2) - 3); - fname = ""; - for (i = 1; i <= length(name); i++) { - s = substr(name, i, 1); - if (s == "_") - s = "-"; - fname = fname s; - } - - printf(".It Ic %s\n", fname); - ok = 1; - } - } - /^ \*/ { - if (ok) { - for (i = 2; i < NF; i++) - printf("%s ", $i); - printf("%s.\n", $i); - ok = 0; - } - } - END { - printf(".El\n"); - printf(".\\\" End of section automatically generated with makelist\n"); - }' - ;; - *) echo $USAGE 1>&2 exit 1 Index: lib/libedit/map.h =================================================================== --- lib/libedit/map.h +++ lib/libedit/map.h @@ -1,4 +1,4 @@ -/* $NetBSD: map.h,v 1.10 2014/07/06 18:15:34 christos Exp $ */ +/* $NetBSD: map.h,v 1.13 2016/05/09 21:46:56 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -41,13 +41,14 @@ #ifndef _h_el_map #define _h_el_map +typedef el_action_t (*el_func_t)(EditLine *, wint_t); + typedef struct el_bindings_t { /* for the "bind" shell command */ - const Char *name; /* function name for bind command */ + const wchar_t *name; /* function name for bind command */ int func; /* function numeric value */ - const Char *description; /* description of function */ + const wchar_t *description; /* description of function */ } el_bindings_t; - typedef struct el_map_t { el_action_t *alt; /* The current alternate key map */ el_action_t *key; /* The current normal key map */ @@ -66,13 +67,14 @@ #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); +libedit_private int map_bind(EditLine *, int, const wchar_t **); +libedit_private int map_init(EditLine *); +libedit_private void map_end(EditLine *); +libedit_private void map_init_vi(EditLine *); +libedit_private void map_init_emacs(EditLine *); +libedit_private int map_set_editor(EditLine *, wchar_t *); +libedit_private int map_get_editor(EditLine *, const wchar_t **); +libedit_private int map_addfunc(EditLine *, const wchar_t *, const wchar_t *, + el_func_t); #endif /* _h_el_map */ Index: lib/libedit/map.c =================================================================== --- lib/libedit/map.c +++ lib/libedit/map.c @@ -1,4 +1,4 @@ -/* $NetBSD: map.c,v 1.43 2016/02/17 19:47:49 christos Exp $ */ +/* $NetBSD: map.c,v 1.52 2019/07/23 10:18:52 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.43 2016/02/17 19:47:49 christos Exp $"); +__RCSID("$NetBSD: map.c,v 1.52 2019/07/23 10:18:52 christos Exp $"); #endif #endif /* not lint && not SCCSID */ #include @@ -51,23 +51,28 @@ #include #include "el.h" +#include "common.h" +#include "emacs.h" +#include "vi.h" +#include "fcns.h" +#include "func.h" #include "help.h" #include "parse.h" -private void map_print_key(EditLine *, el_action_t *, const Char *); -private void map_print_some_keys(EditLine *, el_action_t *, wint_t, wint_t); -private void map_print_all_keys(EditLine *); -private void map_init_nls(EditLine *); -private void map_init_meta(EditLine *); +static void map_print_key(EditLine *, el_action_t *, const wchar_t *); +static void map_print_some_keys(EditLine *, el_action_t *, wint_t, wint_t); +static void map_print_all_keys(EditLine *); +static void map_init_nls(EditLine *); +static void map_init_meta(EditLine *); /* keymap tables ; should be N_KEYS*sizeof(KEYCMD) bytes long */ -private const el_action_t el_map_emacs[] = { +static const el_action_t el_map_emacs[] = { /* 0 */ EM_SET_MARK, /* ^@ */ /* 1 */ ED_MOVE_TO_BEG, /* ^A */ /* 2 */ ED_PREV_CHAR, /* ^B */ - /* 3 */ ED_TTY_SIGINT, /* ^C */ + /* 3 */ ED_IGNORE, /* ^C */ /* 4 */ EM_DELETE_OR_LIST, /* ^D */ /* 5 */ ED_MOVE_TO_END, /* ^E */ /* 6 */ ED_NEXT_CHAR, /* ^F */ @@ -79,21 +84,21 @@ /* 12 */ ED_CLEAR_SCREEN, /* ^L */ /* 13 */ ED_NEWLINE, /* ^M */ /* 14 */ ED_NEXT_HISTORY, /* ^N */ - /* 15 */ ED_TTY_FLUSH_OUTPUT, /* ^O */ + /* 15 */ ED_IGNORE, /* ^O */ /* 16 */ ED_PREV_HISTORY, /* ^P */ - /* 17 */ ED_TTY_START_OUTPUT, /* ^Q */ + /* 17 */ ED_IGNORE, /* ^Q */ /* 18 */ ED_REDISPLAY, /* ^R */ - /* 19 */ ED_TTY_STOP_OUTPUT, /* ^S */ + /* 19 */ ED_IGNORE, /* ^S */ /* 20 */ ED_TRANSPOSE_CHARS, /* ^T */ /* 21 */ EM_KILL_LINE, /* ^U */ /* 22 */ ED_QUOTED_INSERT, /* ^V */ /* 23 */ EM_KILL_REGION, /* ^W */ /* 24 */ ED_SEQUENCE_LEAD_IN, /* ^X */ /* 25 */ EM_YANK, /* ^Y */ - /* 26 */ ED_TTY_SIGTSTP, /* ^Z */ + /* 26 */ ED_IGNORE, /* ^Z */ /* 27 */ EM_META_NEXT, /* ^[ */ - /* 28 */ ED_TTY_SIGQUIT, /* ^\ */ - /* 29 */ ED_TTY_DSUSP, /* ^] */ + /* 28 */ ED_IGNORE, /* ^\ */ + /* 29 */ ED_IGNORE, /* ^] */ /* 30 */ ED_UNASSIGNED, /* ^^ */ /* 31 */ ED_UNASSIGNED, /* ^_ */ /* 32 */ ED_INSERT, /* SPACE */ @@ -330,7 +335,7 @@ * insert mode characters are in the normal keymap, and command mode * in the extended keymap. */ -private const el_action_t el_map_vi_insert[] = { +static const el_action_t el_map_vi_insert[] = { #ifdef KSHVI /* 0 */ ED_UNASSIGNED, /* ^@ */ /* 1 */ ED_INSERT, /* ^A */ @@ -349,9 +354,9 @@ /* 14 */ ED_INSERT, /* ^N */ /* 15 */ ED_INSERT, /* ^O */ /* 16 */ ED_INSERT, /* ^P */ - /* 17 */ ED_TTY_START_OUTPUT, /* ^Q */ + /* 17 */ ED_IGNORE, /* ^Q */ /* 18 */ ED_INSERT, /* ^R */ - /* 19 */ ED_TTY_STOP_OUTPUT, /* ^S */ + /* 19 */ ED_IGNORE, /* ^S */ /* 20 */ ED_INSERT, /* ^T */ /* 21 */ VI_KILL_LINE_PREV, /* ^U */ /* 22 */ ED_QUOTED_INSERT, /* ^V */ @@ -361,7 +366,7 @@ /* 25 */ ED_INSERT, /* ^Y */ /* 26 */ ED_INSERT, /* ^Z */ /* 27 */ VI_COMMAND_MODE, /* ^[ */ /* [ Esc ] key */ - /* 28 */ ED_TTY_SIGQUIT, /* ^\ */ + /* 28 */ ED_IGNORE, /* ^\ */ /* 29 */ ED_INSERT, /* ^] */ /* 30 */ ED_INSERT, /* ^^ */ /* 31 */ ED_INSERT, /* ^_ */ @@ -375,7 +380,7 @@ /* 0 */ ED_UNASSIGNED, /* ^@ */ /* 1 */ ED_MOVE_TO_BEG, /* ^A */ /* 2 */ ED_PREV_CHAR, /* ^B */ - /* 3 */ ED_TTY_SIGINT, /* ^C */ + /* 3 */ ED_IGNORE, /* ^C */ /* 4 */ VI_LIST_OR_EOF, /* ^D */ /* 5 */ ED_MOVE_TO_END, /* ^E */ /* 6 */ ED_NEXT_CHAR, /* ^F */ @@ -387,20 +392,20 @@ /* 12 */ ED_CLEAR_SCREEN, /* ^L */ /* 13 */ ED_NEWLINE, /* ^M */ /* 14 */ ED_NEXT_HISTORY, /* ^N */ - /* 15 */ ED_TTY_FLUSH_OUTPUT, /* ^O */ + /* 15 */ ED_IGNORE, /* ^O */ /* 16 */ ED_PREV_HISTORY, /* ^P */ - /* 17 */ ED_TTY_START_OUTPUT, /* ^Q */ + /* 17 */ ED_IGNORE, /* ^Q */ /* 18 */ ED_REDISPLAY, /* ^R */ - /* 19 */ ED_TTY_STOP_OUTPUT, /* ^S */ + /* 19 */ ED_IGNORE, /* ^S */ /* 20 */ ED_TRANSPOSE_CHARS, /* ^T */ /* 21 */ VI_KILL_LINE_PREV, /* ^U */ /* 22 */ ED_QUOTED_INSERT, /* ^V */ /* 23 */ ED_DELETE_PREV_WORD, /* ^W */ /* 24 */ ED_UNASSIGNED, /* ^X */ - /* 25 */ ED_TTY_DSUSP, /* ^Y */ - /* 26 */ ED_TTY_SIGTSTP, /* ^Z */ + /* 25 */ ED_IGNORE, /* ^Y */ + /* 26 */ ED_IGNORE, /* ^Z */ /* 27 */ VI_COMMAND_MODE, /* ^[ */ - /* 28 */ ED_TTY_SIGQUIT, /* ^\ */ + /* 28 */ ED_IGNORE, /* ^\ */ /* 29 */ ED_UNASSIGNED, /* ^] */ /* 30 */ ED_UNASSIGNED, /* ^^ */ /* 31 */ ED_UNASSIGNED, /* ^_ */ @@ -631,11 +636,11 @@ /* 255 */ ED_INSERT /* M-^? */ }; -private const el_action_t el_map_vi_command[] = { +static const el_action_t el_map_vi_command[] = { /* 0 */ ED_UNASSIGNED, /* ^@ */ /* 1 */ ED_MOVE_TO_BEG, /* ^A */ /* 2 */ ED_UNASSIGNED, /* ^B */ - /* 3 */ ED_TTY_SIGINT, /* ^C */ + /* 3 */ ED_IGNORE, /* ^C */ /* 4 */ ED_UNASSIGNED, /* ^D */ /* 5 */ ED_MOVE_TO_END, /* ^E */ /* 6 */ ED_UNASSIGNED, /* ^F */ @@ -647,11 +652,11 @@ /* 12 */ ED_CLEAR_SCREEN, /* ^L */ /* 13 */ ED_NEWLINE, /* ^M */ /* 14 */ ED_NEXT_HISTORY, /* ^N */ - /* 15 */ ED_TTY_FLUSH_OUTPUT, /* ^O */ + /* 15 */ ED_IGNORE, /* ^O */ /* 16 */ ED_PREV_HISTORY, /* ^P */ - /* 17 */ ED_TTY_START_OUTPUT, /* ^Q */ + /* 17 */ ED_IGNORE, /* ^Q */ /* 18 */ ED_REDISPLAY, /* ^R */ - /* 19 */ ED_TTY_STOP_OUTPUT, /* ^S */ + /* 19 */ ED_IGNORE, /* ^S */ /* 20 */ ED_UNASSIGNED, /* ^T */ /* 21 */ VI_KILL_LINE_PREV, /* ^U */ /* 22 */ ED_UNASSIGNED, /* ^V */ @@ -660,7 +665,7 @@ /* 25 */ ED_UNASSIGNED, /* ^Y */ /* 26 */ ED_UNASSIGNED, /* ^Z */ /* 27 */ EM_META_NEXT, /* ^[ */ - /* 28 */ ED_TTY_SIGQUIT, /* ^\ */ + /* 28 */ ED_IGNORE, /* ^\ */ /* 29 */ ED_UNASSIGNED, /* ^] */ /* 30 */ ED_UNASSIGNED, /* ^^ */ /* 31 */ ED_UNASSIGNED, /* ^_ */ @@ -894,7 +899,7 @@ /* map_init(): * Initialize and allocate the maps */ -protected int +libedit_private int map_init(EditLine *el) { @@ -910,24 +915,24 @@ EL_ABORT((el->errfile, "Vi insert map incorrect\n")); #endif - el->el_map.alt = el_malloc(sizeof(*el->el_map.alt) * N_KEYS); + el->el_map.alt = el_calloc(N_KEYS, sizeof(*el->el_map.alt)); if (el->el_map.alt == NULL) return -1; - el->el_map.key = el_malloc(sizeof(*el->el_map.key) * N_KEYS); + el->el_map.key = el_calloc(N_KEYS, sizeof(*el->el_map.key)); if (el->el_map.key == NULL) return -1; el->el_map.emacs = el_map_emacs; el->el_map.vic = el_map_vi_command; el->el_map.vii = el_map_vi_insert; - el->el_map.help = el_malloc(sizeof(*el->el_map.help) * EL_NUM_FCNS); + el->el_map.help = el_calloc(EL_NUM_FCNS, sizeof(*el->el_map.help)); if (el->el_map.help == NULL) return -1; - (void) memcpy(el->el_map.help, help__get(), + (void) memcpy(el->el_map.help, el_func_help, sizeof(*el->el_map.help) * EL_NUM_FCNS); - el->el_map.func = el_malloc(sizeof(*el->el_map.func) * EL_NUM_FCNS); + el->el_map.func = el_calloc(EL_NUM_FCNS, sizeof(*el->el_map.func)); if (el->el_map.func == NULL) return -1; - memcpy(el->el_map.func, func__get(), sizeof(*el->el_map.func) + memcpy(el->el_map.func, el_func, sizeof(*el->el_map.func) * EL_NUM_FCNS); el->el_map.nfunc = EL_NUM_FCNS; @@ -943,7 +948,7 @@ /* map_end(): * Free the space taken by the editor maps */ -protected void +libedit_private void map_end(EditLine *el) { @@ -964,7 +969,7 @@ /* map_init_nls(): * Find all the printable keys and bind them to self insert */ -private void +static void map_init_nls(EditLine *el) { int i; @@ -972,7 +977,7 @@ el_action_t *map = el->el_map.key; for (i = 0200; i <= 0377; i++) - if (Isprint(i)) + if (iswprint(i)) map[i] = ED_INSERT; } @@ -980,10 +985,10 @@ /* map_init_meta(): * Bind all the meta keys to the appropriate ESC- sequence */ -private void +static void map_init_meta(EditLine *el) { - Char buf[3]; + wchar_t buf[3]; int i; el_action_t *map = el->el_map.key; el_action_t *alt = el->el_map.alt; @@ -1001,7 +1006,7 @@ } else map = alt; } - buf[0] = (Char) i; + buf[0] = (wchar_t)i; buf[2] = 0; for (i = 0200; i <= 0377; i++) switch (map[i]) { @@ -1021,7 +1026,7 @@ /* map_init_vi(): * Initialize the vi bindings */ -protected void +libedit_private void map_init_vi(EditLine *el) { int i; @@ -1051,11 +1056,11 @@ /* map_init_emacs(): * Initialize the emacs bindings */ -protected void +libedit_private void map_init_emacs(EditLine *el) { int i; - Char buf[3]; + wchar_t 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; @@ -1085,15 +1090,15 @@ /* map_set_editor(): * Set the editor */ -protected int -map_set_editor(EditLine *el, Char *editor) +libedit_private int +map_set_editor(EditLine *el, wchar_t *editor) { - if (Strcmp(editor, STR("emacs")) == 0) { + if (wcscmp(editor, L"emacs") == 0) { map_init_emacs(el); return 0; } - if (Strcmp(editor, STR("vi")) == 0) { + if (wcscmp(editor, L"vi") == 0) { map_init_vi(el); return 0; } @@ -1104,18 +1109,18 @@ /* map_get_editor(): * Retrieve the editor */ -protected int -map_get_editor(EditLine *el, const Char **editor) +libedit_private int +map_get_editor(EditLine *el, const wchar_t **editor) { if (editor == NULL) return -1; switch (el->el_map.type) { case MAP_EMACS: - *editor = STR("emacs"); + *editor = L"emacs"; return 0; case MAP_VI: - *editor = STR("vi"); + *editor = L"vi"; return 0; } return -1; @@ -1125,8 +1130,8 @@ /* map_print_key(): * Print the function description for 1 key */ -private void -map_print_key(EditLine *el, el_action_t *map, const Char *in) +static void +map_print_key(EditLine *el, el_action_t *map, const wchar_t *in) { char outbuf[EL_BUFSIZ]; el_bindings_t *bp, *ep; @@ -1137,7 +1142,7 @@ for (bp = el->el_map.help; bp < ep; bp++) if (bp->func == map[(unsigned char) *in]) { (void) fprintf(el->el_outfile, - "%s\t->\t" FSTR "\n", outbuf, bp->name); + "%s\t->\t%ls\n", outbuf, bp->name); return; } } else @@ -1148,16 +1153,16 @@ /* map_print_some_keys(): * Print keys from first to last */ -private void +static void map_print_some_keys(EditLine *el, el_action_t *map, wint_t first, wint_t last) { el_bindings_t *bp, *ep; - Char firstbuf[2], lastbuf[2]; + wchar_t firstbuf[2], lastbuf[2]; char unparsbuf[EL_BUFSIZ], extrabuf[EL_BUFSIZ]; - firstbuf[0] = (Char)first; + firstbuf[0] = first; firstbuf[1] = 0; - lastbuf[0] = (Char)last; + lastbuf[0] = last; lastbuf[1] = 0; if (map[first] == ED_UNASSIGNED) { if (first == last) { @@ -1174,7 +1179,7 @@ if (first == last) { (void) keymacro__decode_str(firstbuf, unparsbuf, sizeof(unparsbuf), STRQQ); - (void) fprintf(el->el_outfile, "%-15s-> " FSTR "\n", + (void) fprintf(el->el_outfile, "%-15s-> %ls\n", unparsbuf, bp->name); } else { (void) keymacro__decode_str(firstbuf, unparsbuf, @@ -1182,7 +1187,7 @@ (void) keymacro__decode_str(lastbuf, extrabuf, sizeof(extrabuf), STRQQ); (void) fprintf(el->el_outfile, - "%-4s to %-7s-> " FSTR "\n", + "%-4s to %-7s-> %ls\n", unparsbuf, extrabuf, bp->name); } return; @@ -1212,7 +1217,7 @@ /* map_print_all_keys(): * Print the function description for all keys. */ -private void +static void map_print_all_keys(EditLine *el) { int prev, i; @@ -1238,25 +1243,25 @@ map_print_some_keys(el, el->el_map.alt, prev, i - 1); (void) fprintf(el->el_outfile, "Multi-character bindings\n"); - keymacro_print(el, STR("")); + keymacro_print(el, L""); (void) fprintf(el->el_outfile, "Arrow key bindings\n"); - terminal_print_arrow(el, STR("")); + terminal_print_arrow(el, L""); } /* map_bind(): * Add/remove/change bindings */ -protected int -map_bind(EditLine *el, int argc, const Char **argv) +libedit_private int +map_bind(EditLine *el, int argc, const wchar_t **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; + const wchar_t *p; + wchar_t inbuf[EL_BUFSIZ]; + wchar_t outbuf[EL_BUFSIZ]; + const wchar_t *in = NULL; + wchar_t *out; el_bindings_t *bp, *ep; int cmd; int key; @@ -1277,11 +1282,6 @@ case 's': ntype = XK_STR; break; -#ifdef notyet - case 'c': - ntype = XK_EXE; - break; -#endif case 'k': key = 1; break; @@ -1302,12 +1302,12 @@ ep = &el->el_map.help[el->el_map.nfunc]; for (bp = el->el_map.help; bp < ep; bp++) (void) fprintf(el->el_outfile, - "" FSTR "\n\t" FSTR "\n", + "%ls\n\t%ls\n", bp->name, bp->description); return 0; default: (void) fprintf(el->el_errfile, - "" FSTR ": Invalid switch `%lc'.\n", + "%ls: Invalid switch `%lc'.\n", argv[0], (wint_t)p[1]); } else @@ -1321,7 +1321,7 @@ in = argv[argc++]; else if ((in = parse__string(inbuf, argv[argc++])) == NULL) { (void) fprintf(el->el_errfile, - "" FSTR ": Invalid \\ or ^ in instring.\n", + "%ls: Invalid \\ or ^ in instring.\n", argv[0]); return -1; } @@ -1354,10 +1354,9 @@ switch (ntype) { case XK_STR: - case XK_EXE: if ((out = parse__string(outbuf, argv[argc])) == NULL) { (void) fprintf(el->el_errfile, - "" FSTR ": Invalid \\ or ^ in outstring.\n", argv[0]); + "%ls: Invalid \\ or ^ in outstring.\n", argv[0]); return -1; } if (key) @@ -1370,7 +1369,7 @@ case XK_CMD: if ((cmd = parse_cmd(el, argv[argc])) == -1) { (void) fprintf(el->el_errfile, - "" FSTR ": Invalid command `" FSTR "'.\n", + "%ls: Invalid command `%ls'.\n", argv[0], argv[argc]); return -1; } @@ -1399,8 +1398,9 @@ /* map_addfunc(): * add a user defined function */ -protected int -map_addfunc(EditLine *el, const Char *name, const Char *help, el_func_t func) +libedit_private int +map_addfunc(EditLine *el, const wchar_t *name, const wchar_t *help, + el_func_t func) { void *p; size_t nf = el->el_map.nfunc + 1; Index: lib/libedit/parse.h =================================================================== --- lib/libedit/parse.h +++ lib/libedit/parse.h @@ -1,4 +1,4 @@ -/* $NetBSD: parse.h,v 1.7 2009/12/30 22:37:40 christos Exp $ */ +/* $NetBSD: parse.h,v 1.9 2016/05/09 21:46:56 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -41,9 +41,9 @@ #ifndef _h_el_parse #define _h_el_parse -protected int parse_line(EditLine *, const Char *); -protected int parse__escape(const Char **); -protected Char *parse__string(Char *, const Char *); -protected int parse_cmd(EditLine *, const Char *); +libedit_private int parse_line(EditLine *, const wchar_t *); +libedit_private int parse__escape(const wchar_t **); +libedit_private wchar_t *parse__string(wchar_t *, const wchar_t *); +libedit_private int parse_cmd(EditLine *, const wchar_t *); #endif /* _h_el_parse */ Index: lib/libedit/parse.c =================================================================== --- lib/libedit/parse.c +++ lib/libedit/parse.c @@ -1,4 +1,4 @@ -/* $NetBSD: parse.c,v 1.35 2016/02/17 19:47:49 christos Exp $ */ +/* $NetBSD: parse.c,v 1.42 2019/07/23 10:18:52 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.35 2016/02/17 19:47:49 christos Exp $"); +__RCSID("$NetBSD: parse.c,v 1.42 2019/07/23 10:18:52 christos Exp $"); #endif #endif /* not lint && not SCCSID */ #include @@ -62,35 +62,35 @@ #include "el.h" #include "parse.h" -private const struct { - const Char *name; - int (*func)(EditLine *, int, const Char **); +static const struct { + const wchar_t *name; + int (*func)(EditLine *, int, const wchar_t **); } cmds[] = { - { STR("bind"), map_bind }, - { STR("echotc"), terminal_echotc }, - { STR("edit"), el_editmode }, - { STR("history"), hist_command }, - { STR("telltc"), terminal_telltc }, - { STR("settc"), terminal_settc }, - { STR("setty"), tty_stty }, - { NULL, NULL } + { L"bind", map_bind }, + { L"echotc", terminal_echotc }, + { L"edit", el_editmode }, + { L"history", hist_command }, + { L"telltc", terminal_telltc }, + { L"settc", terminal_settc }, + { L"setty", tty_stty }, + { NULL, NULL } }; /* parse_line(): * Parse a line and dispatch it */ -protected int -parse_line(EditLine *el, const Char *line) +libedit_private int +parse_line(EditLine *el, const wchar_t *line) { - const Char **argv; + const wchar_t **argv; int argc; - TYPE(Tokenizer) *tok; + TokenizerW *tok; - tok = FUN(tok,init)(NULL); - FUN(tok,str)(tok, line, &argc, &argv); - argc = FUN(el,parse)(el, argc, argv); - FUN(tok,end)(tok); + tok = tok_winit(NULL); + tok_wstr(tok, line, &argc, &argv); + argc = el_wparse(el, argc, argv); + tok_wend(tok); return argc; } @@ -98,26 +98,26 @@ /* el_parse(): * Command dispatcher */ -public int -FUN(el,parse)(EditLine *el, int argc, const Char *argv[]) +int +el_wparse(EditLine *el, int argc, const wchar_t *argv[]) { - const Char *ptr; + const wchar_t *ptr; int i; if (argc < 1) return -1; - ptr = Strchr(argv[0], ':'); + ptr = wcschr(argv[0], L':'); if (ptr != NULL) { - Char *tprog; + wchar_t *tprog; size_t l; if (ptr == argv[0]) return 0; - l = (size_t)(ptr - argv[0] - 1); - tprog = el_malloc((l + 1) * sizeof(*tprog)); + l = (size_t)(ptr - argv[0]); + tprog = el_calloc(l + 1, sizeof(*tprog)); if (tprog == NULL) return 0; - (void) Strncpy(tprog, argv[0], l); + (void) wcsncpy(tprog, argv[0], l); tprog[l] = '\0'; ptr++; l = (size_t)el_match(el->el_prog, tprog); @@ -128,7 +128,7 @@ ptr = argv[0]; for (i = 0; cmds[i].name != NULL; i++) - if (Strcmp(cmds[i].name, ptr) == 0) { + if (wcscmp(cmds[i].name, ptr) == 0) { i = (*cmds[i].func) (el, argc, argv); return -i; } @@ -140,10 +140,10 @@ * Parse a string of the form ^ \ \ \U+xxxx and return * the appropriate character or -1 if the escape is not valid */ -protected int -parse__escape(const Char **ptr) +libedit_private int +parse__escape(const wchar_t **ptr) { - const Char *p; + const wchar_t *p; wint_t c; p = *ptr; @@ -178,28 +178,28 @@ 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; + case 'U': /* Unicode \U+xxxx or \U+xxxxx format */ + { + int i; + const wchar_t hex[] = L"0123456789ABCDEF"; + const wchar_t *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; - } + for (i = 0; i < 5; ++i) { + h = wcschr(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': @@ -240,10 +240,10 @@ /* parse__string(): * Parse the escapes from in and put the raw string out */ -protected Char * -parse__string(Char *out, const Char *in) +libedit_private wchar_t * +parse__string(wchar_t *out, const wchar_t *in) { - Char *rv = out; + wchar_t *rv = out; int n; for (;;) @@ -256,7 +256,7 @@ case '^': if ((n = parse__escape(&in)) == -1) return NULL; - *out++ = (Char)n; + *out++ = (wchar_t)n; break; case 'M': @@ -278,14 +278,14 @@ * Return the command number for the command string given * or -1 if one is not found */ -protected int -parse_cmd(EditLine *el, const Char *cmd) +libedit_private int +parse_cmd(EditLine *el, const wchar_t *cmd) { el_bindings_t *b = el->el_map.help; size_t i; for (i = 0; i < el->el_map.nfunc; i++) - if (Strcmp(b[i].name, cmd) == 0) + if (wcscmp(b[i].name, cmd) == 0) return b[i].func; return -1; } Index: lib/libedit/prompt.h =================================================================== --- lib/libedit/prompt.h +++ lib/libedit/prompt.h @@ -1,4 +1,4 @@ -/* $NetBSD: prompt.h,v 1.13 2016/02/17 19:47:49 christos Exp $ */ +/* $NetBSD: prompt.h,v 1.15 2016/05/09 21:46:56 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -41,19 +41,19 @@ #ifndef _h_el_prompt #define _h_el_prompt -typedef Char *(*el_pfunc_t)(EditLine *); +typedef wchar_t *(*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 */ - Char p_ignore; /* character to start/end literal */ + wchar_t 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, Char, int, int); -protected int prompt_get(EditLine *, el_pfunc_t *, Char *, int); -protected int prompt_init(EditLine *); -protected void prompt_end(EditLine *); +libedit_private void prompt_print(EditLine *, int); +libedit_private int prompt_set(EditLine *, el_pfunc_t, wchar_t, int, int); +libedit_private int prompt_get(EditLine *, el_pfunc_t *, wchar_t *, int); +libedit_private int prompt_init(EditLine *); +libedit_private void prompt_end(EditLine *); #endif /* _h_el_prompt */ Index: lib/libedit/prompt.c =================================================================== --- lib/libedit/prompt.c +++ lib/libedit/prompt.c @@ -1,4 +1,4 @@ -/* $NetBSD: prompt.c,v 1.23 2016/02/16 15:53:48 christos Exp $ */ +/* $NetBSD: prompt.c,v 1.27 2017/06/27 23:25:13 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.23 2016/02/16 15:53:48 christos Exp $"); +__RCSID("$NetBSD: prompt.c,v 1.27 2017/06/27 23:25:13 christos Exp $"); #endif #endif /* not lint && not SCCSID */ #include @@ -49,17 +49,17 @@ #include #include "el.h" -private Char *prompt_default(EditLine *); -private Char *prompt_default_r(EditLine *); +static wchar_t *prompt_default(EditLine *); +static wchar_t *prompt_default_r(EditLine *); /* prompt_default(): * Just a default prompt, in case the user did not provide one */ -private Char * +static wchar_t * /*ARGSUSED*/ prompt_default(EditLine *el __attribute__((__unused__))) { - static Char a[3] = {'?', ' ', '\0'}; + static wchar_t a[3] = L"? "; return a; } @@ -68,11 +68,11 @@ /* prompt_default_r(): * Just a default rprompt, in case the user did not provide one */ -private Char * +static wchar_t * /*ARGSUSED*/ prompt_default_r(EditLine *el __attribute__((__unused__))) { - static Char a[1] = {'\0'}; + static wchar_t a[1] = L""; return a; } @@ -81,12 +81,11 @@ /* prompt_print(): * Print the prompt and update the prompt position. */ -protected void +libedit_private void prompt_print(EditLine *el, int op) { el_prompt_t *elp; - Char *p; - int ignore = 0; + wchar_t *p; if (op == EL_PROMPT) elp = &el->el_prompt; @@ -101,13 +100,17 @@ for (; *p; p++) { if (elp->p_ignore == *p) { - ignore = !ignore; + wchar_t *litstart = ++p; + while (*p && *p != elp->p_ignore) + p++; + if (!*p || !p[1]) { + // XXX: We lose the last literal + break; + } + re_putliteral(el, litstart, p++); continue; } - if (ignore) - terminal__putc(el, *p); - else - re_putc(el, *p, 1); + re_putc(el, *p, 1); } elp->p_pos.v = el->el_refresh.r_cursor.v; @@ -118,7 +121,7 @@ /* prompt_init(): * Initialize the prompt stuff */ -protected int +libedit_private int prompt_init(EditLine *el) { @@ -137,7 +140,7 @@ /* prompt_end(): * Clean up the prompt stuff */ -protected void +libedit_private void /*ARGSUSED*/ prompt_end(EditLine *el __attribute__((__unused__))) { @@ -147,8 +150,8 @@ /* prompt_set(): * Install a prompt printing function */ -protected int -prompt_set(EditLine *el, el_pfunc_t prf, Char c, int op, int wide) +libedit_private int +prompt_set(EditLine *el, el_pfunc_t prf, wchar_t c, int op, int wide) { el_prompt_t *p; @@ -179,8 +182,8 @@ /* prompt_get(): * Retrieve the prompt printing function */ -protected int -prompt_get(EditLine *el, el_pfunc_t *prf, Char *c, int op) +libedit_private int +prompt_get(EditLine *el, el_pfunc_t *prf, wchar_t *c, int op) { el_prompt_t *p; Index: lib/libedit/read.h =================================================================== --- lib/libedit/read.h +++ lib/libedit/read.h @@ -1,4 +1,4 @@ -/* $NetBSD: read.h,v 1.9 2016/02/24 17:13:22 christos Exp $ */ +/* $NetBSD: read.h,v 1.12 2016/05/22 19:44:26 christos Exp $ */ /*- * Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -37,16 +37,11 @@ #ifndef _h_el_read #define _h_el_read -typedef int (*el_rfunc_t)(EditLine *, wchar_t *); +libedit_private int read_init(EditLine *); +libedit_private void read_end(struct el_read_t *); +libedit_private void read_prepare(EditLine *); +libedit_private void read_finish(EditLine *); +libedit_private int el_read_setfn(struct el_read_t *, el_rfunc_t); +libedit_private el_rfunc_t el_read_getfn(struct el_read_t *); -typedef struct el_read_t { - el_rfunc_t read_char; /* Function to read a character */ -} el_read_t; - -protected int read_init(EditLine *); -protected void read_prepare(EditLine *); -protected void read_finish(EditLine *); -protected int el_read_setfn(EditLine *, el_rfunc_t); -protected el_rfunc_t el_read_getfn(EditLine *); - #endif /* _h_el_read */ Index: lib/libedit/read.c =================================================================== --- lib/libedit/read.c +++ lib/libedit/read.c @@ -1,4 +1,4 @@ -/* $NetBSD: read.c,v 1.86 2016/03/02 19:24:20 christos Exp $ */ +/* $NetBSD: read.c,v 1.106 2019/07/23 10:18:52 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -56,35 +56,74 @@ #include #include "el.h" +#include "fcns.h" +#include "read.h" -#define OKCMD -1 /* must be -1! */ +#define EL_MAXMACRO 10 -private int read__fixio(int, int); -private int read_preread(EditLine *); -private int read_char(EditLine *, wchar_t *); -private int read_getcmd(EditLine *, el_action_t *, Char *); -private void read_pop(c_macro_t *); +struct macros { + wchar_t **macro; + int level; + int offset; +}; +struct el_read_t { + struct macros macros; + el_rfunc_t read_char; /* Function to read a character. */ + int read_errno; +}; + +static int read__fixio(int, int); +static int read_char(EditLine *, wchar_t *); +static int read_getcmd(EditLine *, el_action_t *, wchar_t *); +static void read_clearmacros(struct macros *); +static void read_pop(struct macros *); +static const wchar_t *noedit_wgets(EditLine *, int *); + /* read_init(): * Initialize the read stuff */ -protected int +libedit_private int read_init(EditLine *el) { + struct macros *ma; + + if ((el->el_read = el_malloc(sizeof(*el->el_read))) == NULL) + return -1; + + ma = &el->el_read->macros; + if ((ma->macro = el_calloc(EL_MAXMACRO, sizeof(*ma->macro))) == NULL) { + free(el->el_read); + return -1; + } + ma->level = -1; + ma->offset = 0; + /* builtin read_char */ - el->el_read.read_char = read_char; + el->el_read->read_char = read_char; return 0; } +/* el_read_end(): + * Free the data structures used by the read stuff. + */ +libedit_private void +read_end(struct el_read_t *el_read) +{ + read_clearmacros(&el_read->macros); + el_free(el_read->macros.macro); + el_read->macros.macro = NULL; + el_free(el_read); +} /* el_read_setfn(): * Set the read char function to the one provided. * If it is set to EL_BUILTIN_GETCFN, then reset to the builtin one. */ -protected int -el_read_setfn(EditLine *el, el_rfunc_t rc) +libedit_private int +el_read_setfn(struct el_read_t *el_read, el_rfunc_t rc) { - el->el_read.read_char = (rc == EL_BUILTIN_GETCFN) ? read_char : rc; + el_read->read_char = (rc == EL_BUILTIN_GETCFN) ? read_char : rc; return 0; } @@ -93,42 +132,19 @@ * return the current read char function, or EL_BUILTIN_GETCFN * if it is the default one */ -protected el_rfunc_t -el_read_getfn(EditLine *el) +libedit_private el_rfunc_t +el_read_getfn(struct el_read_t *el_read) { - return el->el_read.read_char == read_char ? - EL_BUILTIN_GETCFN : el->el_read.read_char; + return el_read->read_char == read_char ? + EL_BUILTIN_GETCFN : el_read->read_char; } -#ifndef MIN -#define MIN(A,B) ((A) < (B) ? (A) : (B)) -#endif - -#ifdef DEBUG_EDIT -private void -read_debug(EditLine *el) -{ - - if (el->el_line.cursor > el->el_line.lastchar) - (void) fprintf(el->el_errfile, "cursor > lastchar\r\n"); - if (el->el_line.cursor < el->el_line.buffer) - (void) fprintf(el->el_errfile, "cursor < buffer\r\n"); - if (el->el_line.cursor > el->el_line.limit) - (void) fprintf(el->el_errfile, "cursor > limit\r\n"); - if (el->el_line.lastchar > el->el_line.limit) - (void) fprintf(el->el_errfile, "lastchar > limit\r\n"); - if (el->el_line.limit != &el->el_line.buffer[EL_BUFSIZ - 2]) - (void) fprintf(el->el_errfile, "limit != &buffer[EL_BUFSIZ-2]\r\n"); -} -#endif /* DEBUG_EDIT */ - - /* read__fixio(): * Try to recover from a read error */ /* ARGSUSED */ -private int +static int read__fixio(int fd __attribute__((__unused__)), int e) { @@ -186,49 +202,17 @@ } -/* read_preread(): - * Try to read the stuff in the input queue; - */ -private int -read_preread(EditLine *el) -{ - int chrs = 0; - - 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, &chrs); - if (chrs > 0) { - char buf[EL_BUFSIZ]; - - chrs = read(el->el_infd, buf, - (size_t) MIN(chrs, EL_BUFSIZ - 1)); - if (chrs > 0) { - buf[chrs] = '\0'; - el_push(el, buf); - } - } -#endif /* FIONREAD */ -#endif - return chrs > 0; -} - - /* el_push(): * Push a macro */ -public void -FUN(el,push)(EditLine *el, const Char *str) +void +el_wpush(EditLine *el, const wchar_t *str) { - c_macro_t *ma = &el->el_chared.c_macro; + struct macros *ma = &el->el_read->macros; if (str != NULL && ma->level + 1 < EL_MAXMACRO) { ma->level++; - if ((ma->macro[ma->level] = Strdup(str)) != NULL) + if ((ma->macro[ma->level] = wcsdup(str)) != NULL) return; ma->level--; } @@ -238,24 +222,19 @@ /* read_getcmd(): - * Get next command from the input stream, return OKCMD on success. + * Get next command from the input stream, + * return 0 on success or -1 on EOF or error. * Character values > 255 are not looked up in the map, but inserted. */ -private int -read_getcmd(EditLine *el, el_action_t *cmdnum, Char *ch) +static int +read_getcmd(EditLine *el, el_action_t *cmdnum, wchar_t *ch) { - static const Char meta = (Char)0x80; + static const wchar_t meta = (wchar_t)0x80; el_action_t cmd; - wchar_t wc; - int num; - el->el_errno = 0; do { - if ((num = el_wgetc(el, &wc)) != 1) {/* if EOF or error */ - el->el_errno = num == 0 ? 0 : errno; - return 0; /* not OKCMD */ - } - *ch = (Char)wc; + if (el_wgetc(el, ch) != 1) + return -1; #ifdef KANJI if ((*ch & meta)) { @@ -269,11 +248,9 @@ el->el_state.metanext = 0; *ch |= meta; } -#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) { keymacro_value_t val; @@ -282,30 +259,24 @@ cmd = val.cmd; break; case XK_STR: - FUN(el,push)(el, val.str); + el_wpush(el, val.str); break; -#ifdef notyet - case XK_EXE: - /* XXX: In the future to run a user function */ - RunCommand(val.str); - break; -#endif + case XK_NOD: + return -1; default: EL_ABORT((el->el_errfile, "Bad XK_ type \n")); break; } } - if (el->el_map.alt == NULL) - el->el_map.current = el->el_map.key; } while (cmd == ED_SEQUENCE_LEAD_IN); *cmdnum = cmd; - return OKCMD; + return 0; } /* read_char(): * Read a character from the tty. */ -private int +static int read_char(EditLine *el, wchar_t *cp) { ssize_t num_read; @@ -320,7 +291,7 @@ int e = errno; switch (el->el_signal->sig_no) { case SIGCONT: - FUN(el,set)(el, EL_REFRESH); + el_wset(el, EL_REFRESH); /*FALLTHROUGH*/ case SIGWINCH: sig_set(el); @@ -345,9 +316,12 @@ } for (;;) { + mbstate_t mbs; ++cbp; - switch (ct_mbrtowc(cp, cbuf, cbp)) { + /* This only works because UTF8 is stateless. */ + memset(&mbs, 0, sizeof(mbs)); + switch (mbrtowc(cp, cbuf, cbp, &mbs)) { case (size_t)-1: if (cbp > 1) { /* @@ -380,8 +354,8 @@ /* read_pop(): * Pop a macro from the stack */ -private void -read_pop(c_macro_t *ma) +static void +read_pop(struct macros *ma) { int i; @@ -392,22 +366,25 @@ ma->offset = 0; } +static void +read_clearmacros(struct macros *ma) +{ + while (ma->level >= 0) + el_free(ma->macro[ma->level--]); + ma->offset = 0; +} + /* el_wgetc(): * Read a wide character */ -public int +int el_wgetc(EditLine *el, wchar_t *cp) { + struct macros *ma = &el->el_read->macros; int num_read; - c_macro_t *ma = &el->el_chared.c_macro; terminal__flush(el); for (;;) { - if (ma->level < 0) { - if (!read_preread(el)) - break; - } - if (ma->level < 0) break; @@ -426,25 +403,23 @@ return 1; } -#ifdef DEBUG_READ - (void) fprintf(el->el_errfile, "Turning raw mode on\n"); -#endif /* DEBUG_READ */ if (tty_rawmode(el) < 0)/* make sure the tty is set up correctly */ return 0; -#ifdef DEBUG_READ - (void) fprintf(el->el_errfile, "Reading a character\n"); -#endif /* DEBUG_READ */ - num_read = (*el->el_read.read_char)(el, cp); + num_read = (*el->el_read->read_char)(el, cp); + + /* + * Remember the original reason of a read failure + * such that el_wgets() can restore it after doing + * various cleanup operation that might change errno. + */ if (num_read < 0) - el->el_errno = errno; -#ifdef DEBUG_READ - (void) fprintf(el->el_errfile, "Got it %lc\n", *cp); -#endif /* DEBUG_READ */ + el->el_read->read_errno = errno; + return num_read; } -protected void +libedit_private void read_prepare(EditLine *el) { if (el->el_flags & HANDLE_SIGNALS) @@ -458,14 +433,14 @@ we have the wrong size. */ el_resize(el); re_clear_display(el); /* reset the display stuff */ - ch_reset(el, 0); + ch_reset(el); re_refresh(el); /* print the prompt */ if (el->el_flags & UNBUFFERED) terminal__flush(el); } -protected void +libedit_private void read_finish(EditLine *el) { if ((el->el_flags & UNBUFFERED) == 0) @@ -474,56 +449,52 @@ sig_clr(el); } -public const Char * -FUN(el,gets)(EditLine *el, int *nread) +static const wchar_t * +noedit_wgets(EditLine *el, int *nread) { + el_line_t *lp = &el->el_line; + int num; + + while ((num = (*el->el_read->read_char)(el, lp->lastchar)) == 1) { + if (lp->lastchar + 1 >= lp->limit && + !ch_enlargebufs(el, (size_t)2)) + break; + lp->lastchar++; + if (el->el_flags & UNBUFFERED || + lp->lastchar[-1] == '\r' || + lp->lastchar[-1] == '\n') + break; + } + if (num == -1 && errno == EINTR) + lp->lastchar = lp->buffer; + lp->cursor = lp->lastchar; + *lp->lastchar = '\0'; + *nread = (int)(lp->lastchar - lp->buffer); + return *nread ? lp->buffer : NULL; +} + +const wchar_t * +el_wgets(EditLine *el, int *nread) +{ int retval; el_action_t cmdnum = 0; int num; /* how many chars we have read at NL */ - wchar_t wc; - Char ch, *cp; - int crlf = 0; + wchar_t ch; int nrb; -#ifdef FIONREAD - c_macro_t *ma = &el->el_chared.c_macro; -#endif /* FIONREAD */ if (nread == NULL) nread = &nrb; *nread = 0; + el->el_read->read_errno = 0; if (el->el_flags & NO_TTY) { - size_t idx; - - cp = el->el_line.buffer; - while ((num = (*el->el_read.read_char)(el, &wc)) == 1) { - *cp = (Char)wc; - /* make sure there is space for next character */ - if (cp + 1 >= el->el_line.limit) { - idx = (size_t)(cp - el->el_line.buffer); - if (!ch_enlargebufs(el, (size_t)2)) - break; - cp = &el->el_line.buffer[idx]; - } - cp++; - if (el->el_flags & UNBUFFERED) - break; - if (cp[-1] == '\r' || cp[-1] == '\n') - break; - } - if (num == -1) { - if (errno == EINTR) - cp = el->el_line.buffer; - el->el_errno = errno; - } - - goto noedit; + el->el_line.lastchar = el->el_line.buffer; + return noedit_wgets(el, nread); } - #ifdef FIONREAD - if (el->el_tty.t_mode == EX_IO && ma->level < 0) { - long chrs = 0; + if (el->el_tty.t_mode == EX_IO && el->el_read->macros.level < 0) { + int chrs = 0; (void) ioctl(el->el_infd, FIONREAD, &chrs); if (chrs == 0) { @@ -540,83 +511,19 @@ read_prepare(el); if (el->el_flags & EDIT_DISABLED) { - size_t idx; - if ((el->el_flags & UNBUFFERED) == 0) - cp = el->el_line.buffer; - else - cp = el->el_line.lastchar; - + el->el_line.lastchar = el->el_line.buffer; terminal__flush(el); - - while ((num = (*el->el_read.read_char)(el, &wc)) == 1) { - *cp = (Char)wc; - /* make sure there is space next character */ - if (cp + 1 >= el->el_line.limit) { - idx = (size_t)(cp - el->el_line.buffer); - if (!ch_enlargebufs(el, (size_t)2)) - break; - cp = &el->el_line.buffer[idx]; - } - cp++; - crlf = cp[-1] == '\r' || cp[-1] == '\n'; - if (el->el_flags & UNBUFFERED) - break; - if (crlf) - break; - } - - if (num == -1) { - if (errno == EINTR) - cp = el->el_line.buffer; - el->el_errno = errno; - } - - goto noedit; + return noedit_wgets(el, nread); } - for (num = OKCMD; num == OKCMD;) { /* while still editing this - * line */ -#ifdef DEBUG_EDIT - read_debug(el); -#endif /* DEBUG_EDIT */ + for (num = -1; num == -1;) { /* while still editing this line */ /* if EOF or error */ - if ((num = read_getcmd(el, &cmdnum, &ch)) != OKCMD) { - num = -1; -#ifdef DEBUG_READ - (void) fprintf(el->el_errfile, - "Returning from el_gets %d\n", num); -#endif /* DEBUG_READ */ + if (read_getcmd(el, &cmdnum, &ch) == -1) break; - } - 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 ((size_t)cmdnum >= el->el_map.nfunc) { /* BUG CHECK command */ -#ifdef DEBUG_EDIT - (void) fprintf(el->el_errfile, - "ERROR: illegal command from key 0%o\r\n", ch); -#endif /* DEBUG_EDIT */ + if ((size_t)cmdnum >= el->el_map.nfunc) /* BUG CHECK command */ continue; /* try again */ - } /* now do the real command */ -#ifdef DEBUG_READ - { - el_bindings_t *b; - for (b = el->el_map.help; b->name; b++) - if (b->func == cmdnum) - break; - if (b->name) - (void) fprintf(el->el_errfile, - "Executing " FSTR "\n", b->name); - else - (void) fprintf(el->el_errfile, - "Error command = %d\n", cmdnum); - } -#endif /* DEBUG_READ */ /* vi redo needs these way down the levels... */ el->el_state.thiscmd = cmdnum; el->el_state.thisch = ch; @@ -625,16 +532,12 @@ el->el_chared.c_redo.pos < el->el_chared.c_redo.lim) { if (cmdnum == VI_DELETE_PREV_CHAR && el->el_chared.c_redo.pos != el->el_chared.c_redo.buf - && Isprint(el->el_chared.c_redo.pos[-1])) + && iswprint(el->el_chared.c_redo.pos[-1])) el->el_chared.c_redo.pos--; else *el->el_chared.c_redo.pos++ = ch; } retval = (*el->el_map.func[cmdnum]) (el, ch); -#ifdef DEBUG_READ - (void) fprintf(el->el_errfile, - "Returned state %d\n", retval ); -#endif /* DEBUG_READ */ /* save the last command here */ el->el_state.lastcmd = cmdnum; @@ -681,22 +584,15 @@ break; case CC_FATAL: /* fatal error, reset to known state */ -#ifdef DEBUG_READ - (void) fprintf(el->el_errfile, - "*** editor fatal ERROR ***\r\n\n"); -#endif /* DEBUG_READ */ /* put (real) cursor in a known place */ re_clear_display(el); /* reset the display stuff */ - ch_reset(el, 1); /* reset the input pointers */ + ch_reset(el); /* reset the input pointers */ + read_clearmacros(&el->el_read->macros); re_refresh(el); /* print the prompt again */ break; case CC_ERROR: default: /* functions we don't know about */ -#ifdef DEBUG_READ - (void) fprintf(el->el_errfile, - "*** editor ERROR ***\r\n\n"); -#endif /* DEBUG_READ */ terminal_beep(el); terminal__flush(el); break; @@ -713,19 +609,14 @@ if ((el->el_flags & UNBUFFERED) == 0) { read_finish(el); *nread = num != -1 ? num : 0; - } else { + } else *nread = (int)(el->el_line.lastchar - el->el_line.buffer); - } - goto done; -noedit: - el->el_line.cursor = el->el_line.lastchar = cp; - *cp = '\0'; - *nread = (int)(el->el_line.cursor - el->el_line.buffer); -done: + if (*nread == 0) { if (num == -1) { *nread = -1; - errno = el->el_errno; + if (el->el_read->read_errno) + errno = el->el_read->read_errno; } return NULL; } else Index: lib/libedit/readline.c =================================================================== --- lib/libedit/readline.c +++ lib/libedit/readline.c @@ -1,4 +1,4 @@ -/* $NetBSD: readline.c,v 1.126 2016/02/24 17:13:22 christos Exp $ */ +/* $NetBSD: readline.c,v 1.157 2019/08/21 11:11:48 christos Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ #include "config.h" #if !defined(lint) && !defined(SCCSID) -__RCSID("$NetBSD: readline.c,v 1.126 2016/02/24 17:13:22 christos Exp $"); +__RCSID("$NetBSD: readline.c,v 1.157 2019/08/21 11:11:48 christos Exp $"); #endif /* not lint && not SCCSID */ #include __FBSDID("$FreeBSD$"); @@ -54,6 +54,7 @@ #include "readline/readline.h" #include "el.h" +#include "fcns.h" #include "filecomplete.h" void rl_prep_terminal(int); @@ -73,7 +74,7 @@ static char expand_chars[] = { ' ', '\t', '\n', '=', '(', '\0' }; static char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', '$', '>', '<', '=', ';', '|', '&', '{', '(', '\0' }; -char *rl_readline_name = empty; +const char *rl_readline_name = empty; FILE *rl_instream = NULL; FILE *rl_outstream = NULL; int rl_point = 0; @@ -81,7 +82,7 @@ char *rl_line_buffer = NULL; rl_vcpfunc_t *rl_linefunc = NULL; int rl_done = 0; -VFunction *rl_event_hook = NULL; +rl_hook_func_t *rl_event_hook = NULL; KEYMAP_ENTRY_ARRAY emacs_standard_keymap, emacs_meta_keymap, emacs_ctlx_keymap; @@ -96,6 +97,7 @@ int history_base = 1; /* probably never subject to change */ int history_length = 0; +int history_offset = 0; int max_input_history = 0; char history_expansion_char = '!'; char history_subst_char = '^'; @@ -105,9 +107,9 @@ int rl_inhibit_completion = 0; int rl_attempted_completion_over = 0; -char *rl_basic_word_break_characters = break_chars; +const char *rl_basic_word_break_characters = break_chars; char *rl_completer_word_break_characters = NULL; -char *rl_completer_quote_characters = NULL; +const char *rl_completer_quote_characters = NULL; rl_compentry_func_t *rl_completion_entry_function = NULL; char *(*rl_completion_word_break_hook)(void) = NULL; rl_completion_func_t *rl_attempted_completion_function = NULL; @@ -122,6 +124,7 @@ int _rl_print_completions_horizontally = 0; VFunction *rl_redisplay_function = NULL; Function *rl_startup_hook = NULL; +int rl_did_startup_hook = 0; 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; @@ -149,7 +152,7 @@ * in the parsed text when it is passed to the completion function. * Shell uses this to help determine what kind of completing to do. */ -char *rl_special_prefixes = NULL; +const char *rl_special_prefixes = NULL; /* * This is the character appended to the completed words if at the end of @@ -169,7 +172,6 @@ static unsigned char _el_rl_tstp(EditLine *, int); static char *_get_prompt(EditLine *); static int _getc_function(EditLine *, wchar_t *); -static HIST_ENTRY *_move_history(int); static int _history_expand_command(const char *, size_t, size_t, char **); static char *_rl_compat_sub(const char *, const char *, @@ -177,6 +179,7 @@ static int _rl_event_read_char(EditLine *, wchar_t *); static void _rl_update_pos(void); +static HIST_ENTRY rl_he; /* ARGSUSED */ static char * @@ -188,25 +191,6 @@ /* - * generic function for moving around history - */ -static HIST_ENTRY * -_move_history(int op) -{ - HistEvent ev; - static HIST_ENTRY rl_he; - - if (history(h, &ev, op) != 0) - return NULL; - - rl_he.line = ev.str; - rl_he.data = NULL; - - return &rl_he; -} - - -/* * read one key from user defined input function */ static int @@ -215,7 +199,7 @@ { int i; - i = (*rl_getc_function)(NULL); + i = (*rl_getc_function)(rl_instream); if (i == -1) return 0; *c = (wchar_t)i; @@ -276,8 +260,14 @@ if (rl_prompt == NULL) return -1; - while ((p = strchr(rl_prompt, RL_PROMPT_END_IGNORE)) != NULL) - *p = RL_PROMPT_START_IGNORE; + while ((p = strchr(rl_prompt, RL_PROMPT_END_IGNORE)) != NULL) { + /* Remove adjacent end/start markers to avoid double-escapes. */ + if (p[1] == RL_PROMPT_START_IGNORE) { + memmove(p, p + 2, 1 + strlen(p + 2)); + } else { + *p = RL_PROMPT_START_IGNORE; + } + } return 0; } @@ -308,7 +298,9 @@ if (tcgetattr(fileno(rl_instream), &t) != -1 && (t.c_lflag & ECHO) == 0) editmode = 0; - e = el_init(rl_readline_name, rl_instream, rl_outstream, stderr); + e = el_init_internal(rl_readline_name, rl_instream, rl_outstream, + stderr, fileno(rl_instream), fileno(rl_outstream), fileno(stderr), + NO_RESET); if (!editmode) el_set(e, EL_EDITMODE, 0); @@ -335,7 +327,7 @@ el_end(e); return -1; } - el_set(e, EL_PROMPT, _get_prompt, RL_PROMPT_START_IGNORE); + el_set(e, EL_PROMPT_ESC, _get_prompt, RL_PROMPT_START_IGNORE); el_set(e, EL_SIGNAL, rl_catch_signals); /* set default mode to "emacs"-style and read setting afterwards */ @@ -404,8 +396,7 @@ _resize_fun(e, &rl_line_buffer); _rl_update_pos(); - if (rl_startup_hook) - (*rl_startup_hook)(NULL, 0); + tty_end(e, TCSADRAIN); return 0; } @@ -427,19 +418,26 @@ if (e == NULL || h == NULL) rl_initialize(); + if (rl_did_startup_hook == 0 && rl_startup_hook) { + rl_did_startup_hook = 1; + (*rl_startup_hook)(NULL, 0); + } + tty_init(e); + rl_done = 0; (void)setjmp(topbuf); + buf = NULL; /* update prompt accordingly to what has been passed */ if (rl_set_prompt(prompt) == -1) - return NULL; + goto out; if (rl_pre_input_hook) (*rl_pre_input_hook)(NULL, 0); - if (rl_event_hook && !(e->el_flags&NO_TTY)) { + if (rl_event_hook && !(e->el_flags & NO_TTY)) { el_set(e, EL_GETCFN, _rl_event_read_char); used_event_hook = 1; } @@ -459,7 +457,7 @@ buf = strdup(ret); if (buf == NULL) - return NULL; + goto out; lastidx = count - 1; if (buf[lastidx] == '\n') buf[lastidx] = '\0'; @@ -469,6 +467,8 @@ history(h, &ev, H_GETSIZE); history_length = ev.num; +out: + tty_end(e, TCSADRAIN); return buf; } @@ -485,6 +485,7 @@ { if (h == NULL || e == NULL) rl_initialize(); + history_offset = history_length; } @@ -516,7 +517,7 @@ } else s++; } - r = result = el_malloc((len + 1) * sizeof(*r)); + r = result = el_calloc(len + 1, sizeof(*r)); if (result == NULL) return NULL; s = str; @@ -566,7 +567,7 @@ } if ('0' <= cmd[idx] && cmd[idx] <= '9') { - HIST_ENTRY *rl_he; + HIST_ENTRY *he; num = 0; while (cmd[idx] && '0' <= cmd[idx] && cmd[idx] <= '9') { @@ -574,13 +575,13 @@ idx++; } if (sign) - num = history_length - num + 1; + num = history_length - num + history_base; - if (!(rl_he = history_get(num))) + if (!(he = history_get(num))) return NULL; *cindex = idx; - return rl_he->line; + return he->line; } sub = 0; if (cmd[idx] == '?') { @@ -606,7 +607,7 @@ else if (len == 0) return NULL; else { - if ((pat = el_malloc((len + 1) * sizeof(*pat))) == NULL) + if ((pat = el_calloc(len + 1, sizeof(*pat))) == NULL) return NULL; (void)strncpy(pat, cmd + begin, len); pat[len] = '\0'; @@ -700,7 +701,7 @@ } else { if (command[offs + 1] == '#') { /* use command so far */ - if ((aptr = el_malloc((offs + 1) * sizeof(*aptr))) + if ((aptr = el_calloc(offs + 1, sizeof(*aptr))) == NULL) return -1; (void)strncpy(aptr, command, offs); @@ -934,7 +935,7 @@ *output = NULL; if (str[0] == history_subst_char) { /* ^foo^foo2^ is equivalent to !!:s^foo^foo2^ */ - *output = el_malloc((strlen(str) + 4 + 1) * sizeof(**output)); + *output = el_calloc(strlen(str) + 4 + 1, sizeof(**output)); if (*output == NULL) return 0; (*output)[0] = (*output)[1] = history_expansion_char; @@ -1082,7 +1083,7 @@ for (i = (size_t)start, len = 0; i <= (size_t)end; i++) len += strlen(arr[i]) + 1; len++; - result = el_malloc(len * sizeof(*result)); + result = el_calloc(len, sizeof(*result)); if (result == NULL) goto out; @@ -1144,7 +1145,7 @@ result = nresult; } len = (size_t)i - (size_t)start; - temp = el_malloc((size_t)(len + 1) * sizeof(*temp)); + temp = el_calloc(len + 1, sizeof(*temp)); if (temp == NULL) { for (i = 0; i < idx; i++) el_free(result[i]); @@ -1169,12 +1170,22 @@ stifle_history(int max) { HistEvent ev; + HIST_ENTRY *he; if (h == NULL || e == NULL) rl_initialize(); - if (history(h, &ev, H_SETSIZE, max) == 0) + if (history(h, &ev, H_SETSIZE, max) == 0) { max_input_history = max; + if (history_length > max) + history_base = history_length - max; + while (history_length > max) { + he = remove_history(0); + el_free(he->data); + el_free((void *)(unsigned long)he->line); + el_free(he); + } + } } @@ -1352,8 +1363,14 @@ rl_initialize(); if (filename == NULL && (filename = _default_history_file()) == NULL) return errno; - return history(h, &ev, H_LOAD, filename) == -1 ? - (errno ? errno : EINVAL) : 0; + errno = 0; + if (history(h, &ev, H_LOAD, filename) == -1) + return errno ? errno : EINVAL; + if (history(h, &ev, H_GETSIZE) == 0) + history_length = ev.num; + if (history_length < 0) + return EINVAL; + return 0; } @@ -1373,7 +1390,29 @@ (errno ? errno : EINVAL) : 0; } +int +append_history(int n, const char *filename) +{ + HistEvent ev; + FILE *fp; + if (h == NULL || e == NULL) + rl_initialize(); + if (filename == NULL && (filename = _default_history_file()) == NULL) + return errno; + + if ((fp = fopen(filename, "a")) == NULL) + return errno; + + if (history(h, &ev, H_NSAVE_FP, (size_t)n, fp) == -1) { + int serrno = errno ? errno : EINVAL; + fclose(fp); + return serrno; + } + fclose(fp); + return 0; +} + /* * returns history ``num''th event * @@ -1389,25 +1428,37 @@ if (h == NULL || e == NULL) rl_initialize(); + if (num < history_base) + return NULL; + /* save current position */ if (history(h, &ev, H_CURR) != 0) return NULL; curr_num = ev.num; - /* start from the oldest */ - if (history(h, &ev, H_LAST) != 0) - return NULL; /* error */ + /* + * use H_DELDATA to set to nth history (without delete) by passing + * (void **)-1 -- as in history_set_pos + */ + if (history(h, &ev, H_DELDATA, num - history_base, (void **)-1) != 0) + goto out; - /* look forwards for event matching specified offset */ - if (history(h, &ev, H_NEXT_EVDATA, num, &she.data)) - return NULL; - + /* get current entry */ + if (history(h, &ev, H_CURR) != 0) + goto out; + if (history(h, &ev, H_NEXT_EVDATA, ev.num, &she.data) != 0) + goto out; she.line = ev.str; /* restore pointer to where it was */ (void)history(h, &ev, H_SET, curr_num); return &she; + +out: + /* restore pointer to where it was */ + (void)history(h, &ev, H_SET, curr_num); + return NULL; } @@ -1419,17 +1470,20 @@ { HistEvent ev; - if (line == NULL) - return 0; - if (h == NULL || e == NULL) rl_initialize(); - (void)history(h, &ev, H_ENTER, line); - if (history(h, &ev, H_GETSIZE) == 0) + if (history(h, &ev, H_ENTER, line) == -1) + return 0; + + (void)history(h, &ev, H_GETSIZE); + if (ev.num == history_length) + history_base++; + else { + history_offset++; history_length = ev.num; - - return !(history_length > 0); /* return 0 if all is okay */ + } + return 0; } @@ -1519,7 +1573,7 @@ rl_initialize(); (void)history(h, &ev, H_CLEAR); - history_length = 0; + history_offset = history_length = 0; } @@ -1529,30 +1583,58 @@ int where_history(void) { + return history_offset; +} + +static HIST_ENTRY **_history_listp; +static HIST_ENTRY *_history_list; + +HIST_ENTRY ** +history_list(void) +{ HistEvent ev; - int curr_num, off; + HIST_ENTRY **nlp, *nl; + int i; - if (history(h, &ev, H_CURR) != 0) - return 0; - curr_num = ev.num; + if (history(h, &ev, H_LAST) != 0) + return NULL; - (void)history(h, &ev, H_FIRST); - off = 1; - while (ev.num != curr_num && history(h, &ev, H_NEXT) == 0) - off++; + if ((nlp = el_realloc(_history_listp, + ((size_t)history_length + 1) * sizeof(*nlp))) == NULL) + return NULL; + _history_listp = nlp; - return off; + if ((nl = el_realloc(_history_list, + (size_t)history_length * sizeof(*nl))) == NULL) + return NULL; + _history_list = nl; + + i = 0; + do { + _history_listp[i] = &_history_list[i]; + _history_list[i].line = ev.str; + _history_list[i].data = NULL; + if (i++ == history_length) + abort(); + } while (history(h, &ev, H_PREV) == 0); + _history_listp[i] = NULL; + return _history_listp; } - /* * returns current history event or NULL if there is no such event */ HIST_ENTRY * current_history(void) { + HistEvent ev; - return _move_history(H_CURR); + if (history(h, &ev, H_PREV_EVENT, history_offset + 1) != 0) + return NULL; + + rl_he.line = ev.str; + rl_he.data = NULL; + return &rl_he; } @@ -1589,35 +1671,31 @@ int history_set_pos(int pos) { - HistEvent ev; - int curr_num; - if (pos >= history_length || pos < 0) - return -1; + return 0; - (void)history(h, &ev, H_CURR); - curr_num = ev.num; - - /* - * use H_DELDATA to set to nth history (without delete) by passing - * (void **)-1 - */ - if (history(h, &ev, H_DELDATA, pos, (void **)-1)) { - (void)history(h, &ev, H_SET, curr_num); - return -1; - } - return 0; + history_offset = pos; + return 1; } /* * returns previous event in history and shifts pointer accordingly + * Note that readline and editline define directions in opposite ways. */ HIST_ENTRY * previous_history(void) { + HistEvent ev; - return _move_history(H_PREV); + if (history_offset == 0) + return NULL; + + if (history(h, &ev, H_LAST) != 0) + return NULL; + + history_offset--; + return current_history(); } @@ -1627,8 +1705,16 @@ HIST_ENTRY * next_history(void) { + HistEvent ev; - return _move_history(H_NEXT); + if (history_offset >= history_length) + return NULL; + + if (history(h, &ev, H_LAST) != 0) + return NULL; + + history_offset++; + return current_history(); } @@ -1689,7 +1775,7 @@ return -1; curr_num = ev.num; - if (history_set_pos(off) != 0 || history(h, &ev, H_CURR) != 0) + if (!history_set_pos(off) || history(h, &ev, H_CURR) != 0) return -1; for (;;) { @@ -1776,18 +1862,6 @@ return CC_NORM; } -/* - * Display list of strings in columnar format on readline's output stream. - * 'matches' is list of strings, 'len' is number of strings in 'matches', - * 'max' is maximum length of string in 'matches'. - */ -void -rl_display_match_list(char **matches, int len, int max) -{ - - fn_display_match_list(e, matches, (size_t)len, (size_t)max); -} - static const char * /*ARGSUSED*/ _rl_completion_append_character_function(const char *dummy @@ -1801,16 +1875,27 @@ /* + * Display list of strings in columnar format on readline's output stream. + * 'matches' is list of strings, 'len' is number of strings in 'matches', + * 'max' is maximum length of string in 'matches'. + */ +void +rl_display_match_list(char **matches, int len, int max) +{ + + fn_display_match_list(e, matches, (size_t)len, (size_t)max, + _rl_completion_append_character_function); +} + +/* * complete word at current point */ /* ARGSUSED */ int rl_complete(int ignore __attribute__((__unused__)), int invoking_key) { -#ifdef WIDECHAR static ct_buffer_t wbreak_conv, sprefix_conv; -#endif - char *breakchars; + const char *breakchars; if (h == NULL || e == NULL) rl_initialize(); @@ -1839,7 +1924,7 @@ _rl_completion_append_character_function, (size_t)rl_completion_query_items, &rl_completion_type, &rl_attempted_completion_over, - &rl_point, &rl_end, NULL, NULL, NULL); + &rl_point, &rl_end); } @@ -1896,13 +1981,14 @@ * reset the terminal */ /* ARGSUSED */ -void +int rl_reset_terminal(const char *p __attribute__((__unused__))) { if (h == NULL || e == NULL) rl_initialize(); el_reset(e); + return 0; } @@ -2000,8 +2086,8 @@ if (done && rl_linefunc != NULL) { el_set(e, EL_UNBUFFERED, 0); if (done == 2) { - if ((wbuf = strdup(buf)) != NULL) - wbuf[count] = '\0'; + if ((wbuf = strdup(buf)) != NULL) + wbuf[count] = '\0'; } else wbuf = NULL; (*(void (*)(const char *))rl_linefunc)(wbuf); @@ -2023,8 +2109,9 @@ void rl_callback_handler_remove(void) { - el_set(e, EL_UNBUFFERED, 0); rl_linefunc = NULL; + el_end(e); + e = NULL; } void @@ -2090,7 +2177,7 @@ return el_set(e, EL_BIND, "", var, value, NULL) == -1 ? 1 : 0; } -void +int rl_stuff_char(int c) { char buf[2]; @@ -2098,6 +2185,7 @@ buf[0] = (char)c; buf[1] = '\0'; el_insertstr(e, buf); + return 1; } static int @@ -2153,15 +2241,16 @@ rl_point = (int)(li->cursor - li->buffer); rl_end = (int)(li->lastchar - li->buffer); + rl_line_buffer[rl_end] = '\0'; } void rl_get_screen_size(int *rows, int *cols) { if (rows) - el_get(e, EL_GETTC, "li", rows, (void *)0); + el_get(e, EL_GETTC, "li", rows); if (cols) - el_get(e, EL_GETTC, "co", cols, (void *)0); + el_get(e, EL_GETTC, "co", cols); } void @@ -2182,7 +2271,7 @@ len = 1; max = 10; - if ((list = el_malloc(max * sizeof(*list))) == NULL) + if ((list = el_calloc(max, sizeof(*list))) == NULL) return NULL; while ((match = (*fun)(str, (int)(len - 1))) != NULL) { @@ -2217,7 +2306,7 @@ if ((list[0] = strdup(str)) == NULL) goto out; } else { - if ((list[0] = el_malloc((min + 1) * sizeof(*list[0]))) == NULL) + if ((list[0] = el_calloc(min + 1, sizeof(*list[0]))) == NULL) goto out; (void)memcpy(list[0], list[1], min); list[0][min] = '\0'; @@ -2334,3 +2423,25 @@ { return 0; } + +void +rl_resize_terminal(void) +{ + el_resize(e); +} + +void +rl_reset_after_signal(void) +{ + if (rl_prep_term_function) + (*rl_prep_term_function)(); +} + +void +rl_echo_signal_char(int sig) +{ + int c = tty_get_signal_character(e, sig); + if (c == -1) + return; + re_putc(e, c, 0); +} Index: lib/libedit/refresh.h =================================================================== --- lib/libedit/refresh.h +++ lib/libedit/refresh.h @@ -1,4 +1,4 @@ -/* $NetBSD: refresh.h,v 1.9 2016/02/16 15:53:48 christos Exp $ */ +/* $NetBSD: refresh.h,v 1.11 2017/06/27 23:23:48 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -47,12 +47,14 @@ int r_newcv; } el_refresh_t; -protected void re_putc(EditLine *, wint_t, int); -protected void re_clear_lines(EditLine *); -protected void re_clear_display(EditLine *); -protected void re_refresh(EditLine *); -protected void re_refresh_cursor(EditLine *); -protected void re_fastaddc(EditLine *); -protected void re_goto_bottom(EditLine *); +libedit_private void re_putc(EditLine *, wint_t, int); +libedit_private void re_putliteral(EditLine *, const wchar_t *, + const wchar_t *); +libedit_private void re_clear_lines(EditLine *); +libedit_private void re_clear_display(EditLine *); +libedit_private void re_refresh(EditLine *); +libedit_private void re_refresh_cursor(EditLine *); +libedit_private void re_fastaddc(EditLine *); +libedit_private void re_goto_bottom(EditLine *); #endif /* _h_el_refresh */ Index: lib/libedit/refresh.c =================================================================== --- lib/libedit/refresh.c +++ lib/libedit/refresh.c @@ -1,4 +1,4 @@ -/* $NetBSD: refresh.c,v 1.45 2016/03/02 19:24:20 christos Exp $ */ +/* $NetBSD: refresh.c,v 1.56 2019/01/04 03:03:44 uwe 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.45 2016/03/02 19:24:20 christos Exp $"); +__RCSID("$NetBSD: refresh.c,v 1.56 2019/01/04 03:03:44 uwe Exp $"); #endif #endif /* not lint && not SCCSID */ #include @@ -52,18 +52,18 @@ #include "el.h" -private void re_nextline(EditLine *); -private void re_addc(EditLine *, wint_t); -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 *, wint_t); -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); +static void re_nextline(EditLine *); +static void re_addc(EditLine *, wint_t); +static void re_update_line(EditLine *, wchar_t *, wchar_t *, int); +static void re_insert (EditLine *, wchar_t *, int, int, wchar_t *, int); +static void re_delete(EditLine *, wchar_t *, int, int, int); +static void re_fastputc(EditLine *, wint_t); +static void re_clear_eol(EditLine *, int, int, int); +static void re__strncopy(wchar_t *, wchar_t *, size_t); +static void re__copy_and_pad(wchar_t *, const wchar_t *, size_t); #ifdef DEBUG_REFRESH -private void re_printstr(EditLine *, const char *, Char *, Char *); +static void re_printstr(EditLine *, const char *, wchar_t *, wchar_t *); #define __F el->el_errfile #define ELRE_ASSERT(a, b, c) do \ if (/*CONSTCOND*/ a) { \ @@ -76,8 +76,8 @@ /* re_printstr(): * Print a string on the debugging pty */ -private void -re_printstr(EditLine *el, const char *str, Char *f, Char *t) +static void +re_printstr(EditLine *el, const char *str, wchar_t *f, wchar_t *t) { ELRE_DEBUG(1, (__F, "%s:\"", str)); @@ -93,7 +93,7 @@ /* re_nextline(): * Move to the next line or scroll */ -private void +static void re_nextline(EditLine *el) { el->el_refresh.r_cursor.h = 0; /* reset it. */ @@ -106,7 +106,7 @@ */ if (el->el_refresh.r_cursor.v + 1 >= el->el_terminal.t_size.v) { int i, lins = el->el_terminal.t_size.v; - Char *firstline = el->el_vdisplay[0]; + wchar_t *firstline = el->el_vdisplay[0]; for(i = 1; i < lins; i++) el->el_vdisplay[i - 1] = el->el_vdisplay[i]; @@ -125,10 +125,10 @@ /* re_addc(): * Draw c, expanding tabs, control chars etc. */ -private void +static void re_addc(EditLine *el, wint_t c) { - switch (ct_chr_class((Char)c)) { + switch (ct_chr_class(c)) { case CHTYPE_TAB: /* expand the tab */ for (;;) { re_putc(el, ' ', 1); @@ -147,9 +147,9 @@ re_putc(el, c, 1); break; default: { - Char visbuf[VISUAL_WIDTH_MAX]; + wchar_t visbuf[VISUAL_WIDTH_MAX]; ssize_t i, n = - ct_visual_char(visbuf, VISUAL_WIDTH_MAX, (Char)c); + ct_visual_char(visbuf, VISUAL_WIDTH_MAX, c); for (i = 0; n-- > 0; ++i) re_putc(el, visbuf[i], 1); break; @@ -157,35 +157,66 @@ } } +/* re_putliteral(): + * Place the literal string given + */ +libedit_private void +re_putliteral(EditLine *el, const wchar_t *begin, const wchar_t *end) +{ + coord_t *cur = &el->el_refresh.r_cursor; + wint_t c; + int sizeh = el->el_terminal.t_size.h; + int i, w; + c = literal_add(el, begin, end, &w); + if (c == 0 || w <= 0) + return; + el->el_vdisplay[cur->v][cur->h] = c; + + i = w; + if (i > sizeh - cur->h) /* avoid overflow */ + i = sizeh - cur->h; + while (--i > 0) + el->el_vdisplay[cur->v][cur->h + i] = MB_FILL_CHAR; + + cur->h += w; + if (cur->h >= sizeh) { + /* assure end of line */ + el->el_vdisplay[cur->v][sizeh] = '\0'; + re_nextline(el); + } +} + /* re_putc(): * Draw the character given */ -protected void +libedit_private void re_putc(EditLine *el, wint_t c, int shift) { - int i, w = Width(c); + coord_t *cur = &el->el_refresh.r_cursor; + int i, w = wcwidth(c); + int sizeh = el->el_terminal.t_size.h; + ELRE_DEBUG(1, (__F, "printing %5x '%lc'\r\n", c, c)); + if (w == -1) + w = 0; - while (shift && (el->el_refresh.r_cursor.h + w > el->el_terminal.t_size.h)) + while (shift && (cur->h + w > sizeh)) re_putc(el, ' ', 1); - el->el_vdisplay[el->el_refresh.r_cursor.v] - [el->el_refresh.r_cursor.h] = (Char)c; + el->el_vdisplay[cur->v][cur->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[cur->v][cur->h + i] = MB_FILL_CHAR; if (!shift) return; - el->el_refresh.r_cursor.h += w; /* advance to next place */ - if (el->el_refresh.r_cursor.h >= el->el_terminal.t_size.h) { + cur->h += w; /* advance to next place */ + if (cur->h >= sizeh) { /* assure end of line */ - el->el_vdisplay[el->el_refresh.r_cursor.v][el->el_terminal.t_size.h] - = '\0'; + el->el_vdisplay[cur->v][sizeh] = '\0'; re_nextline(el); } } @@ -197,23 +228,26 @@ * virtual image. The routine to re-draw a line can be replaced * easily in hopes of a smarter one being placed there. */ -protected void +libedit_private void re_refresh(EditLine *el) { int i, rhdiff; - Char *cp, *st; + wchar_t *cp, *st; coord_t cur; #ifdef notyet size_t termsz; #endif - ELRE_DEBUG(1, (__F, "el->el_line.buffer = :" FSTR ":\r\n", + ELRE_DEBUG(1, (__F, "el->el_line.buffer = :%ls:\r\n", el->el_line.buffer)); + literal_clear(el); /* reset the Drawing cursor */ el->el_refresh.r_cursor.h = 0; el->el_refresh.r_cursor.v = 0; + terminal_move_to_char(el, 0); + /* temporarily draw rprompt to calculate its size */ prompt_print(el, EL_RPROMPT); @@ -253,7 +287,7 @@ for (cp = st; cp < el->el_line.lastchar; cp++) { if (cp == el->el_line.cursor) { - int w = Width(*cp); + int w = wcwidth(*cp); /* save for later */ cur.h = el->el_refresh.r_cursor.h; cur.v = el->el_refresh.r_cursor.v; @@ -321,10 +355,10 @@ for (; i <= el->el_refresh.r_oldcv; i++) { terminal_move_to_line(el, i); terminal_move_to_char(el, 0); - /* This Strlen should be safe even with MB_FILL_CHARs */ - terminal_clear_EOL(el, (int) Strlen(el->el_display[i])); + /* This wcslen should be safe even with MB_FILL_CHARs */ + terminal_clear_EOL(el, (int) wcslen(el->el_display[i])); #ifdef DEBUG_REFRESH - terminal_overwrite(el, STR("C\b"), 2); + terminal_overwrite(el, L"C\b", 2); #endif /* DEBUG_REFRESH */ el->el_display[i][0] = '\0'; } @@ -342,7 +376,7 @@ /* re_goto_bottom(): * used to go to last used screen line */ -protected void +libedit_private void re_goto_bottom(EditLine *el) { @@ -357,12 +391,12 @@ * insert num characters of s into d (in front of the character) * at dat, maximum length of d is dlen */ -private void +static void /*ARGSUSED*/ re_insert(EditLine *el __attribute__((__unused__)), - Char *d, int dat, int dlen, Char *s, int num) + wchar_t *d, int dat, int dlen, wchar_t *s, int num) { - Char *a, *b; + wchar_t *a, *b; if (num <= 0) return; @@ -408,12 +442,12 @@ /* re_delete(): * delete num characters d at dat, maximum length of d is dlen */ -private void +static void /*ARGSUSED*/ re_delete(EditLine *el __attribute__((__unused__)), - Char *d, int dat, int dlen, int num) + wchar_t *d, int dat, int dlen, int num) { - Char *a, *b; + wchar_t *a, *b; if (num <= 0) return; @@ -442,8 +476,8 @@ /* re__strncopy(): * Like strncpy without padding. */ -private void -re__strncopy(Char *a, Char *b, size_t n) +static void +re__strncopy(wchar_t *a, wchar_t *b, size_t n) { while (n-- && *b) @@ -457,7 +491,7 @@ * in the first or second diff, diff is the difference between the * number of characters between the new and old line. */ -private void +static void re_clear_eol(EditLine *el, int fx, int sx, int diff) { @@ -501,12 +535,12 @@ */ #define MIN_END_KEEP 4 -private void -re_update_line(EditLine *el, Char *old, Char *new, int i) +static void +re_update_line(EditLine *el, wchar_t *old, wchar_t *new, int i) { - Char *o, *n, *p, c; - Char *ofd, *ols, *oe, *nfd, *nls, *ne; - Char *osb, *ose, *nsb, *nse; + wchar_t *o, *n, *p, c; + wchar_t *ofd, *ols, *oe, *nfd, *nls, *ne; + wchar_t *osb, *ose, *nsb, *nse; int fx, sx; size_t len; @@ -971,8 +1005,8 @@ /* re__copy_and_pad(): * Copy string and pad with spaces */ -private void -re__copy_and_pad(Char *dst, const Char *src, size_t width) +static void +re__copy_and_pad(wchar_t *dst, const wchar_t *src, size_t width) { size_t i; @@ -992,10 +1026,10 @@ /* re_refresh_cursor(): * Move to the new cursor position */ -protected void +libedit_private void re_refresh_cursor(EditLine *el) { - Char *cp; + wchar_t *cp; int h, v, th, w; if (el->el_line.cursor >= el->el_line.lastchar) { @@ -1023,7 +1057,7 @@ continue; break; default: - w = Width(*cp); + w = wcwidth(*cp); if (w > 1 && h + w > th) { /* won't fit on line */ h = 0; v++; @@ -1039,7 +1073,7 @@ } /* 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 (cp < el->el_line.lastchar && (w = wcwidth(*cp)) > 1) if (h + w > th) { h = 0; v++; @@ -1055,15 +1089,18 @@ /* re_fastputc(): * Add a character fast. */ -private void +static void re_fastputc(EditLine *el, wint_t c) { - int w = Width((Char)c); + wchar_t *lastline; + int w; + + w = wcwidth(c); while (w > 1 && el->el_cursor.h + w > el->el_terminal.t_size.h) re_fastputc(el, ' '); terminal__putc(el, c); - el->el_display[el->el_cursor.v][el->el_cursor.h++] = (Char)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; @@ -1080,17 +1117,18 @@ */ if (el->el_cursor.v + 1 >= el->el_terminal.t_size.v) { int i, lins = el->el_terminal.t_size.v; - Char *firstline = el->el_display[0]; + lastline = el->el_display[0]; for(i = 1; i < lins; i++) el->el_display[i - 1] = el->el_display[i]; - re__copy_and_pad(firstline, STR(""), (size_t)0); - el->el_display[i - 1] = firstline; + el->el_display[i - 1] = lastline; } else { el->el_cursor.v++; - el->el_refresh.r_oldcv++; + lastline = el->el_display[++el->el_refresh.r_oldcv]; } + re__copy_and_pad(lastline, L"", (size_t)el->el_terminal.t_size.h); + if (EL_HAS_AUTO_MARGINS) { if (EL_HAS_MAGIC_MARGINS) { terminal__putc(el, ' '); @@ -1108,10 +1146,10 @@ * we added just one char, handle it fast. * Assumes that screen cursor == real cursor */ -protected void +libedit_private void re_fastaddc(EditLine *el) { - Char c; + wchar_t c; int rhdiff; c = el->el_line.cursor[-1]; @@ -1135,9 +1173,9 @@ break; case CHTYPE_ASCIICTL: case CHTYPE_NONPRINT: { - Char visbuf[VISUAL_WIDTH_MAX]; + wchar_t visbuf[VISUAL_WIDTH_MAX]; ssize_t i, n = - ct_visual_char(visbuf, VISUAL_WIDTH_MAX, (Char)c); + ct_visual_char(visbuf, VISUAL_WIDTH_MAX, c); for (i = 0; n-- > 0; ++i) re_fastputc(el, visbuf[i]); break; @@ -1150,7 +1188,7 @@ /* re_clear_display(): * clear the screen buffers so that new prompt starts fresh. */ -protected void +libedit_private void re_clear_display(EditLine *el) { int i; @@ -1166,7 +1204,7 @@ /* re_clear_lines(): * Make sure all lines are *really* blank */ -protected void +libedit_private void re_clear_lines(EditLine *el) { Index: lib/libedit/search.h =================================================================== --- lib/libedit/search.h +++ lib/libedit/search.h @@ -1,4 +1,4 @@ -/* $NetBSD: search.h,v 1.12 2016/02/16 15:53:48 christos Exp $ */ +/* $NetBSD: search.h,v 1.14 2016/05/09 21:46:56 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -42,24 +42,24 @@ #define _h_el_search typedef struct el_search_t { - Char *patbuf; /* The pattern buffer */ + wchar_t *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 */ + wchar_t 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 search_init(EditLine *); -protected void search_end(EditLine *); -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 *, wint_t); -protected el_action_t cv_csearch(EditLine *, int, wint_t, int, int); +libedit_private int el_match(const wchar_t *, const wchar_t *); +libedit_private int search_init(EditLine *); +libedit_private void search_end(EditLine *); +libedit_private int c_hmatch(EditLine *, const wchar_t *); +libedit_private void c_setpat(EditLine *); +libedit_private el_action_t ce_inc_search(EditLine *, int); +libedit_private el_action_t cv_search(EditLine *, int); +libedit_private el_action_t ce_search_line(EditLine *, int); +libedit_private el_action_t cv_repeat_srch(EditLine *, wint_t); +libedit_private el_action_t cv_csearch(EditLine *, int, wint_t, int, int); #endif /* _h_el_search */ Index: lib/libedit/search.c =================================================================== --- lib/libedit/search.c +++ lib/libedit/search.c @@ -1,4 +1,4 @@ -/* $NetBSD: search.c,v 1.39 2016/02/24 14:25:38 christos Exp $ */ +/* $NetBSD: search.c,v 1.49 2019/07/23 10:18:52 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.39 2016/02/24 14:25:38 christos Exp $"); +__RCSID("$NetBSD: search.c,v 1.49 2019/07/23 10:18:52 christos Exp $"); #endif #endif /* not lint && not SCCSID */ #include @@ -56,6 +56,7 @@ #include "el.h" #include "common.h" +#include "fcns.h" /* * Adjust cursor in vi mode to include the character under it @@ -67,17 +68,18 @@ /* search_init(): * Initialize the search stuff */ -protected int +libedit_private int search_init(EditLine *el) { - el->el_search.patbuf = el_malloc(EL_BUFSIZ * + el->el_search.patbuf = el_calloc(EL_BUFSIZ, sizeof(*el->el_search.patbuf)); if (el->el_search.patbuf == NULL) return -1; + el->el_search.patbuf[0] = L'\0'; el->el_search.patlen = 0; el->el_search.patdir = -1; - el->el_search.chacha = '\0'; + el->el_search.chacha = L'\0'; el->el_search.chadir = CHAR_FWD; el->el_search.chatflg = 0; return 0; @@ -87,7 +89,7 @@ /* search_end(): * Initialize the search stuff */ -protected void +libedit_private void search_end(EditLine *el) { @@ -100,7 +102,7 @@ /* regerror(): * Handle regular expression errors */ -public void +void /*ARGSUSED*/ regerror(const char *msg) { @@ -111,12 +113,10 @@ /* el_match(): * Return if string matches pattern */ -protected int -el_match(const Char *str, const Char *pat) +libedit_private int +el_match(const wchar_t *str, const wchar_t *pat) { -#ifdef WIDECHAR static ct_buffer_t conv; -#endif #if defined (REGEX) regex_t re; int rv; @@ -128,7 +128,7 @@ extern int re_exec(const char *); #endif - if (Strstr(str, pat) != 0) + if (wcsstr(str, pat) != 0) return 1; #if defined(REGEX) @@ -160,8 +160,8 @@ /* c_hmatch(): * return True if the pattern matches the prefix */ -protected int -c_hmatch(EditLine *el, const Char *str) +libedit_private int +c_hmatch(EditLine *el, const wchar_t *str) { #ifdef SDEBUG (void) fprintf(el->el_errfile, "match `%s' with `%s'\n", @@ -175,7 +175,7 @@ /* c_setpat(): * Set the history seatch pattern */ -protected void +libedit_private void c_setpat(EditLine *el) { if (el->el_state.lastcmd != ED_SEARCH_PREV_HISTORY && @@ -185,11 +185,11 @@ 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) wcsncpy(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 = wcslen(el->el_search.patbuf); } #ifdef SDEBUG (void) fprintf(el->el_errfile, "\neventno = %d\n", @@ -207,16 +207,14 @@ /* ce_inc_search(): * Emacs incremental search */ -protected el_action_t +libedit_private el_action_t ce_inc_search(EditLine *el, int dir) { - 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 *ocursor = el->el_line.cursor, oldpchar = pchar, ch; - const Char *cp; - wchar_t wch; + static const wchar_t STRfwd[] = L"fwd", STRbck[] = L"bck"; + static wchar_t pchar = L':'; /* ':' = normal, '?' = failed */ + static wchar_t endcmd[2] = {'\0', '\0'}; + wchar_t *ocursor = el->el_line.cursor, oldpchar = pchar, ch; + const wchar_t *cp; el_action_t ret = CC_NORM; @@ -255,11 +253,9 @@ *el->el_line.lastchar = '\0'; re_refresh(el); - if (el_wgetc(el, &wch) != 1) + if (el_wgetc(el, &ch) != 1) return ed_end_of_file(el, 0); - ch = (Char)wch; - switch (el->el_map.current[(unsigned char) ch]) { case ED_INSERT: case ED_DIGIT: @@ -333,7 +329,7 @@ default: /* Terminate and execute cmd */ endcmd[0] = ch; - FUN(el,push)(el, endcmd); + el_wpush(el, endcmd); /* FALLTHROUGH */ case 0033: /* ESC: Terminate */ @@ -458,11 +454,11 @@ /* cv_search(): * Vi search. */ -protected el_action_t +libedit_private el_action_t cv_search(EditLine *el, int dir) { - Char ch; - Char tmpbuf[EL_BUFSIZ]; + wchar_t ch; + wchar_t tmpbuf[EL_BUFSIZ]; ssize_t tmplen; #ifdef ANCHOR @@ -474,7 +470,7 @@ el->el_search.patdir = dir; tmplen = c_gets(el, &tmpbuf[LEN], - dir == ED_SEARCH_PREV_HISTORY ? STR("\n/") : STR("\n?") ); + dir == ED_SEARCH_PREV_HISTORY ? L"\n/" : L"\n?" ); if (tmplen == -1) return CC_REFRESH; @@ -493,11 +489,11 @@ #ifdef ANCHOR if (el->el_search.patbuf[0] != '.' && el->el_search.patbuf[0] != '*') { - (void) Strncpy(tmpbuf, el->el_search.patbuf, + (void) wcsncpy(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) wcsncpy(&el->el_search.patbuf[2], tmpbuf, EL_BUFSIZ - 3); el->el_search.patlen++; el->el_search.patbuf[el->el_search.patlen++] = '.'; @@ -511,7 +507,7 @@ tmpbuf[tmplen++] = '*'; #endif tmpbuf[tmplen] = '\0'; - (void) Strncpy(el->el_search.patbuf, tmpbuf, EL_BUFSIZ - 1); + (void) wcsncpy(el->el_search.patbuf, tmpbuf, EL_BUFSIZ - 1); el->el_search.patlen = (size_t)tmplen; } el->el_state.lastcmd = (el_action_t) dir; /* avoid c_setpat */ @@ -532,12 +528,12 @@ /* ce_search_line(): * Look for a pattern inside a line */ -protected el_action_t +libedit_private 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; + wchar_t *cp = el->el_line.cursor; + wchar_t *pattern = el->el_search.patbuf; + wchar_t oc, *ocp; #ifdef ANCHOR ocp = &pattern[1]; oc = *ocp; @@ -574,7 +570,7 @@ /* cv_repeat_srch(): * Vi repeat search */ -protected el_action_t +libedit_private el_action_t cv_repeat_srch(EditLine *el, wint_t c) { @@ -600,21 +596,23 @@ /* cv_csearch(): * Vi character search */ -protected el_action_t +libedit_private el_action_t cv_csearch(EditLine *el, int direction, wint_t ch, int count, int tflag) { - Char *cp; + wchar_t *cp; if (ch == 0) return CC_ERROR; if (ch == (wint_t)-1) { - if (el_wgetc(el, &ch) != 1) + wchar_t c; + if (el_wgetc(el, &c) != 1) return ed_end_of_file(el, 0); + ch = c; } /* Save for ';' and ',' commands */ - el->el_search.chacha = (Char)ch; + el->el_search.chacha = ch; el->el_search.chadir = direction; el->el_search.chatflg = (char)tflag; Index: lib/libedit/sig.h =================================================================== --- lib/libedit/sig.h +++ lib/libedit/sig.h @@ -1,4 +1,4 @@ -/* $NetBSD: sig.h,v 1.10 2016/02/16 15:53:48 christos Exp $ */ +/* $NetBSD: sig.h,v 1.11 2016/05/09 21:46:56 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -63,9 +63,9 @@ volatile sig_atomic_t sig_no; } *el_signal_t; -protected void sig_end(EditLine*); -protected int sig_init(EditLine*); -protected void sig_set(EditLine*); -protected void sig_clr(EditLine*); +libedit_private void sig_end(EditLine*); +libedit_private int sig_init(EditLine*); +libedit_private void sig_set(EditLine*); +libedit_private void sig_clr(EditLine*); #endif /* _h_el_sig */ Index: lib/libedit/sig.c =================================================================== --- lib/libedit/sig.c +++ lib/libedit/sig.c @@ -1,4 +1,4 @@ -/* $NetBSD: sig.c,v 1.24 2016/02/16 19:08:41 christos Exp $ */ +/* $NetBSD: sig.c,v 1.26 2016/05/09 21:46:56 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.24 2016/02/16 19:08:41 christos Exp $"); +__RCSID("$NetBSD: sig.c,v 1.26 2016/05/09 21:46:56 christos Exp $"); #endif #endif /* not lint && not SCCSID */ #include @@ -54,23 +54,23 @@ #include "el.h" #include "common.h" -private EditLine *sel = NULL; +static EditLine *sel = NULL; -private const int sighdl[] = { +static const int sighdl[] = { #define _DO(a) (a), ALLSIGS #undef _DO - 1 }; -private void sig_handler(int); +static void sig_handler(int); /* sig_handler(): * This is the handler called for all signals * XXX: we cannot pass any data so we just store the old editline * state in a private variable */ -private void +static void sig_handler(int signo) { int i, save_errno; @@ -117,7 +117,7 @@ /* sig_init(): * Initialize all signal stuff */ -protected int +libedit_private int sig_init(EditLine *el) { size_t i; @@ -149,7 +149,7 @@ /* sig_end(): * Clear all signal stuff */ -protected void +libedit_private void sig_end(EditLine *el) { @@ -161,7 +161,7 @@ /* sig_set(): * set all the signal handlers */ -protected void +libedit_private void sig_set(EditLine *el) { size_t i; @@ -188,7 +188,7 @@ /* sig_clr(): * clear all the signal handlers */ -protected void +libedit_private void sig_clr(EditLine *el) { size_t i; Index: lib/libedit/sys.h =================================================================== --- lib/libedit/sys.h +++ lib/libedit/sys.h @@ -1,4 +1,4 @@ -/* $NetBSD: sys.h,v 1.23 2016/02/17 19:47:49 christos Exp $ */ +/* $NetBSD: sys.h,v 1.27 2016/05/09 21:46:56 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -59,19 +59,9 @@ # endif #endif -#ifndef public -# define public /* Externally visible functions/variables */ -#endif +/* If your compiler does not support this, define it to be empty. */ +#define libedit_private __attribute__((__visibility__("hidden"))) -#ifndef private -# define private static /* Always hidden internals */ -#endif - -#ifndef protected -# define protected /* Redefined from elsewhere to "static" */ - /* When we want to hide everything */ -#endif - #ifndef __arraycount # define __arraycount(a) (sizeof(a) / sizeof(*(a))) #endif @@ -112,11 +102,6 @@ #define REGEX /* Use POSIX.2 regular expression functions */ #undef REGEXP /* Use UNIX V8 regular expression functions */ -#ifndef WIDECHAR -#define setlocale(c, l) /*LINTED*/NULL -#define nl_langinfo(i) "" -#endif - #if defined(__sun) extern int tgetent(char *, const char *); extern int tgetflag(char *); Index: lib/libedit/terminal.h =================================================================== --- lib/libedit/terminal.h +++ lib/libedit/terminal.h @@ -1,4 +1,4 @@ -/* $NetBSD: terminal.h,v 1.7 2016/02/16 15:53:48 christos Exp $ */ +/* $NetBSD: terminal.h,v 1.9 2016/05/09 21:46:56 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -42,7 +42,7 @@ #define _h_el_terminal typedef struct { /* Symbolic function key bindings */ - const Char *name; /* name of the key */ + const wchar_t *name; /* name of the key */ int key; /* Index in termcap table */ keymacro_value_t fun; /* Function bound to it */ int type; /* Type of function */ @@ -81,31 +81,32 @@ #define A_K_DE 6 #define A_K_NKEYS 7 -protected void terminal_move_to_line(EditLine *, int); -protected void terminal_move_to_char(EditLine *, int); -protected void terminal_clear_EOL(EditLine *, int); -protected void terminal_overwrite(EditLine *, const Char *, size_t); -protected void terminal_insertwrite(EditLine *, Char *, int); -protected void terminal_deletechars(EditLine *, int); -protected void terminal_clear_screen(EditLine *); -protected void terminal_beep(EditLine *); -protected int terminal_change_size(EditLine *, int, int); -protected int terminal_get_size(EditLine *, int *, int *); -protected int terminal_init(EditLine *); -protected void terminal_bind_arrow(EditLine *); -protected void terminal_print_arrow(EditLine *, const Char *); -protected int terminal_clear_arrow(EditLine *, const Char *); -protected int terminal_set_arrow(EditLine *, const Char *, keymacro_value_t *, int); -protected void terminal_end(EditLine *); -protected void terminal_get(EditLine *, const char **); -protected int terminal_set(EditLine *, const char *); -protected int terminal_settc(EditLine *, int, const Char **); -protected int terminal_gettc(EditLine *, int, char **); -protected int terminal_telltc(EditLine *, int, const Char **); -protected int terminal_echotc(EditLine *, int, const Char **); -protected void terminal_writec(EditLine *, wint_t); -protected int terminal__putc(EditLine *, wint_t); -protected void terminal__flush(EditLine *); +libedit_private void terminal_move_to_line(EditLine *, int); +libedit_private void terminal_move_to_char(EditLine *, int); +libedit_private void terminal_clear_EOL(EditLine *, int); +libedit_private void terminal_overwrite(EditLine *, const wchar_t *, size_t); +libedit_private void terminal_insertwrite(EditLine *, wchar_t *, int); +libedit_private void terminal_deletechars(EditLine *, int); +libedit_private void terminal_clear_screen(EditLine *); +libedit_private void terminal_beep(EditLine *); +libedit_private int terminal_change_size(EditLine *, int, int); +libedit_private int terminal_get_size(EditLine *, int *, int *); +libedit_private int terminal_init(EditLine *); +libedit_private void terminal_bind_arrow(EditLine *); +libedit_private void terminal_print_arrow(EditLine *, const wchar_t *); +libedit_private int terminal_clear_arrow(EditLine *, const wchar_t *); +libedit_private int terminal_set_arrow(EditLine *, const wchar_t *, + keymacro_value_t *, int); +libedit_private void terminal_end(EditLine *); +libedit_private void terminal_get(EditLine *, const char **); +libedit_private int terminal_set(EditLine *, const char *); +libedit_private int terminal_settc(EditLine *, int, const wchar_t **); +libedit_private int terminal_gettc(EditLine *, int, char **); +libedit_private int terminal_telltc(EditLine *, int, const wchar_t **); +libedit_private int terminal_echotc(EditLine *, int, const wchar_t **); +libedit_private void terminal_writec(EditLine *, wint_t); +libedit_private int terminal__putc(EditLine *, wint_t); +libedit_private void terminal__flush(EditLine *); /* * Easy access macros Index: lib/libedit/terminal.c =================================================================== --- lib/libedit/terminal.c +++ lib/libedit/terminal.c @@ -1,4 +1,4 @@ -/* $NetBSD: terminal.c,v 1.24 2016/03/22 01:38:17 christos Exp $ */ +/* $NetBSD: terminal.c,v 1.39 2019/07/23 10:18:52 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: terminal.c,v 1.24 2016/03/22 01:38:17 christos Exp $"); +__RCSID("$NetBSD: terminal.c,v 1.39 2019/07/23 10:18:52 christos Exp $"); #endif #endif /* not lint && not SCCSID */ #include @@ -75,6 +75,7 @@ #endif #include "el.h" +#include "fcns.h" /* * IMPORTANT NOTE: these routines are allowed to look at the current screen @@ -90,7 +91,7 @@ #define Str(a) el->el_terminal.t_str[a] #define Val(a) el->el_terminal.t_val[a] -private const struct termcapstr { +static const struct termcapstr { const char *name; const char *long_name; } tstr[] = { @@ -176,7 +177,7 @@ { NULL, NULL } }; -private const struct termcapval { +static const struct termcapval { const char *name; const char *long_name; } tval[] = { @@ -201,27 +202,27 @@ }; /* do two or more of the attributes use me */ -private void terminal_setflags(EditLine *); -private int terminal_rebuffer_display(EditLine *); -private void terminal_free_display(EditLine *); -private int terminal_alloc_display(EditLine *); -private void terminal_alloc(EditLine *, const struct termcapstr *, +static void terminal_setflags(EditLine *); +static int terminal_rebuffer_display(EditLine *); +static void terminal_free_display(EditLine *); +static int terminal_alloc_display(EditLine *); +static void terminal_alloc(EditLine *, const struct termcapstr *, const char *); -private void terminal_init_arrow(EditLine *); -private void terminal_reset_arrow(EditLine *); -private int terminal_putc(int); -private void terminal_tputs(EditLine *, const char *, int); +static void terminal_init_arrow(EditLine *); +static void terminal_reset_arrow(EditLine *); +static int terminal_putc(int); +static void terminal_tputs(EditLine *, const char *, int); #ifdef _REENTRANT -private pthread_mutex_t terminal_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t terminal_mutex = PTHREAD_MUTEX_INITIALIZER; #endif -private FILE *terminal_outfile = NULL; +static FILE *terminal_outfile = NULL; /* terminal_setflags(): * Set the terminal capability flags */ -private void +static void terminal_setflags(EditLine *el) { EL_FLAGS = 0; @@ -266,35 +267,31 @@ /* terminal_init(): * Initialize the terminal stuff */ -protected int +libedit_private int terminal_init(EditLine *el) { - el->el_terminal.t_buf = el_malloc(TC_BUFSIZE * + el->el_terminal.t_buf = el_calloc(TC_BUFSIZE, sizeof(*el->el_terminal.t_buf)); if (el->el_terminal.t_buf == NULL) goto fail1; - el->el_terminal.t_cap = el_malloc(TC_BUFSIZE * + el->el_terminal.t_cap = el_calloc(TC_BUFSIZE, sizeof(*el->el_terminal.t_cap)); if (el->el_terminal.t_cap == NULL) goto fail2; - el->el_terminal.t_fkey = el_malloc(A_K_NKEYS * + el->el_terminal.t_fkey = el_calloc(A_K_NKEYS, sizeof(*el->el_terminal.t_fkey)); if (el->el_terminal.t_fkey == NULL) goto fail3; el->el_terminal.t_loc = 0; - el->el_terminal.t_str = el_malloc(T_str * + el->el_terminal.t_str = el_calloc(T_str, sizeof(*el->el_terminal.t_str)); if (el->el_terminal.t_str == NULL) goto fail4; - (void) memset(el->el_terminal.t_str, 0, T_str * - sizeof(*el->el_terminal.t_str)); - el->el_terminal.t_val = el_malloc(T_val * + el->el_terminal.t_val = el_calloc(T_val, sizeof(*el->el_terminal.t_val)); if (el->el_terminal.t_val == NULL) goto fail5; - (void) memset(el->el_terminal.t_val, 0, T_val * - sizeof(*el->el_terminal.t_val)); (void) terminal_set(el, NULL); terminal_init_arrow(el); return 0; @@ -317,7 +314,7 @@ /* terminal_end(): * Clean up the terminal stuff */ -protected void +libedit_private void terminal_end(EditLine *el) { @@ -339,7 +336,7 @@ /* terminal_alloc(): * Maintain a string pool for termcap strings */ -private void +static void terminal_alloc(EditLine *el, const struct termcapstr *t, const char *cap) { char termbuf[TC_BUFSIZE]; @@ -405,7 +402,7 @@ /* terminal_rebuffer_display(): * Rebuffer the display after the screen changed size */ -private int +static int terminal_rebuffer_display(EditLine *el) { coord_t *c = &el->el_terminal.t_size; @@ -420,46 +417,58 @@ return 0; } - -/* terminal_alloc_display(): - * Allocate a new display. - */ -private int -terminal_alloc_display(EditLine *el) +static wint_t ** +terminal_alloc_buffer(EditLine *el) { + wint_t **b; + coord_t *c = &el->el_terminal.t_size; int i; - Char **b; - coord_t *c = &el->el_terminal.t_size; - b = el_malloc(sizeof(*b) * (size_t)(c->v + 1)); + b = el_calloc((size_t)(c->v + 1), sizeof(*b)); if (b == NULL) - goto done; + return NULL; for (i = 0; i < c->v; i++) { - b[i] = el_malloc(sizeof(**b) * (size_t)(c->h + 1)); + b[i] = el_calloc((size_t)(c->h + 1), sizeof(**b)); if (b[i] == NULL) { while (--i >= 0) el_free(b[i]); el_free(b); - goto done; + return NULL; } } b[c->v] = NULL; - el->el_display = b; + return b; +} - b = el_malloc(sizeof(*b) * (size_t)(c->v + 1)); - if (b == NULL) +static void +terminal_free_buffer(wint_t ***bp) +{ + wint_t **b; + wint_t **bufp; + + if (*bp == NULL) + return; + + b = *bp; + *bp = NULL; + + for (bufp = b; *bufp != NULL; bufp++) + el_free(*bufp); + el_free(b); +} + +/* terminal_alloc_display(): + * Allocate a new display. + */ +static int +terminal_alloc_display(EditLine *el) +{ + el->el_display = terminal_alloc_buffer(el); + if (el->el_display == NULL) goto done; - for (i = 0; i < c->v; i++) { - b[i] = el_malloc(sizeof(**b) * (size_t)(c->h + 1)); - if (b[i] == NULL) { - while (--i >= 0) - el_free(b[i]); - el_free(b); - goto done; - } - } - b[c->v] = NULL; - el->el_vdisplay = b; + el->el_vdisplay = terminal_alloc_buffer(el); + if (el->el_vdisplay == NULL) + goto done; return 0; done: terminal_free_display(el); @@ -470,26 +479,11 @@ /* terminal_free_display(): * Free the display buffers */ -private void +static void terminal_free_display(EditLine *el) { - Char **b; - Char **bufp; - - b = el->el_display; - el->el_display = NULL; - if (b != NULL) { - for (bufp = b; *bufp != NULL; bufp++) - el_free(*bufp); - el_free(b); - } - b = el->el_vdisplay; - el->el_vdisplay = NULL; - if (b != NULL) { - for (bufp = b; *bufp != NULL; bufp++) - el_free(*bufp); - el_free(b); - } + terminal_free_buffer(&el->el_display); + terminal_free_buffer(&el->el_vdisplay); } @@ -497,7 +491,7 @@ * move to line (first line == 0) * as efficiently as possible */ -protected void +libedit_private void terminal_move_to_line(EditLine *el, int where) { int del; @@ -513,39 +507,14 @@ return; } if ((del = where - el->el_cursor.v) > 0) { - while (del > 0) { - if (EL_HAS_AUTO_MARGINS && - el->el_display[el->el_cursor.v][0] != '\0') { - size_t h = (size_t) - (el->el_terminal.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 */ - terminal_move_to_char(el, (int)h); - terminal_overwrite(el, &el->el_display - [el->el_cursor.v][el->el_cursor.h], - (size_t)(el->el_terminal.t_size.h - - el->el_cursor.h)); - /* updates Cursor */ - del--; - } else { - if ((del > 1) && GoodStr(T_DO)) { - terminal_tputs(el, tgoto(Str(T_DO), del, - del), del); - del = 0; - } else { - for (; del > 0; del--) - terminal__putc(el, '\n'); - /* because the \n will become \r\n */ - el->el_cursor.h = 0; - } - } - } + /* + * We don't use DO here because some terminals are buggy + * if the destination is beyond bottom of the screen. + */ + for (; del > 0; del--) + terminal__putc(el, '\n'); + /* because the \n will become \r\n */ + el->el_cursor.h = 0; } else { /* del < 0 */ if (GoodStr(T_UP) && (-del > 1 || !GoodStr(T_up))) terminal_tputs(el, tgoto(Str(T_UP), -del, -del), -del); @@ -562,7 +531,7 @@ /* terminal_move_to_char(): * Move to the character position specified */ -protected void +libedit_private void terminal_move_to_char(EditLine *el, int where) { int del, i; @@ -598,11 +567,9 @@ if (EL_CAN_TAB) { if ((el->el_cursor.h & 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 = @@ -659,8 +626,8 @@ * Overstrike num characters * Assumes MB_FILL_CHARs are present to keep the column count correct */ -protected void -terminal_overwrite(EditLine *el, const Char *cp, size_t n) +libedit_private void +terminal_overwrite(EditLine *el, const wchar_t *cp, size_t n) { if (n == 0) return; @@ -686,15 +653,13 @@ if (EL_HAS_MAGIC_MARGINS) { /* force the wrap to avoid the "magic" * situation */ - Char c; + wchar_t c; if ((c = el->el_display[el->el_cursor.v] [el->el_cursor.h]) != '\0') { terminal_overwrite(el, &c, (size_t)1); -#ifdef WIDECHAR while (el->el_display[el->el_cursor.v] [el->el_cursor.h] == MB_FILL_CHAR) el->el_cursor.h++; -#endif } else { terminal__putc(el, ' '); el->el_cursor.h = 1; @@ -709,7 +674,7 @@ /* terminal_deletechars(): * Delete num characters */ -protected void +libedit_private void terminal_deletechars(EditLine *el, int num) { if (num <= 0) @@ -751,8 +716,8 @@ * characters in the line * Assumes MB_FILL_CHARs are present to keep column count correct */ -protected void -terminal_insertwrite(EditLine *el, Char *cp, int num) +libedit_private void +terminal_insertwrite(EditLine *el, wchar_t *cp, int num) { if (num <= 0) return; @@ -810,7 +775,7 @@ /* terminal_clear_EOL(): * clear to end of line. There are num characters to clear */ -protected void +libedit_private void terminal_clear_EOL(EditLine *el, int num) { int i; @@ -828,7 +793,7 @@ /* terminal_clear_screen(): * Clear the screen */ -protected void +libedit_private void terminal_clear_screen(EditLine *el) { /* clear the whole screen and home */ @@ -849,7 +814,7 @@ /* terminal_beep(): * Beep the way the terminal wants us */ -protected void +libedit_private void terminal_beep(EditLine *el) { if (GoodStr(T_bl)) @@ -860,7 +825,7 @@ } -protected void +libedit_private void terminal_get(EditLine *el, const char **term) { *term = el->el_terminal.t_name; @@ -870,7 +835,7 @@ /* terminal_set(): * Read in the terminal capabilities from the requested terminal */ -protected int +libedit_private int terminal_set(EditLine *el, const char *term) { int i; @@ -959,7 +924,7 @@ * Return the new window size in lines and cols, and * true if the size was changed. */ -protected int +libedit_private int terminal_get_size(EditLine *el, int *lins, int *cols) { @@ -995,12 +960,13 @@ /* terminal_change_size(): * Change the size of the terminal */ -protected int +libedit_private int terminal_change_size(EditLine *el, int lins, int cols) { + coord_t cur = el->el_cursor; /* - * Just in case - */ + * Just in case + */ Val(T_co) = (cols < 2) ? 80 : cols; Val(T_li) = (lins < 1) ? 24 : lins; @@ -1008,6 +974,7 @@ if (terminal_rebuffer_display(el) == -1) return -1; re_clear_display(el); + el->el_cursor = cur; return 0; } @@ -1015,42 +982,42 @@ /* terminal_init_arrow(): * Initialize the arrow key bindings from termcap */ -private void +static void terminal_init_arrow(EditLine *el) { funckey_t *arrow = el->el_terminal.t_fkey; - arrow[A_K_DN].name = STR("down"); + arrow[A_K_DN].name = L"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 = STR("up"); + arrow[A_K_UP].name = L"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 = STR("left"); + arrow[A_K_LT].name = L"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 = STR("right"); + arrow[A_K_RT].name = L"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 = STR("home"); + arrow[A_K_HO].name = L"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 = STR("end"); + arrow[A_K_EN].name = L"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; - arrow[A_K_DE].name = STR("delete"); + arrow[A_K_DE].name = L"delete"; arrow[A_K_DE].key = T_kD; arrow[A_K_DE].fun.cmd = ED_DELETE_NEXT_CHAR; arrow[A_K_DE].type = XK_CMD; @@ -1060,22 +1027,22 @@ /* terminal_reset_arrow(): * Reset arrow key bindings */ -private void +static void terminal_reset_arrow(EditLine *el) { funckey_t *arrow = el->el_terminal.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 wchar_t strA[] = L"\033[A"; + static const wchar_t strB[] = L"\033[B"; + static const wchar_t strC[] = L"\033[C"; + static const wchar_t strD[] = L"\033[D"; + static const wchar_t strH[] = L"\033[H"; + static const wchar_t strF[] = L"\033[F"; + static const wchar_t stOA[] = L"\033OA"; + static const wchar_t stOB[] = L"\033OB"; + static const wchar_t stOC[] = L"\033OC"; + static const wchar_t stOD[] = L"\033OD"; + static const wchar_t stOH[] = L"\033OH"; + static const wchar_t stOF[] = L"\033OF"; keymacro_add(el, strA, &arrow[A_K_UP].fun, arrow[A_K_UP].type); keymacro_add(el, strB, &arrow[A_K_DN].fun, arrow[A_K_DN].type); @@ -1110,15 +1077,15 @@ /* terminal_set_arrow(): * Set an arrow key binding */ -protected int -terminal_set_arrow(EditLine *el, const Char *name, keymacro_value_t *fun, +libedit_private int +terminal_set_arrow(EditLine *el, const wchar_t *name, keymacro_value_t *fun, int type) { funckey_t *arrow = el->el_terminal.t_fkey; int i; for (i = 0; i < A_K_NKEYS; i++) - if (Strcmp(name, arrow[i].name) == 0) { + if (wcscmp(name, arrow[i].name) == 0) { arrow[i].fun = *fun; arrow[i].type = type; return 0; @@ -1130,14 +1097,14 @@ /* terminal_clear_arrow(): * Clear an arrow key binding */ -protected int -terminal_clear_arrow(EditLine *el, const Char *name) +libedit_private int +terminal_clear_arrow(EditLine *el, const wchar_t *name) { funckey_t *arrow = el->el_terminal.t_fkey; int i; for (i = 0; i < A_K_NKEYS; i++) - if (Strcmp(name, arrow[i].name) == 0) { + if (wcscmp(name, arrow[i].name) == 0) { arrow[i].type = XK_NOD; return 0; } @@ -1148,14 +1115,14 @@ /* terminal_print_arrow(): * Print the arrow key bindings */ -protected void -terminal_print_arrow(EditLine *el, const Char *name) +libedit_private void +terminal_print_arrow(EditLine *el, const wchar_t *name) { int i; funckey_t *arrow = el->el_terminal.t_fkey; for (i = 0; i < A_K_NKEYS; i++) - if (*name == '\0' || Strcmp(name, arrow[i].name) == 0) + if (*name == '\0' || wcscmp(name, arrow[i].name) == 0) if (arrow[i].type != XK_NOD) keymacro_kprint(el, arrow[i].name, &arrow[i].fun, arrow[i].type); @@ -1165,7 +1132,7 @@ /* terminal_bind_arrow(): * Bind the arrow keys */ -protected void +libedit_private void terminal_bind_arrow(EditLine *el) { el_action_t *map; @@ -1184,8 +1151,8 @@ terminal_reset_arrow(el); for (i = 0; i < A_K_NKEYS; i++) { - Char wt_str[VISUAL_WIDTH_MAX]; - Char *px; + wchar_t wt_str[VISUAL_WIDTH_MAX]; + wchar_t *px; size_t n; p = el->el_terminal.t_str[arrow[i].key]; @@ -1230,7 +1197,7 @@ /* terminal_putc(): * Add a character */ -private int +static int terminal_putc(int c) { if (terminal_outfile == NULL) @@ -1238,7 +1205,7 @@ return fputc(c, terminal_outfile); } -private void +static void terminal_tputs(EditLine *el, const char *cap, int affcnt) { #ifdef _REENTRANT @@ -1254,14 +1221,16 @@ /* terminal__putc(): * Add a character */ -protected int +libedit_private int terminal__putc(EditLine *el, wint_t c) { char buf[MB_LEN_MAX +1]; ssize_t i; if (c == (wint_t)MB_FILL_CHAR) return 0; - i = ct_encode_char(buf, (size_t)MB_LEN_MAX, (Char)c); + if (c & EL_LITERAL) + return fputs(literal_get(el, c), el->el_outfile); + i = ct_encode_char(buf, (size_t)MB_LEN_MAX, c); if (i <= 0) return (int)i; buf[i] = '\0'; @@ -1271,7 +1240,7 @@ /* terminal__flush(): * Flush output */ -protected void +libedit_private void terminal__flush(EditLine *el) { @@ -1281,11 +1250,11 @@ /* terminal_writec(): * Write the given character out, in a human readable form */ -protected void +libedit_private void terminal_writec(EditLine *el, wint_t c) { - Char visbuf[VISUAL_WIDTH_MAX +1]; - ssize_t vcnt = ct_visual_char(visbuf, VISUAL_WIDTH_MAX, (Char)c); + wchar_t visbuf[VISUAL_WIDTH_MAX +1]; + ssize_t vcnt = ct_visual_char(visbuf, VISUAL_WIDTH_MAX, c); if (vcnt < 0) vcnt = 0; visbuf[vcnt] = '\0'; @@ -1297,10 +1266,10 @@ /* terminal_telltc(): * Print the current termcap characteristics */ -protected int +libedit_private int /*ARGSUSED*/ terminal_telltc(EditLine *el, int argc __attribute__((__unused__)), - const Char **argv __attribute__((__unused__))) + const wchar_t **argv __attribute__((__unused__))) { const struct termcapstr *t; char **ts; @@ -1323,8 +1292,8 @@ const char *ub; if (*ts && **ts) { ub = ct_encode_string(ct_visual_string( - ct_decode_string(*ts, &el->el_scratch)), - &el->el_scratch); + ct_decode_string(*ts, &el->el_scratch), + &el->el_visual), &el->el_scratch); } else { ub = "(empty)"; } @@ -1339,10 +1308,10 @@ /* terminal_settc(): * Change the current terminal characteristics */ -protected int +libedit_private int /*ARGSUSED*/ terminal_settc(EditLine *el, int argc __attribute__((__unused__)), - const Char **argv) + const wchar_t **argv) { const struct termcapstr *ts; const struct termcapval *tv; @@ -1386,7 +1355,7 @@ el->el_terminal.t_val[tv - tval] = 0; else { (void) fprintf(el->el_errfile, - "" FSTR ": Bad value `%s'.\n", argv[0], how); + "%ls: Bad value `%s'.\n", argv[0], how); return -1; } terminal_setflags(el); @@ -1400,7 +1369,7 @@ i = strtol(how, &ep, 10); if (*ep != '\0') { (void) fprintf(el->el_errfile, - "" FSTR ": Bad value `%s'.\n", argv[0], how); + "%ls: Bad value `%s'.\n", argv[0], how); return -1; } el->el_terminal.t_val[tv - tval] = (int) i; @@ -1418,7 +1387,7 @@ /* terminal_gettc(): * Get the current terminal characteristics */ -protected int +libedit_private int /*ARGSUSED*/ terminal_gettc(EditLine *el, int argc __attribute__((__unused__)), char **argv) { @@ -1472,13 +1441,13 @@ /* terminal_echotc(): * Print the termcap string out with variable substitution */ -protected int +libedit_private int /*ARGSUSED*/ terminal_echotc(EditLine *el, int argc __attribute__((__unused__)), - const Char **argv) + const wchar_t **argv) { char *cap, *scap; - Char *ep; + wchar_t *ep; int arg_need, arg_cols, arg_rows; int verbose = 0, silent = 0; char *area; @@ -1509,28 +1478,28 @@ } if (!*argv || *argv[0] == '\0') return 0; - if (Strcmp(*argv, STR("tabs")) == 0) { + if (wcscmp(*argv, L"tabs") == 0) { (void) fprintf(el->el_outfile, fmts, EL_CAN_TAB ? "yes" : "no"); return 0; - } else if (Strcmp(*argv, STR("meta")) == 0) { + } else if (wcscmp(*argv, L"meta") == 0) { (void) fprintf(el->el_outfile, fmts, Val(T_km) ? "yes" : "no"); return 0; - } else if (Strcmp(*argv, STR("xn")) == 0) { + } else if (wcscmp(*argv, L"xn") == 0) { (void) fprintf(el->el_outfile, fmts, EL_HAS_MAGIC_MARGINS ? "yes" : "no"); return 0; - } else if (Strcmp(*argv, STR("am")) == 0) { + } else if (wcscmp(*argv, L"am") == 0) { (void) fprintf(el->el_outfile, fmts, EL_HAS_AUTO_MARGINS ? "yes" : "no"); return 0; - } else if (Strcmp(*argv, STR("baud")) == 0) { + } else if (wcscmp(*argv, L"baud") == 0) { (void) fprintf(el->el_outfile, fmtd, (int)el->el_tty.t_speed); return 0; - } else if (Strcmp(*argv, STR("rows")) == 0 || - Strcmp(*argv, STR("lines")) == 0) { + } else if (wcscmp(*argv, L"rows") == 0 || + wcscmp(*argv, L"lines") == 0) { (void) fprintf(el->el_outfile, fmtd, Val(T_li)); return 0; - } else if (Strcmp(*argv, STR("cols")) == 0) { + } else if (wcscmp(*argv, L"cols") == 0) { (void) fprintf(el->el_outfile, fmtd, Val(T_co)); return 0; } @@ -1551,7 +1520,7 @@ if (!scap || scap[0] == '\0') { if (!silent) (void) fprintf(el->el_errfile, - "echotc: Termcap parameter `" FSTR "' not found.\n", + "echotc: Termcap parameter `%ls' not found.\n", *argv); return -1; } @@ -1594,7 +1563,7 @@ if (*argv && *argv[0]) { if (!silent) (void) fprintf(el->el_errfile, - "echotc: Warning: Extra argument `" FSTR "'.\n", + "echotc: Warning: Extra argument `%ls'.\n", *argv); return -1; } @@ -1609,11 +1578,11 @@ return -1; } arg_cols = 0; - i = Strtol(*argv, &ep, 10); + i = wcstol(*argv, &ep, 10); if (*ep != '\0' || i < 0) { if (!silent) (void) fprintf(el->el_errfile, - "echotc: Bad value `" FSTR "' for rows.\n", + "echotc: Bad value `%ls' for rows.\n", *argv); return -1; } @@ -1622,7 +1591,7 @@ if (*argv && *argv[0]) { if (!silent) (void) fprintf(el->el_errfile, - "echotc: Warning: Extra argument `" FSTR + "echotc: Warning: Extra argument `%ls" "'.\n", *argv); return -1; } @@ -1643,11 +1612,11 @@ "echotc: Warning: Missing argument.\n"); return -1; } - i = Strtol(*argv, &ep, 10); + i = wcstol(*argv, &ep, 10); if (*ep != '\0' || i < 0) { if (!silent) (void) fprintf(el->el_errfile, - "echotc: Bad value `" FSTR "' for cols.\n", + "echotc: Bad value `%ls' for cols.\n", *argv); return -1; } @@ -1659,11 +1628,11 @@ "echotc: Warning: Missing argument.\n"); return -1; } - i = Strtol(*argv, &ep, 10); + i = wcstol(*argv, &ep, 10); if (*ep != '\0' || i < 0) { if (!silent) (void) fprintf(el->el_errfile, - "echotc: Bad value `" FSTR "' for rows.\n", + "echotc: Bad value `%ls' for rows.\n", *argv); return -1; } @@ -1671,14 +1640,14 @@ if (*ep != '\0') { if (!silent) (void) fprintf(el->el_errfile, - "echotc: Bad value `" FSTR "'.\n", *argv); + "echotc: Bad value `%ls'.\n", *argv); return -1; } argv++; if (*argv && *argv[0]) { if (!silent) (void) fprintf(el->el_errfile, - "echotc: Warning: Extra argument `" FSTR + "echotc: Warning: Extra argument `%ls" "'.\n", *argv); return -1; } Index: lib/libedit/tokenizer.c =================================================================== --- lib/libedit/tokenizer.c +++ lib/libedit/tokenizer.c @@ -1,4 +1,4 @@ -/* $NetBSD: tokenizer.c,v 1.24 2016/02/17 19:47:49 christos Exp $ */ +/* $NetBSD: tokenizer.c,v 1.28 2016/04/11 18:56:31 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)tokenizer.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: tokenizer.c,v 1.24 2016/02/17 19:47:49 christos Exp $"); +__RCSID("$NetBSD: tokenizer.c,v 1.28 2016/04/11 18:56:31 christos Exp $"); #endif #endif /* not lint && not SCCSID */ #include @@ -51,7 +51,6 @@ #include #include "histedit.h" -#include "chartype.h" typedef enum { Q_none, Q_single, Q_double, Q_one, Q_doubleone @@ -68,8 +67,22 @@ #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) +#ifdef NARROWCHAR +#define Char char +#define FUN(prefix, rest) prefix ## _ ## rest +#define TYPE(type) type +#define STR(x) x +#define Strchr(s, c) strchr(s, c) +#define tok_strdup(s) strdup(s) +#else +#define Char wchar_t +#define FUN(prefix, rest) prefix ## _w ## rest +#define TYPE(type) type ## W +#define STR(x) L ## x +#define Strchr(s, c) wcschr(s, c) +#define tok_strdup(s) wcsdup(s) +#endif struct TYPE(tokenizer) { Char *ifs; /* In field separator */ @@ -83,13 +96,13 @@ }; -private void FUN(tok,finish)(TYPE(Tokenizer) *); +static void FUN(tok,finish)(TYPE(Tokenizer) *); /* FUN(tok,finish)(): * Finish a word in the tokenizer. */ -private void +static void FUN(tok,finish)(TYPE(Tokenizer) *tok) { @@ -106,7 +119,7 @@ /* FUN(tok,init)(): * Initialize the tokenizer */ -public TYPE(Tokenizer) * +TYPE(Tokenizer) * FUN(tok,init)(const Char *ifs) { TYPE(Tokenizer) *tok = tok_malloc(sizeof(*tok)); @@ -147,7 +160,7 @@ /* FUN(tok,reset)(): * Reset the tokenizer */ -public void +void FUN(tok,reset)(TYPE(Tokenizer) *tok) { @@ -162,7 +175,7 @@ /* FUN(tok,end)(): * Clean up */ -public void +void FUN(tok,end)(TYPE(Tokenizer) *tok) { @@ -191,7 +204,7 @@ * cursorc if !NULL, argv element containing cursor * cursorv if !NULL, offset in argv[cursorc] of cursor */ -public int +int FUN(tok,line)(TYPE(Tokenizer) *tok, const TYPE(LineInfo) *line, int *argc, const Char ***argv, int *cursorc, int *cursoro) { @@ -442,7 +455,7 @@ * Simpler version of tok_line, taking a NUL terminated line * and splitting into words, ignoring cursor state. */ -public int +int FUN(tok,str)(TYPE(Tokenizer) *tok, const Char *line, int *argc, const Char ***argv) { Index: lib/libedit/tokenizern.c =================================================================== --- lib/libedit/tokenizern.c +++ lib/libedit/tokenizern.c @@ -0,0 +1,3 @@ +#include "config.h" +#define NARROWCHAR +#include "tokenizer.c" Index: lib/libedit/tty.h =================================================================== --- lib/libedit/tty.h +++ lib/libedit/tty.h @@ -1,4 +1,4 @@ -/* $NetBSD: tty.h,v 1.19 2016/02/27 18:13:21 christos Exp $ */ +/* $NetBSD: tty.h,v 1.23 2018/12/02 16:58:13 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -457,14 +457,15 @@ 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_rawmode(EditLine *); -protected int tty_cookedmode(EditLine *); -protected int tty_quotemode(EditLine *); -protected int tty_noquotemode(EditLine *); -protected void tty_bind_char(EditLine *, int); +libedit_private int tty_init(EditLine *); +libedit_private void tty_end(EditLine *, int); +libedit_private int tty_stty(EditLine *, int, const wchar_t **); +libedit_private int tty_rawmode(EditLine *); +libedit_private int tty_cookedmode(EditLine *); +libedit_private int tty_quotemode(EditLine *); +libedit_private int tty_noquotemode(EditLine *); +libedit_private void tty_bind_char(EditLine *, int); +libedit_private int tty_get_signal_character(EditLine *, int); typedef struct { ttyperm_t t_t; Index: lib/libedit/tty.c =================================================================== --- lib/libedit/tty.c +++ lib/libedit/tty.c @@ -1,4 +1,4 @@ -/* $NetBSD: tty.c,v 1.59 2016/03/22 01:34:32 christos Exp $ */ +/* $NetBSD: tty.c,v 1.68 2018/12/02 16:58:13 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.59 2016/03/22 01:34:32 christos Exp $"); +__RCSID("$NetBSD: tty.c,v 1.68 2018/12/02 16:58:13 christos Exp $"); #endif #endif /* not lint && not SCCSID */ #include @@ -54,6 +54,7 @@ #include /* for isatty */ #include "el.h" +#include "fcns.h" #include "parse.h" typedef struct ttymodes_t { @@ -68,7 +69,7 @@ } ttymap_t; -private const ttyperm_t ttyperm = { +static const ttyperm_t ttyperm = { { {"iflag:", ICRNL, (INLCR | IGNCR)}, {"oflag:", (OPOST | ONLCR), ONLRET}, @@ -96,7 +97,7 @@ } }; -private const ttychar_t ttychar = { +static const ttychar_t ttychar = { { CINTR, CQUIT, CERASE, CKILL, CEOF, CEOL, CEOL2, CSWTCH, @@ -126,7 +127,7 @@ } }; -private const ttymap_t tty_map[] = { +static const ttymap_t tty_map[] = { #ifdef VERASE {C_ERASE, VERASE, {EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}}, @@ -163,7 +164,7 @@ {ED_UNASSIGNED, ED_UNASSIGNED, ED_UNASSIGNED}} }; -private const ttymodes_t ttymodes[] = { +static const ttymodes_t ttymodes[] = { #ifdef IGNBRK {"ignbrk", IGNBRK, MD_INP}, #endif /* IGNBRK */ @@ -457,21 +458,21 @@ #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 *); -private speed_t tty__getspeed(struct termios *); -private int tty_setup(EditLine *); -private void tty_setup_flags(EditLine *, struct termios *, int); +static int tty_getty(EditLine *, struct termios *); +static int tty_setty(EditLine *, int, const struct termios *); +static int tty__getcharindex(int); +static void tty__getchar(struct termios *, unsigned char *); +static void tty__setchar(struct termios *, unsigned char *); +static speed_t tty__getspeed(struct termios *); +static int tty_setup(EditLine *); +static void tty_setup_flags(EditLine *, struct termios *, int); #define t_qu t_ts /* tty_getty(): * Wrapper for tcgetattr to handle EINTR */ -private int +static int tty_getty(EditLine *el, struct termios *t) { int rv; @@ -483,7 +484,7 @@ /* tty_setty(): * Wrapper for tcsetattr to handle EINTR */ -private int +static int tty_setty(EditLine *el, int action, const struct termios *t) { int rv; @@ -495,10 +496,10 @@ /* tty_setup(): * Get the tty parameters and initialize the editing state */ -private int +static int tty_setup(EditLine *el) { - int rst = 1; + int rst = (el->el_flags & NO_RESET) == 0; if (el->el_flags & EDIT_DISABLED) return 0; @@ -569,7 +570,7 @@ return 0; } -protected int +libedit_private int tty_init(EditLine *el) { @@ -585,9 +586,9 @@ /* tty_end(): * Restore the tty to its original settings */ -protected void +libedit_private void /*ARGSUSED*/ -tty_end(EditLine *el) +tty_end(EditLine *el, int how) { if (el->el_flags & EDIT_DISABLED) return; @@ -595,7 +596,8 @@ if (!el->el_tty.t_initialized) return; - if (tty_setty(el, TCSAFLUSH, &el->el_tty.t_or) == -1) { + if (tty_setty(el, how, &el->el_tty.t_or) == -1) + { #ifdef DEBUG_TTY (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__, strerror(errno)); @@ -607,7 +609,7 @@ /* tty__getspeed(): * Get the tty speed */ -private speed_t +static speed_t tty__getspeed(struct termios *td) { speed_t spd; @@ -620,7 +622,7 @@ /* tty__getspeed(): * Return the index of the asked char in the c_cc array */ -private int +static int tty__getcharindex(int i) { switch (i) { @@ -728,7 +730,7 @@ /* tty__getchar(): * Get the tty characters */ -private void +static void tty__getchar(struct termios *td, unsigned char *s) { @@ -810,7 +812,7 @@ /* tty__setchar(): * Set the tty characters */ -private void +static void tty__setchar(struct termios *td, unsigned char *s) { @@ -892,13 +894,13 @@ /* tty_bind_char(): * Rebind the editline functions */ -protected void +libedit_private void 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; - Char new[2], old[2]; + wchar_t new[2], old[2]; const ttymap_t *tp; el_action_t *map, *alt; const el_action_t *dmap, *dalt; @@ -915,27 +917,29 @@ } for (tp = tty_map; tp->nch != (wint_t)-1; tp++) { - new[0] = (Char)t_n[tp->nch]; - old[0] = (Char)t_o[tp->och]; + new[0] = (wchar_t)t_n[tp->nch]; + old[0] = (wchar_t)t_o[tp->och]; if (new[0] == old[0] && !force) continue; /* Put the old default binding back, and set the new binding */ keymacro_clear(el, map, old); - map[UC(old[0])] = dmap[UC(old[0])]; + map[(unsigned char)old[0]] = dmap[(unsigned char)old[0]]; keymacro_clear(el, map, new); /* MAP_VI == 1, MAP_EMACS == 0... */ - map[UC(new[0])] = tp->bind[el->el_map.type]; + map[(unsigned char)new[0]] = tp->bind[el->el_map.type]; if (dalt) { keymacro_clear(el, alt, old); - alt[UC(old[0])] = dalt[UC(old[0])]; + alt[(unsigned char)old[0]] = + dalt[(unsigned char)old[0]]; keymacro_clear(el, alt, new); - alt[UC(new[0])] = tp->bind[el->el_map.type + 1]; + alt[(unsigned char)new[0]] = + tp->bind[el->el_map.type + 1]; } } } -private tcflag_t * +static tcflag_t * tty__get_flag(struct termios *t, int kind) { switch (kind) { case MD_INP: @@ -953,7 +957,7 @@ } -private tcflag_t +static tcflag_t tty_update_flag(EditLine *el, tcflag_t f, int mode, int kind) { f &= ~el->el_tty.t_t[mode][kind].t_clrmask; @@ -962,7 +966,7 @@ } -private void +static void tty_update_flags(EditLine *el, int kind) { tcflag_t *tt, *ed, *ex; @@ -977,7 +981,7 @@ } -private void +static void tty_update_char(EditLine *el, int mode, int c) { if (!((el->el_tty.t_t[mode][MD_CHAR].t_setmask & C_SH(c))) && (el->el_tty.t_c[TS_IO][c] != el->el_tty.t_c[EX_IO][c])) @@ -990,7 +994,7 @@ /* tty_rawmode(): * Set terminal into 1 character at a time mode. */ -protected int +libedit_private int tty_rawmode(EditLine *el) { @@ -1045,7 +1049,7 @@ if (i != C_NCC) { /* - * Propagate changes only to the unprotected + * Propagate changes only to the unlibedit_private * chars that have been modified just now. */ for (i = 0; i < C_NCC; i++) @@ -1075,7 +1079,7 @@ /* tty_cookedmode(): * Set the tty back to normal mode */ -protected int +libedit_private int tty_cookedmode(EditLine *el) { /* set tty in normal setup */ @@ -1100,7 +1104,7 @@ /* tty_quotemode(): * Turn on quote mode */ -protected int +libedit_private int tty_quotemode(EditLine *el) { if (el->el_tty.t_mode == QU_IO) @@ -1125,7 +1129,7 @@ /* tty_noquotemode(): * Turn off quote mode */ -protected int +libedit_private int tty_noquotemode(EditLine *el) { @@ -1146,14 +1150,15 @@ /* tty_stty(): * Stty builtin */ -protected int +libedit_private int /*ARGSUSED*/ -tty_stty(EditLine *el, int argc __attribute__((__unused__)), const Char **argv) +tty_stty(EditLine *el, int argc __attribute__((__unused__)), + const wchar_t **argv) { const ttymodes_t *m; char x; int aflag = 0; - const Char *s, *d; + const wchar_t *s, *d; char name[EL_BUFSIZ]; struct termios *tios = &el->el_tty.t_ex; int z = EX_IO; @@ -1237,7 +1242,7 @@ return 0; } while (argv && (s = *argv++)) { - const Char *p; + const wchar_t *p; switch (*s) { case '+': case '-': @@ -1248,7 +1253,7 @@ break; } d = s; - p = Strchr(s, '='); + p = wcschr(s, L'='); for (m = ttymodes; m->m_name; m++) if ((p ? strncmp(m->m_name, ct_encode_string(d, &el->el_scratch), (size_t)(p - d)) : @@ -1259,7 +1264,7 @@ if (!m->m_name) { (void) fprintf(el->el_errfile, - "%s: Invalid argument `" FSTR "'.\n", name, d); + "%s: Invalid argument `%ls'.\n", name, d); return -1; } if (p) { @@ -1308,7 +1313,7 @@ /* tty_printchar(): * DEbugging routine to print the tty characters */ -private void +static void tty_printchar(EditLine *el, unsigned char *s) { ttyperm_t *m; @@ -1329,7 +1334,7 @@ #endif /* notyet */ -private void +static void tty_setup_flags(EditLine *el, struct termios *tios, int mode) { int kind; @@ -1338,3 +1343,33 @@ *f = tty_update_flag(el, *f, mode, kind); } } + +libedit_private int +tty_get_signal_character(EditLine *el, int sig) +{ +#ifdef ECHOCTL + tcflag_t *ed = tty__get_flag(&el->el_tty.t_ed, MD_INP); + if ((*ed & ECHOCTL) == 0) + return -1; +#endif + switch (sig) { +#ifdef SIGINT + case SIGINT: + return el->el_tty.t_c[ED_IO][VINTR]; +#endif +#ifdef SIGQUIT + case SIGQUIT: + return el->el_tty.t_c[ED_IO][VQUIT]; +#endif +#ifdef SIGINFO + case SIGINFO: + return el->el_tty.t_c[ED_IO][VSTATUS]; +#endif +#ifdef SIGTSTP + case SIGTSTP: + return el->el_tty.t_c[ED_IO][VSUSP]; +#endif + default: + return -1; + } +} Index: lib/libedit/vi.c =================================================================== --- lib/libedit/vi.c +++ lib/libedit/vi.c @@ -1,4 +1,4 @@ -/* $NetBSD: vi.c,v 1.55 2016/03/02 19:24:20 christos Exp $ */ +/* $NetBSD: vi.c,v 1.63 2019/07/23 10:18:52 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)vi.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: vi.c,v 1.55 2016/03/02 19:24:20 christos Exp $"); +__RCSID("$NetBSD: vi.c,v 1.63 2019/07/23 10:18:52 christos Exp $"); #endif #endif /* not lint && not SCCSID */ #include @@ -56,15 +56,16 @@ #include "el.h" #include "common.h" #include "emacs.h" +#include "fcns.h" #include "vi.h" -private el_action_t cv_action(EditLine *, wint_t); -private el_action_t cv_paste(EditLine *, wint_t); +static el_action_t cv_action(EditLine *, wint_t); +static el_action_t cv_paste(EditLine *, wint_t); /* cv_action(): * Handle vi actions. */ -private el_action_t +static el_action_t cv_action(EditLine *el, wint_t c) { @@ -96,7 +97,7 @@ /* cv_paste(): * Paste previous deletion before or after the cursor */ -private el_action_t +static el_action_t cv_paste(EditLine *el, wint_t c) { c_kill_t *k = &el->el_chared.c_kill; @@ -105,7 +106,7 @@ if (k->buf == NULL || len == 0) return CC_ERROR; #ifdef DEBUG_PASTE - (void) fprintf(el->el_errfile, "Paste: \"" FSTARSTR "\"\n", (int)len, + (void) fprintf(el->el_errfile, "Paste: \"%.*ls\"\n", (int)len, k->buf); #endif @@ -128,7 +129,7 @@ * Vi paste previous deletion to the right of the cursor * [p] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_paste_next(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -141,7 +142,7 @@ * Vi paste previous deletion to the left of the cursor * [P] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_paste_prev(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -154,7 +155,7 @@ * Vi move to the previous space delimited word * [B] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_prev_big_word(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -179,7 +180,7 @@ * Vi move to the previous word * [b] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_prev_word(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -204,7 +205,7 @@ * Vi move to the next space delimited word * [W] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_next_big_word(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -228,7 +229,7 @@ * Vi move to the next word * [w] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_next_word(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -252,7 +253,7 @@ * Vi change case of character under the cursor and advance one character * [~] */ -protected el_action_t +libedit_private el_action_t vi_change_case(EditLine *el, wint_t c) { int i; @@ -263,10 +264,10 @@ for (i = 0; i < el->el_state.argument; i++) { 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 (iswupper(c)) + *el->el_line.cursor = towlower(c); + else if (iswlower(c)) + *el->el_line.cursor = towupper(c); if (++el->el_line.cursor >= el->el_line.lastchar) { el->el_line.cursor--; @@ -283,7 +284,7 @@ * Vi change prefix command * [c] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_change_meta(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -300,7 +301,7 @@ * Vi enter insert mode at the beginning of line * [I] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_insert_at_bol(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -316,7 +317,7 @@ * Vi replace character under the cursor with the next character typed * [r] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_replace_char(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -335,7 +336,7 @@ * Vi enter replace mode * [R] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_replace_mode(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -351,7 +352,7 @@ * Vi replace character under the cursor and enter insert mode * [s] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_substitute_char(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -366,7 +367,7 @@ * Vi substitute entire line * [S] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_substitute_line(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -384,7 +385,7 @@ * Vi change to end of line * [C] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_change_to_eol(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -402,7 +403,7 @@ * Vi enter insert mode * [i] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_insert(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -417,7 +418,7 @@ * Vi enter insert mode after the cursor * [a] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_add(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -442,7 +443,7 @@ * Vi enter insert mode at end of line * [A] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_add_at_eol(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -458,7 +459,7 @@ * Vi delete prefix command * [d] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_delete_meta(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -471,7 +472,7 @@ * Vi move to the end of the current space delimited word * [E] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_end_big_word(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -495,7 +496,7 @@ * Vi move to the end of the current word * [e] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_end_word(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -519,7 +520,7 @@ * Vi undo last change * [u] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_undo(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -546,7 +547,7 @@ * Vi enter command mode (use alternative key bindings) * [] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_command_mode(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -571,7 +572,7 @@ * Vi move to the beginning of line * [0] */ -protected el_action_t +libedit_private el_action_t vi_zero(EditLine *el, wint_t c) { @@ -591,7 +592,7 @@ * Vi move to previous character (backspace) * [^H] in insert mode only */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_delete_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -609,7 +610,7 @@ * Vi list choices for completion or indicate end of file if empty line * [^D] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_list_or_eof(EditLine *el, wint_t c) { @@ -646,11 +647,11 @@ * Vi cut from beginning of line to cursor * [^U] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_kill_line_prev(EditLine *el, wint_t c __attribute__((__unused__))) { - Char *kp, *cp; + wchar_t *kp, *cp; cp = el->el_line.buffer; kp = el->el_chared.c_kill.buf; @@ -667,7 +668,7 @@ * Vi search history previous * [?] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_search_prev(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -680,7 +681,7 @@ * Vi search history next * [/] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_search_next(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -693,7 +694,7 @@ * Vi repeat current search in the same search direction * [n] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_repeat_search_next(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -710,7 +711,7 @@ * [N] */ /*ARGSUSED*/ -protected el_action_t +libedit_private el_action_t vi_repeat_search_prev(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -727,7 +728,7 @@ * Vi move to the character specified next * [f] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_next_char(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -739,7 +740,7 @@ * Vi move to the character specified previous * [F] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -751,7 +752,7 @@ * Vi move up to the character specified next * [t] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_to_next_char(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -763,7 +764,7 @@ * Vi move up to the character specified previous * [T] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_to_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -775,7 +776,7 @@ * Vi repeat current character search in the same search direction * [;] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_repeat_next_char(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -789,7 +790,7 @@ * Vi repeat current character search in the opposite search direction * [,] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_repeat_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -807,22 +808,22 @@ * Vi go to matching () {} or [] * [%] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_match(EditLine *el, wint_t c __attribute__((__unused__))) { - const Char match_chars[] = STR("()[]{}"); - Char *cp; + const wchar_t match_chars[] = L"()[]{}"; + wchar_t *cp; size_t delta, i, count; - Char o_ch, c_ch; + wchar_t o_ch, c_ch; *el->el_line.lastchar = '\0'; /* just in case */ - i = Strcspn(el->el_line.cursor, match_chars); + i = wcscspn(el->el_line.cursor, match_chars); o_ch = el->el_line.cursor[i]; if (o_ch == 0) return CC_ERROR; - delta = (size_t)(Strchr(match_chars, o_ch) - match_chars); + delta = (size_t)(wcschr(match_chars, o_ch) - match_chars); c_ch = match_chars[delta ^ 1]; count = 1; delta = 1 - (delta & 1) * 2; @@ -854,7 +855,7 @@ * Vi undo all changes to line * [U] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_undo_line(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -868,7 +869,7 @@ * [|] * NB netbsd vi goes to screen column 'n', posix says nth character */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_to_column(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -882,7 +883,7 @@ * Vi yank to end of line * [Y] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_yank_end(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -896,7 +897,7 @@ * Vi yank * [y] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_yank(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -908,7 +909,7 @@ * Vi comment out current command * [#] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_comment_out(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -926,7 +927,7 @@ * NB: posix implies that we should enter insert mode, however * this is against historical precedent... */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_alias(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -944,7 +945,7 @@ alias_text = (*el->el_chared.c_aliasfun)(el->el_chared.c_aliasarg, alias_name); if (alias_text != NULL) - FUN(el,push)(el, ct_decode_string(alias_text, &el->el_scratch)); + el_wpush(el, ct_decode_string(alias_text, &el->el_scratch)); return CC_NORM; } @@ -952,7 +953,7 @@ * Vi go to specified history file line. * [G] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_to_history_line(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -961,7 +962,7 @@ if (el->el_history.eventno == 0) { - (void) Strncpy(el->el_history.buf, el->el_line.buffer, + (void) wcsncpy(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); @@ -997,7 +998,7 @@ * Vi edit history line with vi * [v] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_histedit(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -1008,7 +1009,7 @@ char tempfile[] = "/tmp/histedit.XXXXXXXXXX"; char *cp = NULL; size_t len; - Char *line = NULL; + wchar_t *line = NULL; if (el->el_state.doingarg) { if (vi_to_history_line(el, 0) == CC_ERROR) @@ -1020,15 +1021,15 @@ return CC_ERROR; len = (size_t)(el->el_line.lastchar - el->el_line.buffer); #define TMP_BUFSIZ (EL_BUFSIZ * MB_LEN_MAX) - cp = el_malloc(TMP_BUFSIZ * sizeof(*cp)); + cp = el_calloc(TMP_BUFSIZ, sizeof(*cp)); if (cp == NULL) goto error; - line = el_malloc(len * sizeof(*line) + 1); + line = el_calloc(len + 1, sizeof(*line)); if (line == NULL) goto error; - Strncpy(line, el->el_line.buffer, len); + wcsncpy(line, el->el_line.buffer, len); line[len] = '\0'; - ct_wcstombs(cp, line, TMP_BUFSIZ - 1); + wcstombs(cp, line, TMP_BUFSIZ - 1); cp[TMP_BUFSIZ - 1] = '\0'; len = strlen(cp); write(fd, cp, len); @@ -1050,7 +1051,7 @@ if (st > 0) { cp[st] = '\0'; len = (size_t)(el->el_line.limit - el->el_line.buffer); - len = ct_mbstowcs(el->el_line.buffer, cp, len); + len = mbstowcs(el->el_line.buffer, cp, len); if (len > 0 && el->el_line.buffer[len - 1] == '\n') --len; } @@ -1081,27 +1082,27 @@ * Who knows where this one came from! * '_' in vi means 'entire current line', so 'cc' is a synonym for 'c_' */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_history_word(EditLine *el, wint_t c __attribute__((__unused__))) { - const Char *wp = HIST_FIRST(el); - const Char *wep, *wsp; + const wchar_t *wp = HIST_FIRST(el); + const wchar_t *wep, *wsp; int len; - Char *cp; - const Char *lim; + wchar_t *cp; + const wchar_t *lim; if (wp == NULL) return CC_ERROR; wep = wsp = NULL; do { - while (Isspace(*wp)) + while (iswspace(*wp)) wp++; if (*wp == 0) break; wsp = wp; - while (*wp && !Isspace(*wp)) + while (*wp && !iswspace(*wp)) wp++; wep = wp; } while ((!el->el_state.doingarg || --el->el_state.argument > 0) @@ -1131,7 +1132,7 @@ * Vi redo last non-motion command * [.] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ vi_redo(EditLine *el, wint_t c __attribute__((__unused__))) { @@ -1149,7 +1150,7 @@ /* sanity */ r->pos = r->lim - 1; r->pos[0] = 0; - FUN(el,push)(el, r->buf); + el_wpush(el, r->buf); } el->el_state.thiscmd = r->cmd;