Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

PATCH: padding, again



This makes padding use character numbers rather than widths by default
(so this is basically the old system, except that multibyte characters
are respected),  and adds the flag (m) to use widths of multibyte
characters.  It needs better testing but it's not completely broken, so
here it is.

Index: Doc/Zsh/expn.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/expn.yo,v
retrieving revision 1.70
diff -u -r1.70 expn.yo
--- Doc/Zsh/expn.yo	15 Sep 2006 13:17:27 -0000	1.70
+++ Doc/Zsh/expn.yo	19 Sep 2006 16:36:35 -0000
@@ -869,11 +869,23 @@
 once directly to the left of each word, truncated if necessary, before
 var(string1) is used to produce any remaining padding.
 
-If the tt(MULTIBYTE) option is in effect, screen character widths will
-be used for the calculation of padding; otherwise individual bytes are
-treat as occupying one unit of width.  Control characters are always
-assumed to be one unit wide; this allows the mechanism to be used
-for generating repetitions of control characters.
+If the tt(MULTIBYTE) option is in effect, the flag tt(m) may also
+be given, in which case widths will be used for the calculation of
+padding; otherwise individual multibyte characters are treated as occupying
+one unit of width.
+
+IF the tt(MULTIBYTE) option is not in effect, each byte in the string is
+treated as occupying one unit of width.
+
+Control characters are always assumed to be one unit wide; this allows the
+mechanism to be used for generating repetitions of control characters.
+)
+item(tt(m))(
+Only useful together with tt(l) and tt(r) when the tt(MULTIBYTE) option
+is in effect.  Use the character width reported by the system in
+calculating the how much of the string it occupies.  Most printable
+characters have a width of one unit, however certain Asian character sets
+and certain special effects use wider characters.
 )
 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)
Index: Src/subst.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/subst.c,v
retrieving revision 1.60
diff -u -r1.60 subst.c
--- Src/subst.c	15 Sep 2006 13:17:27 -0000	1.60
+++ Src/subst.c	19 Sep 2006 16:36:36 -0000
@@ -738,11 +738,20 @@
  * will be used.
  */
 
-/**/
 static char *
 dopadding(char *str, int prenum, int postnum, char *preone, char *postone,
-	  char *premul, char *postmul)
+	  char *premul, char *postmul
+#ifdef MULTIBYTE_SUPPORT
+	  , int multi_width
+#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;
@@ -761,11 +770,11 @@
     if (!postmul || !*postmul)
 	postmul = def;
 
-    ls = MB_METASTRWIDTH(str);
-    lpreone = preone ? MB_METASTRWIDTH(preone) : 0;
-    lpostone = postone ? MB_METASTRWIDTH(postone) : 0;
-    lpremul = MB_METASTRWIDTH(premul);
-    lpostmul = MB_METASTRWIDTH(postmul);
+    ls = MB_METASTRLEN2(str, multi_width);
+    lpreone = preone ? MB_METASTRLEN2(preone, multi_width) : 0;
+    lpostone = postone ? MB_METASTRLEN2(postone, multi_width) : 0;
+    lpremul = MB_METASTRLEN2(premul, multi_width);
+    lpostmul = MB_METASTRLEN2(postmul, multi_width);
 
     if (prenum + postnum == ls)
 	return str;
@@ -808,14 +817,14 @@
 		MB_METACHARINIT();
 		while (f > 0) {
 		    str += MB_METACHARLENCONV(str, &cchar);
-		    f -= WCWIDTH(cchar);
+		    f -= WCPADWIDTH(cchar);
 		}
 		/* Now finish the first half. */
 		for (c = prenum; c > 0; ) {
 		    cl = MB_METACHARLENCONV(str, &cchar);
 		    while (cl--)
 			*r++ = *str++;
-		    c -= WCWIDTH(cchar);
+		    c -= WCPADWIDTH(cchar);
 		}
 	    } else {
 		if (f <= lpreone) {
@@ -829,7 +838,7 @@
 			/* So skip. */
 			for (t = preone; f > 0; ) {
 			    t += MB_METACHARLENCONV(t, &cchar);
-			    f -= WCWIDTH(cchar);
+			    f -= WCPADWIDTH(cchar);
 			}
 			/* Then copy the entire remainder. */
 			while (*t)
@@ -847,7 +856,7 @@
 			    m = lpremul - m;
 			    for (t = premul; m > 0; ) {
 				t += MB_METACHARLENCONV(t, &cchar);
-				m -= WCWIDTH(cchar);
+				m -= WCPADWIDTH(cchar);
 			    }
 			    /* Output the rest. */
 			    while (*t)
@@ -860,7 +869,7 @@
 				cl = MB_METACHARLENCONV(t, &cchar);
 				while (cl--)
 				    *r++ = *t++;
-				c -= WCWIDTH(cchar);
+				c -= WCPADWIDTH(cchar);
 			    }
 			}
 		    }
