about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2008-04-17 12:52:13 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2008-04-17 12:52:13 +0000
commit72bd9ee6d92ef8521a7a4b4f2f658940906d5c4f (patch)
treec369e585b693247720fafb00adf8bdc3d871d92f
parent78ce07b49f08964eaa08d68eb8f6a5595bbcfbc6 (diff)
downloadzsh-72bd9ee6d92ef8521a7a4b4f2f658940906d5c4f.tar.gz
zsh-72bd9ee6d92ef8521a7a4b4f2f658940906d5c4f.tar.xz
zsh-72bd9ee6d92ef8521a7a4b4f2f658940906d5c4f.zip
24825: fix internal word-boundary widgets
-rw-r--r--ChangeLog4
-rw-r--r--Src/Zle/zle_word.c313
-rw-r--r--Src/utils.c11
3 files changed, 236 insertions, 92 deletions
diff --git a/ChangeLog b/ChangeLog
index 45acd817d..bd7f13e38 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2008-04-17  Peter Stephenson  <pws@csr.com>
 
+	* 24825: Src/utils.c, Src/Zle/zle_word.c: fix internal
+	word-boundary widgets and make zero-width punctuation
+	characters always part of a word.
+
 	* unposted: NEWS: list new features so far since 4.3.6.
 
 	* Vincent Lefevre: 24818: Doc/Zsh/options.yo (modified),
diff --git a/Src/Zle/zle_word.c b/Src/Zle/zle_word.c
index c1fff7213..ef8220056 100644
--- a/Src/Zle/zle_word.c
+++ b/Src/Zle/zle_word.c
@@ -31,9 +31,13 @@
 #include "zle_word.pro"
 
 /*
- * HERE: our handling of combining characters may be wrong.  We
- * should make sure we only consider a combining character part of
- * a word if the base character is.
+ * In principle we shouldn't consider a zero-length punctuation
+ * character (i.e. a modifier of some sort) part of the word unless
+ * the base character has.  However, we only consider them part of
+ * a word if we so consider all alphanumerics, so the distinction
+ * only applies if the characters are modifying something they probably
+ * ought not to be modifying.  It's not really clear we need to
+ * be clever about this not very useful case.
  */
 
 /**/
@@ -147,11 +151,20 @@ viforwardblankwordend(UNUSED(char **args))
     if (n < 0)
 	return 1;
     while (n--) {
-	/* HERE: the zlecs + 1 here is suspect */
-	while (zlecs != zlell && ZC_iblank(zleline[zlecs + 1]))
-	    INCCS();
-	while (zlecs != zlell && !ZC_iblank(zleline[zlecs + 1]))
-	    INCCS();
+	while (zlecs != zlell) {
+	    int pos = zlecs;
+	    INCPOS(pos);
+	    if (!ZC_iblank(zleline[pos]))
+		break;
+	    zlecs = pos;
+	}
+	while (zlecs != zlell) {
+	    int pos = zlecs;
+	    INCPOS(pos);
+	    if (ZC_iblank(zleline[pos]))
+		break;
+	    zlecs = pos;
+	}
     }
     if (zlecs != zlell && virangeflag)
 	INCCS();
@@ -173,15 +186,37 @@ viforwardwordend(char **args)
     }
     while (n--) {
 	/* HERE: the zlecs + 1 here is suspect */
-	if (ZC_iblank(zleline[zlecs + 1]))
-	    while (zlecs != zlell && ZC_iblank(zleline[zlecs + 1]))
-		INCCS();
-	if (Z_vialnum(zleline[zlecs + 1]))
-	    while (zlecs != zlell && Z_vialnum(zleline[zlecs + 1]))
-		INCCS();
-	else
-	    while (zlecs != zlell && !Z_vialnum(zleline[zlecs + 1]) && !ZC_iblank(zleline[zlecs + 1]))
-		INCCS();
+	int pos;
+	while (zlecs != zlell) {
+	    pos = zlecs;
+	    INCPOS(pos);
+	    if (!ZC_inblank(zleline[pos]))
+		break;
+	    zlecs = pos;
+	}
+	if (zlecs != zlell) {
+	    pos = zlecs;
+	    INCPOS(pos);
+	    if (Z_vialnum(zleline[pos])) {
+		for (;;) {
+		    zlecs = pos;
+		    if (zlecs == zlell)
+			break;
+		    INCPOS(pos);
+		    if (!Z_vialnum(zleline[pos]))
+			break;
+		}
+	    } else {
+		for (;;) {
+		    zlecs = pos;
+		    if (zlecs == zlell)
+			break;
+		    INCPOS(pos);
+		    if (Z_vialnum(zleline[pos]) || ZC_iblank(zleline[pos]))
+			break;
+		}
+	    }
+	}
     }
     if (zlecs != zlell && virangeflag)
 	INCCS();
