summaryrefslogtreecommitdiff
path: root/Src/Zle/zle_refresh.c
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2008-01-22 10:14:01 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2008-01-22 10:14:01 +0000
commit088e8a9c8d19d0675bde3fabdde1b1e35129725b (patch)
tree0fadfdafe4b88d9cff83a5d74eb58778f60fd0ee /Src/Zle/zle_refresh.c
parenta199833e23147036edfcddfc3ab2752c7c20a686 (diff)
downloadzsh-088e8a9c8d19d0675bde3fabdde1b1e35129725b.tar.gz
zsh-088e8a9c8d19d0675bde3fabdde1b1e35129725b.zip
24434: handle unprintable and zero-width wide characters
by displaying as hex
Diffstat (limited to 'Src/Zle/zle_refresh.c')
-rw-r--r--Src/Zle/zle_refresh.c50
1 files changed, 45 insertions, 5 deletions
diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c
index cdda42287..3f3de2c68 100644
--- a/Src/Zle/zle_refresh.c
+++ b/Src/Zle/zle_refresh.c
@@ -447,6 +447,10 @@ zrefresh(void)
int tmpalloced; /* flag to free tmpline when finished */
int remetafy; /* flag that zle line is metafied */
struct rparams rpms;
+#ifdef MULTIBYTE_SUPPORT
+ int width; /* width of wide character */
+#endif
+
/* If this is called from listmatches() (indirectly via trashzle()), and *
* that was called from the end of zrefresh(), then we don't need to do *
@@ -633,8 +637,7 @@ zrefresh(void)
while ((++t0) & 7);
}
#ifdef MULTIBYTE_SUPPORT
- else if (iswprint(*t)) {
- int width = wcwidth(*t);
+ else if (iswprint(*t) && (width = wcwidth(*t)) > 0) {
if (width > rpms.sen - rpms.s) {
/*
* Too wide to fit. Insert spaces to end of current line.
@@ -649,7 +652,7 @@ zrefresh(void)
rpms.nvcs = rpms.s - nbuf[rpms.nvln = rpms.ln];
}
}
- if (width > rpms.sen - rpms.s) {
+ if (width > rpms.sen - rpms.s || width == 0) {
/*
* The screen width is too small to fit even one
* occurrence.
@@ -663,7 +666,11 @@ zrefresh(void)
}
}
#endif
- else if (ZC_icntrl(*t)) { /* other control character */
+ else if (ZC_icntrl(*t)
+#ifdef MULTIBYTE_SUPPORT
+ && (unsigned)*t <= 0xffU
+#endif
+ ) { /* other control character */
*rpms.s++ = ZWC('^');
if (rpms.s == rpms.sen) {
/* text wrapped */
@@ -671,9 +678,42 @@ zrefresh(void)
break;
}
*rpms.s++ = (((unsigned int)*t & ~0x80u) > 31) ? ZWC('?') : (*t | ZWC('@'));
- } else { /* normal character */
+ }
+#ifdef MULTIBYTE_SUPPORT
+ else {
+ /*
+ * Not printable or zero width.
+ * Resort to hackery.
+ */
+ char dispchars[11];
+ char *dispptr = dispchars;
+ wchar_t wc;
+
+ if ((unsigned)*t > 0xffffU) {
+ sprintf(dispchars, "<%.08x>", (unsigned)*t);
+ } else {
+ sprintf(dispchars, "<%.04x>", (unsigned)*t);
+ }
+ while (*dispptr) {
+ if (mbtowc(&wc, dispptr, 1) == 1 /* paranoia */)
+ {
+ *rpms.s++ = wc;
+ if (rpms.s == rpms.sen) {
+ /* text wrapped */
+ if (nextline(&rpms, 1))
+ break;
+ }
+ }
+ dispptr++;
+ }
+ if (*dispptr) /* nextline said stop processing */
+ break;
+ }
+#else
+ else { /* normal character */
*rpms.s++ = *t;
}
+#endif
if (rpms.s == rpms.sen) {
/* text wrapped */
if (nextline(&rpms, 1))