summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--Src/Zle/complist.c73
-rw-r--r--Src/Zle/compresult.c37
-rw-r--r--Src/Zle/zle_tricky.c27
-rw-r--r--Src/utils.c11
-rw-r--r--Src/zsh.h13
6 files changed, 116 insertions, 51 deletions
diff --git a/ChangeLog b/ChangeLog
index 45cdc3731..d126bf235 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2006-08-11 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * 22599: Src/utils.c, Src/zsh.h, Src/Zle/complist.c,
+ Src/Zle/compresult.c, Src/Zle/zle_tricky.c: use wide character
+ widths in completion.
+
2006-08-10 Peter Stephenson <pws@csr.com>
* unposted: Doc/Zsh/compsys.yo: trivial typo.
diff --git a/Src/Zle/complist.c b/Src/Zle/complist.c
index c90af8480..d982b22ce 100644
--- a/Src/Zle/complist.c
+++ b/Src/Zle/complist.c
@@ -888,57 +888,78 @@ compprintfmt(char *fmt, int n, int dopr, int doesc, int ml, int *stop)
} else
fmt = mlistp;
}
- for (p = fmt; *p; p++) {
- int chr = (*p == Meta) ? *++p ^ 32 : *p;
- if (doesc && chr == '%') {
- chr = (*++p == Meta) ? *++p ^ 32 : *p;
- if (chr) {
+ MB_METACHARINIT();
+ for (p = fmt; *p; ) {
+ convchar_t cchar;
+ int len, width;
+
+ len = MB_METACHARLENCONV(p, &cchar);
+#ifdef MULTIBYTE_SUPPORT
+ if (cchar == WEOF) {
+ cchar = (wchar_t)p;
+ width = 1;
+ }
+ else
+#endif
+ width = WCWIDTH(cchar);
+
+ if (doesc && cchar == ZWC('%')) {
+ p += len;
+ if (*p) {
+ len = MB_METACHARLENCONV(p, &cchar);
+#ifdef MULTIBYTE_SUPPORT
+ if (cchar == WEOF)
+ cchar = (wchar_t)p;
+#endif
+ p += len;
+
m = 0;
- switch (chr) {
- case '%':
+ switch (cchar) {
+ case ZWC('%'):
if (dopr == 1)
putc('%', shout);
cc++;
break;
- case 'n':
+ case ZWC('n'):
if (!stat) {
sprintf(nc, "%d", n);
if (dopr == 1)
fputs(nc, shout);
+ /* everything here is ASCII... */
cc += strlen(nc);
}
break;
- case 'B':
+ case ZWC('B'):
b = 1;
if (dopr)
tcout(TCBOLDFACEBEG);
break;
- case 'b':
+ case ZWC('b'):
b = 0; m = 1;
if (dopr)
tcout(TCALLATTRSOFF);
break;
- case 'S':
+ case ZWC('S'):
s = 1;
if (dopr)
tcout(TCSTANDOUTBEG);
break;
- case 's':
+ case ZWC('s'):
s = 0; m = 1;
if (dopr)
tcout(TCSTANDOUTEND);
break;
- case 'U':
+ case ZWC('U'):
u = 1;
if (dopr)
tcout(TCUNDERLINEBEG);
break;
- case 'u':
+ case ZWC('u'):
u = 0; m = 1;
if (dopr)
tcout(TCUNDERLINEEND);
break;
- case '{':
+ case ZWC('{'):
for (p++; *p && (*p != '%' || p[1] != '}'); p++)
if (dopr)
putc(*p == Meta ? *++p ^ 32 : *p, shout);
@@ -947,14 +968,14 @@ compprintfmt(char *fmt, int n, int dopr, int doesc, int ml, int *stop)
else
p--;
break;
- case 'm':
+ case ZWC('m'):
if (stat) {
sprintf(nc, "%d/%d", (n ? mlastm : mselect),
listdat.nlist);
m = 2;
}
break;
- case 'M':
+ case ZWC('M'):
if (stat) {
sprintf(nbuf, "%d/%d", (n ? mlastm : mselect),
listdat.nlist);
@@ -962,20 +983,20 @@ compprintfmt(char *fmt, int n, int dopr, int doesc, int ml, int *stop)
m = 2;
}
break;
- case 'l':
+ case ZWC('l'):
if (stat) {
sprintf(nc, "%d/%d", ml + 1, listdat.nlines);
m = 2;
}
break;
- case 'L':
+ case ZWC('L'):
if (stat) {
sprintf(nbuf, "%d/%d", ml + 1, listdat.nlines);
sprintf(nc, "%-9s", nbuf);
m = 2;
}
break;
- case 'p':
+ case ZWC('p'):
if (stat) {
if (ml == listdat.nlines - 1)
strcpy(nc, "Bottom");
@@ -987,7 +1008,7 @@ compprintfmt(char *fmt, int n, int dopr, int doesc, int ml, int *stop)
m = 2;
}
break;
- case 'P':
+ case ZWC('P'):
if (stat) {
if (ml == listdat.nlines - 1)
strcpy(nc, "Bottom");
@@ -1001,6 +1022,7 @@ compprintfmt(char *fmt, int n, int dopr, int doesc, int ml, int *stop)
break;
}
if (m == 2 && dopr == 1) {
+ /* nc only contains ASCII text */
int l = strlen(nc);
if (l + cc > columns - 2)
@@ -1018,9 +1040,11 @@ compprintfmt(char *fmt, int n, int dopr, int doesc, int ml, int *stop)
} else
break;
} else {
- if ((++cc == columns - 2 || chr == '\n') && stat)
+ cc += width;
+
+ if ((cc >= columns - 2 || cchar == ZWC('\n')) && stat)
dopr = 2;
- if (chr == '\n') {
+ if (cchar == ZWC('\n')) {
if (dopr == 1 && mlbeg >= 0 && tccan(TCCLEAREOL))
tcout(TCCLEAREOL);
l += 1 + ((cc - 1) / columns);
@@ -1031,7 +1055,8 @@ compprintfmt(char *fmt, int n, int dopr, int doesc, int ml, int *stop)
dopr = 0;
continue;
}
- putc(chr, shout);
+ while (len--)
+ putc(*p++, shout);
if ((beg = !(cc % columns)) && !stat) {
ml++;
fputs(" \010", shout);
diff --git a/Src/Zle/compresult.c b/Src/Zle/compresult.c
index e3adc0803..e28212c19 100644
--- a/Src/Zle/compresult.c
+++ b/Src/Zle/compresult.c
@@ -573,7 +573,7 @@ unambig_data(int *cp, char **pp, char **ip)
return scache;
}
-/* Insert the given match. This returns the number of characters inserted.
+/* Insert the given match. This returns the number of bytes inserted.
* scs is used to return the position where a automatically created suffix
* has to be inserted. */
@@ -986,7 +986,12 @@ do_single(Cmatch m)
if (m->suf) {
havesuff = 1;
- minfo.insc = ztrlen(m->suf);
+ /*
+ * This strlen(0 got converted to a ztrlen(), but I don't
+ * think that's correct since it's dealing with raw bytes,
+ * right?
+ */
+ minfo.insc = strlen(m->suf);
minfo.len -= minfo.insc;
if (minfo.we) {
minfo.end += minfo.insc;
@@ -1466,7 +1471,7 @@ calclist(int showall)
/* We have an ylist, lets see, if it contains newlines. */
hidden = 1;
while (!nl && *pp) {
- if (ztrlen(*pp) >= columns)
+ if (MB_METASTRWIDTH(*pp) >= columns)
nl = 1;
else
nl = !!strchr(*pp++, '\n');
@@ -1479,12 +1484,16 @@ calclist(int showall)
g->flags |= CGF_LINES;
hidden = 1;
while ((sptr = *pp)) {
- while (sptr && *sptr) {
- /* TODO: we need to use wcwidth() here */
- nlines += (nlptr = strchr(sptr, '\n'))
- ? 1 + (nlptr - sptr - 1) / columns
- : (ztrlen(sptr) - 1) / columns;
- sptr = nlptr ? nlptr+1 : NULL;
+ while (*sptr) {
+ if ((nlptr = strchr(sptr, '\n'))) {
+ *nlptr = '\0';
+ nlines += 1 + (MB_METASTRWIDTH(sptr)-1) / columns;
+ *nlptr = '\n';
+ sptr = nlptr + 1;
+ } else {
+ nlines += (MB_METASTRWIDTH(sptr)-1) / columns;
+ break;
+ }
}
nlines++;
pp++;
@@ -1492,7 +1501,7 @@ calclist(int showall)
/*** nlines--; */
} else {
while (*pp) {
- l = ztrlen(*pp);
+ l = MB_METASTRWIDTH(*pp);
ndisp++;
if (l > glong)
glong = l;
@@ -1605,7 +1614,7 @@ calclist(int showall)
g->width = 1;
while (*pp)
- glines += 1 + (ztrlen(*pp++) / columns);
+ glines += 1 + (MB_METASTRWIDTH(*pp++) / columns);
}
}
} else {
@@ -1648,7 +1657,7 @@ calclist(int showall)
VARARR(int, ylens, yl);
for (i = 0; *pp; i++, pp++)
- ylens[i] = ztrlen(*pp) + CM_SPACE;
+ ylens[i] = MB_METASTRWIDTH(*pp) + CM_SPACE;
if (g->flags & CGF_ROWS) {
int nth, tcol, len;
@@ -1954,7 +1963,7 @@ printlist(int over, CLPrintFunc printm, int showall)
while ((p = *pp++)) {
zputs(p, shout);
if (*pp) {
- if (ztrlen(p) % columns)
+ if (MB_METASTRWIDTH(p) % columns)
putc('\n', shout);
else
fputs(" \010", shout);
@@ -1976,7 +1985,7 @@ printlist(int over, CLPrintFunc printm, int showall)
zputs(*pq, shout);
if (i) {
a = (g->widths ? g->widths[mc] : g->width) -
- strlen(*pq);
+ MB_METASTRWIDTH(*pq);
while (a--)
putc(' ', shout);
}
diff --git a/Src/Zle/zle_tricky.c b/Src/Zle/zle_tricky.c
index fbe04ca5d..50c4a50da 100644
--- a/Src/Zle/zle_tricky.c
+++ b/Src/Zle/zle_tricky.c
@@ -2072,9 +2072,9 @@ printfmt(char *fmt, int n, int dopr, int doesc)
char *p = fmt, nc[DIGBUFSIZE];
int l = 0, cc = 0, b = 0, s = 0, u = 0, m;
- for (; *p; p++) {
+ MB_METACHARINIT();
+ for (; *p; ) {
/* Handle the `%' stuff (%% == %, %n == <number of matches>). */
- /* TODO: we need to use wcwidth() to count cc */
if (doesc && *p == '%') {
if (*++p) {
m = 0;
@@ -2088,7 +2088,7 @@ printfmt(char *fmt, int n, int dopr, int doesc)
sprintf(nc, "%d", n);
if (dopr)
fprintf(shout, nc);
- cc += strlen(nc);
+ cc += MB_METASTRWIDTH(nc);
break;
case 'B':
b = 1;
@@ -2140,9 +2140,10 @@ printfmt(char *fmt, int n, int dopr, int doesc)
}
} else
break;
+ p++;
} else {
- cc++;
if (*p == '\n') {
+ cc++;
if (dopr) {
if (tccan(TCCLEAREOL))
tcout(TCCLEAREOL);
@@ -2155,12 +2156,20 @@ printfmt(char *fmt, int n, int dopr, int doesc)
}
l += 1 + ((cc - 1) / columns);
cc = 0;
+ putc('\n', shout);
+ p++;
+ } else {
+ convchar_t cchar;
+ int clen = MB_METACHARLENCONV(p, &cchar);
+ if (dopr) {
+ while (clen--)
+ putc(*p++, shout);
+ } else
+ p += clen;
+ cc += WCWIDTH(cchar);
+ if (dopr && !(cc % columns))
+ fputs(" \010", shout);
}
- if (dopr) {
- putc(*p, shout);
- if (!(cc % columns))
- fputs(" \010", shout);
- }
}
}
if (dopr) {
diff --git a/Src/utils.c b/Src/utils.c
index 8fdf2c0ab..2bfae667c 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -3937,11 +3937,13 @@ mb_metacharlenconv(const char *s, wint_t *wcp)
* Total number of multibyte characters in metafied string s.
* Same answer as iterating mb_metacharlen() and counting calls
* until end of string.
+ *
+ * If width is 1, return total character width rather than number.
*/
/**/
int
-mb_metastrlen(char *ptr)
+mb_metastrlen(char *ptr, int width)
{
char inchar, *laststart;
size_t ret;
@@ -3971,9 +3973,12 @@ mb_metastrlen(char *ptr)
/* Reset, treat as single character */
memset(&mb_shiftstate, 0, sizeof(mb_shiftstate));
ptr = laststart + (*laststart == Meta) + 1;
- }
+ num++;
+ } else if (width)
+ num += wcwidth(wc);
+ else
+ num++;
laststart = ptr;
- num++;
num_in_char = 0;
}
}
diff --git a/Src/zsh.h b/Src/zsh.h
index 25399b9d9..3c455b939 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -1928,7 +1928,15 @@ typedef char *(*ZleGetLineFn) _((int *, int *));
typedef wint_t convchar_t;
#define MB_METACHARLENCONV(str, cp) mb_metacharlenconv((str), (cp))
#define MB_METACHARLEN(str) mb_metacharlenconv(str, NULL)
-#define MB_METASTRLEN(str) mb_metastrlen(str)
+#define MB_METASTRLEN(str) mb_metastrlen(str, 0)
+#define MB_METASTRWIDTH(str) mb_metastrlen(str, 1)
+
+/*
+ * Note WCWIDTH() takes wint_t, typically as a convchar_t.
+ * It's written to use the wint_t from mb_metacharlenconv() without
+ * further tests.
+ */
+#define WCWIDTH(wc) ((wc == WEOF) ? 1 : wcwidth(wc))
#define MB_INCOMPLETE ((size_t)-2)
#define MB_INVALID ((size_t)-1)
@@ -1954,6 +1962,9 @@ typedef int convchar_t;
#define MB_METACHARLENCONV(str, cp) metacharlenconv((str), (cp))
#define MB_METACHARLEN(str) (*(str) == Meta ? 2 : 1)
#define MB_METASTRLEN(str) ztrlen(str)
+#define MB_METASTRWIDTH(str) ztrlen(str)
+
+#define WCWIDTH(c) (1)
/* Leave character or string as is. */
#define ZWC(c) c