1
0
mirror of git://git.code.sf.net/p/zsh/code synced 2024-09-25 05:27:12 +02:00

rationalise widths of non-printing characters to zero.

This commit is contained in:
Peter Stephenson 2010-03-27 19:04:35 +00:00
parent 691be6d0fc
commit 815cc9fc0d
4 changed files with 81 additions and 35 deletions

View File

@ -1,3 +1,9 @@
2010-03-26 Peter Stephenson <p.w.stephenson@ntlworld.com>
* 27831: Doc/Zsh/expn.yo, Src/input.c, Src/subst.c, Src/utils.c:
add ${(mm)...} to count displayed characters and rationalise use
of wcwidth so that negative numbers are treated as zero.
2010-03-25 Peter Stephenson <pws@csr.com>
* unposted: Test/A02alias.ztst: change sort to cat to
@ -12968,5 +12974,5 @@
*****************************************************
* This is used by the shell to define $ZSH_PATCHLEVEL
* $Revision: 1.4945 $
* $Revision: 1.4946 $
*****************************************************

View File

@ -1004,6 +1004,14 @@ calculating the how much of the string it occupies or the overall
length of the string. Most printable characters have a width of one
unit, however certain Asian character sets and certain special effects
use wider characters; combining characters have zero width.
Non-printable characters are arbitrarily counted as zero width; how they
would actually be displayed will vary.
If the tt(m) is repeated, the character either counts zero (if it has
zero width), else one. For printable character strings this has the
effect of counting the number of glyphs (visibly separate characters),
except for the case where combining characters themselves have non-zero
width (true in certain alphabets).
)
item(tt(r:)var(expr)tt(::)var(string1)tt(::)var(string2)tt(:))(
As tt(l), but pad the words on the right and insert var(string2)

View File

@ -675,6 +675,40 @@ strcatsub(char **d, char *pb, char *pe, char *src, int l, char *s, int glbsub,
return dest;
}
#ifdef MULTIBYTE_SUPPORT
#define WCPADWIDTH(cchar, mw) wcpadwidth(cchar, mw)
/*
* Width of character for padding purposes.
* 0: all characters count 1.
* 1: use width of multibyte character.
* 2: non-zero width characters count 1, zero width 0.
*/
static int
wcpadwidth(wchar_t wc, int multi_width)
{
int width;
switch (multi_width)
{
case 0:
return 1;
case 1:
width = WCWIDTH(wc);
if (width >= 0)
return width;
return 0;
default:
return WCWIDTH(wc) > 0 ? 1 : 0;
}
}
#else
#define WCPADWIDTH(cchar, mw) (1)
#endif
/*
* Pad the string str, returning a result from the heap (or str itself,
* if it didn't need padding). If str is too large, it will be truncated.
@ -703,12 +737,6 @@ dopadding(char *str, int prenum, int postnum, char *preone, char *postone,
#endif
)
{
#ifdef MULTIBYTE_SUPPORT
#define WCPADWIDTH(cchar) (multi_width ? WCWIDTH(cchar) : 1)
#else
#define WCPADWIDTH(cchar) (1)
#endif
char *def, *ret, *t, *r;
int ls, ls2, lpreone, lpostone, lpremul, lpostmul, lr, f, m, c, cc, cl;
convchar_t cchar;
@ -775,14 +803,14 @@ dopadding(char *str, int prenum, int postnum, char *preone, char *postone,
MB_METACHARINIT();
while (f > 0) {
str += MB_METACHARLENCONV(str, &cchar);
f -= WCPADWIDTH(cchar);
f -= WCPADWIDTH(cchar, multi_width);
}
/* Now finish the first half. */
for (c = prenum; c > 0; ) {
cl = MB_METACHARLENCONV(str, &cchar);
while (cl--)
*r++ = *str++;
c -= WCPADWIDTH(cchar);
c -= WCPADWIDTH(cchar, multi_width);
}
} else {
if (f <= lpreone) {
@ -796,7 +824,7 @@ dopadding(char *str, int prenum, int postnum, char *preone, char *postone,
/* So skip. */
for (t = preone; f > 0; ) {
t += MB_METACHARLENCONV(t, &cchar);
f -= WCPADWIDTH(cchar);
f -= WCPADWIDTH(cchar, multi_width);
}
/* Then copy the entire remainder. */
while (*t)
@ -814,7 +842,7 @@ dopadding(char *str, int prenum, int postnum, char *preone, char *postone,
m = lpremul - m;
for (t = premul; m > 0; ) {
t += MB_METACHARLENCONV(t, &cchar);
m -= WCPADWIDTH(cchar);
m -= WCPADWIDTH(cchar, multi_width);
}
/* Output the rest. */
while (*t)
@ -827,7 +855,7 @@ dopadding(char *str, int prenum, int postnum, char *preone, char *postone,
cl = MB_METACHARLENCONV(t, &cchar);
while (cl--)
*r++ = *t++;
c -= WCPADWIDTH(cchar);
c -= WCPADWIDTH(cchar, multi_width);
}
}
}
@ -840,7 +868,7 @@ dopadding(char *str, int prenum, int postnum, char *preone, char *postone,
/* Output the first half width of the original string. */
for (c = ls2; c > 0; ) {
cl = MB_METACHARLENCONV(str, &cchar);
c -= WCPADWIDTH(cchar);
c -= WCPADWIDTH(cchar, multi_width);
while (cl--)
*r++ = *str++;
}
@ -854,7 +882,7 @@ dopadding(char *str, int prenum, int postnum, char *preone, char *postone,
MB_METACHARINIT();
for (c = postnum; c > 0; ) {
cl = MB_METACHARLENCONV(str, &cchar);
c -= WCPADWIDTH(cchar);
c -= WCPADWIDTH(cchar, multi_width);
while (cl--)
*r++ = *str++;
}
@ -867,7 +895,7 @@ dopadding(char *str, int prenum, int postnum, char *preone, char *postone,
/* Can't fit unrepeated string, truncate it */
for (c = f; c > 0; ) {
cl = MB_METACHARLENCONV(postone, &cchar);
c -= WCPADWIDTH(cchar);
c -= WCPADWIDTH(cchar, multi_width);
while (cl--)
*r++ = *postone++;
}
@ -890,7 +918,7 @@ dopadding(char *str, int prenum, int postnum, char *preone, char *postone,
MB_METACHARINIT();
while (m > 0) {
cl = MB_METACHARLENCONV(postmul, &cchar);
m -= WCPADWIDTH(cchar);
m -= WCPADWIDTH(cchar, multi_width);
while (cl--)
*r++ = *postmul++;
}
@ -914,14 +942,14 @@ dopadding(char *str, int prenum, int postnum, char *preone, char *postone,
MB_METACHARINIT();
while (f > 0) {
str += MB_METACHARLENCONV(str, &cchar);
f -= WCPADWIDTH(cchar);
f -= WCPADWIDTH(cchar, multi_width);
}
/* Copy the rest of the original string */
for (c = prenum; c > 0; ) {
cl = MB_METACHARLENCONV(str, &cchar);
while (cl--)
*r++ = *str++;
c -= WCPADWIDTH(cchar);
c -= WCPADWIDTH(cchar, multi_width);
}
} else {
/*
@ -942,7 +970,7 @@ dopadding(char *str, int prenum, int postnum, char *preone, char *postone,
MB_METACHARINIT();
for (t = preone; f > 0; ) {
t += MB_METACHARLENCONV(t, &cchar);
f -= WCPADWIDTH(cchar);
f -= WCPADWIDTH(cchar, multi_width);
}
/* Copy the rest of preone */
while (*t)
@ -966,14 +994,14 @@ dopadding(char *str, int prenum, int postnum, char *preone, char *postone,
MB_METACHARINIT();
for (t = premul; m > 0; ) {
t += MB_METACHARLENCONV(t, &cchar);
m -= WCPADWIDTH(cchar);
m -= WCPADWIDTH(cchar, multi_width);
}
/* Now the rest of the repeated string. */
while (c > 0) {
cl = MB_METACHARLENCONV(t, &cchar);
while (cl--)
*r++ = *t++;
c -= WCPADWIDTH(cchar);
c -= WCPADWIDTH(cchar, multi_width);
}
}
for (cc = f / lpremul; cc--;) {
@ -985,7 +1013,7 @@ dopadding(char *str, int prenum, int postnum, char *preone, char *postone,
cl = MB_METACHARLENCONV(t, &cchar);
while (cl--)
*r++ = *t++;
c -= WCPADWIDTH(cchar);
c -= WCPADWIDTH(cchar, multi_width);
}
}
}
@ -1023,7 +1051,7 @@ dopadding(char *str, int prenum, int postnum, char *preone, char *postone,
cl = MB_METACHARLENCONV(str, &cchar);
while (cl--)
*r++ = *str++;
c -= WCPADWIDTH(cchar);
c -= WCPADWIDTH(cchar, multi_width);
}
} else {
/*
@ -1035,7 +1063,7 @@ dopadding(char *str, int prenum, int postnum, char *preone, char *postone,
cl = MB_METACHARLENCONV(str, &cchar);
while (cl--)
*r++ = *str++;
c -= WCPADWIDTH(cchar);
c -= WCPADWIDTH(cchar, multi_width);
}
MB_METACHARINIT();
if (f <= lpostone) {
@ -1048,7 +1076,7 @@ dopadding(char *str, int prenum, int postnum, char *preone, char *postone,
cl = MB_METACHARLENCONV(postone, &cchar);
while (cl--)
*r++ = *postone++;
c -= WCPADWIDTH(cchar);
c -= WCPADWIDTH(cchar, multi_width);
}
}
} else {
@ -1059,7 +1087,7 @@ dopadding(char *str, int prenum, int postnum, char *preone, char *postone,
cl = MB_METACHARLENCONV(postone, &cchar);
while (cl--)
*r++ = *postone++;
c -= WCPADWIDTH(cchar);
c -= WCPADWIDTH(cchar, multi_width);
}
}
if (lpostmul) {
@ -1070,7 +1098,7 @@ dopadding(char *str, int prenum, int postnum, char *preone, char *postone,
cl = MB_METACHARLENCONV(t, &cchar);
while (cl--)
*r++ = *t++;
c -= WCPADWIDTH(cchar);
c -= WCPADWIDTH(cchar, multi_width);
}
}
/*
@ -1083,7 +1111,7 @@ dopadding(char *str, int prenum, int postnum, char *preone, char *postone,
cl = MB_METACHARLENCONV(postmul, &cchar);
while (cl--)
*r++ = *postmul++;
m -= WCPADWIDTH(cchar);
m -= WCPADWIDTH(cchar, multi_width);
}
}
}
@ -1782,7 +1810,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
case 'm':
#ifdef MULTIBYTE_SUPPORT
multi_width = 1;
multi_width++;
#endif
break;

View File

@ -4406,6 +4406,8 @@ mb_metacharlenconv(const char *s, wint_t *wcp)
* until end of string.
*
* If width is 1, return total character width rather than number.
* If width is greater than 1, return 1 if character has non-zero width,
* else 0.
*/
/**/
@ -4444,13 +4446,15 @@ mb_metastrlen(char *ptr, int width)
} else if (width) {
/*
* Returns -1 if not a printable character. We
* turn this into 1 for backward compatibility.
* turn this into 0.
*/
int wcw = WCWIDTH(wc);
if (wcw >= 0)
num += wcw;
else
num++;
if (wcw > 0) {
if (width == 1)
num += wcw;
else
num++;
}
} else
num++;
laststart = ptr;
@ -5859,8 +5863,8 @@ privasserted(void)
cap_free(caps);
return 1;
}
cap_free(caps);
}
cap_free(caps);
}
#endif /* HAVE_CAP_GET_PROC */
return 0;