diff --git a/lib/libedit/Makefile b/lib/libedit/Makefile index a7ed9f8161f1..8a02211504a8 100644 --- a/lib/libedit/Makefile +++ b/lib/libedit/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.64 2017/06/27 23:25:13 christos Exp $ +# $NetBSD: Makefile,v 1.65 2017/06/30 20:26:52 kre Exp $ # @(#)Makefile 8.1 (Berkeley) 6/4/93 USE_SHLIBDIR= yes @@ -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 diff --git a/lib/libedit/literal.c b/lib/libedit/literal.c index 9a4e7f9bb130..6c2496f2f044 100644 --- a/lib/libedit/literal.c +++ b/lib/libedit/literal.c @@ -1,4 +1,4 @@ -/* $NetBSD: literal.c,v 1.2 2017/06/29 02:54:40 kre Exp $ */ +/* $NetBSD: literal.c,v 1.3 2017/06/30 20:26:52 kre Exp $ */ /*- * Copyright (c) 2017 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ #include "config.h" #if !defined(lint) && !defined(SCCSID) -__RCSID("$NetBSD: literal.c,v 1.2 2017/06/29 02:54:40 kre Exp $"); +__RCSID("$NetBSD: literal.c,v 1.3 2017/06/30 20:26:52 kre Exp $"); #endif /* not lint && not SCCSID */ /* @@ -47,15 +47,14 @@ 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) { - el_literal_t *l = &el->el_literal; literal_clear(el); - el_free(l->l_buf); } libedit_private void @@ -63,33 +62,60 @@ 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) +literal_add(EditLine *el, const wchar_t *buf, const wchar_t *end, int *wp) { - // XXX: Only for narrow chars now. 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); - b = el_malloc(len + 2); + 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 (i = 0; i < len; i++) - b[i] = (char)buf[i]; - b[len] = (char)end[1]; - b[len + 1] = '\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) { - l->l_len += 10; - char **bp = el_realloc(l->l_buf, sizeof(*l->l_buf) * 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; @@ -102,6 +128,7 @@ 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); diff --git a/lib/libedit/literal.h b/lib/libedit/literal.h index 5e78d71f1a25..a8e0a416888b 100644 --- a/lib/libedit/literal.h +++ b/lib/libedit/literal.h @@ -1,4 +1,4 @@ -/* $NetBSD: literal.h,v 1.1 2017/06/27 23:25:13 christos Exp $ */ +/* $NetBSD: literal.h,v 1.2 2017/06/30 20:26:52 kre Exp $ */ /*- * Copyright (c) 2017 The NetBSD Foundation, Inc. @@ -47,7 +47,7 @@ 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 *); + const wchar_t *, int *); libedit_private const char *literal_get(EditLine *, wint_t); #endif /* _h_el_literal */ diff --git a/lib/libedit/refresh.c b/lib/libedit/refresh.c index 212e7f07dee4..fe5187c5f066 100644 --- a/lib/libedit/refresh.c +++ b/lib/libedit/refresh.c @@ -1,4 +1,4 @@ -/* $NetBSD: refresh.c,v 1.53 2017/06/27 23:29:12 christos Exp $ */ +/* $NetBSD: refresh.c,v 1.54 2017/06/30 20:26:52 kre 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.53 2017/06/27 23:29:12 christos Exp $"); +__RCSID("$NetBSD: refresh.c,v 1.54 2017/06/30 20:26:52 kre Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -164,12 +164,20 @@ 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); - if (c == 0) + c = literal_add(el, begin, end, &w); + if (c == 0 || w <= 0) return; el->el_vdisplay[cur->v][cur->h] = c; - cur->h += 1; /* XXX: only for narrow */ + + 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';