@@ -873,7 +882,7 @@
 		/* Output the first half width of the original string. */
 		for (c = ls2; c > 0; ) {
 		    cl = MB_METACHARLENCONV(str, &cchar);
-		    c -= WCWIDTH(cchar);
+		    c -= WCPADWIDTH(cchar);
 		    while (cl--)
 			*r++ = *str++;
 		}
@@ -887,7 +896,7 @@
 		MB_METACHARINIT();
 		for (c = postnum; c > 0; ) {
 		    cl = MB_METACHARLENCONV(str, &cchar);
-		    c -= WCWIDTH(cchar);
+		    c -= WCPADWIDTH(cchar);
 		    while (cl--)
 			*r++ = *str++;
 		}
@@ -900,7 +909,7 @@
 			/* Can't fit unrepeated string, truncate it */
 			for (c = f; c > 0; ) {
 			    cl = MB_METACHARLENCONV(postone, &cchar);
-			    c -= WCWIDTH(cchar);
+			    c -= WCPADWIDTH(cchar);
 			    while (cl--)
 				*r++ = *postone++;
 			}
@@ -923,7 +932,7 @@
 			    MB_METACHARINIT();
 			    while (m > 0) {
 				cl = MB_METACHARLENCONV(postmul, &cchar);
-				m -= WCWIDTH(cchar);
+				m -= WCPADWIDTH(cchar);
 				while (cl--)
 				    *r++ = *postmul++;
 			    }
@@ -947,14 +956,14 @@
 		MB_METACHARINIT();
 		while (f > 0) {
 		    str += MB_METACHARLENCONV(str, &cchar);
-		    f -= WCWIDTH(cchar);
+		    f -= WCPADWIDTH(cchar);
 		}
 		/* Copy the rest of the original string */
 		for (c = prenum; c > 0; ) {
 		    cl = MB_METACHARLENCONV(str, &cchar);
 		    while (cl--)
 			*r++ = *str++;
-		    c -= WCWIDTH(cchar);
+		    c -= WCPADWIDTH(cchar);
 		}
 	    } else {
 		/*
@@ -975,7 +984,7 @@
 			MB_METACHARINIT();
 			for (t = preone; f > 0; ) {
 			    t += MB_METACHARLENCONV(t, &cchar);
-			    f -= WCWIDTH(cchar);
+			    f -= WCPADWIDTH(cchar);
 			}
 			/* Copy the rest of preone */
 			while (*t)
@@ -999,14 +1008,14 @@
 			    MB_METACHARINIT();
 			    for (t = premul; m > 0; ) {
 				t += MB_METACHARLENCONV(t, &cchar);
-				m -= WCWIDTH(cchar);
+				m -= WCPADWIDTH(cchar);
 			    }
 			    /* Now the rest of the repeated string. */
 			    while (c > 0) {
 				cl = MB_METACHARLENCONV(t, &cchar);
 				while (cl--)
 				    *r++ = *t++;
-				c -= WCWIDTH(cchar);
+				c -= WCPADWIDTH(cchar);
 			    }
 			}
 			for (cc = f / lpremul; cc--;) {
@@ -1018,7 +1027,7 @@
 				cl = MB_METACHARLENCONV(t, &cchar);
 				while (cl--)
 				    *r++ = *t++;
-				c -= WCWIDTH(cchar);
+				c -= WCPADWIDTH(cchar);
 			    }
 			}
 		    }
@@ -1056,7 +1065,7 @@
 		cl = MB_METACHARLENCONV(str, &cchar);
 		while (cl--)
 		    *r++ = *str++;
