int viforwardword(char **args) { int n = zmult; if (n < 0) { int ret; zmult = -n; ret = backwardword(args); zmult = n; return ret; } while (n--) { int nl; if (Z_vialnum(zleline[zlecs])) while (zlecs != zlell && Z_vialnum(zleline[zlecs])) INCCS(); else while (zlecs != zlell && !Z_vialnum(zleline[zlecs]) && !ZC_inblank(zleline[zlecs])) INCCS(); if (wordflag && !n) return 0; nl = (zleline[zlecs] == ZWC('\n')); while (zlecs != zlell && nl < 2 && ZC_inblank(zleline[zlecs])) { INCCS(); nl += (zleline[zlecs] == ZWC('\n')); } } return 0; }
int vireplacechars(UNUSED(char **args)) { ZLE_INT_T ch; int n = zmult, fail = 0, newchars = 0; if (n > 0) { int pos = zlecs; while (n-- > 0) { if (pos == zlell || zleline[pos] == ZWC('\n')) { fail = 1; break; } newchars++; INCPOS(pos); } n = pos - zlecs; } startvichange(1); /* check argument range */ if (n < 1 || fail) { if(vichgrepeat) vigetkey(); if(vichgflag) { free(vichgbuf); vichgbuf = NULL; vichgflag = 0; } return 1; } /* get key */ if((ch = vigetkey()) == ZLEEOF) { vichgflag = 0; return 1; } /* do change */ if (ch == ZWC('\r') || ch == ZWC('\n')) { /* <return> handled specially */ zlecs += n - 1; backkill(n - 1, CUT_RAW); zleline[zlecs++] = '\n'; } else { /* * Make sure we delete displayed characters, including * attach combining characters. n includes this as a raw * buffer offset. * Use shiftchars so as not to adjust the cursor position; * we are overwriting anything that remains directly. */ if (n > newchars) shiftchars(zlecs, n - newchars); else if (n < newchars) spaceinline(newchars - n); while (newchars--) zleline[zlecs++] = ch; zlecs--; } vichgflag = 0; return 0; }
int viforwardword(char **args) { int n = zmult; if (n < 0) { int ret; zmult = -n; ret = vibackwardword(args); zmult = n; return ret; } while (n--) { int nl; int cc = wordclass(zleline[zlecs]); while (zlecs != zlell && wordclass(zleline[zlecs]) == cc) { INCCS(); } if (wordflag && !n) return 0; nl = (zleline[zlecs] == ZWC('\n')); while (zlecs != zlell && nl < 2 && ZC_inblank(zleline[zlecs])) { INCCS(); nl += (zleline[zlecs] == ZWC('\n')); } } return 0; }
mod_export int getzlequery(void) { ZLE_INT_T c; #ifdef FIONREAD int val; /* check for typeahead, which is treated as a negative response */ ioctl(SHTTY, FIONREAD, (char *)&val); if (val) { putc('n', shout); return 0; } #endif /* get a character from the tty and interpret it */ c = getfullchar(0); if (c == ZWC('\t')) c = ZWC('y'); else if (ZC_icntrl(c) || c == ZLEEOF) c = ZWC('n'); else c = ZC_tolower(c); /* echo response and return */ if (c != ZWC('\n')) { REFRESH_ELEMENT re; re.chr = c; re.atr = 0; zwcputc(&re, NULL); } return c == ZWC('y'); }
int vibackwardblankword(char **args) { int n = zmult; if (n < 0) { int ret; zmult = -n; ret = viforwardblankword(args); zmult = n; return ret; } while (n--) { int nl = 0; while (zlecs) { int pos = zlecs; DECPOS(pos); if (!ZC_inblank(zleline[pos])) break; nl += (zleline[pos] == ZWC('\n')); if (nl == 2) break; zlecs = pos; } while (zlecs) { int pos = zlecs; DECPOS(pos); if (ZC_inblank(zleline[pos])) break; zlecs = pos; } } return 0; }
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 vijoin(UNUSED(char **args)) { int x, pos; startvichange(-1); if ((x = findeol()) == zlell) return 1; zlecs = x + 1; pos = zlecs; for (; zlecs != zlell && ZC_iblank(zleline[zlecs]); INCPOS(zlecs)) ; x = 1 + (zlecs - pos); backdel(x, CUT_RAW); if (zlecs) { int pos = zlecs; DECPOS(pos); if (ZC_iblank(zleline[pos])) { zlecs = pos; return 0; } } spaceinline(1); zleline[zlecs] = ZWC(' '); 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(); } }
mod_export void makesuffixstr(char *f, char *s, int n) { if (f) { zsfree(suffixfunc); suffixfunc = ztrdup(f); suffixfunclen = n; } else if (s) { int inv, i, z = 0; ZLE_STRING_T ws, lasts, wptr; if (*s == '^' || *s == '!') { inv = 1; s++; } else inv = 0; s = getkeystring(s, &i, GETKEYS_SUFFIX, &z); s = metafy(s, i, META_USEHEAP); ws = stringaszleline(s, 0, &i, NULL, NULL); if (z) suffixnoinslen = inv ? 0 : n; else if (inv) { /* * negative match, \- wasn't present, so it *should* * have this suffix length */ suffixnoinslen = n; } lasts = wptr = ws; while (i) { if (i >= 3 && wptr[1] == ZWC('-')) { ZLE_CHAR_T str[2]; if (wptr > lasts) addsuffix(inv ? SUFTYP_NEGSTR : SUFTYP_POSSTR, 0, lasts, wptr - lasts, n); str[0] = *wptr; str[1] = wptr[2]; addsuffix(inv ? SUFTYP_NEGRNG : SUFTYP_POSRNG, 0, str, 2, n); wptr += 3; i -= 3; lasts = wptr; } else { wptr++; i--; } } if (wptr > lasts) addsuffix(inv ? SUFTYP_NEGSTR : SUFTYP_POSSTR, 0, lasts, wptr - lasts, n); free(ws); } else makesuffix(n); }
int findeol(void) { int x = zlecs; while (x != zlell && zleline[x] != ZWC('\n')) x++; return x; }
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; }
int findbol(void) { int x = zlecs; while (x > 0 && zleline[x - 1] != ZWC('\n')) x--; return x; }
mod_export void makesuffixstr(char *f, char *s, int n) { if (f) { zsfree(suffixfunc); suffixfunc = ztrdup(f); suffixfunclen = n; } else if (s) { int inv, i, z = 0; ZLE_STRING_T ws, lasts, wptr; if (*s == '^' || *s == '!') { inv = 1; s++; } else inv = 0; s = getkeystring(s, &i, GETKEYS_SUFFIX, &z); s = metafy(s, i, META_USEHEAP); ws = stringaszleline(s, 0, &i, NULL, NULL); /* Remove suffix on uninsertable characters if \- was given * * and the character class wasn't negated -- or vice versa. */ suffixnoinsrem = z ^ inv; suffixlen = n; lasts = wptr = ws; while (i) { if (i >= 3 && wptr[1] == ZWC('-')) { ZLE_CHAR_T str[2]; if (wptr > lasts) addsuffix(inv ? SUFTYP_NEGSTR : SUFTYP_POSSTR, 0, lasts, wptr - lasts, n); str[0] = *wptr; str[1] = wptr[2]; addsuffix(inv ? SUFTYP_NEGRNG : SUFTYP_POSRNG, 0, str, 2, n); wptr += 3; i -= 3; lasts = wptr; } else { wptr++; i--; } } if (wptr > lasts) addsuffix(inv ? SUFTYP_NEGSTR : SUFTYP_POSSTR, 0, lasts, wptr - lasts, n); free(ws); } else makesuffix(n); }
int whatcursorposition(UNUSED(char **args)) { char msg[100]; char *s = msg, *mbstr; int bol = findbol(), len; ZLE_CHAR_T c = zleline[zlecs]; if (zlecs == zlell) strucpy(&s, "EOF"); else { strucpy(&s, "Char: "); switch (c) { case ZWC(' '): strucpy(&s, "SPC"); break; case ZWC('\t'): strucpy(&s, "TAB"); break; case ZWC('\n'): strucpy(&s, "LFD"); break; default: /* * convert a single character, remembering it may * turn into a multibyte string or be metafied. */ mbstr = zlelineasstring(zleline+zlecs, 1, 0, &len, NULL, 1); strcpy(s, mbstr); s += len; } sprintf(s, " (0%o, %u, 0x%x)", (unsigned int)c, (unsigned int)c, (unsigned int)c); s += strlen(s); } sprintf(s, " point %d of %d(%d%%) column %d", zlecs+1, zlell+1, zlell ? 100 * zlecs / zlell : 0, zlecs - bol); showmsg(msg); return 0; }
int killline(char **args) { int i = 0, n = zmult; if (n < 0) { int ret; zmult = -n; ret = backwardkillline(args); zmult = n; return ret; } while (n--) { if (zleline[zlecs] == ZWC('\n')) zlecs++, i++; else while (zlecs != zlell && zleline[zlecs] != ZWC('\n')) zlecs++, i++; } backkill(i, CUT_RAW); clearlist = 1; return 0; }
int vibackwardword(char **args) { int n = zmult; if (n < 0) { int ret; zmult = -n; ret = backwardword(args); zmult = n; return ret; } while (n--) { int nl = 0; while (zlecs) { DECCS(); if (!ZC_inblank(zleline[zlecs])) break; nl += (zleline[zlecs] == ZWC('\n')); if (nl == 2) { INCCS(); break; } } if (zlecs) { int pos = zlecs; if (Z_vialnum(zleline[pos])) { for (;;) { zlecs = pos; if (zlecs == 0) break; DECPOS(pos); if (!Z_vialnum(zleline[pos])) break; } } else { for (;;) { zlecs = pos; if (zlecs == 0) break; DECPOS(pos); if (Z_vialnum(zleline[pos]) || ZC_inblank(zleline[pos])) break; } } } } return 0; }
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; }
int vijoin(UNUSED(char **args)) { int x, pos; int n = zmult; int visual = region_active; startvichange(-1); if (n < 1) return 1; if (visual && zlecs > mark) { exchangepointandmark(zlenoargs); x = findeol(); if (x >= mark) { exchangepointandmark(zlenoargs); return 1; } } else if ((x = findeol()) == zlell || (visual && x >= mark)) return 1; while (n) { zlecs = x + 1; pos = zlecs; for (; zlecs != zlell && ZC_iblank(zleline[zlecs]); INCPOS(zlecs)) ; x = 1 + (zlecs - pos); backdel(x, CUT_RAW); if (zlecs) { int pos = zlecs; DECPOS(pos); if (ZC_iblank(zleline[pos])) { zlecs = pos; return 0; } } spaceinline(1); zleline[zlecs] = ZWC(' '); if ((!visual && --n < 2) || (x = findeol()) == zlell || (visual && x >= mark)) return 0; } return 0; }
int vibackwardword(char **args) { int n = zmult; if (n < 0) { int ret; zmult = -n; ret = viforwardword(args); zmult = n; return ret; } while (n--) { int nl = 0; while (zlecs) { DECCS(); if (!ZC_inblank(zleline[zlecs])) break; nl += (zleline[zlecs] == ZWC('\n')); if (nl == 2) { INCCS(); break; } } if (zlecs) { int pos = zlecs; int cc = wordclass(zleline[pos]); for (;;) { zlecs = pos; if (zlecs == 0) break; DECPOS(pos); if (wordclass(zleline[pos]) != cc || ZC_inblank(zleline[pos])) break; } } } return 0; }
static ZLE_STRING_T makequote(ZLE_STRING_T str, size_t *len) { int qtct = 0; ZLE_STRING_T l, ol; ZLE_STRING_T end = str + *len; for (l = str; l < end; l++) if (*l == ZWC('\'')) qtct++; *len += 2 + qtct*3; l = ol = (ZLE_STRING_T)zhalloc(*len * ZLE_CHAR_SIZE); *l++ = ZWC('\''); for (; str < end; str++) if (*str == ZWC('\'')) { *l++ = ZWC('\''); *l++ = ZWC('\\'); *l++ = ZWC('\''); *l++ = ZWC('\''); } else *l++ = *str; *l++ = ZWC('\''); return ol; }
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; }
int visetbuffer(UNUSED(char **args)) { ZLE_INT_T ch; if ((zmod.flags & MOD_VIBUF) || (((ch = getfullchar(0)) < ZWC('1') || ch > ZWC('9')) && (ch < ZWC('a') || ch > ZWC('z')) && (ch < ZWC('A') || ch > ZWC('Z')))) return 1; if (ch >= ZWC('A') && ch <= ZWC('Z')) /* needed in cut() */ zmod.flags |= MOD_VIAPP; else zmod.flags &= ~MOD_VIAPP; /* FIXME how portable is it for multibyte encoding? */ zmod.vibuf = ZC_tolower(ch); if (ch >= ZWC('1') && ch <= ZWC('9')) zmod.vibuf += - (int)ZWC('1') + 26; else zmod.vibuf += - (int)ZWC('a'); zmod.flags |= MOD_VIBUF; prefixflag = 1; return 0; }
mod_export char * zlelineasstring(ZLE_STRING_T instr, int inll, int incs, int *outllp, int *outcsp, int useheap) { int outcs, outll, sub; struct region_highlight *rhp; #ifdef MULTIBYTE_SUPPORT char *s; int i, j; size_t mb_len = 0; mbstate_t mbs; s = zalloc(inll * MB_CUR_MAX + 1); outcs = 0; memset(&mbs, 0, sizeof(mbs)); for (i=0; i < inll; i++) { if (incs == 0) outcs = mb_len; incs--; if (region_highlights && outcsp == &zlemetacs) { for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS; rhp < region_highlights + n_region_highlights; rhp++) { if (rhp->flags & ZRH_PREDISPLAY) sub = predisplaylen; else sub = 0; if (rhp->start - sub == 0) rhp->start_meta = sub + mb_len; rhp->start--; if (rhp->end - sub == 0) rhp->end_meta = sub + mb_len; rhp->end--; } } #ifdef __STDC_ISO_10646__ if (ZSH_INVALID_WCHAR_TEST(instr[i])) { s[mb_len++] = ZSH_INVALID_WCHAR_TO_CHAR(instr[i]); } else #endif { j = wcrtomb(s + mb_len, instr[i], &mbs); if (j == -1) { /* invalid char */ s[mb_len++] = ZWC('?'); memset(&mbs, 0, sizeof(mbs)); } else { mb_len += j; } } } if (incs == 0) outcs = mb_len; if (region_highlights && outcsp == &zlemetacs) { for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS; rhp < region_highlights + n_region_highlights; rhp++) { if (rhp->flags & ZRH_PREDISPLAY) sub = predisplaylen; else sub = 0; if (rhp->start - sub == 0) rhp->start_meta = sub + mb_len; if (rhp->end - sub == 0) rhp->end_meta = sub + mb_len; } } s[mb_len] = '\0'; outll = mb_len; #else outll = inll; outcs = incs; if (region_highlights && outcsp == &zlemetacs) { for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS; rhp < region_highlights + n_region_highlights; rhp++) { rhp->start_meta = rhp->start; rhp->end_meta = rhp->end; } } #endif /* * *outcsp and *outllp are to be indexes into the final string, * not character offsets, so we need to take account of any * metafiable characters. */ if (outcsp != NULL || outllp != NULL) { #ifdef MULTIBYTE_SUPPORT char *strp = s; #else char *strp = instr; #endif char *stopcs = strp + outcs; char *stopll = strp + outll; char *startp = strp; if (region_highlights && outcsp == &zlemetacs) { for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS; rhp < region_highlights + n_region_highlights; rhp++) { /* Used as temporary storage */ rhp->start = rhp->start_meta; rhp->end = rhp->end_meta; } } while (strp < stopll) { if (imeta(*strp)) { if (strp < stopcs) outcs++; if (region_highlights && outcsp == &zlemetacs) { for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS; rhp < region_highlights + n_region_highlights; rhp++) { if (rhp->flags & ZRH_PREDISPLAY) sub = predisplaylen; else sub = 0; if (strp < startp + rhp->start - sub) { rhp->start_meta++; } if (strp < startp + rhp->end - sub) { rhp->end_meta++; } } } outll++; } strp++; } if (outcsp != NULL) *outcsp = outcs; if (outllp != NULL) *outllp = outll; } #ifdef MULTIBYTE_SUPPORT if (useheap) { char *ret = metafy(s, mb_len, META_HEAPDUP); zfree(s, inll * MB_CUR_MAX + 1); return ret; } return metafy(s, mb_len, META_REALLOC); #else return metafy(instr, inll, useheap ? META_HEAPDUP : META_DUP); #endif }
void doinsert(ZLE_STRING_T zstr, int len) { ZLE_STRING_T s; ZLE_CHAR_T c1 = *zstr; /* first character */ int neg = zmult < 0; /* insert *after* the cursor? */ int m = neg ? -zmult : zmult; /* number of copies to insert */ int count; UNMETACHECK(); iremovesuffix(c1, 0); invalidatelist(); /* In overwrite mode, don't replace newlines. */ if (insmode || zleline[zlecs] == ZWC('\n')) spaceinline(m * len); else { int pos = zlecs, diff, i; #ifdef MULTIBYTE_SUPPORT /* * Calculate the number of character positions we are * going to be using. The algorithm is that * anything that shows up as a logical single character * (i.e. even if control, or double width, or with combining * characters) is treated as 1 for the purpose of replacing * what's there already. * * This can cause inserting of a combining character in * places where it should overwrite, such as the start * of a line. However, combining characters aren't * useful there anyway and this doesn't cause any * particular harm. */ for (i = 0, count = 0; i < len * m; i++) { if (!IS_COMBINING(zstr[i])) count++; } #else count = len * m; #endif /* * Ensure we replace a complete combining characterfor each * character we overwrite. Switch to inserting at first newline. */ for (i = count; pos < zlell && zleline[pos] != ZWC('\n') && i--; ) { INCPOS(pos); } /* * Calculate how many raw line places we need. * pos - zlecs is the raw line distance we're replacing, * m * len the number we're inserting. */ diff = pos - zlecs - m * len; if (diff < 0) { spaceinline(-diff); } else if (diff > 0) { /* * We use shiftchars() here because we don't * want combining char alignment fixed up: we * are going to write over any that remain. */ shiftchars(zlecs, diff); } } while (m--) for (s = zstr, count = len; count; s++, count--) zleline[zlecs++] = *s; if (neg) zlecs += zmult * len; /* if we ended up on a combining character, skip over it */ CCRIGHT(); }
mod_export void iremovesuffix(ZLE_INT_T c, int keep) { if (suffixfunc) { Shfunc shfunc = getshfunc(suffixfunc); if (shfunc) { LinkList args = newlinklist(); char buf[20]; int osc = sfcontext; int wasmeta = (zlemetaline != 0); if (wasmeta) { /* * The suffix removal function runs as a normal * ZLE function, not a completion function, so * the line should be unmetafied if this was * called from completion. (It may not be since * we may decide to remove the suffix later.) */ unmetafy_line(); } sprintf(buf, "%d", suffixfunclen); addlinknode(args, suffixfunc); addlinknode(args, buf); startparamscope(); makezleparams(0); sfcontext = SFC_COMPLETE; doshfunc(shfunc, args, 1); sfcontext = osc; endparamscope(); if (wasmeta) metafy_line(); } zsfree(suffixfunc); suffixfunc = NULL; } else { int sl = 0, flags = 0; struct suffixset *ss; if (c == NO_INSERT_CHAR) { sl = suffixnoinsrem ? suffixlen : 0; } else { ZLE_CHAR_T ch = c; /* * Search for a match for ch in the suffix list. * We stop if we encounter a match in a positive or negative * list, using the suffix length specified or zero respectively. * If we reached the end and passed through a negative * list, we use the suffix length for that, else zero. * This would break if it were possible to have negative * sets with different suffix length: that's not supposed * to happen. */ int negsuflen = 0, found = 0; for (ss = suffixlist; ss; ss = ss->next) { switch (ss->tp) { case SUFTYP_POSSTR: if (ZS_memchr(ss->chars, ch, ss->lenstr)) { sl = ss->lensuf; found = 1; } break; case SUFTYP_NEGSTR: if (ZS_memchr(ss->chars, ch, ss->lenstr)) { sl = 0; found = 1; } else { negsuflen = ss->lensuf; } break; case SUFTYP_POSRNG: if (ss->chars[0] <= ch && ch <= ss->chars[1]) { sl = ss->lensuf; found = 1; } break; case SUFTYP_NEGRNG: if (ss->chars[0] <= ch && ch <= ss->chars[1]) { sl = 0; found = 1; } else { negsuflen = ss->lensuf; } break; } if (found) { flags = ss->flags; break; } } if (!found) sl = negsuflen; } if (sl) { /* must be shifting wide character lengths */ backdel(sl, CUT_RAW); if (flags & SUFFLAGS_SPACE) { /* Add a space and advance over it */ spaceinline(1); if (zlemetaline) { zlemetaline[zlemetacs++] = ' '; } else { zleline[zlecs++] = ZWC(' '); } } if (!keep) invalidatelist(); } } fixsuffix(); }
mod_export void spaceinline(int ct) { int i, sub; struct region_highlight *rhp; if (zlemetaline) { sizeline(ct + zlemetall); for (i = zlemetall; --i >= zlemetacs;) zlemetaline[i + ct] = zlemetaline[i]; zlemetall += ct; zlemetaline[zlemetall] = '\0'; if (mark > zlemetacs) mark += ct; if (region_highlights) { for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS; rhp < region_highlights + n_region_highlights; rhp++) { if (rhp->flags & ZRH_PREDISPLAY) sub = predisplaylen; else sub = 0; if (rhp->start_meta - sub >= zlemetacs) { rhp->start_meta += ct; } if (rhp->end_meta - sub >= zlemetacs) { rhp->end_meta += ct; } } } } else { sizeline(ct + zlell); for (i = zlell; --i >= zlecs;) zleline[i + ct] = zleline[i]; zlell += ct; zleline[zlell] = ZWC('\0'); if (mark > zlecs) mark += ct; if (region_highlights) { for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS; rhp < region_highlights + n_region_highlights; rhp++) { if (rhp->flags & ZRH_PREDISPLAY) sub = predisplaylen; else sub = 0; if (rhp->start - sub >= zlecs) { rhp->start += ct; } if (rhp->end - sub >= zlecs) { rhp->end += ct; } } } } region_active = 0; }
Thingy executenamedcommand(char *prmt) { Thingy cmd, retval = NULL; int l, len, feep = 0, listed = 0, curlist = 0; int ols = (listshown && validlist), olll = lastlistlen; char *cmdbuf, *ptr; char *okeymap = ztrdup(curkeymapname); clearlist = 1; /* prmt may be constant */ prmt = ztrdup(prmt); l = strlen(prmt); cmdbuf = (char *)zhalloc(l + NAMLEN + 2 #ifdef MULTIBYTE_SUPPORT + 2 * MB_CUR_MAX #endif ); strcpy(cmdbuf, prmt); zsfree(prmt); statusline = cmdbuf; selectlocalmap(command_keymap); selectkeymap("main", 1); ptr = cmdbuf += l; len = 0; for (;;) { *ptr = '_'; ptr[1] = '\0'; zrefresh(); if (!(cmd = getkeycmd()) || cmd == Th(z_sendbreak)) { statusline = NULL; selectkeymap(okeymap, 1); zsfree(okeymap); if ((listshown = ols)) { showinglist = -2; lastlistlen = olll; } else if (listed) clearlist = listshown = 1; retval = NULL; goto done; } if(cmd == Th(z_clearscreen)) { clearscreen(zlenoargs); if (curlist) { int zmultsav = zmult; zmult = 1; listlist(namedcmdll); showinglist = 0; zmult = zmultsav; } } else if(cmd == Th(z_redisplay)) { redisplay(zlenoargs); if (curlist) { int zmultsav = zmult; zmult = 1; listlist(namedcmdll); showinglist = 0; zmult = zmultsav; } } else if(cmd == Th(z_viquotedinsert)) { *ptr = '^'; zrefresh(); getfullchar(0); if(LASTFULLCHAR == ZLEEOF || !LASTFULLCHAR || len >= NAMLEN) feep = 1; else { int ret = zlecharasstring(LASTFULLCHAR, ptr); len += ret; ptr += ret; curlist = 0; } } else if(cmd == Th(z_quotedinsert)) { if(getfullchar(0) == ZLEEOF || !LASTFULLCHAR || len == NAMLEN) feep = 1; else { int ret = zlecharasstring(LASTFULLCHAR, ptr); len += ret; ptr += ret; curlist = 0; } } else if(cmd == Th(z_backwarddeletechar) || cmd == Th(z_vibackwarddeletechar)) { if (len) { ptr = backwardmetafiedchar(cmdbuf, ptr, NULL); len = ptr - cmdbuf; curlist = 0; } } else if(cmd == Th(z_killregion) || cmd == Th(z_backwardkillword) || cmd == Th(z_vibackwardkillword)) { if (len) curlist = 0; while (len) { convchar_t cc; ptr = backwardmetafiedchar(cmdbuf, ptr, &cc); len = ptr - cmdbuf; if (cc == ZWC('-')) break; } } else if(cmd == Th(z_killwholeline) || cmd == Th(z_vikillline) || cmd == Th(z_backwardkillline)) { len = 0; ptr = cmdbuf; if (listed) clearlist = listshown = 1; curlist = 0; } else if (cmd == Th(z_bracketedpaste)) { char *insert = bracketedstring(); size_t inslen = strlen(insert); if (len + inslen > NAMLEN) feep = 1; else { strcpy(ptr, insert); len += inslen; ptr += inslen; if (listed) { clearlist = listshown = 1; listed = 0; } else curlist = 0; } free(insert); } else { if(cmd == Th(z_acceptline) || cmd == Th(z_vicmdmode)) { Thingy r; unambiguous: *ptr = 0; r = rthingy(cmdbuf); if (!(r->flags & DISABLED)) { unrefthingy(r); statusline = NULL; selectkeymap(okeymap, 1); zsfree(okeymap); if ((listshown = ols)) { showinglist = -2; lastlistlen = olll; } else if (listed) clearlist = listshown = 1; retval = r; goto done; } unrefthingy(r); } if(cmd == Th(z_selfinsertunmeta)) { fixunmeta(); cmd = Th(z_selfinsert); } if (cmd == Th(z_listchoices) || cmd == Th(z_deletecharorlist) || cmd == Th(z_expandorcomplete) || cmd == Th(z_completeword) || cmd == Th(z_expandorcompleteprefix) || cmd == Th(z_vicmdmode) || cmd == Th(z_acceptline) || lastchar == ' ' || lastchar == '\t') { namedcmdambig = 100; namedcmdll = newlinklist(); *ptr = '\0'; namedcmdstr = cmdbuf; scanhashtable(thingytab, 1, 0, DISABLED, scancompcmd, 0); namedcmdstr = NULL; if (empty(namedcmdll)) { feep = 1; if (listed) clearlist = listshown = 1; curlist = 0; } else if (cmd == Th(z_listchoices) || cmd == Th(z_deletecharorlist)) { int zmultsav = zmult; *ptr = '_'; ptr[1] = '\0'; zmult = 1; listlist(namedcmdll); listed = curlist = 1; showinglist = 0; zmult = zmultsav; } else if (!nextnode(firstnode(namedcmdll))) { strcpy(ptr = cmdbuf, peekfirst(namedcmdll)); len = strlen(ptr); ptr += len; if (cmd == Th(z_acceptline) || cmd == Th(z_vicmdmode)) goto unambiguous; } else { strcpy(cmdbuf, peekfirst(namedcmdll)); ptr = cmdbuf + namedcmdambig; *ptr = '_'; ptr[1] = '\0'; if (isset(AUTOLIST) && !(isset(LISTAMBIGUOUS) && namedcmdambig > len)) { int zmultsav = zmult; if (isset(LISTBEEP)) feep = 1; zmult = 1; listlist(namedcmdll); listed = curlist = 1; showinglist = 0; zmult = zmultsav; } len = namedcmdambig; } } else { if (len == NAMLEN || cmd != Th(z_selfinsert)) feep = 1; else { #ifdef MULTIBYTE_SUPPORT if (!lastchar_wide_valid) getrestchar(lastchar, NULL, NULL); if (lastchar_wide == WEOF) feep = 1; else #endif if (ZC_icntrl(LASTFULLCHAR)) feep = 1; else { int ret = zlecharasstring(LASTFULLCHAR, ptr); len += ret; ptr += ret; if (listed) { clearlist = listshown = 1; listed = 0; } else curlist = 0; } } } } if (feep) handlefeep(zlenoargs); feep = 0; } done: selectlocalmap(NULL); return retval; }
char * zleread(char **lp, char **rp, int flags, int context, char *init, char *finish) { char *s, **bracket; int old_errno = errno; int tmout = getiparam("TMOUT"); #if defined(HAVE_POLL) || defined(HAVE_SELECT) /* may not be set, but that's OK since getiparam() returns 0 == off */ baud = getiparam("BAUD"); costmult = (baud) ? 3840000L / baud : 0; #endif /* ZLE doesn't currently work recursively. This is needed in case a * * select loop is used in a function called from ZLE. vared handles * * this differently itself. */ if(zleactive) { char *pptbuf; int pptlen; pptbuf = unmetafy(promptexpand(lp ? *lp : NULL, 0, NULL, NULL, &pmpt_attr), &pptlen); write_loop(2, pptbuf, pptlen); free(pptbuf); return shingetline(); } /* * The current status is what we need if we are going * to display a prompt. We'll remember it here for * use further in. */ pre_zle_status = lastval; keytimeout = (time_t)getiparam("KEYTIMEOUT"); if (!shout) { if (SHTTY != -1) init_shout(); if (!shout) return NULL; /* We could be smarter and default to a system read. */ /* If we just got a new shout, make sure the terminal is set up. */ if (termflags & TERM_UNKNOWN) init_term(); } fflush(shout); fflush(stderr); intr(); insmode = unset(OVERSTRIKE); eofsent = 0; resetneeded = 0; fetchttyinfo = 0; trashedzle = 0; raw_lp = lp; lpromptbuf = promptexpand(lp ? *lp : NULL, 1, NULL, NULL, &pmpt_attr); raw_rp = rp; rpmpt_attr = pmpt_attr; rpromptbuf = promptexpand(rp ? *rp : NULL, 1, NULL, NULL, &rpmpt_attr); free_prepostdisplay(); zlereadflags = flags; zlecontext = context; histline = curhist; vistartchange = -1; zleline = (ZLE_STRING_T)zalloc(((linesz = 256) + 2) * ZLE_CHAR_SIZE); *zleline = ZWC('\0'); virangeflag = lastcmd = done = zlecs = zlell = mark = 0; vichgflag = 0; viinsbegin = 0; statusline = NULL; selectkeymap("main", 1); initundo(); fixsuffix(); if ((s = getlinknode(bufstack))) { setline(s, ZSL_TOEND); zsfree(s); if (stackcs != -1) { zlecs = stackcs; stackcs = -1; if (zlecs > zlell) zlecs = zlell; CCLEFT(); } if (stackhist != -1) { histline = stackhist; stackhist = -1; } handleundo(); } /* * If main is linked to the viins keymap, we need to register * explicitly that we're now in vi insert mode as there's * no user operation to indicate this. */ if (openkeymap("main") == openkeymap("viins")) viinsert_init(); selectlocalmap(NULL); if (isset(PROMPTCR)) putc('\r', shout); if (tmout) alarm(tmout); /* * On some windowing systems we may enter this function before the * terminal is fully opened and sized, resulting in an infinite * series of SIGWINCH when the handler prints the prompt before we * have done so here. Therefore, hold any such signal until the * first full refresh has completed. The important bit is that the * handler must not see zleactive = 1 until ZLE really is active. * See the end of adjustwinsize() in Src/utils.c */ queue_signals(); zleactive = 1; resetneeded = 1; /* * Start of the main zle read. * Fully reset error conditions, including user interrupt. */ errflag = retflag = 0; lastcol = -1; initmodifier(&zmod); prefixflag = 0; zrefresh(); unqueue_signals(); /* Should now be safe to acknowledge SIGWINCH */ zlecallhook(init, NULL); if ((bracket = getaparam("zle_bracketed_paste")) && arrlen(bracket) == 2) fputs(*bracket, shout); zrefresh(); zlecore(); if (errflag) setsparam((zlecontext == ZLCON_VARED) ? "ZLE_VARED_ABORTED" : "ZLE_LINE_ABORTED", zlegetline(NULL, NULL)); if ((bracket = getaparam("zle_bracketed_paste")) && arrlen(bracket) == 2) fputs(bracket[1], shout); if (done && !exit_pending && !errflag) zlecallhook(finish, NULL); statusline = NULL; invalidatelist(); trashzle(); free(lpromptbuf); free(rpromptbuf); zleactive = zlereadflags = lastlistlen = zlecontext = 0; alarm(0); freeundo(); if (eofsent || errflag || exit_pending) { s = NULL; } else { zleline[zlell++] = ZWC('\n'); s = zlegetline(NULL, NULL); } free(zleline); zleline = NULL; forget_edits(); errno = old_errno; /* highlight no longer valid */ set_region_highlight(NULL, NULL); return s; }
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(); }
void shiftchars(int to, int cnt) { struct region_highlight *rhp; int sub; if (mark >= to + cnt) mark -= cnt; else if (mark > to) mark = to; if (zlemetaline) { /* before to is updated... */ if (region_highlights) { for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS; rhp < region_highlights + n_region_highlights; rhp++) { if (rhp->flags & ZRH_PREDISPLAY) sub = predisplaylen; else sub = 0; if (rhp->start_meta - sub > to) { if (rhp->start_meta - sub > to + cnt) rhp->start_meta -= cnt; else rhp->start_meta = to; } if (rhp->end_meta - sub > to) { if (rhp->end_meta - sub > to + cnt) rhp->end_meta -= cnt; else rhp->end_meta = to; } } } while (to + cnt < zlemetall) { zlemetaline[to] = zlemetaline[to + cnt]; to++; } zlemetaline[zlemetall = to] = '\0'; } else { /* before to is updated... */ if (region_highlights) { for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS; rhp < region_highlights + n_region_highlights; rhp++) { if (rhp->flags & ZRH_PREDISPLAY) sub = predisplaylen; else sub = 0; if (rhp->start - sub > to) { if (rhp->start - sub > to + cnt) rhp->start -= cnt; else rhp->start = to; } if (rhp->end - sub > to) { if (rhp->end - sub > to + cnt) rhp->end -= cnt; else rhp->end = to; } } } while (to + cnt < zlell) { zleline[to] = zleline[to + cnt]; to++; } zleline[zlell = to] = ZWC('\0'); } region_active = 0; }