summary refs log tree commit diff
path: root/Src/Zle
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Zle')
-rw-r--r--Src/Zle/zle_misc.c25
-rw-r--r--Src/Zle/zle_vi.c27
-rw-r--r--Src/Zle/zle_word.c4
3 files changed, 39 insertions, 17 deletions
diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c
index 27253a333..e00f22b04 100644
--- a/Src/Zle/zle_misc.c
+++ b/Src/Zle/zle_misc.c
@@ -47,14 +47,27 @@ doinsert(ZLE_STRING_T zstr, int len)
     iremovesuffix(c1, 0);
     invalidatelist();
 
-    if(insmode)
+    if (insmode)
 	spaceinline(m * len);
-    else if(zlecs + m * len > zlell)
-	spaceinline(zlecs + m * len - zlell);
-    while(m--)
-	for(s = zstr, count = len; count; s++, count--)
+    else {
+	int pos = zlecs, count = m * len, i = count, diff;
+	/*
+	 * Ensure we replace a complete combining character
+	 * for each character we overwrite.
+	 */
+	while (pos < zlell && i--) {
+	    INCPOS(pos);
+	}
+	diff = pos - zlecs - count;
+	if (diff < 0) {
+	    spaceinline(-diff);
+	} else if (diff > 0)
+	    foredel(diff, CUT_RAW);
+    }
+    while (m--)
+	for (s = zstr, count = len; count; s++, count--)
 	    zleline[zlecs++] = *s;
-    if(neg)
+    if (neg)
 	zlecs += zmult * len;
     /* if we ended up on a combining character, skip over it */
     CCRIGHT();
diff --git a/Src/Zle/zle_vi.c b/Src/Zle/zle_vi.c
index b8215454f..16b741b75 100644
--- a/Src/Zle/zle_vi.c
+++ b/Src/Zle/zle_vi.c
@@ -498,18 +498,19 @@ int
 vireplacechars(UNUSED(char **args))
 {
     ZLE_INT_T ch;
-    int n = zmult, origcs = zlecs, fail = 0;
+    int n = zmult, fail = 0, newchars = 0;
 
     if (n > 0) {
+	int pos = zlecs;
 	while (n-- > 0) {
-	    if (zlecs == zlell || zleline[zlell] == ZWC('\n')) {
+	    if (pos == zlell || zleline[pos] == ZWC('\n')) {
 		fail = 1;
 		break;
 	    }
-	    INCCS();
+	    newchars++;
+	    INCPOS(pos);
 	}
-	n = zlecs - origcs;
-	zlecs = origcs;
+	n = pos - zlecs;
     }
     startvichange(1);
     /* check argument range */
@@ -535,8 +536,16 @@ vireplacechars(UNUSED(char **args))
 	backkill(n - 1, CUT_RAW);
 	zleline[zlecs++] = '\n';
     } else {
-	/* HERE: we shouldn't replace combining chars, we should delete them */
-	while (n--)
+	/*
+	 * Make sure we delete displayed characters, including
+	 * attach combining characters. n includes this as a raw
+	 * buffer offset.
+	 */
+	if (n > newchars)
+	    foredel(n - newchars, CUT_RAW);
+	else if (n < newchars)
+	    spaceinline(newchars - n);
+	while (newchars--)
 	    zleline[zlecs++] = ch;
 	zlecs--;
     }
@@ -792,14 +801,14 @@ viputafter(UNUSED(char **args))
 	vifirstnonblank(zlenoargs);
     } else {
 	if (zlecs != findeol())
-	    zlecs++;
+	    INCCS();
 	while (n--) {
 	    spaceinline(buf->len);
 	    ZS_memcpy(zleline + zlecs, buf->buf, buf->len);
 	    zlecs += buf->len;
 	}
 	if (zlecs)
-	    zlecs--;
+	    DECCS();
     }
     return 0;
 }
diff --git a/Src/Zle/zle_word.c b/Src/Zle/zle_word.c
index 368079053..e59304ecd 100644
--- a/Src/Zle/zle_word.c
+++ b/Src/Zle/zle_word.c
@@ -441,7 +441,7 @@ vibackwardkillword(UNUSED(char **args))
 	    }
 	}
     }
-    backkill(zlecs - x, CUT_FRONT);
+    backkill(zlecs - x, CUT_FRONT|CUT_RAW);
     return 0;
 }
 
@@ -475,7 +475,7 @@ backwardkillword(char **args)
 	    x = pos;
 	}
     }
-    backkill(zlecs - x, CUT_FRONT);
+    backkill(zlecs - x, CUT_FRONT|CUT_RAW);
     return 0;
 }