about summary refs log tree commit diff
path: root/Src/Zle
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2003-10-28 16:52:17 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2003-10-28 16:52:17 +0000
commit40dcdf68a2368b0e889a6be5d7b6323101fcbe9f (patch)
treec0428f62747bfb85bf45a6aa2c30874b928bd235 /Src/Zle
parent0d78947de1c8480825836d76a6c6c36591e4b13e (diff)
downloadzsh-40dcdf68a2368b0e889a6be5d7b6323101fcbe9f.tar.gz
zsh-40dcdf68a2368b0e889a6be5d7b6323101fcbe9f.tar.xz
zsh-40dcdf68a2368b0e889a6be5d7b6323101fcbe9f.zip
19209: Rename zcalloc to zshcalloc.
Diffstat (limited to 'Src/Zle')
-rw-r--r--Src/Zle/compcore.c12
-rw-r--r--Src/Zle/compctl.c30
-rw-r--r--Src/Zle/complete.c4
-rw-r--r--Src/Zle/computil.c2
-rw-r--r--Src/Zle/zle_keymap.c160
-rw-r--r--Src/Zle/zle_main.c160
-rw-r--r--Src/Zle/zle_refresh.c4
-rw-r--r--Src/Zle/zle_thingy.c20
8 files changed, 297 insertions, 95 deletions
diff --git a/Src/Zle/compcore.c b/Src/Zle/compcore.c
index 3ea9e8c4c..03e5eafc7 100644
--- a/Src/Zle/compcore.c
+++ b/Src/Zle/compcore.c
@@ -616,7 +616,7 @@ callcompfunc(char *s, char *fn)
 		untokenize(*q = ztrdup(*p));
 	    *q = NULL;
 	} else
-	    compwords = (char **) zcalloc(sizeof(char *));
+	    compwords = (char **) zshcalloc(sizeof(char *));
 
 	compparameter = ztrdup(compparameter);
 	compredirect = ztrdup(compredirect);
