summaryrefslogtreecommitdiff
path: root/Src/Zle/complist.c
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2005-09-29 17:32:34 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2005-09-29 17:32:34 +0000
commit046f4cf49e1a082f78b0acadadae8855db5cb37e (patch)
tree1c4191795ecab9f349cadb17f9c60102ec1809e6 /Src/Zle/complist.c
parent6183db6faa0815f09267062769c602a1de3d9e81 (diff)
downloadzsh-046f4cf49e1a082f78b0acadadae8855db5cb37e.tar.gz
zsh-046f4cf49e1a082f78b0acadadae8855db5cb37e.zip
21784: Improved character widths for formatted multibyte character output
Diffstat (limited to 'Src/Zle/complist.c')
-rw-r--r--Src/Zle/complist.c182
1 files changed, 128 insertions, 54 deletions
diff --git a/Src/Zle/complist.c b/Src/Zle/complist.c
index 3c94ae11b..0b6601cea 100644
--- a/Src/Zle/complist.c
+++ b/Src/Zle/complist.c
@@ -548,22 +548,136 @@ clprintfmt(Listcols c, char *p, int ml)
return 0;
}
-/* Local version of nicezputs() with in-string colouring. */
+/*
+ * Local version of nicezputs() with in-string colouring
+ * and scrolling.
+ */
static int
-clnicezputs(Listcols c, char *s, int ml)
+clnicezputs(Listcols colors, char *s, int ml)
{
- int cc, i = 0, col = 0, ask, oml = ml;
+ int i = 0, col = 0, ask, oml = ml;
char *t;
+ ZLE_CHAR_T cc;
+#ifdef ZLE_UNICODE_SUPPORT
+ /*
+ * ums is the untokenized, unmetafied string (length umlen)
+ * uptr is a pointer into it
+ * sptr is the start of the nice character representation
+ * wptr is the point at which the wide character itself starts
+ * (but may be the end of the string if the character was fully
+ * prettified).
+ * ret is the return status from the conversion to a wide character
+ * umleft is the remaining length of the unmetafied string to output
+ * umlen is the full length of the unmetafied string
+ * width is the full printing width of a prettified character,
+ * including both ASCII prettification and the wide character itself.
+ * ps is the shift state of the conversion to wide characters.
+ */
+ char *ums, *uptr, *sptr, *wptr;
+ int ret, umleft, umlen, width;
+ mbstate_t ps;
- initiscol(c);
+ memset(&ps, 0, sizeof(ps));
+ ums = ztrdup(s);
+ untokenize(ums);
+ uptr = unmetafy(ums, &umlen);
+ umleft = umlen;
- while ((cc = *s++)) {
- doiscol(c, i++);
+ if (colors)
+ initiscol(colors);
+
+ while (umleft > 0) {
+ ret = mbrtowc(&cc, uptr, umleft, &ps);
+
+ if (ret <= 0)
+ {
+ /*
+ * Eek! Now we're stuffed. I'm just going to
+ * make this up... Note that this may also handle
+ * an input NULL, which we want to be a real character
+ * rather than terminator.
+ */
+ sptr = nicechar(*s);
+ /* everything here is ASCII... */
+ width = strlen(sptr);
+ wptr = sptr + width;
+ ret = 1;
+ }
+ else
+ {
+ sptr = wcs_nicechar(cc, &width, &wptr);
+ }
+
+ umleft -= ret;
+ uptr += ret;
+ if (colors) {
+ /*
+ * The code for the colo[u]ri[s/z]ation is obscure (surprised?)
+ * but if we do it for every input character, as we do in
+ * the simple case, we shouldn't go too far wrong.
+ */
+ while (ret--)
+ doiscol(colors, i++);
+ }
+
+ /*
+ * Loop over characters in the output of the nice
+ * representation. This will often correspond to one input
+ * (possibly multibyte) character.
+ */
+ for (t = sptr; *t; t++) {
+ /* Input is metafied... */
+ int nc = (*t == Meta) ? STOUC(*++t ^ 32) : STOUC(*t);
+ /* Is the screen full? */
+ if (ml == mlend - 1 && col == columns - 1) {
+ mlprinted = ml - oml;
+ return 0;
+ }
+ if (t < wptr) {
+ /* outputting ASCII, so single-width */
+ putc(nc, shout);
+ col++;
+ width--;
+ } else {
+ /* outputting a single wide character, do the lot */
+ putc(nc, shout);
+ /* don't check column until finished */
+ if (t[1])
+ continue;
+ /* now we've done the entire rest of the representation */
+ col += width;
+ }
+ /*
+ * There might be problems with characters of printing width
+ * greater than one here.
+ */
+ if (col >= columns) {
+ ml++;
+ if (mscroll && !--mrestlines && (ask = asklistscroll(ml))) {
+ mlprinted = ml - oml;
+ return ask;
+ }
+ col -= columns;
+ if (colors)
+ fputs(" \010", shout);
+ }
+ }
+ }
+
+ free(ums);
+#else
+
+ if (colors)
+ initiscol(colors);
+
+ while ((cc = *s)) {
+ if (colors)
+ doiscol(colors, i++);
if (itok(cc)) {
if (cc <= Comma)
cc = ztokens[cc - Pound];
- else
+ else
continue;
}
if (cc == Meta)
@@ -583,10 +697,12 @@ clnicezputs(Listcols c, char *s, int ml)
return ask;
}
col = 0;
- fputs(" \010", shout);
+ if (colors)
+ fputs(" \010", shout);
}
}
}
+#endif
mlprinted = ml - oml;
return 0;
}
@@ -959,46 +1075,6 @@ compzputs(char const *s, int ml)
return 0;
}
-/* This is like nicezputs(), but allows scrolling. */
-
-/**/
-static int
-compnicezputs(char *s, int ml)
-{
- int c, col = 0, ask, oml = ml;
- char *t;
-
- while ((c = *s++)) {
- if (itok(c)) {
- if (c <= Comma)
- c = ztokens[c - Pound];
- else
- continue;
- }
- if (c == Meta)
- c = *s++ ^ 32;
-
- for (t = nicechar(c); *t; t++) {
- int nc = (*t == Meta) ? STOUC(*++t ^ 32) : STOUC(*t);
- if (ml == mlend - 1 && col == columns - 1) {
- mlprinted = ml - oml;
- return 0;
- }
- putc(nc, shout);
- if (++col == columns) {
- ml++;
- if (mscroll && !--mrestlines && (ask = asklistscroll(ml))) {
- mlprinted = ml - oml;
- return ask;
- }
- col = 0;
- }
- }
- }
- mlprinted = ml - oml;
- return 0;
-}
-
/**/
static int
compprintlist(int showall)
@@ -1458,7 +1534,7 @@ clprintm(Cmgroup g, Cmatch *mp, int mc, int ml, int lastc, int width)
}
}
if (!dolist(ml)) {
- mlprinted = niceztrlen(m->disp ? m->disp : m->str) / columns;
+ mlprinted = ZMB_nicewidth(m->disp ? m->disp : m->str) / columns;
return 0;
}
if (m->gnum == mselect) {
@@ -1479,15 +1555,13 @@ clprintm(Cmgroup g, Cmatch *mp, int mc, int ml, int lastc, int width)
else
subcols = putmatchcol(&mcolors, g->name, (m->disp ? m->disp : m->str));
- if (subcols)
- ret = clnicezputs(&mcolors, (m->disp ? m->disp : m->str), ml);
- else
- ret = compnicezputs((m->disp ? m->disp : m->str), ml);
+ ret = clnicezputs(subcols ? &mcolors : NULL,
+ (m->disp ? m->disp : m->str), ml);
if (ret) {
zcoff();
return 1;
}
- len = niceztrlen(m->disp ? m->disp : m->str);
+ len = ZMB_nicewidth(m->disp ? m->disp : m->str);
mlprinted = len / columns;
if ((g->flags & CGF_FILES) && m->modec) {