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:
parent
36c7a0a0b3
commit
2ccad2310e
@ -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) {
|
||||
|
11
Src/utils.c
11
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;
|
||||
}
|
||||
}
|
||||
|
13
Src/zsh.h
13
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
|
||||
|
Loading…
Reference in New Issue
Block a user