1
0
mirror of git://git.code.sf.net/p/zsh/code synced 2024-09-28 15:01:21 +02:00

22599: use wide character widths in completion

This commit is contained in:
Peter Stephenson 2006-08-11 21:30:38 +00:00
parent 36c7a0a0b3
commit 2ccad2310e
6 changed files with 116 additions and 51 deletions

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

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

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

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

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

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