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).
This commit is contained in:
kre 2017-06-30 20:26:52 +00:00
parent 5ca98f2167
commit e3112e6cea
4 changed files with 57 additions and 21 deletions

View File

@ -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

View File

@ -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);

View File

@ -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 */

View File

@ -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';