Module Name: src Committed By: snj Date: Sun Jul 23 14:41:26 UTC 2017
Modified Files: src/lib/libedit [netbsd-8]: Makefile editline.3 editrc.5 el.c el.h prompt.c read.c refresh.c refresh.h terminal.c Added Files: src/lib/libedit [netbsd-8]: literal.c literal.h Log Message: Pull up following revision(s) (requested by kre in ticket #102): lib/libedit/Makefile: 1.64-1.65 lib/libedit/editline.3: 1.94-1.96 lib/libedit/editrc.5: 1.33 lib/libedit/el.c: 1.93-1.94 lib/libedit/el.h: 1.42 lib/libedit/literal.c: 1.1-1.3 lib/libedit/literal.h: 1.1-1.2 lib/libedit/prompt.c: 1.27 lib/libedit/read.c: 1.103 lib/libedit/refresh.c: 1.52-1.54 lib/libedit/refresh.h: 1.11 lib/libedit/terminal.c: 1.33 Make the default editrc file be $EDITRC (from env) if set, falling back to $HOME/.editrc otherwise. Better support for this in sh coming. -- Include EDITRC in doc. -- mention the limitation of the literal sequence delimiter. -- - handle literal escape sequence printing. - factor out common code in allocation and freeing of the display. -- - add literal sequence handling. -- remove unused variable -- add literal escape sequence support, patterned after the tcsh ones. -- fix comment -- Fix an obvious, but almost invisible typo (avoid some core dumps). -- Allow wide characters (properly encoded as byte strings according to LC_CTYPE) to be (perhaps part of) the "invisible" characters in a prompt, or the required prompt character which follows the literal sequence (this character must be one with a printing column width >= 1). The literal indicator character (which is just a marker, and not printed anywhere) (the PSlit parameter in sh(1)) can also be a wide char (passed to libedit as a wchar_t, encoded as that by sh(1) or other applications that support this.) Note: this has currently only been tested with everything ascii (C locale). -- Remove workaround for ancient HTML generation code. To generate a diff of this commit: cvs rdiff -u -r1.63 -r1.63.8.1 src/lib/libedit/Makefile cvs rdiff -u -r1.93 -r1.93.4.1 src/lib/libedit/editline.3 cvs rdiff -u -r1.32 -r1.32.8.1 src/lib/libedit/editrc.5 \ src/lib/libedit/terminal.c cvs rdiff -u -r1.92 -r1.92.8.1 src/lib/libedit/el.c cvs rdiff -u -r1.41 -r1.41.8.1 src/lib/libedit/el.h cvs rdiff -u -r0 -r1.3.4.2 src/lib/libedit/literal.c cvs rdiff -u -r0 -r1.2.4.2 src/lib/libedit/literal.h cvs rdiff -u -r1.26 -r1.26.8.1 src/lib/libedit/prompt.c cvs rdiff -u -r1.102 -r1.102.6.1 src/lib/libedit/read.c cvs rdiff -u -r1.51 -r1.51.8.1 src/lib/libedit/refresh.c cvs rdiff -u -r1.10 -r1.10.8.1 src/lib/libedit/refresh.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/libedit/Makefile diff -u src/lib/libedit/Makefile:1.63 src/lib/libedit/Makefile:1.63.8.1 --- src/lib/libedit/Makefile:1.63 Tue May 24 17:42:54 2016 +++ src/lib/libedit/Makefile Sun Jul 23 14:41:26 2017 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.63 2016/05/24 17:42:54 christos Exp $ +# $NetBSD: Makefile,v 1.63.8.1 2017/07/23 14:41:26 snj Exp $ # @(#)Makefile 8.1 (Berkeley) 6/4/93 USE_SHLIBDIR= yes @@ -15,7 +15,7 @@ CWARNFLAGS.gcc+= -Wconversion CWARNFLAGS.clang+= -Wno-cast-qual SRCS = chared.c chartype.c common.c el.c eln.c emacs.c filecomplete.c \ - hist.c history.c historyn.c keymacro.c map.c \ + hist.c history.c historyn.c keymacro.c literal.c map.c \ parse.c prompt.c read.c readline.c refresh.c search.c sig.c \ terminal.c tokenizer.c tokenizern.c tty.c vi.c @@ -133,6 +133,7 @@ tc1: libedit.a tc1.o # XXX .if defined(HAVE_GCC) COPTS.editline.c+= -Wno-cast-qual +COPTS.literal.c+= -Wno-sign-conversion COPTS.tokenizer.c+= -Wno-cast-qual COPTS.tokenizern.c+= -Wno-cast-qual .endif Index: src/lib/libedit/editline.3 diff -u src/lib/libedit/editline.3:1.93 src/lib/libedit/editline.3:1.93.4.1 --- src/lib/libedit/editline.3:1.93 Mon Apr 10 15:02:40 2017 +++ src/lib/libedit/editline.3 Sun Jul 23 14:41:26 2017 @@ -1,4 +1,4 @@ -.\" $NetBSD: editline.3,v 1.93 2017/04/10 15:02:40 abhinav Exp $ +.\" $NetBSD: editline.3,v 1.93.4.1 2017/07/23 14:41:26 snj Exp $ .\" .\" Copyright (c) 1997-2014 The NetBSD Foundation, Inc. .\" All rights reserved. @@ -26,7 +26,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd May 22, 2016 +.Dd June 27, 2017 .Dt EDITLINE 3 .Os .Sh NAME @@ -358,6 +358,8 @@ terminal without affecting the state of 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 @@ -667,6 +669,8 @@ If is .Dv NULL , try +.Pa $EDITRC +and if that is not set .Pa $HOME/.editrc . Refer to .Xr editrc 5 @@ -856,7 +860,7 @@ The caller is responsible for free'ing t .El .Pp .Fn history -returns \*[Gt]= 0 if the operation +returns >= 0 if the operation .Fa op succeeds. Otherwise, \-1 is returned and Index: src/lib/libedit/editrc.5 diff -u src/lib/libedit/editrc.5:1.32 src/lib/libedit/editrc.5:1.32.8.1 --- src/lib/libedit/editrc.5:1.32 Sun May 22 23:54:20 2016 +++ src/lib/libedit/editrc.5 Sun Jul 23 14:41:26 2017 @@ -1,4 +1,4 @@ -.\" $NetBSD: editrc.5,v 1.32 2016/05/22 23:54:20 christos Exp $ +.\" $NetBSD: editrc.5,v 1.32.8.1 2017/07/23 14:41:26 snj Exp $ .\" .\" Copyright (c) 1997-2000 The NetBSD Foundation, Inc. .\" All rights reserved. @@ -293,10 +293,18 @@ then the character is set to List the values of all the terminal capabilities (see .Xr termcap 5 ) . .El +.Sh ENVIRONMENT +.Bl -tag -width "~/.editrcXXX" +.It Ev EDITRC +Names the default configuration file for the +.Xr editline 3 +library. +.El .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 Index: src/lib/libedit/terminal.c diff -u src/lib/libedit/terminal.c:1.32 src/lib/libedit/terminal.c:1.32.8.1 --- src/lib/libedit/terminal.c:1.32 Mon May 9 21:46:56 2016 +++ src/lib/libedit/terminal.c Sun Jul 23 14:41:26 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: terminal.c,v 1.32 2016/05/09 21:46:56 christos Exp $ */ +/* $NetBSD: terminal.c,v 1.32.8.1 2017/07/23 14:41:26 snj 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.32 2016/05/09 21:46:56 christos Exp $"); +__RCSID("$NetBSD: terminal.c,v 1.32.8.1 2017/07/23 14:41:26 snj Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -419,46 +419,58 @@ terminal_rebuffer_display(EditLine *el) return 0; } - -/* terminal_alloc_display(): - * Allocate a new display. - */ -static int -terminal_alloc_display(EditLine *el) +static wchar_t ** +terminal_alloc_buffer(EditLine *el) { - int i; - wchar_t **b; + wint_t **b; coord_t *c = &el->el_terminal.t_size; + int i; b = el_malloc(sizeof(*b) * (size_t)(c->v + 1)); 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)); 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; + el->el_vdisplay = terminal_alloc_buffer(el); + if (el->el_vdisplay == 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; return 0; done: terminal_free_display(el); @@ -472,23 +484,8 @@ done: static void terminal_free_display(EditLine *el) { - wchar_t **b; - wchar_t **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); } @@ -1254,6 +1251,8 @@ terminal__putc(EditLine *el, wint_t c) ssize_t i; if (c == (wint_t)MB_FILL_CHAR) return 0; + 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; Index: src/lib/libedit/el.c diff -u src/lib/libedit/el.c:1.92 src/lib/libedit/el.c:1.92.8.1 --- src/lib/libedit/el.c:1.92 Sun May 22 19:44:26 2016 +++ src/lib/libedit/el.c Sun Jul 23 14:41:26 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: el.c,v 1.92 2016/05/22 19:44:26 christos Exp $ */ +/* $NetBSD: el.c,v 1.92.8.1 2017/07/23 14:41:26 snj 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.92 2016/05/22 19:44:26 christos Exp $"); +__RCSID("$NetBSD: el.c,v 1.92.8.1 2017/07/23 14:41:26 snj Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -115,6 +115,7 @@ el_init_fd(const char *prog, FILE *fin, (void) hist_init(el); (void) prompt_init(el); (void) sig_init(el); + (void) literal_init(el); if (read_init(el) == -1) { el_end(el); return NULL; @@ -146,6 +147,7 @@ el_end(EditLine *el) hist_end(el); prompt_end(el); sig_end(el); + literal_end(el); el_free(el->el_prog); el_free(el->el_visual.cbuff); @@ -524,18 +526,22 @@ el_source(EditLine *el, const char *fnam 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_malloc(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 @@ -545,6 +551,9 @@ el_source(EditLine *el, const char *fnam return -1; #endif } + if (fname[0] == '\0') + return -1; + if (fp == NULL) fp = fopen(fname, "r"); if (fp == NULL) { Index: src/lib/libedit/el.h diff -u src/lib/libedit/el.h:1.41 src/lib/libedit/el.h:1.41.8.1 --- src/lib/libedit/el.h:1.41 Tue May 24 15:00:45 2016 +++ src/lib/libedit/el.h Sun Jul 23 14:41:26 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: el.h,v 1.41 2016/05/24 15:00:45 christos Exp $ */ +/* $NetBSD: el.h,v 1.41.8.1 2017/07/23 14:41:26 snj Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -94,6 +94,7 @@ typedef struct el_state_t { #include "tty.h" #include "prompt.h" +#include "literal.h" #include "keymacro.h" #include "terminal.h" #include "refresh.h" @@ -115,8 +116,8 @@ struct editline { int el_errfd; /* Error file descriptor */ int el_flags; /* Various flags. */ coord_t el_cursor; /* Cursor location */ - wchar_t **el_display; /* Real screen image = what is there */ - wchar_t **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 */ @@ -125,6 +126,7 @@ struct editline { 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 */ Index: src/lib/libedit/prompt.c diff -u src/lib/libedit/prompt.c:1.26 src/lib/libedit/prompt.c:1.26.8.1 --- src/lib/libedit/prompt.c:1.26 Mon May 9 21:46:56 2016 +++ src/lib/libedit/prompt.c Sun Jul 23 14:41:26 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: prompt.c,v 1.26 2016/05/09 21:46:56 christos Exp $ */ +/* $NetBSD: prompt.c,v 1.26.8.1 2017/07/23 14:41:26 snj 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.26 2016/05/09 21:46:56 christos Exp $"); +__RCSID("$NetBSD: prompt.c,v 1.26.8.1 2017/07/23 14:41:26 snj Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -84,7 +84,6 @@ prompt_print(EditLine *el, int op) { el_prompt_t *elp; wchar_t *p; - int ignore = 0; if (op == EL_PROMPT) elp = &el->el_prompt; @@ -99,13 +98,17 @@ prompt_print(EditLine *el, int op) 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; Index: src/lib/libedit/read.c diff -u src/lib/libedit/read.c:1.102 src/lib/libedit/read.c:1.102.6.1 --- src/lib/libedit/read.c:1.102 Sun Dec 11 15:47:06 2016 +++ src/lib/libedit/read.c Sun Jul 23 14:41:26 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: read.c,v 1.102 2016/12/11 15:47:06 christos Exp $ */ +/* $NetBSD: read.c,v 1.102.6.1 2017/07/23 14:41:26 snj Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)read.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: read.c,v 1.102 2016/12/11 15:47:06 christos Exp $"); +__RCSID("$NetBSD: read.c,v 1.102.6.1 2017/07/23 14:41:26 snj Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -229,10 +229,9 @@ read_getcmd(EditLine *el, el_action_t *c { static const wchar_t meta = (wchar_t)0x80; el_action_t cmd; - int num; do { - if ((num = el_wgetc(el, ch)) != 1) + if (el_wgetc(el, ch) != 1) return -1; #ifdef KANJI Index: src/lib/libedit/refresh.c diff -u src/lib/libedit/refresh.c:1.51 src/lib/libedit/refresh.c:1.51.8.1 --- src/lib/libedit/refresh.c:1.51 Mon May 9 21:46:56 2016 +++ src/lib/libedit/refresh.c Sun Jul 23 14:41:26 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: refresh.c,v 1.51 2016/05/09 21:46:56 christos Exp $ */ +/* $NetBSD: refresh.c,v 1.51.8.1 2017/07/23 14:41:26 snj 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.51 2016/05/09 21:46:56 christos Exp $"); +__RCSID("$NetBSD: refresh.c,v 1.51.8.1 2017/07/23 14:41:26 snj Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -155,6 +155,35 @@ re_addc(EditLine *el, wint_t c) } } +/* 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 @@ -162,30 +191,30 @@ re_addc(EditLine *el, wint_t c) libedit_private void re_putc(EditLine *el, wint_t c, int shift) { + 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] = 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); } } @@ -210,10 +239,13 @@ re_refresh(EditLine *el) 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); Index: src/lib/libedit/refresh.h diff -u src/lib/libedit/refresh.h:1.10 src/lib/libedit/refresh.h:1.10.8.1 --- src/lib/libedit/refresh.h:1.10 Mon May 9 21:46:56 2016 +++ src/lib/libedit/refresh.h Sun Jul 23 14:41:26 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: refresh.h,v 1.10 2016/05/09 21:46:56 christos Exp $ */ +/* $NetBSD: refresh.h,v 1.10.8.1 2017/07/23 14:41:26 snj Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -47,6 +47,8 @@ typedef struct { } el_refresh_t; 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 *); Added files: Index: src/lib/libedit/literal.c diff -u /dev/null src/lib/libedit/literal.c:1.3.4.2 --- /dev/null Sun Jul 23 14:41:26 2017 +++ src/lib/libedit/literal.c Sun Jul 23 14:41:26 2017 @@ -0,0 +1,136 @@ +/* $NetBSD: literal.c,v 1.3.4.2 2017/07/23 14:41:26 snj 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.3.4.2 2017/07/23 14:41:26 snj Exp $"); +#endif /* not lint && not SCCSID */ + +/* + * literal.c: Literal sequences handling. + */ +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#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, w - n, buf[i]); + n += ct_encode_char(b + n, 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: src/lib/libedit/literal.h diff -u /dev/null src/lib/libedit/literal.h:1.2.4.2 --- /dev/null Sun Jul 23 14:41:26 2017 +++ src/lib/libedit/literal.h Sun Jul 23 14:41:26 2017 @@ -0,0 +1,53 @@ +/* $NetBSD: literal.h,v 1.2.4.2 2017/07/23 14:41:26 snj 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. + */ + +/* + * 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 */