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:
parent
691be6d0fc
commit
815cc9fc0d
@ -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 $
|
||||
*****************************************************
|
||||
|
@ -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)
|
||||
|
84
Src/subst.c
84
Src/subst.c
@ -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;
|
||||
|
||||
|
16
Src/utils.c
16
Src/utils.c
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user