@@ -202,11 +237,20 @@ backwardword(char **args)
 	return ret;
     }
     while (n--) {
-	/* HERE: the zlecs - 1 here is suspect */
-	while (zlecs && !ZC_iword(zleline[zlecs - 1]))
-	    DECCS();
-	while (zlecs && ZC_iword(zleline[zlecs - 1]))
-	    DECCS();
+	while (zlecs) {
+	    int pos = zlecs;
+	    DECPOS(pos);
+	    if (ZC_iword(zleline[pos]))
+		break;
+	    zlecs = pos;
+	}
+	while (zlecs) {
+	    int pos = zlecs;
+	    DECPOS(pos);
+	    if (!ZC_iword(zleline[pos]))
+		break;
+	    zlecs = pos;
+	}
     }
     return 0;
 }
@@ -225,15 +269,36 @@ vibackwardword(char **args)
 	return ret;
     }
     while (n--) {
-	/* HERE: the zlecs - 1 here is suspect */
-	while (zlecs && ZC_iblank(zleline[zlecs - 1]))
-	    DECCS();
-	if (Z_vialnum(zleline[zlecs - 1]))
-	    while (zlecs && Z_vialnum(zleline[zlecs - 1]))
-		DECCS();
-	else
-	    while (zlecs && !Z_vialnum(zleline[zlecs - 1]) && !ZC_iblank(zleline[zlecs - 1]))
-		DECCS();
+	while (zlecs) {
+	    int pos = zlecs;
+	    DECPOS(pos);
+	    if (!ZC_iblank(zleline[pos]))
+		break;
+	    zlecs = pos;
+	}
+	if (zlecs) {
+	    int pos = zlecs;
+	    DECPOS(pos);
+	    if (Z_vialnum(zleline[pos])) {
+		for (;;) {
+		    zlecs = pos;
+		    if (zlecs == 0)
+			break;
+		    DECPOS(pos);
+		    if (!Z_vialnum(zleline[pos]))
+			break;
+		}
+	    } else {
+		for (;;) {
+		    zlecs = pos;
+		    if (zlecs == 0)
+			break;
+		    DECPOS(pos);
+		    if (Z_vialnum(zleline[pos]) || ZC_iblank(zleline[pos]))
+			break;
+		}
+	    }
+	}
     }
     return 0;
 }
@@ -252,10 +317,20 @@ vibackwardblankword(char **args)
 	return ret;
     }
     while (n--) {
-	while (zlecs && ZC_iblank(zleline[zlecs - 1]))
-	    DECCS();
-	while (zlecs && !ZC_iblank(zleline[zlecs - 1]))
-	    DECCS();
+	while (zlecs) {
+	    int pos = zlecs;
+	    DECPOS(pos);
+	    if (!ZC_iblank(zleline[pos]))
+		break;
+	    zlecs = pos;
+	}
+	while (zlecs) {
+	    int pos = zlecs;
+	    DECPOS(pos);
+	    if (ZC_iblank(zleline[pos]))
+		break;
+	    zlecs = pos;
+	}
     }
     return 0;
 }
@@ -274,10 +349,20 @@ emacsbackwardword(char **args)
 	return ret;
     }
     while (n--) {
-	while (zlecs && !ZC_iword(zleline[zlecs - 1]))
-	    DECCS();
-	while (zlecs && ZC_iword(zleline[zlecs - 1]))
-	    DECCS();
+	while (zlecs) {
+	    int pos = zlecs;
+	    DECPOS(pos);
+	    if (ZC_iword(zleline[pos]))
+		break;
+	    zlecs = pos;
+	}
+	while (zlecs) {
+	    int pos = zlecs;
+	    DECPOS(pos);
+	    if (!ZC_iword(zleline[pos]))
+		break;
+	    zlecs = pos;
+	}
     }
     return 0;
 }
