int killregion(UNUSED(char **args)) { if (mark > zlell) mark = zlell; if (region_active == 2) { int a, b; regionlines(&a, &b); zlecs = a; region_active = 0; cut(zlecs, b - zlecs, CUT_RAW); shiftchars(zlecs, b - zlecs); if (zlell) { if (zlecs == zlell) DECCS(); foredel(1, 0); vifirstnonblank(zlenoargs); } } else if (mark > zlecs) { if (invicmdmode()) INCPOS(mark); forekill(mark - zlecs, CUT_RAW); } else { if (invicmdmode()) INCCS(); backkill(zlecs - mark, CUT_FRONT|CUT_RAW); } return 0; }
int vibackwarddeletechar(char **args) { int n = zmult; if (invicmdmode()) startvichange(-1); /* handle negative argument */ if (n < 0) { int ret; zmult = -n; ret = videletechar(args); zmult = n; return ret; } /* It is an error to be at the beginning of the line, or (in * * insert mode) to delete past the beginning of insertion. */ if ((!invicmdmode() && zlecs - n < viinsbegin) || zlecs == findbol()) { return 1; } /* Put argument into the acceptable range -- it is not an error to * * specify a greater count than the number of available characters. */ /* HERE: we should do the test properly with DECPOS(). */ if (n > zlecs - findbol()) { n = zlecs - findbol(); /* do the deletion */ backkill(n, CUT_FRONT|CUT_RAW); } else backkill(n, CUT_FRONT); return 0; }
int copyregionaskill(char **args) { int start, end; if (*args) { int len; ZLE_STRING_T line = stringaszleline(*args, 0, &len, NULL, NULL); cuttext(line, len, CUT_REPLACE); free(line); } else { if (mark > zlell) mark = zlell; if (mark > zlecs) { start = zlecs; end = mark; } else { start = mark; end = zlecs; } if (invicmdmode()) INCPOS(end); cut(start, end - start, mark > zlecs ? 0 : CUT_FRONT); } 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 setline(char *s, int flags) { char *scp; UNMETACHECK(); if (flags & ZSL_COPY) scp = ztrdup(s); else scp = s; /* * TBD: we could make this more efficient by passing the existing * allocated line to stringaszleline. */ free(zleline); zleline = stringaszleline(scp, 0, &zlell, &linesz, NULL); if ((flags & ZSL_TOEND) && (zlecs = zlell) && invicmdmode()) DECCS(); else if (zlecs > zlell) zlecs = zlell; CCRIGHT(); if (flags & ZSL_COPY) free(scp); }
int viyank(UNUSED(char **args)) { int c2, ret = 1; startvichange(1); if ((c2 = getvirange(0)) != -1) { cut(zlecs, c2 - zlecs, CUT_YANK); ret = 0; } vichgflag = 0; /* cursor now at the start of the range yanked. For line mode * restore the column position */ if (vilinerange && lastcol != -1) { int x = findeol(); if ((zlecs += lastcol) >= x) { zlecs = x; if (zlecs > findbol() && invicmdmode()) DECCS(); } #ifdef MULTIBYTE_SUPPORT else CCRIGHT(); #endif lastcol = -1; } return ret; }
int vicmdmode(UNUSED(char **args)) { if (invicmdmode() || selectkeymap("vicmd", 0)) return 1; mergeundo(); vichgflag = 0; if (zlecs != findbol()) DECCS(); 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(); } }
void zlecore(void) { Keymap km; #if !defined(HAVE_POLL) && defined(HAVE_SELECT) struct timeval tv; fd_set foofd; FD_ZERO(&foofd); #endif pushheap(); /* * A widget function may decide to exit the shell. * We never exit directly from functions, to allow * the shell to tidy up, so we have to test for * that explicitly. */ while (!done && !errflag && !exit_pending) { UNMETACHECK(); statusline = NULL; vilinerange = 0; reselectkeymap(); selectlocalmap(invicmdmode() && region_active && (km = openkeymap("visual")) ? km : NULL); bindk = getkeycmd(); selectlocalmap(NULL); if (bindk) { if (!zlell && isfirstln && !(zlereadflags & ZLRF_IGNOREEOF) && lastchar == eofchar) { /* * Slight hack: this relies on getkeycmd returning * a value for the EOF character. However, * undefined-key is fine. That's necessary because * otherwise we can't distinguish this case from * a ^C. */ eofsent = 1; break; } if (execzlefunc(bindk, zlenoargs, 0)) { handlefeep(zlenoargs); if (eofsent) break; } handleprefixes(); /* for vi mode, make sure the cursor isn't somewhere illegal */ if (invicmdmode() && zlecs > findbol() && (zlecs == zlell || zleline[zlecs] == ZWC('\n'))) DECCS(); handleundo(); } else { errflag |= ERRFLAG_ERROR; break; } #ifdef HAVE_POLL if (baud && !(lastcmd & ZLE_MENUCMP)) { struct pollfd pfd; int to = cost * costmult / 1000; /* milliseconds */ if (to > 500) to = 500; pfd.fd = SHTTY; pfd.events = POLLIN; if (!kungetct && poll(&pfd, 1, to) <= 0) zrefresh(); } else #else # ifdef HAVE_SELECT if (baud && !(lastcmd & ZLE_MENUCMP)) { FD_SET(SHTTY, &foofd); tv.tv_sec = 0; if ((tv.tv_usec = cost * costmult) > 500000) tv.tv_usec = 500000; if (!kungetct && select(SHTTY+1, (SELECT_ARG_2_T) & foofd, NULL, NULL, &tv) <= 0) zrefresh(); } else # endif #endif if (!kungetct) zrefresh(); freeheap(); } region_active = 0; popheap(); }
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) { 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. 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; 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; 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 && virangeflag != 2) || ret == -1) { mark = mpos; 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) INCPOS(pos); 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 && 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. */ if(vilinerange) { int newcs = findbol(); lastcol = zlecs - newcs; zlecs = pos; pos = findeol(); zlecs = newcs; } return pos; }