int viputafter(UNUSED(char **args)) { Cutbuffer buf = &cutbuf; int n = zmult; startvichange(-1); if (n < 0) return 1; if (zmod.flags & MOD_VIBUF) buf = &vibuf[zmod.vibuf]; if (!buf->buf) return 1; if(buf->flags & CUTBUFFER_LINE) { zlecs = findeol(); spaceinline(buf->len + 1); zleline[zlecs++] = ZWC('\n'); ZS_memcpy(zleline + zlecs, buf->buf, buf->len); vifirstnonblank(zlenoargs); } else { if (zlecs != findeol()) INCCS(); while (n--) { spaceinline(buf->len); ZS_memcpy(zleline + zlecs, buf->buf, buf->len); zlecs += buf->len; } if (zlecs) DECCS(); } return 0; }
int quoteregion(UNUSED(char **args)) { ZLE_STRING_T str; size_t len; int extra = invicmdmode(); if (mark > zlell) mark = zlell; if (region_active == 2) { int a, b; regionlines(&a, &b); zlecs = a; mark = b; extra = 0; } else if (mark < zlecs) { int tmp = mark; mark = zlecs; zlecs = tmp; } if (extra) INCPOS(mark); str = (ZLE_STRING_T)hcalloc((len = mark - zlecs) * ZLE_CHAR_SIZE); ZS_memcpy(str, zleline + zlecs, len); foredel(len, CUT_RAW); str = makequote(str, &len); spaceinline(len); ZS_memcpy(zleline + zlecs, str, len); mark = zlecs; zlecs += len; return 0; }
void mkundoent(void) { int pre, suf; int sh = zlell < lastll ? zlell : lastll; struct change *ch; UNMETACHECK(); if(lastll == zlell && !ZS_memcmp(lastline, zleline, zlell)) { lastcs = zlecs; return; } for(pre = 0; pre < sh && zleline[pre] == lastline[pre]; ) pre++; for(suf = 0; suf < sh - pre && zleline[zlell - 1 - suf] == lastline[lastll - 1 - suf]; ) suf++; ch = zalloc(sizeof(*ch)); ch->next = NULL; ch->hist = histline; ch->off = pre; ch->old_cs = lastcs; ch->new_cs = zlecs; if(suf + pre == lastll) { ch->del = NULL; ch->dell = 0; } else { ch->dell = lastll - pre - suf; ch->del = (ZLE_STRING_T)zalloc(ch->dell * ZLE_CHAR_SIZE); ZS_memcpy(ch->del, lastline + pre, ch->dell); } if(suf + pre == zlell) { ch->ins = NULL; ch->insl = 0; } else { ch->insl = zlell - pre - suf; ch->ins = (ZLE_STRING_T)zalloc(ch->insl * ZLE_CHAR_SIZE); ZS_memcpy(ch->ins, zleline + pre, ch->insl); } if(nextchanges) { ch->flags = CH_PREV; ch->prev = endnextchanges; endnextchanges->flags |= CH_NEXT; endnextchanges->next = ch; } else { nextchanges = ch; ch->flags = 0; ch->prev = NULL; } ch->changeno = ++undo_changeno; endnextchanges = ch; }
static void transpose_swap(int start, int middle, int end) { int len1, len2; ZLE_STRING_T first; len1 = middle - start; len2 = end - middle; first = (ZLE_STRING_T)zalloc(len1 * ZLE_CHAR_SIZE); ZS_memcpy(first, zleline + start, len1); /* Move may be overlapping... */ ZS_memmove(zleline + start, zleline + middle, len2); ZS_memcpy(zleline + start + len2, first, len1); zfree(first, len1 * ZLE_CHAR_SIZE); }
int copyprevshellword(UNUSED(char **args)) { LinkList l; LinkNode n; int i; char *p = NULL; if (zmult <= 0) return 1; if ((l = bufferwords(NULL, NULL, &i, LEXFLAGS_ZLE))) { i -= (zmult-1); if (i < 0) return 1; for (n = firstnode(l); n; incnode(n)) if (!i--) { p = getdata(n); break; } } if (p) { int len; ZLE_STRING_T lineadd = stringaszleline(p, 0, &len, NULL, NULL); spaceinline(len); ZS_memcpy(zleline + zlecs, lineadd, len); zlecs += len; free(lineadd); } return 0; }
/* position: 0 is before, 1 after, 2 split the line */ static void pastebuf(Cutbuffer buf, int mult, int position) { int cc; if (buf->flags & CUTBUFFER_LINE) { if (position == 2) { if (!zlecs) position = 0; else if (zlecs == zlell) position = 1; } if (position == 2) { yankb = zlecs; spaceinline(buf->len + 2); zleline[zlecs++] = ZWC('\n'); ZS_memcpy(zleline + zlecs, buf->buf, buf->len); zlecs += buf->len; zleline[zlecs] = ZWC('\n'); yanke = zlecs + 1; } else if (position != 0) { yankb = zlecs = findeol(); spaceinline(buf->len + 1); zleline[zlecs++] = ZWC('\n'); yanke = zlecs + buf->len; ZS_memcpy(zleline + zlecs, buf->buf, buf->len); } else { yankb = zlecs = findbol(); spaceinline(buf->len + 1); ZS_memcpy(zleline + zlecs, buf->buf, buf->len); yanke = zlecs + buf->len + 1; zleline[zlecs + buf->len] = ZWC('\n'); } vifirstnonblank(zlenoargs); } else { if (position == 1 && zlecs != findeol()) INCCS(); yankb = zlecs; cc = buf->len; while (mult--) { spaceinline(cc); ZS_memcpy(zleline + zlecs, buf->buf, cc); zlecs += cc; } yanke = zlecs; if (zlecs && invicmdmode()) DECCS(); } }
int yankpop(UNUSED(char **args)) { int cc, kctstart = kct; Cutbuffer buf; if (!(lastcmd & ZLE_YANK) || !kring || !kctbuf) { kctbuf = NULL; 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 == ZWC('\0')); zlecs = yankb; foredel(yanke - yankb, CUT_RAW); cc = buf->len; spaceinline(cc); ZS_memcpy(zleline + zlecs, buf->buf, cc); zlecs += cc; yanke = zlecs; return 0; }
void setlastline(void) { UNMETACHECK(); if(lastlinesz != linesz) lastline = realloc(lastline, (lastlinesz = linesz) * ZLE_CHAR_SIZE); ZS_memcpy(lastline, zleline, (lastll = zlell)); lastcs = zlecs; }
int quoteline(UNUSED(char **args)) { ZLE_STRING_T str; size_t len = zlell; str = makequote(zleline, &len); sizeline(len); ZS_memcpy(zleline, str, len); zlecs = zlell = len; return 0; }
void initundo(void) { nextchanges = NULL; changes = curchange = zalloc(sizeof(*curchange)); curchange->prev = curchange->next = NULL; curchange->del = curchange->ins = NULL; curchange->dell = curchange->insl = 0; lastline = zalloc((lastlinesz = linesz) * ZLE_CHAR_SIZE); ZS_memcpy(lastline, zleline, (lastll = zlell)); lastcs = zlecs; }
int quoteregion(UNUSED(char **args)) { ZLE_STRING_T str; size_t len; if (mark > zlell) mark = zlell; if (mark < zlecs) { int tmp = mark; mark = zlecs; zlecs = tmp; } str = (ZLE_STRING_T)hcalloc((len = mark - zlecs) * ZLE_CHAR_SIZE); ZS_memcpy(str, zleline + zlecs, len); foredel(len, CUT_RAW); str = makequote(str, &len); spaceinline(len); ZS_memcpy(zleline + zlecs, str, len); mark = zlecs; zlecs += len; return 0; }
mod_export void addsuffix(int tp, int flags, ZLE_STRING_T chars, int lenstr, int lensuf) { struct suffixset *newsuf = zalloc(sizeof(struct suffixset)); newsuf->next = suffixlist; suffixlist = newsuf; newsuf->tp = tp; newsuf->flags = flags; if (lenstr) { newsuf->chars = zalloc(lenstr*sizeof(ZLE_CHAR_T)); ZS_memcpy(newsuf->chars, chars, lenstr); } else newsuf->chars = NULL; newsuf->lenstr = lenstr; newsuf->lensuf = lensuf; }
static void set_rbuffer(UNUSED(Param pm), char *x) { ZLE_STRING_T y; int len; if (x && *x != ZWC('\0')) y = stringaszleline(x, 0, &len, NULL, NULL); else y = ZWS(""), len = 0; sizeline(zlell = zlecs + len); ZS_memcpy(zleline + zlecs, y, len); zsfree(x); if (len) free(y); fixsuffix(); menucmp = 0; }
static int applychange(struct change *ch) { if(ch->hist != histline) { zle_setline(quietgethist(ch->hist)); zlecs = ch->old_cs; return 0; } zlecs = ch->off; if(ch->del) foredel(ch->dell, CUT_RAW); if(ch->ins) { spaceinline(ch->insl); ZS_memcpy(zleline + zlecs, ch->ins, ch->insl); zlecs += ch->insl; } zlecs = ch->new_cs; return 1; }
int copyprevword(UNUSED(char **args)) { int len, t0 = zlecs, t1; if (zmult > 0) { int count = zmult; for (;;) { t1 = t0; while (t0) { int prev = t0; DECPOS(prev); if (ZC_iword(zleline[prev])) break; t0 = prev; } while (t0) { int prev = t0; DECPOS(prev); if (!ZC_iword(zleline[prev])) break; t0 = prev; } if (!--count) break; if (t0 == 0) return 1; } } else return 1; len = t1 - t0; spaceinline(len); ZS_memcpy(zleline + zlecs, zleline + t0, len); zlecs += len; return 0; }
int yank(UNUSED(char **args)) { int n = zmult; if (n < 0) return 1; if (zmod.flags & MOD_VIBUF) kctbuf = &vibuf[zmod.vibuf]; else kctbuf = &cutbuf; if (!kctbuf->buf) return 1; yankb = yankcs = mark = zlecs; while (n--) { kct = -1; spaceinline(kctbuf->len); ZS_memcpy(zleline + zlecs, kctbuf->buf, kctbuf->len); zlecs += kctbuf->len; yanke = zlecs; } return 0; }
static int getvirange(int wf) { int pos = zlecs, mpos = mark, ret = 0; int visual = region_active; /* movement command might set it */ int mult1 = zmult, hist1 = histline; Thingy k2; if (visual) { if (!zlell) return -1; pos = mark; vilinerange = (visual == 2); region_active = 0; } else { virangeflag = 1; wordflag = wf; mark = -1; /* use operator-pending keymap if one exists */ Keymap km = openkeymap("viopp"); if (km) selectlocalmap(km); /* Now we need to execute the movement command, to see where it * * actually goes. virangeflag here indicates to the movement * * function that it should place the cursor at the end of the * * range, rather than where the cursor would actually go if it * * were executed normally. This makes a difference to some * * commands, but not all. For example, if searching forward * * for a character, under normal circumstances the cursor lands * * on the character. For a range, the range must include the * * character, so the cursor gets placed after the character if * * virangeflag is set. */ zmod.flags &= ~MOD_TMULT; do { vilinerange = 0; prefixflag = 0; if (!(k2 = getkeycmd()) || (k2->flags & DISABLED) || k2 == Th(z_sendbreak)) { wordflag = 0; virangeflag = 0; mark = mpos; return -1; } /* * With k2 == bindk, the command key is repeated: * a number of lines is used. If the function used * returns 1, we fail. */ if ((k2 == bindk) ? dovilinerange() : execzlefunc(k2, zlenoargs, 1)) ret = -1; if(vichgrepeat) zmult = mult1; else zmult = mult1 * zmod.tmult; } while(prefixflag && !ret); wordflag = 0; selectlocalmap(NULL); /* It is an error to use a non-movement command to delimit the * * range. We here reject the case where the command modified * * the line, or selected a different history line. */ if (histline != hist1 || zlell != lastll || memcmp(zleline, lastline, zlell)) { histline = hist1; ZS_memcpy(zleline, lastline, zlell = lastll); zlecs = pos; mark = mpos; virangeflag = 0; return -1; } /* Can't handle an empty file. Also, if the movement command * * failed, or didn't move, it is an error. */ if (!zlell || (zlecs == pos && (mark == -1 || mark == zlecs) && virangeflag != 2) || ret == -1) { mark = mpos; virangeflag = 0; return -1; } virangeflag = 0; /* if the mark has moved, ignore the original cursor position * * and use the mark. */ if (mark != -1) pos = mark; } mark = mpos; /* Get the range the right way round. zlecs is placed at the * * start of the range, and pos (the return value of this * * function) is the end. */ if (zlecs > pos) { int tmp = zlecs; zlecs = pos; pos = tmp; } /* visual selection mode needs to include additional position */ if (visual == 1 && pos < zlell && invicmdmode()) INCPOS(pos); /* Was it a line-oriented move? If so, the command will have set * * the vilinerange flag. In this case, entire lines are taken, * * rather than just the sequence of characters delimited by pos * * and zlecs. The terminating newline is left out of the range, * * which the real command must deal with appropriately. At this * * point we just need to make the range encompass entire lines. */ vilinerange = (zmod.flags & MOD_LINE) || (vilinerange && !(zmod.flags & MOD_CHAR)); if (vilinerange) { int newcs = findbol(); lastcol = zlecs - newcs; zlecs = pos; pos = findeol(); zlecs = newcs; } else if (!visual) { /* for a character-wise move don't include a newline at the * * end of the range */ int prev = pos; DECPOS(prev); if (zleline[prev] == ZWC('\n')) pos = prev; } return pos; }
int transposewords(UNUSED(char **args)) { int p1, p2, p3, p4, pt, len, x = zlecs, pos; ZLE_STRING_T temp, pp; int n = zmult; int neg = n < 0, ocs = zlecs; if (neg) n = -n; while (x != zlell && zleline[x] != ZWC('\n') && !ZC_iword(zleline[x])) INCPOS(x); if (x == zlell || zleline[x] == ZWC('\n')) { x = zlecs; 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; } 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; } if (!p3) return 1; p1 = p2 = pt = p3; while (n--) { for (p2 = pt; p2; ) { pos = p2; DECPOS(pos); if (ZC_iword(zleline[pos])) break; p2 = pos; } if (!p2) return 1; for (p1 = p2; p1; ) { pos = p1; DECPOS(pos); if (!ZC_iword(zleline[pos])) break; p1 = pos; } pt = p1; } pp = temp = (ZLE_STRING_T)zhalloc((p4 - p1)*ZLE_CHAR_SIZE); len = p4 - p3; ZS_memcpy(pp, zleline + p3, len); pp += len; len = p3 - p2; ZS_memcpy(pp, zleline + p2, len); pp += len; ZS_memcpy(pp, zleline + p1, p2 - p1); ZS_memcpy(zleline + p1, temp, p4 - p1); if (neg) zlecs = ocs; else zlecs = p4; return 0; }
static int getvirange(int wf) { int pos = zlecs, ret = 0; int mult1 = zmult, hist1 = histline; Thingy k2; virangeflag = 1; wordflag = wf; /* Now we need to execute the movement command, to see where it * * actually goes. virangeflag here indicates to the movement * * function that it should place the cursor at the end of the * * range, rather than where the cursor would actually go if it * * were executed normally. This makes a difference to some * * commands, but not all. For example, if searching forward * * for a character, under normal circumstances the cursor lands * * on the character. For a range, the range must include the * * character, so the cursor gets placed after the character if * * virangeflag is set. vi-match-bracket needs to change the * * value of virangeflag under some circumstances, meaning that * * we need to change the *starting* position. */ zmod.flags &= ~MOD_TMULT; do { vilinerange = 0; prefixflag = 0; if (!(k2 = getkeycmd()) || (k2->flags & DISABLED) || k2 == Th(z_sendbreak)) { wordflag = 0; virangeflag = 0; return -1; } /* * With k2 == bindk, the command key is repeated: * a number of lines is used. If the function used * returns 1, we fail. */ if ((k2 == bindk) ? dovilinerange() : execzlefunc(k2, zlenoargs, 1)) ret = -1; if(vichgrepeat) zmult = mult1; else zmult = mult1 * zmod.tmult; } while(prefixflag && !ret); wordflag = 0; virangeflag = 0; /* It is an error to use a non-movement command to delimit the * * range. We here reject the case where the command modified * * the line, or selected a different history line. */ if (histline != hist1 || zlell != lastll || memcmp(zleline, lastline, zlell)) { histline = hist1; ZS_memcpy(zleline, lastline, zlell = lastll); zlecs = pos; return -1; } /* Can't handle an empty file. Also, if the movement command * * failed, or didn't move, it is an error. */ if (!zlell || (zlecs == pos && virangeflag != 2) || ret == -1) return -1; /* vi-match-bracket changes the value of virangeflag when * * moving to the opening bracket, meaning that we need to * * change the *starting* position. */ if(virangeflag == -1) { int origcs = zlecs; zlecs = pos; INCCS(); pos = zlecs; zlecs = origcs; } /* Get the range the right way round. zlecs is placed at the * * start of the range, and pos (the return value of this * * function) is the end. */ if (zlecs > pos) { int tmp = zlecs; zlecs = pos; pos = tmp; } /* Was it a line-oriented move? If so, the command will have set * * the vilinerange flag. In this case, entire lines are taken, * * rather than just the sequence of characters delimited by pos * * and zlecs. The terminating newline is left out of the range, * * which the real command must deal with appropriately. At this * * point we just need to make the range encompass entire lines. */ if(vilinerange) { int newcs = findbol(); zlecs = pos; pos = findeol(); zlecs = newcs; } return pos; }
void cuttext(ZLE_STRING_T line, int ct, int flags) { if (!ct) return; UNMETACHECK(); if (zmod.flags & MOD_VIBUF) { struct cutbuffer *b = &vibuf[zmod.vibuf]; if (!(zmod.flags & MOD_VIAPP) || !b->buf) { free(b->buf); b->buf = (ZLE_STRING_T)zalloc(ct * ZLE_CHAR_SIZE); ZS_memcpy(b->buf, line, ct); b->len = ct; b->flags = vilinerange ? CUTBUFFER_LINE : 0; } else { int len = b->len; if(vilinerange) b->flags |= CUTBUFFER_LINE; b->buf = (ZLE_STRING_T) realloc((char *)b->buf, (ct + len + !!(b->flags & CUTBUFFER_LINE)) * ZLE_CHAR_SIZE); if (b->flags & CUTBUFFER_LINE) b->buf[len++] = ZWC('\n'); ZS_memcpy(b->buf + len, line, ct); b->len = len + ct; } return; } else { /* Save in "1, shifting "1-"8 along to "2-"9 */ int n; free(vibuf[34].buf); for(n=34; n>26; n--) vibuf[n] = vibuf[n-1]; vibuf[26].buf = (ZLE_STRING_T)zalloc(ct * ZLE_CHAR_SIZE); ZS_memcpy(vibuf[26].buf, line, ct); vibuf[26].len = ct; vibuf[26].flags = vilinerange ? CUTBUFFER_LINE : 0; } if (!cutbuf.buf) { cutbuf.buf = (ZLE_STRING_T)zalloc(ZLE_CHAR_SIZE); cutbuf.buf[0] = ZWC('\0'); cutbuf.len = cutbuf.flags = 0; } else if (!(lastcmd & ZLE_KILL) || (flags & CUT_REPLACE)) { Cutbuffer kptr; if (!kring) { kringsize = KRINGCTDEF; kring = (Cutbuffer)zshcalloc(kringsize * sizeof(struct cutbuffer)); } else kringnum = (kringnum + 1) % kringsize; kptr = kring + kringnum; if (kptr->buf) free(kptr->buf); *kptr = cutbuf; cutbuf.buf = (ZLE_STRING_T)zalloc(ZLE_CHAR_SIZE); cutbuf.buf[0] = ZWC('\0'); cutbuf.len = cutbuf.flags = 0; } if (flags & (CUT_FRONT|CUT_REPLACE)) { ZLE_STRING_T s = (ZLE_STRING_T)zalloc((cutbuf.len + ct)*ZLE_CHAR_SIZE); ZS_memcpy(s, line, ct); ZS_memcpy(s + ct, cutbuf.buf, cutbuf.len); free(cutbuf.buf); cutbuf.buf = s; cutbuf.len += ct; } else { cutbuf.buf = realloc((char *)cutbuf.buf, (cutbuf.len + ct) * ZLE_CHAR_SIZE); ZS_memcpy(cutbuf.buf + cutbuf.len, line, ct); cutbuf.len += ct; } if(vilinerange) cutbuf.flags |= CUTBUFFER_LINE; else cutbuf.flags &= ~CUTBUFFER_LINE; }