summaryrefslogtreecommitdiff
path: root/Src/Zle/zle_misc.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Zle/zle_misc.c')
-rw-r--r--Src/Zle/zle_misc.c69
1 files changed, 57 insertions, 12 deletions
diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c
index 592a590b5..d63b52caa 100644
--- a/Src/Zle/zle_misc.c
+++ b/Src/Zle/zle_misc.c
@@ -331,28 +331,35 @@ copyregionaskill(char **args)
return 0;
}
+/*
+ * kct: index into kill ring, or -1 for original cutbuffer of yank.
+ * yankb, yanke: mark the start and end of last yank in editing buffer.
+ */
static int kct, yankb, yanke;
+/* The original cutbuffer, either cutbuf or one of the vi buffers. */
+static Cutbuffer kctbuf;
/**/
int
yank(char **args)
{
- Cutbuffer buf = &cutbuf;
int n = zmult;
if (n < 0)
return 1;
if (zmod.flags & MOD_VIBUF)
- buf = &vibuf[zmod.vibuf];
- if (!buf->buf)
+ kctbuf = &vibuf[zmod.vibuf];
+ else
+ kctbuf = &cutbuf;
+ if (!kctbuf->buf)
return 1;
mark = cs;
yankb = cs;
while (n--) {
- kct = kringnum;
- spaceinline(buf->len);
- memcpy((char *)line + cs, buf->buf, buf->len);
- cs += buf->len;
+ kct = -1;
+ spaceinline(kctbuf->len);
+ memcpy((char *)line + cs, kctbuf->buf, kctbuf->len);
+ cs += kctbuf->len;
yanke = cs;
}
return 0;
@@ -362,18 +369,56 @@ yank(char **args)
int
yankpop(char **args)
{
- int cc;
+ int cc, kctstart = kct;
+ Cutbuffer buf;
- if (!(lastcmd & ZLE_YANK) || !kring[kct].buf)
+ if (!(lastcmd & ZLE_YANK))
return 1;
+ do {
+ /*
+ * This is supposed to make the yankpop loop
+ * original buffer -> kill ring in order -> original buffer -> ...
+ * where the original buffer is -1 and the remainder are
+ * indices into the kill ring, remember that we need to start
+ * that at kringnum rather than zero.
+ */
+ if (kct == -1)
+ kct = kringnum;
+ else {
+ int kctnew = (kct + kringsize - 1) % kringsize;
+ if (kctnew == kringnum)
+ kct = -1;
+ else
+ kct = kctnew;
+ }
+ if (kct == -1)
+ buf = kctbuf; /* Use original cutbuffer */
+ else
+ buf = kring+kct; /* Use somewhere in the kill ring */
+ /* Careful to prevent infinite looping */
+ if (kct == kctstart)
+ return 1;
+ /*
+ * Skip unset buffers instead of stopping as we used to do.
+ * Also skip zero-length buffers.
+ * There are two reasons for this:
+ * 1. We now map the array $killring directly into the
+ * killring, instead of via some extra size-checking logic.
+ * When $killring has been set, a buffer will always have
+ * at least a zero-length string in it.
+ * 2. The old logic was inconsistent; when the kill ring
+ * was full, we could loop round and round it, otherwise
+ * we just stopped when we hit the first empty buffer.
+ */
+ } while (!buf->buf || !*buf->buf);
+
cs = yankb;
foredel(yanke - yankb);
- cc = kring[kct].len;
+ cc = buf->len;
spaceinline(cc);
- memcpy((char *)line + cs, kring[kct].buf, cc);
+ memcpy((char *)line + cs, buf->buf, cc);
cs += cc;
yanke = cs;
- kct = (kct + KRINGCT - 1) % KRINGCT;
return 0;
}