diff options
Diffstat (limited to 'Src/Zle/zle_main.c')
-rw-r--r-- | Src/Zle/zle_main.c | 106 |
1 files changed, 91 insertions, 15 deletions
diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c index 9bea76e9b..dda2f56e6 100644 --- a/Src/Zle/zle_main.c +++ b/Src/Zle/zle_main.c @@ -471,7 +471,7 @@ calc_timeout(struct ztmout *tmoutp, long do_keytmout) tfdat = (Timedfn)getdata(tfnode); diff = tfdat->when - time(NULL); - if (diff < 0) { + if (diff <= 0) { /* Already due; call it and rescan. */ tfdat->func(); continue; @@ -924,13 +924,13 @@ getbyte(long do_keytmout, int *timeout) ret = STOUC(cc); } /* - * vichgbuf is raw bytes, not wide characters, so is dealt + * curvichg.buf is raw bytes, not wide characters, so is dealt * with here. */ if (vichgflag) { - if (vichgbufptr == vichgbufsz) - vichgbuf = realloc(vichgbuf, vichgbufsz *= 2); - vichgbuf[vichgbufptr++] = ret; + if (curvichg.bufptr == curvichg.bufsz) + curvichg.buf = realloc(curvichg.buf, curvichg.bufsz *= 2); + curvichg.buf[curvichg.bufptr++] = ret; } errno = old_errno; return lastchar = ret; @@ -1041,28 +1041,43 @@ getrestchar(int inchar, char *outstr, int *outcount) #endif /**/ -void redrawhook(void) +void +redrawhook(void) { Thingy initthingy; if ((initthingy = rthingy_nocreate("zle-line-pre-redraw"))) { + /* Duplicating most of zlecallhook() to save additional state */ + int saverrflag = errflag, savretflag = retflag; int lastcmd_prev = lastcmd; int old_incompfunc = incompfunc; char *args[2]; Thingy lbindk_save = lbindk, bindk_save = bindk; + refthingy(lbindk_save); refthingy(bindk_save); args[0] = initthingy->nam; args[1] = NULL; + + /* The generic redraw hook cannot be a completion function, so + * temporarily reset state for special variable handling etc. + */ incompfunc = 0; - execzlefunc(initthingy, args, 0); + execzlefunc(initthingy, args, 1); incompfunc = old_incompfunc; + + /* Restore errflag and retflag as zlecallhook() does */ + errflag = saverrflag | (errflag & ERRFLAG_INT); + retflag = savretflag; + unrefthingy(initthingy); unrefthingy(lbindk); unrefthingy(bindk); lbindk = lbindk_save; bindk = bindk_save; + /* we can't set ZLE_NOTCOMMAND since it's not a legit widget, so - * restore lastcmd manually so that we don't mess up the global state */ + * restore lastcmd manually so that we don't mess up the global state + */ lastcmd = lastcmd_prev; } } @@ -1159,11 +1174,19 @@ zlecore(void) } - region_active = 0; popheap(); } -/* Read a line. It is returned metafied. */ +/* Read a line. It is returned metafied. + * + * Parameters: + * - lp: left prompt, e.g., $PS1 + * - rp: right prompt, e.g., $RPS1 + * - flags: ZLRF_* flags (I think), see zlereadflags + * - context: ZLCON_* flags (I think), see zlecontext + * - init: "zle-line-init" + * - finish: "zle-line-finish" + */ /**/ char * @@ -1223,6 +1246,7 @@ zleread(char **lp, char **rp, int flags, int context, char *init, char *finish) resetneeded = 0; fetchttyinfo = 0; trashedzle = 0; + clearflag = 0; raw_lp = lp; lpromptbuf = promptexpand(lp ? *lp : NULL, 1, NULL, NULL, &pmpt_attr); raw_rp = rp; @@ -1238,6 +1262,7 @@ zleread(char **lp, char **rp, int flags, int context, char *init, char *finish) *zleline = ZWC('\0'); virangeflag = lastcmd = done = zlecs = zlell = mark = yankb = yanke = 0; vichgflag = 0; + viinrepeat = 0; viinsbegin = 0; statusline = NULL; selectkeymap("main", 1); @@ -1293,6 +1318,7 @@ zleread(char **lp, char **rp, int flags, int context, char *init, char *finish) lastcol = -1; initmodifier(&zmod); prefixflag = 0; + region_active = 0; zrefresh(); @@ -1300,7 +1326,11 @@ zleread(char **lp, char **rp, int flags, int context, char *init, char *finish) zlecallhook(init, NULL); - if ((bracket = getaparam("zle_bracketed_paste", &bracket_len)) && bracket_len == 2) + if (zleline && *zleline) + redrawhook(); + + if ((bracket = getaparam("zle_bracketed_paste", &bracket_len)) && + bracket_len == 2) fputs(*bracket, shout); zrefresh(); @@ -1342,6 +1372,16 @@ zleread(char **lp, char **rp, int flags, int context, char *init, char *finish) return s; } +/**/ +static int +execimmortal(Thingy func, char **args) +{ + Thingy immortal = rthingy_nocreate(dyncat(".", func->nam)); + if (immortal) + return execzlefunc(immortal, args, 0); + return 1; +} + /* * Execute a widget. The third argument indicates that the global * variable bindk should be set temporarily so that WIDGET etc. @@ -1353,6 +1393,8 @@ int execzlefunc(Thingy func, char **args, int set_bindk) { int r = 0, ret = 0, remetafy = 0; + int nestedvichg = vichgflag; + int isrepeat = (viinrepeat == 3); Widget w; Thingy save_bindk = bindk; @@ -1362,8 +1404,10 @@ execzlefunc(Thingy func, char **args, int set_bindk) unmetafy_line(); remetafy = 1; } + if (isrepeat) + viinrepeat = 2; - if(func->flags & DISABLED) { + if (func->flags & DISABLED) { /* this thingy is not the name of a widget */ char *nm = nicedup(func->nam, 0); char *msg = tricat("No such widget `", nm, "'"); @@ -1371,7 +1415,7 @@ execzlefunc(Thingy func, char **args, int set_bindk) zsfree(nm); showmsg(msg); zsfree(msg); - ret = 1; + ret = execimmortal(func, args); } else if((w = func->widget)->flags & (WIDGET_INT|WIDGET_NCOMP)) { int wflags = w->flags; @@ -1435,7 +1479,7 @@ execzlefunc(Thingy func, char **args, int set_bindk) zsfree(nm); showmsg(msg); zsfree(msg); - ret = 1; + ret = execimmortal(func, args); } else { int osc = sfcontext, osi = movefd(0); int oxt = isset(XTRACE); @@ -1457,6 +1501,12 @@ execzlefunc(Thingy func, char **args, int set_bindk) opts[XTRACE] = oxt; sfcontext = osc; endparamscope(); + if (errflag == ERRFLAG_ERROR) { + int saverr = errflag; + errflag &= ~ERRFLAG_ERROR; + if ((ret = execimmortal(func, args)) != 0) + errflag |= saverr; + } lastcmd = w->flags & ~(WIDGET_INUSE|WIDGET_FREE); if (inuse) { w->flags &= WIDGET_INUSE|WIDGET_FREE; @@ -1485,6 +1535,25 @@ execzlefunc(Thingy func, char **args, int set_bindk) CCRIGHT(); if (remetafy) metafy_line(); + + /* if this widget constituted the vi change, end it */ + if (vichgflag == 2 && !nestedvichg) { + if (invicmdmode()) { + if (ret) { + free(curvichg.buf); + } else { + if (lastvichg.buf) + free(lastvichg.buf); + lastvichg = curvichg; + } + vichgflag = 0; + curvichg.buf = NULL; + } else + vichgflag = 1; /* vi change continues while in insert mode */ + } + if (isrepeat) + viinrepeat = !invicmdmode(); + return ret; } @@ -1620,6 +1689,7 @@ bin_vared(char *name, char **args, Options ops, UNUSED(int func)) return 1; } else if (v) { if (*s) { + unqueue_signals(); zwarnnam(name, "not an identifier: `%s'", args[0]); return 1; } @@ -1856,11 +1926,17 @@ int recursiveedit(UNUSED(char **args)) { int locerror; + int q = queue_signal_level(); + + /* zlecore() expects to be entered with signal queue disabled */ + dont_queue_signals(); redrawhook(); zrefresh(); zlecore(); + restore_queue_signals(q); + locerror = errflag ? 1 : 0; errflag = done = eofsent = 0; @@ -2185,7 +2261,7 @@ finish_(UNUSED(Module m)) cleanup_keymaps(); deletehashtable(thingytab); - zfree(vichgbuf, vichgbufsz); + zfree(lastvichg.buf, lastvichg.bufsz); zfree(kungetbuf, kungetsz); free_isrch_spots(); if (rdstrs) |