diff options
Diffstat (limited to 'Src/Zle')
-rw-r--r-- | Src/Zle/zle_misc.c | 25 | ||||
-rw-r--r-- | Src/Zle/zle_vi.c | 27 | ||||
-rw-r--r-- | Src/Zle/zle_word.c | 4 |
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; } |