Module Name:    src
Committed By:   kre
Date:           Fri Jun 30 20:26:52 UTC 2017

Modified Files:
        src/lib/libedit: Makefile literal.c literal.h refresh.c

Log Message:
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).


To generate a diff of this commit:
cvs rdiff -u -r1.64 -r1.65 src/lib/libedit/Makefile
cvs rdiff -u -r1.2 -r1.3 src/lib/libedit/literal.c
cvs rdiff -u -r1.1 -r1.2 src/lib/libedit/literal.h
cvs rdiff -u -r1.53 -r1.54 src/lib/libedit/refresh.c

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.64 src/lib/libedit/Makefile:1.65
--- src/lib/libedit/Makefile:1.64	Tue Jun 27 23:25:13 2017
+++ src/lib/libedit/Makefile	Fri Jun 30 20:26:52 2017
@@ -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

Index: src/lib/libedit/literal.c
diff -u src/lib/libedit/literal.c:1.2 src/lib/libedit/literal.c:1.3
--- src/lib/libedit/literal.c:1.2	Thu Jun 29 02:54:40 2017
+++ src/lib/libedit/literal.c	Fri Jun 30 20:26:52 2017
@@ -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);

Index: src/lib/libedit/literal.h
diff -u src/lib/libedit/literal.h:1.1 src/lib/libedit/literal.h:1.2
--- src/lib/libedit/literal.h:1.1	Tue Jun 27 23:25:13 2017
+++ src/lib/libedit/literal.h	Fri Jun 30 20:26:52 2017
@@ -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(EditLi
 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 */

Index: src/lib/libedit/refresh.c
diff -u src/lib/libedit/refresh.c:1.53 src/lib/libedit/refresh.c:1.54
--- src/lib/libedit/refresh.c:1.53	Tue Jun 27 23:29:12 2017
+++ src/lib/libedit/refresh.c	Fri Jun 30 20:26:52 2017
@@ -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_
 	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';

Reply via email to