/* * zle_params.c - ZLE special parameters * * This file is part of zsh, the Z shell. * * Copyright (c) 1992-1997 Paul Falstad * All rights reserved. * * Permission is hereby granted, without written agreement and without * license or royalty fees, to use, copy, modify, and distribute this * software and to distribute modified versions of this software for any * purpose, provided that the above copyright notice and the following * two paragraphs appear in all copies of this software. * * In no event shall Paul Falstad or the Zsh Development Group be liable * to any party for direct, indirect, special, incidental, or consequential * damages arising out of the use of this software and its documentation, * even if Paul Falstad and the Zsh Development Group have been advised of * the possibility of such damage. * * Paul Falstad and the Zsh Development Group specifically disclaim any * warranties, including, but not limited to, the implied warranties of * merchantability and fitness for a particular purpose. The software * provided hereunder is on an "as is" basis, and Paul Falstad and the * Zsh Development Group have no obligation to provide maintenance, * support, updates, enhancements, or modifications. * */ #include "zle.mdh" #include "zle_params.pro" /* * ZLE SPECIAL PARAMETERS: * * These special parameters are created, with a local scope, when * running user-defined widget functions. Reading and writing them * reads and writes bits of ZLE state. The parameters are: * * BUFFER (scalar) entire buffer contents * CURSOR (integer) cursor position; 0 <= $CURSOR <= $#BUFFER * LBUFFER (scalar) portion of buffer to the left of the cursor * RBUFFER (scalar) portion of buffer to the right of the cursor */ #define FN(X) ( (void (*) _((void))) (X) ) static struct zleparam { char *name; int type; void (*setfn) _((void)); void (*getfn) _((void)); void (*unsetfn) _((Param, int)); void *data; } zleparams[] = { { "BUFFER", PM_SCALAR, FN(set_buffer), FN(get_buffer), zleunsetfn, NULL }, { "CURSOR", PM_INTEGER, FN(set_cursor), FN(get_cursor), zleunsetfn, NULL }, { "MARK", PM_INTEGER, FN(set_mark), FN(get_mark), zleunsetfn, NULL }, { "LBUFFER", PM_SCALAR, FN(set_lbuffer), FN(get_lbuffer), zleunsetfn, NULL }, { "RBUFFER", PM_SCALAR, FN(set_rbuffer), FN(get_rbuffer), zleunsetfn, NULL }, { "PREBUFFER", PM_SCALAR | PM_READONLY, NULL, FN(get_prebuffer), zleunsetfn, NULL }, { "WIDGET", PM_SCALAR | PM_READONLY, NULL, FN(get_widget), zleunsetfn, NULL }, { "LASTWIDGET", PM_SCALAR | PM_READONLY, NULL, FN(get_lwidget), zleunsetfn, NULL }, { "KEYMAP", PM_SCALAR | PM_READONLY, NULL, FN(get_keymap), zleunsetfn, NULL }, { "KEYS", PM_SCALAR | PM_READONLY, NULL, FN(get_keys), zleunsetfn, NULL }, { "NUMERIC", PM_INTEGER | PM_UNSET, FN(set_numeric), FN(get_numeric), unset_numeric, NULL }, { "HISTNO", PM_INTEGER | PM_READONLY, NULL, FN(get_histno), zleunsetfn, NULL }, { "BUFFERLINES", PM_INTEGER | PM_READONLY, NULL, FN(get_bufferlines), zleunsetfn, NULL }, { "PENDING", PM_INTEGER | PM_READONLY, NULL, FN(get_pending), zleunsetfn, NULL }, { "CUTBUFFER", PM_SCALAR, FN(set_cutbuffer), FN(get_cutbuffer), unset_cutbuffer, NULL }, { "killring", PM_ARRAY, FN(set_killring), FN(get_killring), unset_killring, NULL }, { "PREDISPLAY", PM_SCALAR, FN(set_predisplay), FN(get_predisplay), zleunsetfn, NULL }, { "POSTDISPLAY", PM_SCALAR, FN(set_postdisplay), FN(get_postdisplay), zleunsetfn, NULL }, { "LASTSEARCH", PM_SCALAR | PM_READONLY, NULL, FN(get_lsearch), zleunsetfn, NULL }, { NULL, 0, NULL, NULL, NULL, NULL } }; /**/ mod_export void makezleparams(int ro) { struct zleparam *zp; for(zp = zleparams; zp->name; zp++) { Param pm = createparam(zp->name, (zp->type |PM_SPECIAL|PM_REMOVABLE| PM_LOCAL|(ro ? PM_READONLY : 0))); if (!pm) pm = (Param) paramtab->getnode(paramtab, zp->name); DPUTS(!pm, "param not set in makezleparams"); pm->level = locallevel + 1; pm->u.data = zp->data; switch(PM_TYPE(zp->type)) { case PM_SCALAR: pm->sets.cfn = (void (*) _((Param, char *))) zp->setfn; pm->gets.cfn = (char *(*) _((Param))) zp->getfn; break; case PM_ARRAY: pm->sets.afn = (void (*) _((Param, char **))) zp->setfn; pm->gets.afn = (char **(*) _((Param))) zp->getfn; break; case PM_INTEGER: pm->sets.ifn = (void (*) _((Param, zlong))) zp->setfn; pm->gets.ifn = (zlong (*) _((Param))) zp->getfn; pm->ct = 10; break; } pm->unsetfn = zp->unsetfn; if ((zp->type & PM_UNSET) && (zmod.flags & MOD_MULT)) pm->flags &= ~PM_UNSET; } } /* Special unset function for ZLE special parameters: act like the standard * * unset function if this is a user-initiated unset, but nothing is done if * * the parameter is merely going out of scope (which it will do). */ /**/ static void zleunsetfn(Param pm, int exp) { if(exp) stdunsetfn(pm, exp); } /**/ static void set_buffer(Param pm, char *x) { if(x) { unmetafy(x, &ll); sizeline(ll); strcpy((char *)line, x); zsfree(x); if(cs > ll) cs = ll; } else cs = ll = 0; fixsuffix(); menucmp = 0; } /**/ static char * get_buffer(Param pm) { return metafy((char *)line, ll, META_HEAPDUP); } /**/ static void set_cursor(Param pm, zlong x) { if(x < 0) cs = 0; else if(x > ll) cs = ll; else cs = x; fixsuffix(); menucmp = 0; } /**/ static zlong get_cursor(Param pm) { return cs; } /**/ static void set_mark(Param pm, zlong x) { if (x < 0) mark = 0; else if (x > ll) mark = ll; else mark = x; } /**/ static zlong get_mark(Param pm) { return mark; } /**/ static void set_lbuffer(Param pm, char *x) { char *y; int len; if(x) unmetafy(y = x, &len); else y = "", len = 0; sizeline(ll - cs + len); memmove(line + len, line + cs, ll - cs); memcpy(line, y, len); ll = ll - cs + len; cs = len; zsfree(x); fixsuffix(); menucmp = 0; } /**/ static char * get_lbuffer(Param pm) { return metafy((char *)line, cs, META_HEAPDUP); } /**/ static void set_rbuffer(Param pm, char *x) { char *y; int len; if(x) unmetafy(y = x, &len); else y = "", len = 0; sizeline(ll = cs + len); memcpy(line + cs, y, len); zsfree(x); fixsuffix(); menucmp = 0; } /**/ static char * get_rbuffer(Param pm) { return metafy((char *)line + cs, ll - cs, META_HEAPDUP); } /**/ static char * get_prebuffer(Param pm) { if (chline) return dupstrpfx(chline, hptr - chline); else return dupstring(""); } /**/ static char * get_widget(Param pm) { return bindk->nam; } /**/ static char * get_lwidget(Param pm) { return (lbindk ? lbindk->nam : ""); } /**/ static char * get_keymap(Param pm) { return dupstring(curkeymapname); } /**/ static char * get_keys(Param pm) { return keybuf; } /**/ static void set_numeric(Param pm, zlong x) { zmult = x; zmod.flags = MOD_MULT; } /**/ static zlong get_numeric(Param pm) { return zmult; } /**/ static void unset_numeric(Param pm, int exp) { if (exp) { stdunsetfn(pm, exp); zmod.flags = 0; zmult = 1; } } /**/ static zlong get_histno(Param pm) { return histline; } /**/ static zlong get_bufferlines(Param pm) { return nlnct; } /**/ static zlong get_pending(Param pm) { return noquery(0); } /**/ static char * get_cutbuffer(Param pm) { if (cutbuf.buf) return metafy(cutbuf.buf, cutbuf.len, META_HEAPDUP); else return ""; } /**/ static void set_cutbuffer(Param pm, char *x) { if (cutbuf.buf) free(cutbuf.buf); cutbuf.flags = 0; if (x) { unmetafy(x, &cutbuf.len); cutbuf.buf = zalloc(cutbuf.len); strcpy((char *)cutbuf.buf, x); zsfree(x); } else { cutbuf.buf = NULL; cutbuf.len = 0; } } /**/ static void unset_cutbuffer(Param pm, int exp) { if (exp) { stdunsetfn(pm, exp); if (cutbuf.buf) { free(cutbuf.buf); cutbuf.buf = NULL; cutbuf.len = 0; } } } /**/ static void set_killring(Param pm, char **x) { int kpos, kcnt; char **p; kcnt = 0; kpos = kringnum; if (x) { /* * Insert the elements into the kill ring, up to a maximum * of KRINGCT. We always handle the ring in the order * a series of yank-pops would show, i.e. starting with * the most recently cut and going backwards. */ for (p = x; kcnt < KRINGCT && *p; kcnt++, p++) { Cutbuffer kptr = kring + kpos; if (kptr->buf) free(kptr->buf); kptr->buf = (char *)zalloc(strlen(*p)); strcpy(kptr->buf, *p); unmetafy(kptr->buf, &kptr->len); kptr->flags = 0; kpos = (kpos + KRINGCT - 1) % KRINGCT; } freearray(x); } /* * Any values unsupplied are to be unset. */ for (; kcnt < KRINGCT; kcnt++) { Cutbuffer kptr = kring + kpos; if (kptr->buf) { free(kptr->buf); kptr->buf = NULL; kptr->flags = kptr->len = 0; } kpos = (kpos + KRINGCT - 1) % KRINGCT; } } /**/ static char ** get_killring(Param pm) { /* * Return the kill ring with the most recently killed first. * Stop as soon as we find something which isn't set, i.e. * don't fill in bogus entries. */ int kpos, kcnt; char **ret, **p; for (kpos = kringnum, kcnt = 0; kcnt < KRINGCT; kcnt++) { if (!kring[kpos].buf) break; kpos = (kpos + KRINGCT - 1) % KRINGCT; } p = ret = (char **)zhalloc((kcnt+1) * sizeof(char *)); for (kpos = kringnum; kcnt; kcnt--) { *p++ = metafy((char *)kring[kpos].buf, kring[kpos].len, META_HEAPDUP); kpos = (kpos + KRINGCT - 1) % KRINGCT; } *p = NULL; return ret; } /**/ static void unset_killring(Param pm, int exp) { if (exp) { set_killring(pm, NULL); stdunsetfn(pm, exp); } } static void set_prepost(unsigned char **textvar, int *lenvar, char *x) { if (*lenvar) { zfree(*textvar, *lenvar); *textvar = NULL; *lenvar = 0; } if (x) { unmetafy(x, lenvar); *textvar = (unsigned char *)zalloc(*lenvar); memcpy((char *)*textvar, x, *lenvar); free(x); } } static char * get_prepost(unsigned char *text, int len) { return metafy((char *)text, len, META_HEAPDUP); } /**/ static void set_predisplay(Param pm, char *x) { set_prepost(&predisplay, &predisplaylen, x); } /**/ static char * get_predisplay(Param pm) { return get_prepost(predisplay, predisplaylen); } /**/ static void set_postdisplay(Param pm, char *x) { set_prepost(&postdisplay, &postdisplaylen, x); } /**/ static char * get_postdisplay(Param pm) { return get_prepost(postdisplay, postdisplaylen); } /**/ void free_prepostdisplay(void) { if (predisplaylen) set_prepost(&predisplay, &predisplaylen, NULL); if (postdisplaylen) set_prepost(&postdisplay, &postdisplaylen, NULL); } /**/ static char * get_lsearch(Param pm) { if (previous_search_len) return metafy(previous_search, previous_search_len, META_HEAPDUP); else return ""; }