@@ -2706,7 +2706,7 @@ dupmatch(Cmatch m, int nbeg, int nend)
 {
     Cmatch r;
 
-    r = (Cmatch) zcalloc(sizeof(struct cmatch));
+    r = (Cmatch) zshcalloc(sizeof(struct cmatch));
 
     r->str = ztrdup(m->str);
     r->ipre = ztrdup(m->ipre);
@@ -2803,7 +2803,7 @@ permmatches(int last)
 	    if (g->mcount > 1)
 		diffmatches = 1;
 
-	    n = (Cmgroup) zcalloc(sizeof(struct cmgroup));
+	    n = (Cmgroup) zshcalloc(sizeof(struct cmgroup));
 
 	    if (g->perm) {
 		g->perm->next = NULL;
@@ -2821,7 +2821,7 @@ permmatches(int last)
 	    n->num = gn++;
 	    n->flags = g->flags;
 	    n->mcount = g->mcount;
-	    n->matches = p = (Cmatch *) zcalloc((n->mcount + 1) * sizeof(Cmatch));
+	    n->matches = p = (Cmatch *) zshcalloc((n->mcount + 1) * sizeof(Cmatch));
 	    n->name = ztrdup(g->name);
 	    for (q = g->matches; *q; q++, p++)
 		*p = dupmatch(*q, nbrbeg, nbrend);
@@ -2835,9 +2835,9 @@ permmatches(int last)
 		n->ylist = NULL;
 
 	    if ((n->ecount = g->ecount)) {
-		n->expls = ep = (Cexpl *) zcalloc((n->ecount + 1) * sizeof(Cexpl));
+		n->expls = ep = (Cexpl *) zshcalloc((n->ecount + 1) * sizeof(Cexpl));
 		for (eq = g->expls; (o = *eq); eq++, ep++) {
-		    *ep = e = (Cexpl) zcalloc(sizeof(struct cexpl));
+		    *ep = e = (Cexpl) zshcalloc(sizeof(struct cexpl));
 		    e->count = (fi ? o->fcount : o->count);
 		    e->fcount = 0;
 		    e->str = ztrdup(o->str);
diff --git a/Src/Zle/compctl.c b/Src/Zle/compctl.c
index b4981a842..d364e09d4 100644
--- a/Src/Zle/compctl.c
+++ b/Src/Zle/compctl.c
@@ -242,7 +242,7 @@ compctlread(char *name, char **args, char *ops, char *reply)
 	if (ops['A'] && !ops['e']) {
 	    /* the -A option means that one array is specified, instead of
 	    many parameters */
-	    char **p, **b = (char **)zcalloc((clwnum + 1) * sizeof(char *));
+	    char **p, **b = (char **)zshcalloc((clwnum + 1) * sizeof(char *));
 
 	    for (i = 0, p = b; i < clwnum; p++, i++)
 		*p = ztrdup(clwords[i]);
@@ -893,7 +893,7 @@ get_compctl(char *name, char ***av, Compctl cc, int first, int isdef, int cl)
 		    cc->xor = &cc_default;
 	    } else {
 		/* more flags follow:  prepare to loop again */
-		cc->xor = (Compctl) zcalloc(sizeof(*cc));
+		cc->xor = (Compctl) zshcalloc(sizeof(*cc));
 		cc = cc->xor;
 		memset((void *)&cct, 0, sizeof(cct));
 		cct.mask2 = CC_CCCONT;
@@ -930,7 +930,7 @@ get_xcompctl(char *name, char ***av, Compctl cc, int isdef)
 	/* o keeps track of or's, m remembers the starting condition,
 	 * c is the current condition being parsed
 	 */
-	o = m = c = (Compcond) zcalloc(sizeof(*c));
+	o = m = c = (Compcond) zshcalloc(sizeof(*c));
 	/* Loop over each condition:  something like 's[...][...], p[...]' */
 	for (t = *argv; *t;) {
 	    while (*t == ' ')
@@ -1021,20 +1021,20 @@ get_xcompctl(char *name, char ***av, Compctl cc, int isdef)
 	    /* Allocate space for all the arguments of the conditions */
 	    if (c->type == CCT_POS ||
 		c->type == CCT_NUMWORDS) {
-		c->u.r.a = (int *)zcalloc(n * sizeof(int));
-		c->u.r.b = (int *)zcalloc(n * sizeof(int));
+		c->u.r.a = (int *)zshcalloc(n * sizeof(int));
+		c->u.r.b = (int *)zshcalloc(n * sizeof(int));
 	    } else if (c->type == CCT_CURSUF ||
 		       c->type == CCT_CURPRE ||
 		       c->type == CCT_QUOTE)
-		c->u.s.s = (char **)zcalloc(n * sizeof(char *));
+		c->u.s.s = (char **)zshcalloc(n * sizeof(char *));
 
 	    else if (c->type == CCT_RANGESTR ||
 		     c->type == CCT_RANGEPAT) {
-		c->u.l.a = (char **)zcalloc(n * sizeof(char *));
-		c->u.l.b = (char **)zcalloc(n * sizeof(char *));
+		c->u.l.a = (char **)zshcalloc(n * sizeof(char *));
+		c->u.l.b = (char **)zshcalloc(n * sizeof(char *));
 	    } else {
-		c->u.s.p = (int *)zcalloc(n * sizeof(int));
-		c->u.s.s = (char **)zcalloc(n * sizeof(char *));
+		c->u.s.p = (int *)zshcalloc(n * sizeof(int));
+		c->u.s.s = (char **)zshcalloc(n * sizeof(char *));
 	    }
 	    /* Now loop over the actual arguments */
 	    for (l = 0; *t == '['; l++, t++) {
@@ -1137,17 +1137,17 @@ get_xcompctl(char *name, char ***av, Compctl cc, int isdef)
 		t++;
 	    if (*t == ',') {
 		/* Another condition to `or' */
-		o->or = c = (Compcond) zcalloc(sizeof(*c));
+		o->or = c = (Compcond) zshcalloc(sizeof(*c));
 		o = c;
 		t++;
 	    } else if (*t) {
 		/* Another condition to `and' */
-		c->and = (Compcond) zcalloc(sizeof(*c));
+		c->and = (Compcond) zshcalloc(sizeof(*c));
 		c = c->and;
 	    }
 	}
 	/* Assign condition to current compctl */
-	*next = (Compctl) zcalloc(sizeof(*cc));
+	*next = (Compctl) zshcalloc(sizeof(*cc));
 	(*next)->cond = m;
 	argv++;
 	/* End of the condition; get the flags that go with it. */
@@ -1271,7 +1271,7 @@ cc_reassign(Compctl cc)
      */
     Compctl c2;
 
-    c2 = (Compctl) zcalloc(sizeof *cc);
+    c2 = (Compctl) zshcalloc(sizeof *cc);
     c2->xor = cc->xor;
     c2->ext = cc->ext;
     c2->refc = 1;
@@ -1587,7 +1587,7 @@ bin_compctl(char *name, char **argv, char *ops, int func)
 	if ((ret = get_gmatcher(name, argv)))
 	    return ret - 1;
 
-	cc = (Compctl) zcalloc(sizeof(*cc));
+	cc = (Compctl) zshcalloc(sizeof(*cc));
 	if (get_compctl(name, &argv, cc, 1, 0, 0)) {
 	    freecompctl(cc);
 	    return 1;
diff --git a/Src/Zle/complete.c b/Src/Zle/complete.c
index 5f034a4a9..b9dc9f27a 100644
--- a/Src/Zle/complete.c
+++ b/Src/Zle/complete.c
@@ -686,7 +686,7 @@ restrict_range(int b, int e)
 	    e = wl;
 
 	i = e - b + 1;
-	p = (char **) zcalloc((i + 1) * sizeof(char *));
+	p = (char **) zshcalloc((i + 1) * sizeof(char *));
 
 	for (q = p, pp = compwords + b; i; i--, q++, pp++)
 	    *q = ztrdup(*pp);
@@ -1158,7 +1158,7 @@ compunsetfn(Param pm, int exp)
 		*((char **) pm->u.data) = ztrdup("");
 	    } else if (PM_TYPE(pm->flags) == PM_ARRAY) {
 		freearray(*((char ***) pm->u.data));
-		*((char ***) pm->u.data) = zcalloc(sizeof(char *));
+		*((char ***) pm->u.data) = zshcalloc(sizeof(char *));
 	    } else if (PM_TYPE(pm->flags) == PM_HASHED) {
 		deleteparamtable(pm->u.hash);
 		pm->u.hash = NULL;
diff --git a/Src/Zle/computil.c b/Src/Zle/computil.c
index 157a179af..500ad3163 100644
--- a/Src/Zle/computil.c
+++ b/Src/Zle/computil.c
@@ -124,7 +124,7 @@ cd_init(char *nam, char *sep, char **args, int disp)
     cd_state.showd = disp;
 
     while (*args) {
-	*setp = set = (Cdset) zcalloc(sizeof(*set));
+	*setp = set = (Cdset) zshcalloc(sizeof(*set));
 	setp = &(set->next);
 
 	if (!(ap = get_user_var(*args))) {
diff --git a/Src/Zle/zle_keymap.c b/Src/Zle/zle_keymap.c
index 28203655e..9ac6dc8ed 100644
--- a/Src/Zle/zle_keymap.c
+++ b/Src/Zle/zle_keymap.c
@@ -86,6 +86,16 @@ struct bindstate {
     char *lastseq;
     Thingy bind;
     char *str;
+    char *prefix;
+    int prefixlen;
+};
+
+/* This structure is used when scanning for prefix bindings to remove */
+
+struct remprefstate {
+    Keymap km;
+    char *prefix;
+    int prefixlen;
 };
 
 #define BS_LIST (1<<0)
@@ -146,7 +156,7 @@ createkeymapnamtab(void)
 static KeymapName
 makekeymapnamnode(Keymap keymap)
 {
-    KeymapName kmn = (KeymapName) zcalloc(sizeof(*kmn));
+    KeymapName kmn = (KeymapName) zshcalloc(sizeof(*kmn));
 
     kmn->keymap = keymap;
     return kmn;
@@ -191,7 +201,7 @@ newkeytab(char *kmname)
 static Key
 makekeynode(Thingy t, char *str)
 {
-    Key k = (Key) zcalloc(sizeof(*k));
+    Key k = (Key) zshcalloc(sizeof(*k));
 
     k->bind = t;
     k->str = str;
@@ -220,7 +230,7 @@ static HashTable copyto;
 mod_export Keymap
 newkeymap(Keymap tocopy, char *kmname)
 {
-    Keymap km = zcalloc(sizeof(*km));
+    Keymap km = zshcalloc(sizeof(*km));
     int i;
 
     km->rc = 0;
@@ -834,6 +844,19 @@ bin_bindkey_bind(char *name, char *kmname, Keymap km, char **argv, char *ops, ch
 	zwarnnam(name, "keymap `%s' is protected", kmname, 0);
 	return 1;
     }
+    if (func == 'r' && ops['p']) {
+	char *useq, *bseq;
+	int len;
+	struct remprefstate rps;
+	rps.km = km;
+	while ((useq = *argv++)) {
+	    bseq = getkeystring(useq, &len, 2, NULL);
+	    rps.prefix = metafy(bseq, len, META_USEHEAP);
+	    rps.prefixlen = strlen(rps.prefix);
+	    scankeymap(km, 0, scanremoveprefix, &rps);
+	}
+	return 0;
+    }
     do {
 	char *useq = *argv, *bseq, *seq, *str;
 	int len;
@@ -878,6 +901,20 @@ bin_bindkey_bind(char *name, char *kmname, Keymap km, char **argv, char *ops, ch
     return ret;
 }
 
+/* Remove bindings for key sequences which have the given (proper) prefix. */
+
+/**/
+static void
+scanremoveprefix(char *seq, Thingy bind, char *str, void *magic)
+{
+    struct remprefstate *rps = magic;
+
+    if (strncmp(seq, rps->prefix, rps->prefixlen) || !seq[rps->prefixlen])
+	return;
+
+    bindkey(rps->km, seq, refthingy(t_undefinedkey), NULL);
+}
+
 /* List key bindings.  If an argument is given, list just that one *
  * binding, otherwise list the entire keymap.  If the -L option is *
  * given, list in the form of bindkey commands.                    */
@@ -890,7 +927,7 @@ bin_bindkey_list(char *name, char *kmname, Keymap km, char **argv, char *ops, ch
 
     bs.flags = ops['L'] ? BS_LIST : 0;
     bs.kmname = kmname;
-    if(argv[0]) {
+    if(argv[0] && !ops['p']) {
 	int len;
 	char *seq;
 
@@ -899,8 +936,23 @@ bin_bindkey_list(char *name, char *kmname, Keymap km, char **argv, char *ops, ch
 	bs.flags |= BS_ALL;
 	bs.firstseq = bs.lastseq = seq;
 	bs.bind = keybind(km, seq, &bs.str);
+	bs.prefix = NULL;
+	bs.prefixlen = 0;
 	bindlistout(&bs);
     } else {
+	/* empty prefix is equivalent to no prefix */
+	if (ops['p'] && (!argv[0] || argv[0][0])) {
+	    if (!argv[0]) {
+		zwarnnam(name, "option -p requires a prefix string", NULL, 0);
+		return 1;
+	    }
+	    bs.prefix = getkeystring(argv[0], &bs.prefixlen, 2, NULL);
+	    bs.prefix = metafy(bs.prefix, bs.prefixlen, META_HREALLOC);
+	    bs.prefixlen = strlen(bs.prefix);
+	} else {
+	    bs.prefix = NULL;
+	    bs.prefixlen = 0;
+	}
 	bs.firstseq = ztrdup("");
 	bs.lastseq = ztrdup("");
 	bs.bind = t_undefinedkey;
@@ -919,6 +971,10 @@ scanbindlist(char *seq, Thingy bind, char *str, void *magic)
 {
     struct bindstate *bs = magic;
 
+    if (bs->prefixlen &&
+	(strncmp(seq, bs->prefix, bs->prefixlen) || !seq[bs->prefixlen]))
+	return;
+
     if(bind == bs->bind && (bind || !strcmp(str, bs->str)) &&
        ztrlen(seq) == 1 && ztrlen(bs->lastseq) == 1) {
 	int l = bs->lastseq[1] ?
@@ -1011,6 +1067,66 @@ cleanup_keymaps(void)
     zfree(keybuf, keybufsz);
 }
 
+static char *cursorptr;
+
+/* utility function for termcap output routine to add to string */
+
+static int 
+add_cursor_char(int c)
+{
+    *cursorptr++ = c;
+    return 0;
+}
+
+/* interrogate termcap for cursor keys and add bindings to keymap */
+
+/**/
+static void
+add_cursor_key(Keymap km, int tccode, Thingy thingy, int defchar)
+{
+    char buf[2048];
+    int ok = 0;
+
+    /*
+     * Be careful not to try too hard with bindings for dubious or
+     * dysfunctional terminals.
+     */
+    if (tccan(tccode) && !(termflags & (TERM_NOUP|TERM_BAD|TERM_UNKNOWN))) {
+	/*
+	 * We can use the real termcap sequence.  We need to
+	 * persuade termcap to output `move cursor 1 char' and capture it.
+	 */
+	cursorptr = buf;
+	tputs(tcstr[tccode], 1, add_cursor_char);
+	*cursorptr = '\0';
+
+	/*
+	 * Sanity checking.  If the cursor key is zero-length (unlikely,
+	 * but this is termcap we're talking about), or it's a single
+	 * character, then we don't bind it.
+	 */
+	if (buf[0] && buf[1] && (buf[0] != Meta || buf[2]))
+	    ok = 1;
+    }
+    if (!ok) {
+	/* Assume the normal VT100-like values. */
+	sprintf(buf, "\33[%c", defchar);
+    }
+    bindkey(km, buf, refthingy(thingy), NULL);
+
+    /*
+     * If the string looked like \e[? or \eO?, bind the other one, too.
+     * This is necessary to make cursor keys work on many xterms with
+     * both normal and application modes.
+     */
+    if (buf[0] == '\33' && (buf[1] == '[' || buf[1] == 'O') && 
+	buf[2] && !buf[3])
+    {
+	buf[1] = (buf[1] == '[') ? 'O' : '[';
+	bindkey(km, buf, refthingy(thingy), NULL);
+    }
+}
+
 /* Create the default keymaps.  For efficiency reasons, this function   *
  * assigns directly to the km->first array.  It knows that there are no *
  * prefix bindings in the way, and that it is using a simple keymap.    */
@@ -1023,6 +1139,7 @@ default_bindings(void)
     Keymap emap = newkeymap(NULL, "emacs");
     Keymap amap = newkeymap(NULL, "vicmd");
     Keymap smap = newkeymap(NULL, ".safe");
+    Keymap vimaps[2], kptr;
     char buf[3], *ed;
     int i;
 
@@ -1066,25 +1183,22 @@ default_bindings(void)
     /* vt100 arrow keys are bound by default, for historical reasons. *
      * Both standard and keypad modes are supported.                  */
 
-    /* vi command mode: arrow keys */
-    bindkey(amap, "\33[A",  refthingy(t_uplineorhistory), NULL);
-    bindkey(amap, "\33[B",  refthingy(t_downlineorhistory), NULL);
-    bindkey(amap, "\33[C",  refthingy(t_viforwardchar), NULL);
-    bindkey(amap, "\33[D",  refthingy(t_vibackwardchar), NULL);
-    bindkey(amap, "\33OA",  refthingy(t_uplineorhistory), NULL);
-    bindkey(amap, "\33OB",  refthingy(t_downlineorhistory), NULL);
-    bindkey(amap, "\33OC",  refthingy(t_viforwardchar), NULL);
-    bindkey(amap, "\33OD",  refthingy(t_vibackwardchar), NULL);
-
-    /* emacs mode: arrow keys */
-    bindkey(emap, "\33[A",  refthingy(t_uplineorhistory), NULL);
-    bindkey(emap, "\33[B",  refthingy(t_downlineorhistory), NULL);
-    bindkey(emap, "\33[C",  refthingy(t_forwardchar), NULL);
-    bindkey(emap, "\33[D",  refthingy(t_backwardchar), NULL);
-    bindkey(emap, "\33OA",  refthingy(t_uplineorhistory), NULL);
-    bindkey(emap, "\33OB",  refthingy(t_downlineorhistory), NULL);
-    bindkey(emap, "\33OC",  refthingy(t_forwardchar), NULL);
-    bindkey(emap, "\33OD",  refthingy(t_backwardchar), NULL);
+    vimaps[0] = vmap;
+    vimaps[1] = amap;
+    for (i = 0; i < 2; i++) {
+	kptr = vimaps[i];
+	/* vi command and insert modes: arrow keys */
+	add_cursor_key(kptr, TCUPCURSOR, t_uplineorhistory, 'A');
+	add_cursor_key(kptr, TCDOWNCURSOR, t_downlineorhistory, 'B');
+	add_cursor_key(kptr, TCLEFTCURSOR, t_vibackwardchar, 'D');
+	add_cursor_key(kptr, TCRIGHTCURSOR, t_viforwardchar, 'C');
+    }
+
+    /* emacs mode: arrow keys */ 
+    add_cursor_key(emap, TCUPCURSOR, t_uplineorhistory, 'A');
+    add_cursor_key(emap, TCDOWNCURSOR, t_downlineorhistory, 'B');
+    add_cursor_key(emap, TCLEFTCURSOR, t_backwardchar, 'D');
+    add_cursor_key(emap, TCRIGHTCURSOR, t_forwardchar, 'C');
    
     /* emacs mode: ^X sequences */
     bindkey(emap, "\30*",   refthingy(t_expandword), NULL);
diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c
index aa5086597..6156b40d0 100644
--- a/Src/Zle/zle_main.c
+++ b/Src/Zle/zle_main.c
@@ -76,7 +76,10 @@ mod_export Thingy lbindk, bindk;
 /**/
 int insmode;
 
-static int eofchar, eofsent;
+/**/
+mod_export int eofchar;
+
+static int eofsent;
 static long keytimeout;
 
 #ifdef HAVE_SELECT
@@ -313,6 +316,7 @@ breakread(int fd, char *buf, int n)
 
     FD_ZERO(&f);
     FD_SET(fd, &f);
+
     return (select(fd + 1, (SELECT_ARG_2_T) & f, NULL, NULL, NULL) == -1 ?
 	    EOF : read(fd, buf, n));
 }
@@ -395,7 +399,13 @@ getkey(int keytmout)
 # endif
 #endif
 	}
-	while ((r = read(SHTTY, &cc, 1)) != 1) {
+	for (;;) {
+	    int q = queue_signal_level();
+	    dont_queue_signals();
+	    r = read(SHTTY, &cc, 1);
+	    restore_queue_signals(q);
+	    if (r == 1)
+		break;
 	    if (r == 0) {
 		/* The test for IGNOREEOF was added to make zsh ignore ^Ds
 		   that were typed while commands are running.  Unfortuantely
@@ -556,7 +566,7 @@ zleread(char *lp, char *rp, int flags)
 	reselectkeymap();
 	selectlocalmap(NULL);
 	bindk = getkeycmd();
-	if (!ll && isfirstln && c == eofchar) {
+	if (!ll && isfirstln && unset(IGNOREEOF) && c == eofchar) {
 	    eofsent = 1;
 	    break;
 	}
@@ -630,23 +640,36 @@ execzlefunc(Thingy func, char **args)
     } else if((w = func->widget)->flags & (WIDGET_INT|WIDGET_NCOMP)) {
 	int wflags = w->flags;
 
-	if(!(wflags & ZLE_KEEPSUFFIX))
-	    removesuffix();
-	if(!(wflags & ZLE_MENUCMP)) {
-	    fixsuffix();
-	    invalidatelist();
+	if (keybuf[0] == eofchar && !keybuf[1] &&
+	    !ll && isfirstln && isset(IGNOREEOF)) {
+	    showmsg((!islogin) ? "zsh: use 'exit' to exit." :
+		    "zsh: use 'logout' to logout.");
+	    ret = 1;
+	} else {
+	    if(!(wflags & ZLE_KEEPSUFFIX))
+		removesuffix();
+	    if(!(wflags & ZLE_MENUCMP)) {
+		fixsuffix();
+		invalidatelist();
+	    }
+	    if (wflags & ZLE_LINEMOVE)
+		vilinerange = 1;
+	    if(!(wflags & ZLE_LASTCOL))
+		lastcol = -1;
+	    if (wflags & WIDGET_NCOMP) {
+		int atcurhist = histline == curhist;
+		compwidget = w;
+		ret = completecall(args);
+		if (atcurhist)
+		    histline = curhist;
+	    } else {
+		queue_signals();
+		ret = w->u.fn(args);
+		unqueue_signals();
+	    }
+	    if (!(wflags & ZLE_NOTCOMMAND))
+		lastcmd = wflags;
 	}
-	if (wflags & ZLE_LINEMOVE)
-	    vilinerange = 1;
-	if(!(wflags & ZLE_LASTCOL))
-	    lastcol = -1;
-	if (wflags & WIDGET_NCOMP) {
-	    compwidget = w;
-	    ret = completecall(args);
-	} else
-	    ret = w->u.fn(args);
-	if (!(wflags & ZLE_NOTCOMMAND))
-	    lastcmd = wflags;
 	r = 1;
     } else {
 	Eprog prog = getshfunc(w->u.fnnam);
@@ -735,11 +758,15 @@ bin_vared(char *name, char **args, char *ops, int func)
     struct value vbuf;
     Value v;
     Param pm = 0;
-    int create = 0, ifl;
+    int create = 0, ifl, ieof;
     int type = PM_SCALAR, obreaks = breaks, haso = 0;
     char *p1 = NULL, *p2 = NULL;
     FILE *oshout = NULL;
 
+    if ((interact && unset(USEZLE)) || !strcmp(term, "emacs")) {
+	zwarnnam(name, "ZLE not enabled", NULL, 0);
+	return 1;
+    }
     if (zleactive) {
 	zwarnnam(name, "ZLE cannot be used recursively (yet)", NULL, 0);
 	return 1;
@@ -810,17 +837,65 @@ bin_vared(char *name, char **args, char *ops, int func)
     }
     /* handle non-existent parameter */
     s = args[0];
+    queue_signals();
     v = fetchvalue(&vbuf, &s, (!create || type == PM_SCALAR),
 		   SCANPM_WANTKEYS|SCANPM_WANTVALS|SCANPM_MATCHMANY);
     if (!v && !create) {
+	unqueue_signals();
 	zwarnnam(name, "no such variable: %s", args[0], 0);
 	return 1;
     } else if (v) {
-	s = getstrvalue(v);
-	pm = v->pm;
+	if (v->isarr) {
+	    /* Array: check for separators and quote them. */
+	    char **arr = getarrvalue(v), **aptr, **tmparr, **tptr;
+	    tptr = tmparr = (char **)zhalloc(sizeof(char *)*(arrlen(arr)+1));
+	    for (aptr = arr; *aptr; aptr++) {
+		int sepcount = 0;
+		/*
+		 * See if this word contains a separator character
+		 * or backslash
+		 */
+		for (t = *aptr; *t; t++) {
+		    if (*t == Meta) {
+			if (isep(t[1] ^ 32))
+			    sepcount++;
+			t++;
+		    } else if (isep(*t) || *t == '\\')
+			sepcount++;
+		}
+		if (sepcount) {
+		    /* Yes, so allocate enough space to quote it. */
+		    char *newstr, *nptr;
+		    newstr = zhalloc(strlen(*aptr)+sepcount+1);
+		    /* Go through string quoting separators */
+		    for (t = *aptr, nptr = newstr; *t; ) {
+			if (*t == Meta) {
+			    if (isep(t[1] ^ 32))
+				*nptr++ = '\\';
+			    *nptr++ = *t++;
+			} else if (isep(*t) || *t == '\\')
+			    *nptr++ = '\\';
+			*nptr++ = *t++;
+		    }
+		    *nptr = '\0';
+		    /* Stick this into the array of words to join up */
+		    *tptr++ = newstr;
+		} else
+		    *tptr++ = *aptr; /* No, keep original array element */
+	    }
+	    *tptr = NULL;
+	    s = sepjoin(tmparr, NULL, 0);
+	} else {
+	    s = ztrdup(getstrvalue(v));
+	}
+	unqueue_signals();
     } else if (*s) {
+	unqueue_signals();
 	zwarnnam(name, "invalid parameter name: %s", args[0], 0);
 	return 1;
+    } else {
+	unqueue_signals();
+	s = ztrdup(s);
     }
 
     if (SHTTY == -1) {
@@ -835,22 +910,23 @@ bin_vared(char *name, char **args, char *ops, int func)
 	haso = 1;
     }
     /* edit the parameter value */
-    zpushnode(bufstack, ztrdup(s));
+    zpushnode(bufstack, s);
 
     varedarg = *args;
     ifl = isfirstln;
-    if (ops['e'])
-	isfirstln = 1;
     if (ops['h'])
-	hbegin(1);
+	hbegin(2);
+    isfirstln = ops['e'];
+    ieof = opts[IGNOREEOF];
+    opts[IGNOREEOF] = 0;
     t = (char *) zleread(p1, p2, ops['h'] ? ZLRF_HISTORY : 0);
+    opts[IGNOREEOF] = ieof;
     if (ops['h'])
-	hend();
+	hend(NULL);
     isfirstln = ifl;
     varedarg = ova;
     if (haso) {
-	close(SHTTY);
-	fclose(shout);
+	fclose(shout);	/* close(SHTTY) */
 	shout = oshout;
 	SHTTY = -1;
     }
@@ -864,24 +940,27 @@ bin_vared(char *name, char **args, char *ops, int func)
     if (t[strlen(t) - 1] == '\n')
 	t[strlen(t) - 1] = '\0';
     /* final assignment of parameter value */
-    if (create && (!pm || (type && PM_TYPE(pm->flags) != type))) {
-	if (pm)
-	    unsetparam(args[0]);
+    if (create) {
+	unsetparam(args[0]);
 	createparam(args[0], type);
-	pm = 0;
     }
-    if (!pm)
-	pm = (Param) paramtab->getnode(paramtab, args[0]);
+    queue_signals();
+    pm = (Param) paramtab->getnode(paramtab, args[0]);
     if (pm && (PM_TYPE(pm->flags) & (PM_ARRAY|PM_HASHED))) {
 	char **a;
 
-	a = spacesplit(t, 1, 0);
+	/*
+	 * Use spacesplit with fourth argument 1: identify quoted separators,
+	 * unquote but don't split.
+	 */
+	a = spacesplit(t, 1, 0, 1);
 	if (PM_TYPE(pm->flags) == PM_ARRAY)
 	    setaparam(args[0], a);
 	else
 	    sethparam(args[0], a);
     } else
 	setsparam(args[0], t);
+    unqueue_signals();
     return 0;
 }
 
@@ -1015,9 +1094,9 @@ zleaftertrap(Hookdef dummy, void *dat)
 }
 
 static struct builtin bintab[] = {
-    BUILTIN("bindkey", 0, bin_bindkey, 0, -1, 0, "evaMldDANmrsLR", NULL),
+    BUILTIN("bindkey", 0, bin_bindkey, 0, -1, 0, "evaMldDANmrsLRp", NULL),
     BUILTIN("vared",   0, bin_vared,   1,  7, 0, NULL,             NULL),
-    BUILTIN("zle",     0, bin_zle,     0, -1, 0, "lDANCLmMgGcRaU", NULL),
+    BUILTIN("zle",     0, bin_zle,     0, -1, 0, "lDANCLmMgGcRaUI", NULL),
 };
 
 /* The order of the entries in this table has to match the *HOOK
@@ -1040,7 +1119,6 @@ setup_(Module m)
 {
     /* Set up editor entry points */
     trashzleptr = trashzle;
-    gotwordptr = gotword;
     refreshptr = zrefresh;
     spaceinlineptr = spaceinline;
     zlereadptr = zleread;
@@ -1054,6 +1132,7 @@ setup_(Module m)
     /* miscellaneous initialisations */
     stackhist = stackcs = -1;
     kungetbuf = (char *) zalloc(kungetsz = 32);
+    comprecursive = 0;
 
     /* initialise the keymap system */
     init_keymaps();
@@ -1062,7 +1141,7 @@ setup_(Module m)
 
     incompfunc = incompctlfunc = hascompmod = 0;
 
-    clwords = (char **) zcalloc((clwsize = 16) * sizeof(char *));
+    clwords = (char **) zshcalloc((clwsize = 16) * sizeof(char *));
 
     return 0;
 }
@@ -1117,7 +1196,6 @@ finish_(Module m)
 
     /* editor entry points */
     trashzleptr = noop_function;
-    gotwordptr = noop_function;
     refreshptr = noop_function;
     spaceinlineptr = noop_function_int;
     zlereadptr = fallback_zleread;
diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c
index c432907d1..68860f391 100644
--- a/Src/Zle/zle_refresh.c
+++ b/Src/Zle/zle_refresh.c
@@ -133,8 +133,8 @@ resetvideo(void)
 	    free(nbuf);
 	    free(obuf);
 	}
-	nbuf = (char **)zcalloc((winh + 1) * sizeof(char *));
-	obuf = (char **)zcalloc((winh + 1) * sizeof(char *));
+	nbuf = (char **)zshcalloc((winh + 1) * sizeof(char *));
+	obuf = (char **)zshcalloc((winh + 1) * sizeof(char *));
 	nbuf[0] = (char *)zalloc(winw + 2);
 	obuf[0] = (char *)zalloc(winw + 2);
 
diff --git a/Src/Zle/zle_thingy.c b/Src/Zle/zle_thingy.c
index 1d1eaacf3..f40bd18b8 100644
--- a/Src/Zle/zle_thingy.c
+++ b/Src/Zle/zle_thingy.c
@@ -107,7 +107,7 @@ scanemptythingies(HashNode hn, int flags)
 static Thingy
 makethingynode(void)
 {
-    Thingy t = (Thingy) zcalloc(sizeof(*t));
+    Thingy t = (Thingy) zshcalloc(sizeof(*t));
 
     t->flags = DISABLED;
     return t;
@@ -339,6 +339,7 @@ bin_zle(char *name, char **args, char *ops, int func)
 	{ 'R', bin_zle_refresh, 0, -1 },
 	{ 'M', bin_zle_mesg, 1, 1 },
 	{ 'U', bin_zle_unget, 1, 1 },
+	{ 'I', bin_zle_invalidate, 0, 0 },
 	{ 0,   bin_zle_call, 0, -1 },
     };
     struct opn const *op, *opp;
@@ -396,10 +397,8 @@ bin_zle_refresh(char *name, char **args, char *ops, char func)
     char *s = statusline;
     int sl = statusll, ocl = clearlist;
 
-    if (!zleactive) {
-	zwarnnam(name, "can only be called from widget function", NULL, 0);
+    if (!zleactive)
 	return 1;
-    }
     statusline = NULL;
     statusll = 0;
     if (*args) {
@@ -628,7 +627,7 @@ bin_zle_call(char *name, char **args, char *ops, char func)
 		    return 1;
 		}
 		if (!args[0][1])
-		    args++;
+		    *++args = "" - 1;
 		modsave = zmod;
 		saveflag = 1;
 		zmod.mult = atoi(num);
@@ -656,6 +655,17 @@ bin_zle_call(char *name, char **args, char *ops, char func)
     return ret;
 }
 
+/**/
+static int
+bin_zle_invalidate(char *name, char **args, char *ops, char func)
+{
+    if (zleactive) {
+	trashzle();
+	return 0;
+    } else
+	return 1;
+}
+
 /*******************/
 /* initialiasation */
 /*******************/