-		c -= WCWIDTH(cchar);
+		c -= WCPADWIDTH(cchar);
 	    }
 	} else {
 	    /*
@@ -1068,7 +1077,7 @@
 		cl = MB_METACHARLENCONV(str, &cchar);
 		while (cl--)
 		    *r++ = *str++;
-		c -= WCWIDTH(cchar);
+		c -= WCPADWIDTH(cchar);
 	    }
 	    MB_METACHARINIT();
 	    if (f <= lpostone) {
@@ -1081,7 +1090,7 @@
 			cl = MB_METACHARLENCONV(postone, &cchar);
 			while (cl--)
 			    *r++ = *postone++;
-			c -= WCWIDTH(cchar);
+			c -= WCPADWIDTH(cchar);
 		    }
 		}
 	    } else {
@@ -1092,7 +1101,7 @@
 			cl = MB_METACHARLENCONV(postone, &cchar);
 			while (cl--)
 			    *r++ = *postone++;
-			c -= WCWIDTH(cchar);
+			c -= WCPADWIDTH(cchar);
 		    }
 		}
 		if (lpostmul) {
@@ -1103,7 +1112,7 @@
 			    cl = MB_METACHARLENCONV(t, &cchar);
 			    while (cl--)
 				*r++ = *t++;
-			    c -= WCWIDTH(cchar);
+			    c -= WCPADWIDTH(cchar);
 			}
 		    }
 		    /*
@@ -1116,7 +1125,7 @@
 			    cl = MB_METACHARLENCONV(postmul, &cchar);
 			    while (cl--)
 				*r++ = *postmul++;
-			    m -= WCWIDTH(cchar);
+			    m -= WCPADWIDTH(cchar);
 			}
 		    }
 		}
@@ -1414,6 +1423,10 @@
     char *replstr = NULL;
     /* The numbers for (l) and (r) */
     zlong prenum = 0, postnum = 0;
+#ifdef MULTIBYTE_SUPPORT
+    /* The (m) flag: use width of multibyte characters */
+    int multi_width = 1;
+#endif
     /*
      * Whether the value has been copied.  Optimisation:  if we
      * are modifying an expression, we only need to copy it the
@@ -1702,6 +1715,12 @@
 		    s = t;
 		    break;
 
+		case 'm':
+#ifdef MULTIBYTE_SUPPORT
+		    multi_width = 1;
+#endif
+		    break;
+
 		case 'p':
 		    escapes = 1;
 		    break;
@@ -3048,7 +3067,11 @@
 	    while ((x = *aval++)) {
 		if (prenum || postnum)
 		    x = dopadding(x, prenum, postnum, preone, postone,
-				  premul, postmul);
+				  premul, postmul
+#ifdef MULTIBYTE_SUPPORT
+				  , multi_width
+#endif
+			);
 		if (eval && subst_parse_str(&x, (qt && !nojoin), quoteerr))
 		    return NULL;
 		xlen = strlen(x);
@@ -3092,7 +3115,11 @@
 	    x = aval[0];
 	    if (prenum || postnum)
 		x = dopadding(x, prenum, postnum, preone, postone,
-			      premul, postmul);
+			      premul, postmul
+#ifdef MULTIBYTE_SUPPORT
+			      , multi_width
+#endif
+		    );
 	    if (eval && subst_parse_str(&x, (qt && !nojoin), quoteerr))
 		return NULL;
 	    xlen = strlen(x);
@@ -3107,7 +3134,11 @@
 		x = aval[i++];
 		if (prenum || postnum)
 		    x = dopadding(x, prenum, postnum, preone, postone,
-				  premul, postmul);
+				  premul, postmul
+#ifdef MULTIBYTE_SUPPORT
+				  , multi_width
+#endif
+			);
 		if (eval && subst_parse_str(&x, (qt && !nojoin), quoteerr))
 		    return NULL;
 		if (qt && !*x && isarr != 2)
@@ -3123,7 +3154,11 @@
 	    x = aval[i];
 	    if (prenum || postnum)
 		x = dopadding(x, prenum, postnum, preone, postone,
-			      premul, postmul);
+			      premul, postmul
+#ifdef MULTIBYTE_SUPPORT
+			      , multi_width
+#endif
+		    );
 	    if (eval && subst_parse_str(&x, (qt && !nojoin), quoteerr))
 		return NULL;
 	    xlen = strlen(x);
@@ -3147,7 +3182,11 @@
 	x = val;
 	if (prenum || postnum)
 	    x = dopadding(x, prenum, postnum, preone, postone,
-			  premul, postmul);
+			  premul, postmul
+#ifdef MULTIBYTE_SUPPORT
+			  , multi_width
+#endif
+		);
 	if (eval && subst_parse_str(&x, (qt && !nojoin), quoteerr))
 	    return NULL;
 	xlen = strlen(x);
Index: Src/zsh.h
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/zsh.h,v
retrieving revision 1.99
diff -u -r1.99 zsh.h
--- Src/zsh.h	17 Sep 2006 19:28:46 -0000	1.99
+++ Src/zsh.h	19 Sep 2006 16:36:37 -0000
@@ -2008,6 +2008,7 @@
 #define MB_METACHARLEN(str)	mb_metacharlenconv(str, NULL)
 #define MB_METASTRLEN(str)	mb_metastrlen(str, 0)
 #define MB_METASTRWIDTH(str)	mb_metastrlen(str, 1)
+#define MB_METASTRLEN2(str, widthp)	mb_metastrlen(str, widthp)
 
 /*
  * Note WCWIDTH() takes wint_t, typically as a convchar_t.
@@ -2041,6 +2042,7 @@
 #define MB_METACHARLEN(str)	(*(str) == Meta ? 2 : 1)
 #define MB_METASTRLEN(str)	ztrlen(str)
 #define MB_METASTRWIDTH(str)	ztrlen(str)
+#define MB_METASTRLEN2(str, widthp)	ztrlen(str)
 
 #define WCWIDTH(c)	(1)
 
-- 
Peter Stephenson <pws@xxxxxxx>                  Software Engineer
CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
Cambridge, CB4 0WZ, UK                          Tel: +44 (0)1223 692070


To access the latest news from CSR copy this link into a web browser:  http://www.csr.com/email_sig.php



Messages sorted by: Reverse Date, Date, Thread, Author