@@ -296,14 +381,20 @@ backwarddeleteword(char **args)
 	return ret;
     }
     while (n--) {
-	/*
-	 * HERE: the zlecs - 1 here is suspect, and we should
-	 * do the DECCS() thing.
-	 */
-	while (x && !ZC_iword(zleline[x - 1]))
-	    x--;
-	while (x && ZC_iword(zleline[x - 1]))
-	    x--;
+	while (x) {
+	    int pos = x;
+	    DECPOS(pos);
+	    if (ZC_iword(zleline[pos]))
+		break;
+	    x = pos;
+	}
+	while (x) {
+	    int pos = x;
+	    DECPOS(pos);
+	    if (!ZC_iword(zleline[pos]))
+		break;
+	    x = pos;
+	}
     }
     backdel(zlecs - x, CUT_RAW);
     return 0;
@@ -320,18 +411,36 @@ vibackwardkillword(UNUSED(char **args))
 	return 1;
 /* this taken from "vibackwardword" */
     while (n--) {
-	/*
-	 * HERE: the zlecs - 1 here is suspect, and we should
-	 * do the DECCS() thing.
-	 */
-	while ((x > lim) && ZC_iblank(zleline[x - 1]))
-	    x--;
-	if (Z_vialnum(zleline[x - 1]))
-	    while ((x > lim) && Z_vialnum(zleline[x - 1]))
-		x--;
-	else
-	    while ((x > lim) && !Z_vialnum(zleline[x - 1]) && !ZC_iblank(zleline[x - 1]))
-		x--;
+	while (x > lim) {
+	    int pos = x;
+	    DECPOS(pos);
+	    if (!ZC_iblank(zleline[pos]))
+		break;
+	    x = pos;
+	}
+	if (x > lim) {
+	    int pos = x;
+	    DECPOS(pos);
+	    if (Z_vialnum(zleline[pos])) {
+		for (;;) {
+		    x = pos;
+		    if (x <= lim)
+			break;
+		    DECPOS(pos);
+		    if (!Z_vialnum(zleline[pos]))
+			break;
+		}
+	    } else {
+		for (;;) {
+		    x = pos;
+		    if (x <= lim)
+			break;
+		    DECPOS(pos);
+		    if (Z_vialnum(zleline[pos]) || ZC_iblank(zleline[pos]))
+			break;
+		}
+	    }
+	}
     }
     backkill(zlecs - x, CUT_FRONT);
     return 0;
@@ -352,14 +461,20 @@ backwardkillword(char **args)
 	return ret;
     }
     while (n--) {
-	/*
-	 * HERE: the zlecs - 1 here is suspect, and we should
-	 * do the DECCS() thing.
-	 */
-	while (x && !ZC_iword(zleline[x - 1]))
-	    x--;
-	while (x && ZC_iword(zleline[x - 1]))
-	    x--;
+	while (x) {
+	    int pos = x;
+	    DECPOS(pos);
+	    if (ZC_iword(zleline[x]))
+		break;
+	    x = pos;
+	}
+	while (x) {
+	    int pos = x;
+	    DECPOS(pos);
+	    if (!ZC_iword(zleline[x]))
+		break;
+	    x = pos;
+	}
     }
     backkill(zlecs - x, CUT_FRONT);
     return 0;
@@ -451,11 +566,10 @@ deleteword(char **args)
 	return ret;
     }
     while (n--) {
-	/* HERE: we should do the INCCS() thing */
 	while (x != zlell && !ZC_iword(zleline[x]))
-	    x++;
+	    INCPOS(x);
 	while (x != zlell && ZC_iword(zleline[x]))
-	    x++;
+	    INCPOS(x);
     }
     foredel(x - zlecs, CUT_RAW);
     return 0;
@@ -476,11 +590,10 @@ killword(char **args)
 	return ret;
     }
     while (n--) {
-	/* HERE: we should do the INCCS() thing */
 	while (x != zlell && !ZC_iword(zleline[x]))
-	    x++;
+	    INCPOS(x);
 	while (x != zlell && ZC_iword(zleline[x]))
-	    x++;
+	    INCPOS(x);
     }
     forekill(x - zlecs, CUT_RAW);
     return 0;
@@ -490,7 +603,7 @@ killword(char **args)
 int
 transposewords(UNUSED(char **args))
 {
-    int p1, p2, p3, p4, len, x = zlecs;
+    int p1, p2, p3, p4, len, x = zlecs, pos;
     ZLE_STRING_T temp, pp;
     int n = zmult;
     int neg = n < 0, ocs = zlecs;
@@ -498,28 +611,54 @@ transposewords(UNUSED(char **args))
     if (neg)
 	n = -n;
     while (n--) {
-	/*
-	 * HERE: we should do the INCCS() thing.
-	 * A great deal of the following needs rewriting.
-	 */
 	while (x != zlell && zleline[x] != ZWC('\n') && !ZC_iword(zleline[x]))
-	    x++;
+	    INCPOS(x);
 	if (x == zlell || zleline[x] == ZWC('\n')) {
 	    x = zlecs;
-	    while (x && zleline[x - 1] != ZWC('\n') && !ZC_iword(zleline[x]))
-		x--;
-	    if (!x || zleline[x - 1] == ZWC('\n'))
+	    while (x) {
+		if (ZC_iword(zleline[x]))
+		    break;
+		pos = x;
+		DECPOS(pos);
+		if (zleline[pos] == ZWC('\n'))
+		    break;
+		x = pos;
+	    }
+	    if (!x)
+		return 1;
+	    pos = x;
+	    DECPOS(pos);
+	    if (zleline[pos] == ZWC('\n'))
 		return 1;
+	    x = pos;
+	}
+	for (p4 = x; p4 != zlell && ZC_iword(zleline[p4]); INCPOS(p4))
+	    ;
+	for (p3 = p4; p3; ) {
+	    pos = p3;
+	    DECPOS(pos);
+	    if (!ZC_iword(zleline[pos]))
+		break;
+	    p3 = pos;
 	}
-	for (p4 = x; p4 != zlell && ZC_iword(zleline[p4]); p4++);
-	for (p3 = p4; p3 && ZC_iword(zleline[p3 - 1]); p3--);
 	if (!p3)
 	    return 1;
-	for (p2 = p3; p2 && !ZC_iword(zleline[p2 - 1]); p2--);
+	for (p2 = p3; p2; ) {
+	    pos = p2;
+	    DECPOS(pos);
+	    if (ZC_iword(zleline[pos]))
+		break;
+	    p2 = pos;
+	}
 	if (!p2)
 	    return 1;
-	for (p1 = p2; p1 && ZC_iword(zleline[p1 - 1]); p1--);
-
+	for (p1 = p2; p1; ) {
+	    pos = p1;
+	    DECPOS(pos);
+	    if (!ZC_iword(zleline[pos]))
+		break;
+	    p1 = pos;
+	}
 	pp = temp = (ZLE_STRING_T)zhalloc((p4 - p1)*ZLE_CHAR_SIZE);
 	len = p4 - p3;
 	ZS_memcpy(pp, zleline + p3, len);
diff --git a/Src/utils.c b/Src/utils.c
index b4770befe..21a3a0c34 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -3082,12 +3082,13 @@ wcsitype(wchar_t c, int itype)
 	    if (iswalnum(c))
 		return 1;
 	    /*
-	     * If we are handling combining characters, anything
-	     * printable with zero width needs to be considered
-	     * part of a word.
+	     * If we are handling combining characters, any punctuation
+	     * characters with zero width needs to be considered part of
+	     * a word.  If we are not handling combining characters then
+	     * logically they are still part of the word, even if they
+	     * don't get displayed properly, so always do this.
 	     */
-	    if (isset(COMBININGCHARS) &&
-		iswprint(c) && wcwidth(c) == 0)
+	    if (iswpunct(c) && wcwidth(c) == 0)
 		return 1;
 	    return !!wmemchr(wordchars_wide.chars, c, wordchars_wide.len);