home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / UNIX / Shells / zsh-3.0.5-MIHS / src / Src / zle_main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-09-25  |  29.4 KB  |  1,214 lines

  1. /*
  2.  * $Id: zle_main.c,v 2.29 1996/10/25 19:27:45 hzoli Exp $
  3.  *
  4.  * zle_main.c - main routines for line editor
  5.  *
  6.  * This file is part of zsh, the Z shell.
  7.  *
  8.  * Copyright (c) 1992-1996 Paul Falstad
  9.  * All rights reserved.
  10.  *
  11.  * Permission is hereby granted, without written agreement and without
  12.  * license or royalty fees, to use, copy, modify, and distribute this
  13.  * software and to distribute modified versions of this software for any
  14.  * purpose, provided that the above copyright notice and the following
  15.  * two paragraphs appear in all copies of this software.
  16.  *
  17.  * In no event shall Paul Falstad or the Zsh Development Group be liable
  18.  * to any party for direct, indirect, special, incidental, or consequential
  19.  * damages arising out of the use of this software and its documentation,
  20.  * even if Paul Falstad and the Zsh Development Group have been advised of
  21.  * the possibility of such damage.
  22.  *
  23.  * Paul Falstad and the Zsh Development Group specifically disclaim any
  24.  * warranties, including, but not limited to, the implied warranties of
  25.  * merchantability and fitness for a particular purpose.  The software
  26.  * provided hereunder is on an "as is" basis, and Paul Falstad and the
  27.  * Zsh Development Group have no obligation to provide maintenance,
  28.  * support, updates, enhancements, or modifications.
  29.  *
  30.  */
  31.  
  32. /*
  33.  * Note on output from zle (PWS 1995/05/23):
  34.  *
  35.  * All input and output from the editor should be to/from the file descriptor
  36.  * `SHTTY' and FILE `shout'.  (Normally, the former is used for input
  37.  * operations, reading one key at a time, and the latter for output
  38.  * operations, flushing after each refresh()).  Thus fprintf(shout, ...),
  39.  * putc(..., shout), etc., should be used for output within zle.
  40.  *
  41.  * However, the functions printbind() and printbinding() can be invoked from
  42.  * the builtin bindkey as well as zle, in which case output should be to
  43.  * stdout.  For this purpose, the static variable FILE *bindout exists, which
  44.  * is set to stdout in bin_bindkey() and shout in zleread().
  45.  */
  46.  
  47. #define ZLEGLOBALS
  48. #define ZLE
  49. #include "zsh.h"
  50.  
  51. static int emacs_cur_bindtab[256], eofchar, eofsent;
  52. static int viins_cur_bindtab[256];
  53.  
  54. static Key cky;
  55.  
  56. static char *keybuf = NULL;
  57. static int buflen;
  58. static long keytimeout;
  59.  
  60. /* set up terminal */
  61.  
  62. /**/
  63. void
  64. setterm(void)
  65. {
  66.     struct ttyinfo ti;
  67.  
  68. #if defined(CLOBBERS_TYPEAHEAD) && defined(FIONREAD)
  69.     int val;
  70.  
  71.     ioctl(SHTTY, FIONREAD, (char *)&val);
  72.     if (val)
  73.     return;
  74. #endif
  75.  
  76. /* sanitize the tty */
  77. #ifdef HAS_TIO
  78.     shttyinfo.tio.c_lflag |= ICANON | ECHO;
  79. # ifdef FLUSHO
  80.     shttyinfo.tio.c_lflag &= ~FLUSHO;
  81. # endif
  82. #else                /* not HAS_TIO */
  83.     shttyinfo.sgttyb.sg_flags = (shttyinfo.sgttyb.sg_flags & ~CBREAK) | ECHO;
  84.     shttyinfo.lmodes &= ~LFLUSHO;
  85. #endif
  86.  
  87.     attachtty(mypgrp);
  88.     ti = shttyinfo;
  89. #ifdef HAS_TIO
  90.     if (unset(FLOWCONTROL))
  91.     ti.tio.c_iflag &= ~IXON;
  92.     ti.tio.c_lflag &= ~(ICANON | ECHO
  93. # ifdef FLUSHO
  94.             | FLUSHO
  95. # endif
  96.     );
  97. # ifdef TAB3
  98.     ti.tio.c_oflag &= ~TAB3;
  99. # else
  100. #  ifdef OXTABS
  101.     ti.tio.c_oflag &= ~OXTABS;
  102. #  else
  103.     ti.tio.c_oflag &= ~XTABS;
  104. #  endif
  105. # endif
  106.     ti.tio.c_oflag |= ONLCR;
  107.     ti.tio.c_cc[VQUIT] =
  108. # ifdef VDISCARD
  109.     ti.tio.c_cc[VDISCARD] =
  110. # endif
  111. # ifdef VSUSP
  112.     ti.tio.c_cc[VSUSP] =
  113. # endif
  114. # ifdef VDSUSP
  115.     ti.tio.c_cc[VDSUSP] =
  116. # endif
  117. # ifdef VSWTCH
  118.     ti.tio.c_cc[VSWTCH] =
  119. # endif
  120. # ifdef VLNEXT
  121.     ti.tio.c_cc[VLNEXT] =
  122. # endif
  123.     VDISABLEVAL;
  124. # if defined(VSTART) && defined(VSTOP)
  125.     if (unset(FLOWCONTROL))
  126.     ti.tio.c_cc[VSTART] = ti.tio.c_cc[VSTOP] = VDISABLEVAL;
  127. # endif
  128.     eofchar = ti.tio.c_cc[VEOF];
  129.     ti.tio.c_cc[VMIN] = 1;
  130.     ti.tio.c_cc[VTIME] = 0;
  131.     ti.tio.c_iflag |= (INLCR | ICRNL);
  132.  /* this line exchanges \n and \r; it's changed back in getkey
  133.     so that the net effect is no change at all inside the shell.
  134.     This double swap is to allow typeahead in common cases, eg.
  135.  
  136.     % bindkey -s '^J' 'echo foo^M'
  137.     % sleep 10
  138.     echo foo<return>  <--- typed before sleep returns
  139.  
  140.     The shell sees \n instead of \r, since it was changed by the kernel
  141.     while zsh wasn't looking. Then in getkey() \n is changed back to \r,
  142.     and it sees "echo foo<accept line>", as expected. Without the double
  143.     swap the shell would see "echo foo\n", which is translated to
  144.     "echo fooecho foo<accept line>" because of the binding.
  145.     Note that if you type <line-feed> during the sleep the shell just sees
  146.     \n, which is translated to \r in getkey(), and you just get another
  147.     prompt. For type-ahead to work in ALL cases you have to use
  148.     stty inlcr.
  149.     This workaround is due to Sven Wischnowsky <oberon@cs.tu-berlin.de>.
  150.  
  151.     Unfortunately it's IMPOSSIBLE to have a general solution if both
  152.     <return> and <line-feed> are mapped to the same character. The shell
  153.     could check if there is input and read it before setting it's own
  154.     terminal modes but if we get a \n we don't know whether to keep it or
  155.     change to \r :-(
  156.     */
  157.  
  158. #else                /* not HAS_TIO */
  159.     ti.sgttyb.sg_flags = (ti.sgttyb.sg_flags | CBREAK) & ~ECHO & ~XTABS;
  160.     ti.lmodes &= ~LFLUSHO;
  161.     eofchar = ti.tchars.t_eofc;
  162.     ti.tchars.t_quitc =
  163.     ti.ltchars.t_suspc =
  164.     ti.ltchars.t_flushc =
  165.     ti.ltchars.t_dsuspc = ti.ltchars.t_lnextc = -1;
  166. #endif
  167.  
  168. #if defined(TTY_NEEDS_DRAINING) && defined(TIOCOUTQ) && defined(HAVE_SELECT)
  169.     if (baud) {            /**/
  170.     int n = 0;
  171.  
  172.     while ((ioctl(SHTTY, TIOCOUTQ, (char *)&n) >= 0) && n) {
  173.         struct timeval tv;
  174.  
  175.         tv.tv_sec = n / baud;
  176.         tv.tv_usec = ((n % baud) * 1000000) / baud;
  177.         select(0, NULL, NULL, NULL, &tv);
  178.     }
  179.     }
  180. #endif
  181.  
  182.     settyinfo(&ti);
  183. }
  184.  
  185. static char *kungetbuf;
  186. static int kungetct, kungetsz;
  187.  
  188. /**/
  189. void
  190. ungetkey(int ch)
  191. {
  192.     if (kungetct == kungetsz)
  193.     kungetbuf = realloc(kungetbuf, kungetsz *= 2);
  194.     kungetbuf[kungetct++] = ch;
  195. }
  196.  
  197. /**/
  198. void
  199. ungetkeys(char *s, int len)
  200. {
  201.     s += len;
  202.     while (len--)
  203.     ungetkey(*--s);
  204. }
  205.  
  206. #if defined(pyr) && defined(HAVE_SELECT)
  207. static int
  208. breakread(int fd, char *buf, int n)
  209. {
  210.     fd_set f;
  211.  
  212.     FD_ZERO(&f);
  213.     FD_SET(fd, &f);
  214.     return (select(fd + 1, (SELECT_ARG_2_T) & f, NULL, NULL, NULL) == -1 ?
  215.         EOF : read(fd, buf, n));
  216. }
  217.  
  218. # define read    breakread
  219. #endif
  220.  
  221. /**/
  222. int
  223. getkey(int keytmout)
  224. {
  225.     char cc;
  226.     unsigned int ret;
  227.     long exp100ths;
  228.     int die = 0, r, icnt = 0;
  229.     int old_errno = errno;
  230.  
  231. #ifdef HAVE_SELECT
  232.     fd_set foofd;
  233.  
  234. #else
  235. # ifdef HAS_TIO
  236.     struct ttyinfo ti;
  237.  
  238. # endif
  239. #endif
  240.  
  241.     if (kungetct)
  242.     ret = STOUC(kungetbuf[--kungetct]);
  243.     else {
  244.     if (keytmout) {
  245.         if (keytimeout > 500)
  246.         exp100ths = 500;
  247.         else if (keytimeout > 0)
  248.         exp100ths = keytimeout;
  249.         else
  250.         exp100ths = 0;
  251. #ifdef HAVE_SELECT
  252.         if (exp100ths) {
  253.         struct timeval expire_tv;
  254.  
  255.         expire_tv.tv_sec = exp100ths / 100;
  256.         expire_tv.tv_usec = (exp100ths % 100) * 10000L;
  257.         FD_ZERO(&foofd);
  258.         FD_SET(SHTTY, &foofd);
  259.         if (select(SHTTY+1, (SELECT_ARG_2_T) & foofd,
  260.                NULL, NULL, &expire_tv) <= 0)
  261.             return EOF;
  262.         }
  263. #else
  264. # ifdef HAS_TIO
  265.         ti = shttyinfo;
  266.         ti.tio.c_lflag &= ~ICANON;
  267.         ti.tio.c_cc[VMIN] = 0;
  268.         ti.tio.c_cc[VTIME] = exp100ths / 10;
  269. #  ifdef HAVE_TERMIOS_H
  270.         tcsetattr(SHTTY, TCSANOW, &ti.tio);
  271. #  else
  272.         ioctl(SHTTY, TCSETA, &ti.tio);
  273. #  endif
  274.         r = read(SHTTY, &cc, 1);
  275. #  ifdef HAVE_TERMIOS_H
  276.         tcsetattr(SHTTY, TCSANOW, &shttyinfo.tio);
  277. #  else
  278.         ioctl(SHTTY, TCSETA, &shttyinfo.tio);
  279. #  endif
  280.         return (r <= 0) ? EOF : cc;
  281. # endif
  282. #endif
  283.     }
  284.     while ((r = read(SHTTY, &cc, 1)) != 1) {
  285.         if (r == 0) {
  286.         /* The test for IGNOREEOF was added to make zsh ignore ^Ds
  287.            that were typed while commands are running.  Unfortuantely
  288.            this caused trouble under at least one system (SunOS 4.1).
  289.            Here shells that lost their xterm (e.g. if it was killed
  290.            with -9) didn't fail to read from the terminal but instead
  291.            happily continued to read EOFs, so that the above read
  292.            returned with 0, and, with IGNOREEOF set, this caused
  293.            an infinite loop.  The simple way around this was to add
  294.            the counter (icnt) so that this happens 20 times and than
  295.            the shell gives up (yes, this is a bit dirty...). */
  296.         if (isset(IGNOREEOF) && icnt++ < 20)
  297.             continue;
  298.         stopmsg = 1;
  299.         zexit(1, 0);
  300.         }
  301.         icnt = 0;
  302.         if (errno == EINTR) {
  303.         die = 0;
  304.         if (!errflag && !retflag && !breaks)
  305.             continue;
  306.         errflag = 0;
  307.         errno = old_errno;
  308.         return EOF;
  309.         } else if (errno == EWOULDBLOCK) {
  310.         fcntl(0, F_SETFL, 0);
  311.         } else if (errno == EIO && !die) {
  312.         ret = opts[MONITOR];
  313.         opts[MONITOR] = 1;
  314.         attachtty(mypgrp);
  315.         refresh();    /* kludge! */
  316.         opts[MONITOR] = ret;
  317.         die = 1;
  318.         } else if (errno != 0) {
  319.         zerr("error on TTY read: %e", NULL, errno);
  320.         stopmsg = 1;
  321.         zexit(1, 0);
  322.         }
  323.     }
  324.     if (cc == '\r')        /* undo the exchange of \n and \r determined by */
  325.         cc = '\n';        /* setterm() */
  326.     else if (cc == '\n')
  327.         cc = '\r';
  328.  
  329.     ret = STOUC(cc);
  330.     }
  331.     if (vichgflag) {
  332.     if (vichgbufptr == vichgbufsz)
  333.         vichgbuf = realloc(vichgbuf, vichgbufsz *= 2);
  334.     vichgbuf[vichgbufptr++] = ret;
  335.     }
  336.     errno = old_errno;
  337.     return ret;
  338. }
  339.  
  340. /* Where to print out bindings:  either stdout, or the zle output shout */
  341. static FILE *bindout;
  342.  
  343. /* Read a line.  It is returned metafied. */
  344.  
  345. /**/
  346. unsigned char *
  347. zleread(char *lp, char *rp)
  348. {
  349.     unsigned char *s;
  350.     int old_errno = errno;
  351.     int tmout = getiparam("TMOUT");
  352.  
  353. #ifdef HAVE_SELECT
  354.     long costmult;
  355.     struct timeval tv;
  356.     fd_set foofd;
  357.  
  358.     baud = getiparam("BAUD");
  359.     costmult = (baud) ? 3840000L / baud : 0;
  360.     tv.tv_sec = 0;
  361. #endif
  362.  
  363.     keytimeout = getiparam("KEYTIMEOUT");
  364.     if (!shout) {
  365.     if (SHTTY != -1)
  366.         init_shout();
  367.  
  368.     if (!shout)
  369.         return NULL;
  370.     /* We could be smarter and default to a system read. */
  371.  
  372.     /* If we just got a new shout, make sure the terminal is set up. */
  373.     if (termflags & TERM_UNKNOWN)
  374.         init_term();
  375.     }
  376.  
  377.     fflush(shout);
  378.     fflush(stderr);
  379.     intr();
  380.     insmode = unset(OVERSTRIKE);
  381.     eofsent = 0;
  382.     resetneeded = 0;
  383.     lpmpt = lp;
  384.     rpmpt = rp;
  385.     PERMALLOC {
  386.     histline = curhist;
  387. #ifdef HAVE_SELECT
  388.     FD_ZERO(&foofd);
  389. #endif
  390.     undoing = 1;
  391.     line = (unsigned char *)zalloc((linesz = 256) + 2);
  392.     virangeflag = vilinerange = lastcmd = done = cs = ll = mark = 0;
  393.     curhistline = NULL;
  394.     zmult = 1;
  395.     vibufspec = 0;
  396.     vibufappend = 0;
  397.     gotmult = gotvibufspec = 0;
  398.     bindtab = mainbindtab;
  399.     addedsuffix = complexpect = vichgflag = 0;
  400.     viinsbegin = 0;
  401.     statusline = NULL;
  402.     bindout = shout;        /* always print bindings on terminal */
  403.     if ((s = (unsigned char *)getlinknode(bufstack))) {
  404.         setline((char *)s);
  405.         zsfree((char *)s);
  406.         if (stackcs != -1) {
  407.         cs = stackcs;
  408.         stackcs = -1;
  409.         if (cs > ll)
  410.             cs = ll;
  411.         }
  412.         if (stackhist != -1) {
  413.         histline = stackhist;
  414.         stackhist = -1;
  415.         }
  416.     }
  417.     initundo();
  418.     if (isset(PROMPTCR))
  419.         putc('\r', shout);
  420.     if (tmout)
  421.         alarm(tmout);
  422.     zleactive = 1;
  423.     resetneeded = 1;
  424.     refresh();
  425.     errflag = retflag = 0;
  426.     while (!done && !errflag) {
  427.         struct zlecmd *zc;
  428.  
  429.         statusline = NULL;
  430.         bindk = getkeycmd();
  431.         if (!ll && isfirstln && c == eofchar) {
  432.         eofsent = 1;
  433.         break;
  434.         }
  435.         if (bindk != -1) {
  436.         int ce = complexpect;
  437.  
  438.         zc = zlecmds + bindk;
  439.         if (!(lastcmd & ZLE_ARG)) {
  440.             zmult = 1;
  441.             vibufspec = 0;
  442.             gotmult = gotvibufspec = 0;
  443.         }
  444.         if ((lastcmd & ZLE_UNDO) != (zc->flags & ZLE_UNDO) && undoing)
  445.             addundo();
  446.         if (bindk != z_sendstring) {
  447.             if (!(zc->flags & ZLE_MENUCMP))
  448.             invalidatelist();
  449.             if (!(zc->flags & ZLE_MENUCMP) &&
  450.             addedsuffix && !(zc->flags & ZLE_DELETE) &&
  451.             !((zc->flags & ZLE_INSERT) && c != ' ' &&
  452.               (c != '/' || addedsuffix > 1 || line[cs-1] != c))) {
  453.             backdel(addedsuffix);
  454.             }
  455.             if (!menucmp && !((zc->flags & ZLE_INSERT) && /*{*/
  456.                       complexpect == 2 && c == '}'))
  457.             addedsuffix = 0;
  458.         }
  459.         if (zc->func)
  460.             (*zc->func) ();
  461.         /* for vi mode, make sure the cursor isn't somewhere illegal */
  462.         if (bindtab == altbindtab && cs > findbol() &&
  463.             (cs == ll || line[cs] == '\n'))
  464.             cs--;
  465.         if (ce == complexpect && ce && !menucmp)
  466.             complexpect = 0;
  467.         if (bindk != z_sendstring)
  468.             lastcmd = zc->flags;
  469.         if (!(lastcmd & ZLE_UNDO) && undoing)
  470.             addundo();
  471.         } else {
  472.         errflag = 1;
  473.         break;
  474.         }
  475. #ifdef HAVE_SELECT
  476.         if (baud && !(lastcmd & ZLE_MENUCMP)) {
  477.         FD_SET(SHTTY, &foofd);
  478.         if ((tv.tv_usec = cost * costmult) > 500000)
  479.             tv.tv_usec = 500000;
  480.         if (!kungetct && select(SHTTY+1, (SELECT_ARG_2_T) & foofd,
  481.                     NULL, NULL, &tv) <= 0)
  482.             refresh();
  483.         } else
  484. #endif
  485.         if (!kungetct)
  486.             refresh();
  487.     }
  488.     statusline = NULL;
  489.     invalidatelist();
  490.     trashzle();
  491.     zleactive = 0;
  492.     alarm(0);
  493.     } LASTALLOC;
  494.     zsfree(curhistline);
  495.     free(lastline);        /* freeundo */
  496.     if (eofsent) {
  497.     free(line);
  498.     line = NULL;
  499.     } else {
  500.     line[ll++] = '\n';
  501.     line = (unsigned char *) metafy((char *) line, ll, META_REALLOC);
  502.     }
  503.     forget_edits();
  504.     errno = old_errno;
  505.     return line;
  506. }
  507.  
  508. /**/
  509. int
  510. getkeycmd(void)
  511. {
  512.     int ret;
  513.     static int hops = 0;
  514.  
  515.     cky = NULL;
  516.     if (!keybuf)
  517.     keybuf = (char *)zalloc(buflen = 50);
  518.     keybuf[1] = '\0';
  519.  
  520.     if ((c = getkey(0)) < 0)
  521.     return -1;
  522.     keybuf[0] = c;
  523.     if ((ret = bindtab[c]) == z_prefix) {
  524.     int lastlen = 0, t0 = 1, firstc = c;
  525.     Key ky;
  526.  
  527.     if ((cky = (Key) keybindtab->getnode(keybindtab, keybuf))->func == z_undefinedkey)
  528.         cky = NULL;
  529.     else
  530.         lastlen = 1;
  531.     if (!c)
  532.         keybuf[0] = (char)0x80;
  533.     for (;;) {
  534.         if ((c = getkey(cky ? 1 : 0)) >= 0) {
  535.         if (t0 == buflen - 1)
  536.             keybuf = (char *)realloc(keybuf, buflen *= 2);
  537.         keybuf[t0++] = (c) ? c : 0x80;
  538.         keybuf[t0] = '\0';
  539.         ky = (Key) keybindtab->getnode(keybindtab, keybuf);
  540.         } else
  541.         ky = NULL;
  542.         if (ky) {
  543.         if (ky->func == z_undefinedkey)
  544.             continue;
  545.         cky = ky;
  546.         if (!ky->prefixct) {
  547.             ret = ky->func;
  548.             break;
  549.         }
  550.         lastlen = t0;
  551.         } else if (cky) {
  552.         ungetkeys(keybuf + lastlen, t0 - lastlen);
  553.         keybuf[lastlen] = '\0';
  554.         if(vichgflag)
  555.             vichgbufptr -= t0 - lastlen;
  556.         ret = cky->func;
  557.         if (lastlen == 1)
  558.             keybuf[0] = firstc;
  559.         c = keybuf[lastlen - 1];
  560.         break;
  561.         } else
  562.         return z_undefinedkey;
  563.     }
  564.     }
  565.     if (ret == z_executenamedcmd && !statusline) {
  566.     while(ret == z_executenamedcmd)
  567.         ret = executenamedcommand("execute: ");
  568.     if(ret == -1)
  569.         ret = z_undefinedkey;
  570.     else if(ret != z_executelastnamedcmd)
  571.         lastnamed = ret;
  572.     }
  573.     if (ret == z_executelastnamedcmd)
  574.     ret = lastnamed;
  575.     if (ret == z_sendstring) {
  576. #define MAXHOPS 20
  577.     if (++hops == MAXHOPS) {
  578.         zerr("string inserting another one too many times", NULL, 0);
  579.         hops = 0;
  580.         return -1;
  581.     }
  582.     } else
  583.     hops = 0;
  584.     if (ret == z_vidigitorbeginningofline)
  585.     ret = (lastcmd & ZLE_DIGIT) ? z_digitargument : z_vibeginningofline;
  586.     return ret;
  587. }
  588.  
  589. /**/
  590. void
  591. ungetkeycmd(void)
  592. {
  593.     int len = strlen(keybuf);
  594.  
  595.     ungetkeys(keybuf, len ? len : 1);
  596. }
  597.  
  598.  
  599. /**/
  600. void
  601. sendstring(void)
  602. {
  603.     if (!cky)
  604.     cky = (Key) keybindtab->getnode(keybindtab, keybuf);
  605.     if(cky)
  606.     ungetkeys(cky->str, cky->len);
  607.     else
  608.     feep();
  609. }
  610.  
  611. /**/
  612. Key
  613. makefunckey(int fun)
  614. {
  615.     Key ky = (Key) zcalloc(sizeof *ky);
  616.  
  617.     ky->func = fun;
  618.     return ky;
  619. }
  620.  
  621. /* initialize the key bindings */
  622.  
  623. /**/
  624. void
  625. initkeybindings(void)
  626. {
  627.     Key ky;
  628.     char buf[3], *s;
  629.     int i;
  630.  
  631.     lastnamed = z_undefinedkey;
  632.     for (i = 0; i < 32; i++)
  633.     viins_cur_bindtab[i] = viinsbind[i];
  634.     for (i = 32; i < 256; i++)
  635.     viins_cur_bindtab[i] = z_selfinsert;
  636.     viins_cur_bindtab[127] = z_backwarddeletechar;
  637.     for (i = 0; i < 128; i++)
  638.     emacs_cur_bindtab[i] = emacsbind[i];
  639.     for (i = 128; i < 256; i++)
  640.     emacs_cur_bindtab[i] = z_selfinsert;
  641.  
  642.     /* If VISUAL or EDITOR contain the string "vi" when    *
  643.      * initializing the keymaps, then the main keymap will *
  644.      * be bound to vi insert mode by default.              */
  645.     if (((s = zgetenv("VISUAL")) && strstr(s, "vi")) ||
  646.     ((s = zgetenv("EDITOR")) && strstr(s, "vi"))) {
  647.     mainbindtab = viins_cur_bindtab;
  648.     keybindtab = vikeybindtab;
  649.     } else {
  650.     mainbindtab = emacs_cur_bindtab;
  651.     keybindtab = emkeybindtab;
  652.     }
  653.  
  654.     for (i = 0200; i < 0240; i++)
  655.     emacs_cur_bindtab[i] = viins_cur_bindtab[i] = z_undefinedkey;
  656.     for (i = 0; i < 128; i++)
  657.     altbindtab[i] = vicmdbind[i];
  658.     for (i = 128; i < 256; i++)
  659.     altbindtab[i] = emacsbind[i];
  660.     bindtab = mainbindtab;
  661.     if (!kungetbuf)
  662.     kungetbuf = (char *) zalloc(kungetsz = 32);
  663.  
  664.     emkeybindtab->addnode(emkeybindtab, ztrdup("\33\133"), ky = makefunckey(z_undefinedkey));
  665.     ky->prefixct = 4;
  666.     emkeybindtab->addnode(emkeybindtab, ztrdup("\33\133C"), makefunckey(z_forwardchar));
  667.     emkeybindtab->addnode(emkeybindtab, ztrdup("\33\133D"), makefunckey(z_backwardchar));
  668.     emkeybindtab->addnode(emkeybindtab, ztrdup("\33\133A"), makefunckey(z_uplineorhistory));
  669.     emkeybindtab->addnode(emkeybindtab, ztrdup("\33\133B"), makefunckey(z_downlineorhistory));
  670.     vikeybindtab->addnode(vikeybindtab, ztrdup("\33"), ky = makefunckey(z_vicmdmode));
  671.     ky->prefixct = 4;
  672.     vikeybindtab->addnode(vikeybindtab, ztrdup("\33\133"), ky = makefunckey(z_undefinedkey));
  673.     ky->prefixct = 4;
  674.     vikeybindtab->addnode(vikeybindtab, ztrdup("\33\133C"), makefunckey(z_forwardchar));
  675.     vikeybindtab->addnode(vikeybindtab, ztrdup("\33\133D"), makefunckey(z_backwardchar));
  676.     vikeybindtab->addnode(vikeybindtab, ztrdup("\33\133A"), makefunckey(z_uplineorhistory));
  677.     vikeybindtab->addnode(vikeybindtab, ztrdup("\33\133B"), makefunckey(z_downlineorhistory));
  678.     emkeybindtab->addnode(emkeybindtab, ztrdup("\30"), ky = makefunckey(z_undefinedkey));
  679.     ky->prefixct = 15;
  680.     emkeybindtab->addnode(emkeybindtab, ztrdup("\30*"), makefunckey(z_expandword));
  681.     emkeybindtab->addnode(emkeybindtab, ztrdup("\30g"), makefunckey(z_listexpand));
  682.     emkeybindtab->addnode(emkeybindtab, ztrdup("\30G"), makefunckey(z_listexpand));
  683.     emkeybindtab->addnode(emkeybindtab, ztrdup("\30\16"), makefunckey(z_infernexthistory));
  684.     emkeybindtab->addnode(emkeybindtab, ztrdup("\30\13"), makefunckey(z_killbuffer));
  685.     emkeybindtab->addnode(emkeybindtab, ztrdup("\30\6"), makefunckey(z_vifindnextchar));
  686.     emkeybindtab->addnode(emkeybindtab, ztrdup("\30\17"), makefunckey(z_overwritemode));
  687.     emkeybindtab->addnode(emkeybindtab, ztrdup("\30\25"), makefunckey(z_undo));
  688.     emkeybindtab->addnode(emkeybindtab, ztrdup("\30\26"), makefunckey(z_vicmdmode));
  689.     emkeybindtab->addnode(emkeybindtab, ztrdup("\30\12"), makefunckey(z_vijoin));
  690.     emkeybindtab->addnode(emkeybindtab, ztrdup("\30\2"), makefunckey(z_vimatchbracket));
  691.     emkeybindtab->addnode(emkeybindtab, ztrdup("\30s"), makefunckey(z_historyincrementalsearchforward));
  692.     emkeybindtab->addnode(emkeybindtab, ztrdup("\30r"), makefunckey(z_historyincrementalsearchbackward));
  693.     emkeybindtab->addnode(emkeybindtab, ztrdup("\30u"), makefunckey(z_undo));
  694.     emkeybindtab->addnode(emkeybindtab, ztrdup("\30\30"), makefunckey(z_exchangepointandmark));
  695.     emkeybindtab->addnode(emkeybindtab, ztrdup("\33"), ky = makefunckey(z_undefinedkey));
  696.     ky->prefixct = 4;
  697.  
  698.     strcpy(buf, "\33q");
  699.     for (i = 128; i < 256; i++)
  700.     if (emacsbind[i] != z_undefinedkey) {
  701.         buf[1] = i & 0x7f;
  702.         emkeybindtab->addnode(emkeybindtab, ztrdup(buf), makefunckey(emacsbind[i]));
  703.         ky->prefixct++;
  704.     }
  705.     stackhist = stackcs = -1;
  706. }
  707.  
  708. /**/
  709. char *
  710. getkeystring(char *s, int *len, int fromwhere, int *misc)
  711. {
  712.     char *buf = ((fromwhere == 2)
  713.          ? zalloc(strlen(s) + 1) : alloc(strlen(s) + 1));
  714.     char *t = buf, *u = NULL;
  715.     char svchar = '\0';
  716.     int meta = 0, control = 0;
  717.  
  718.     for (; *s; s++) {
  719.     if (*s == '\\' && s[1]) {
  720.         switch (*++s) {
  721.         case 'a':
  722. #ifdef __STDC__
  723.         *t++ = '\a';
  724. #else
  725.         *t++ = '\07';
  726. #endif
  727.         break;
  728.         case 'n':
  729.         *t++ = '\n';
  730.         break;
  731.         case 'b':
  732.         *t++ = '\b';
  733.         break;
  734.         case 't':
  735.         *t++ = '\t';
  736.         break;
  737.         case 'v':
  738.         *t++ = '\v';
  739.         break;
  740.         case 'f':
  741.         *t++ = '\f';
  742.         break;
  743.         case 'r':
  744.         *t++ = '\r';
  745.         break;
  746.         case 'E':
  747.         if (!fromwhere) {
  748.             *t++ = '\\', s--;
  749.             continue;
  750.         }
  751.         case 'e':
  752.         *t++ = '\033';
  753.         break;
  754.         case 'M':
  755.         if (fromwhere) {
  756.             if (s[1] == '-')
  757.             s++;
  758.             meta = 1 + control;    /* preserve the order of ^ and meta */
  759.         } else
  760.             *t++ = '\\', s--;
  761.         continue;
  762.         case 'C':
  763.         if (fromwhere) {
  764.             if (s[1] == '-')
  765.             s++;
  766.             control = 1;
  767.         } else
  768.             *t++ = '\\', s--;
  769.         continue;
  770.         case Meta:
  771.         *t++ = '\\', s--;
  772.         break;
  773.         case 'c':
  774.         if (fromwhere < 2) {
  775.             *misc = 1;
  776.             break;
  777.         }
  778.         default:
  779.         if ((idigit(*s) && *s < '8') || *s == 'x') {
  780.             if (!fromwhere)
  781.             if (*s == '0')
  782.                 s++;
  783.             else if (*s != 'x') {
  784.                 *t++ = '\\', s--;
  785.                 continue;
  786.             }
  787.             if (s[1] && s[2] && s[3]) {
  788.             svchar = s[3];
  789.             s[3] = '\0';
  790.             u = s;
  791.             }
  792.             *t++ = zstrtol(s + (*s == 'x'), &s,
  793.                    (*s == 'x') ? 16 : 8);
  794.             if (svchar) {
  795.             u[3] = svchar;
  796.             svchar = '\0';
  797.             }
  798.             s--;
  799.         } else {
  800.             if (!fromwhere && *s != '\\')
  801.             *t++ = '\\';
  802.             *t++ = *s;
  803.         }
  804.         break;
  805.         }
  806.     } else if (*s == '^' && fromwhere == 2) {
  807.         control = 1;
  808.         continue;
  809.     } else if (*s == Meta)
  810.         *t++ = *++s ^ 32;
  811.     else
  812.         *t++ = *s;
  813.     if (meta == 2) {
  814.         t[-1] |= 0x80;
  815.         meta = 0;
  816.     }
  817.     if (control) {
  818.         if (t[-1] == '?')
  819.         t[-1] = 0x7f;
  820.         else
  821.         t[-1] &= 0x9f;
  822.         control = 0;
  823.     }
  824.     if (meta) {
  825.         t[-1] |= 0x80;
  826.         meta = 0;
  827.     }
  828.     }
  829.     *t = '\0';
  830.     *len = t - buf;
  831.     return buf;
  832. }
  833.  
  834. /**/
  835. void
  836. printbind(char *s, int len, int metanul)
  837. {
  838.     int ch;
  839.  
  840.     putc('"', bindout);
  841.     metanul |= len == 1;
  842.     while (len--) {
  843.     ch = STOUC(*s++);
  844.     if (ch & 0x80) {
  845.          if (ch != 0x80 || metanul)
  846.         fprintf(bindout, "\\M-");
  847.         ch &= 0x7f;
  848.     }
  849.     if (icntrl(ch))
  850.         switch (ch) {
  851.         case 0x7f:
  852.         fprintf(bindout, "^?");
  853.         break;
  854.         default:
  855.         fprintf(bindout, "^%c", (ch | 0x40));
  856.         break;
  857.     } else {
  858.         if (ch == '\\' || ch == '^' || ch == '"')
  859.         putc('\\', bindout);
  860.         putc(ch, bindout);
  861.     }
  862.     }
  863.     putc('"', bindout);
  864. }
  865.  
  866. /**/
  867. void
  868. printbinding(HashNode hn, int printflags)
  869. {
  870.     Key k = (Key) hn;
  871.     int len;
  872.  
  873.     if (k->func == z_undefinedkey)
  874.     return;
  875.     printbind(k->nam, (len = strlen(k->nam)) ? len : 1, 0);
  876.     putc('\t', bindout);
  877.     if (k->func == z_sendstring) {
  878.     printbind(k->str, k->len, 1);
  879.     putc('\n', bindout);
  880.     } else
  881.     fprintf(bindout, "%s\n", zlecmds[k->func].name);
  882. }
  883.  
  884. /**/
  885. int
  886. bin_bindkey(char *name, char **argv, char *ops, int junc)
  887. {
  888.     int i, *tab;
  889.  
  890.     if (ops['v'] && ops['e']) {
  891.     zerrnam(name, "incompatible options", NULL, 0);
  892.     return 1;
  893.     }
  894.     if (ops['v'] || ops['e'] || ops['d'] || ops['m']) {
  895.     if (*argv) {
  896.         zerrnam(name, "too many arguments", NULL, 0);
  897.         return 1;
  898.     }
  899.     if (ops['d']) {
  900.         /* empty the hash tables for multi-character bindings */
  901.         emkeybindtab->emptytable(emkeybindtab);
  902.         vikeybindtab->emptytable(vikeybindtab);
  903.  
  904.         /* reset all key bindings to initial setting */
  905.         initkeybindings();
  906.     }
  907.     if (ops['e']) {
  908.         mainbindtab = emacs_cur_bindtab;
  909.         keybindtab = emkeybindtab;
  910.     } else if (ops['v']) {
  911.         mainbindtab = viins_cur_bindtab;
  912.         keybindtab = vikeybindtab;
  913.     }
  914.     if (ops['m'])
  915.         for (i = 128; i < 256; i++)
  916.         if (mainbindtab[i] == z_selfinsert)
  917.             mainbindtab[i] = emacsbind[i];
  918.     return 0;
  919.     }
  920.     tab = (ops['a']) ? altbindtab : mainbindtab;
  921.  
  922.     /* print bindings to stdout */
  923.     bindout = stdout;
  924.     if (!*argv) {
  925.     char buf[2];
  926.  
  927.     buf[1] = '\0';
  928.     for (i = 0; i < 256; i++) {
  929.         buf[0] = i;
  930.         printbind(buf, 1, 1);
  931.         if (i < 254 && tab[i] == tab[i + 1] && tab[i] == tab[i + 2]) {
  932.         printf(" to ");
  933.         while (tab[i] == tab[i + 1])
  934.             i++;
  935.         buf[0] = i;
  936.         printbind(buf, 1, 1);
  937.         }
  938.         printf("\t%s\n", zlecmds[tab[i]].name);
  939.     }
  940.     scanhashtable(keybindtab, 1, 0, 0, printbinding, 0);
  941.     return 0;
  942.     }
  943.     while (*argv) {
  944.     Key ky = NULL, cur = NULL;
  945.     char *s;
  946.     int func, len, firstzero = 0;
  947.  
  948.     s = getkeystring(*argv++, &len, 2, NULL);
  949.     if (len > 1) {
  950.         if (s[0])
  951.         firstzero = 0;
  952.         else
  953.         firstzero = 1;
  954.         for (i = 0; i < len; i++)
  955.         if (!s[i])
  956.             s[i] = (char)0x80;
  957.     }
  958.     if (!*argv || ops['r']) {
  959.         if (len == 1)
  960.         func = tab[STOUC(*s)];
  961.         else
  962.         func = (ky = (Key) keybindtab->getnode(keybindtab, s)) ? ky->func
  963.             : z_undefinedkey;
  964.         if (func == z_undefinedkey) {
  965.         zerrnam(name, "in-string is not bound", NULL, 0);
  966.         zfree(s, len);
  967.         return 1;
  968.         }
  969.         if (ops['r']) {
  970.         if (len == 1 && func != z_prefix) {
  971.             tab[STOUC(*s)] = z_undefinedkey;
  972.             if (func == z_sendstring)
  973.             free(keybindtab->removenode(keybindtab, s));
  974.         } else {
  975.             if (ky && ky->prefixct) {
  976.             if (ky->func == z_sendstring) {
  977.                 zfree(ky->str, ky->len);
  978.                 ky->str = NULL;
  979.             }
  980.             ky->func = z_undefinedkey;
  981.             } else
  982.             free(keybindtab->removenode(keybindtab, s));
  983.             if (len > 1) {
  984.             s[--len] = '\0';
  985.             while (len > 1) {
  986.                 (ky = (Key) keybindtab->getnode(keybindtab, s))->prefixct--;
  987.                 if (!ky->prefixct && ky->func == z_undefinedkey)
  988.                 free(keybindtab->removenode(keybindtab, s));
  989.                 s[--len] = '\0';
  990.             }
  991.             (ky = (Key) keybindtab->getnode(keybindtab, s))->prefixct--;
  992.             if (!ky->prefixct) {
  993.                 int *otab = ops['a'] ? mainbindtab : altbindtab;
  994.                 tab[STOUC(*s)] = ky->func;
  995.                 /*
  996.                  * If the bindtab we are not using also
  997.                  * adds this key as a prefix, it must also
  998.                  * be reset.
  999.                  */
  1000.                 if (otab[STOUC(*s)] == z_prefix)
  1001.                 otab[STOUC(*s)] = ky->func;
  1002.                 if (ky->func != z_sendstring)
  1003.                 free(keybindtab->removenode(keybindtab, s));
  1004.             }
  1005.             }
  1006.         }
  1007.         zfree(s, len);
  1008.         continue;
  1009.         }
  1010.         if (func == z_sendstring) {
  1011.         if (len == 1)
  1012.             ky = (Key) keybindtab->getnode(keybindtab, s);
  1013.         printbind(ky->str, ky->len, 1);
  1014.         putchar('\n');
  1015.         } else
  1016.         printf("%s\n", zlecmds[func].name);
  1017.         zfree(s, len);
  1018.         return 0;
  1019.     }
  1020.     if (!ops['s']) {
  1021.         for (i = 0; i != ZLECMDCOUNT; i++)
  1022.         if (!strcmp(*argv, zlecmds[i].name))
  1023.             break;
  1024.         if (i == ZLECMDCOUNT) {
  1025.         zerr("undefined function: %s", *argv, 0);
  1026.         zfree(s, len);
  1027.         return 1;
  1028.         }
  1029.         func = i;
  1030.     } else
  1031.         func = z_sendstring;
  1032.  
  1033.     if (len == 1 && tab[STOUC(*s)] != z_prefix) {
  1034.         if (ops['s']) {
  1035.         keybindtab->addnode(keybindtab, ztrdup(s), cur = makefunckey(z_sendstring));
  1036.         } else if (tab[STOUC(*s)] == z_sendstring)
  1037.         free(keybindtab->removenode(keybindtab, s));
  1038.         tab[STOUC(*s)] = func;
  1039.     } else {
  1040.         if (!(cur = (Key) keybindtab->getnode(keybindtab, s))
  1041.         || (cur->func == z_undefinedkey))
  1042.         for (i = len - 1; i > 0; i--) {
  1043.             char sav;
  1044.  
  1045.             sav = s[i];
  1046.             s[i] = '\0';
  1047.             if (i == 1 && firstzero)
  1048.             *s = '\0';
  1049.             if (!(ky = (Key) keybindtab->getnode(keybindtab, s)))
  1050.             keybindtab->addnode(keybindtab, ztrdup(s), ky = makefunckey(z_undefinedkey));
  1051.             ky->prefixct++;
  1052.             s[i] = sav;
  1053.             if (i == 1 && firstzero)
  1054.             *s = (char)0x80;
  1055.         }
  1056.         if (cur) {
  1057.         if (cur->str) {
  1058.             zfree(cur->str, cur->len);
  1059.             cur->str = NULL;
  1060.         }
  1061.         cur->func = func;
  1062.         } else
  1063.         keybindtab->addnode(keybindtab, ztrdup(s), cur = makefunckey(func));
  1064.         if (firstzero)
  1065.         *s = 0;
  1066.         if (tab[STOUC(*s)] != z_prefix) {
  1067.         cur->func = tab[STOUC(*s)];
  1068.         tab[STOUC(*s)] = z_prefix;
  1069.         }
  1070.     }
  1071.     if (ops['s']) {
  1072.         cur->str = getkeystring(*argv, &cur->len, 2, NULL);
  1073.         cur->str = (char *)realloc(cur->str, cur->len);
  1074.     }
  1075.     argv++;
  1076.     zfree(s, len);
  1077.     }
  1078.     return 0;
  1079. }
  1080.  
  1081. /**/
  1082. void
  1083. freekeynode(HashNode hn)
  1084. {
  1085.     Key k = (Key) hn;
  1086.  
  1087.     zsfree(k->nam);
  1088.     if (k->str)
  1089.     zfree(k->str, k->len);
  1090.     zfree(k, sizeof(struct key));
  1091. }
  1092.  
  1093. extern int clearflag;
  1094.  
  1095. /**/
  1096. void
  1097. describekeybriefly(void)
  1098. {
  1099.     int cmd;
  1100.     int len;
  1101.  
  1102.     if (statusline)
  1103.     return;
  1104.     statusline = "Describe key briefly: _";
  1105.     statusll = strlen(statusline);
  1106.     refresh();
  1107.     cmd = getkeycmd();
  1108.     statusline = NULL;
  1109.     if (cmd < 0)
  1110.     return;
  1111.     trashzle();
  1112.     clearflag = (isset(USEZLE) && !termflags &&
  1113.          (isset(ALWAYSLASTPROMPT) && !gotmult)) ||
  1114.     (unset(ALWAYSLASTPROMPT) && gotmult);
  1115.     printbind(keybuf, (len = strlen(keybuf)) ? len : 1, 0);
  1116.     fprintf(shout, " is ");
  1117.     if (cmd == z_sendstring) {
  1118.     if (!cky)
  1119.         cky = (Key) keybindtab->getnode(keybindtab, keybuf);
  1120.     printbind(cky->str, cky->len, 1);
  1121.     }
  1122.     else
  1123.     fprintf(shout, "%s", zlecmds[cmd].name);
  1124.     if (clearflag)
  1125.     putc('\r', shout), tcmultout(TCUP, TCMULTUP, nlnct);
  1126.     else
  1127.     putc('\n', shout);
  1128.     showinglist = 0;
  1129. }
  1130.  
  1131. static int func, funcfound;
  1132. #define MAXFOUND 4
  1133.  
  1134. static void
  1135. printfuncbind(HashNode hn, int printflags)
  1136. {
  1137.     Key k = (Key) hn;
  1138.     int len = strlen(k->nam);
  1139.  
  1140.     if (k->func != func || funcfound >= MAXFOUND ||
  1141.     ((len <= 1) && mainbindtab[*k->nam] == z_sendstring))
  1142.     return;
  1143.     if (!funcfound++)
  1144.     fprintf(shout, " on");
  1145.     putc(' ', shout);
  1146.     printbind(k->nam, len, 0);
  1147. }
  1148.  
  1149. /**/
  1150. void
  1151. whereis(void)
  1152. {
  1153.     int i;
  1154.  
  1155.     if ((func = executenamedcommand("Where is: ")) == -1)
  1156.     return;
  1157.     funcfound = 0;
  1158.     trashzle();
  1159.     clearflag = (isset(USEZLE) && !termflags &&
  1160.          (isset(ALWAYSLASTPROMPT) && !gotmult)) ||
  1161.     (unset(ALWAYSLASTPROMPT) && gotmult);
  1162.     if (func == z_selfinsert || func == z_undefinedkey)
  1163.     fprintf(shout, "%s is on many keys", zlecmds[func].name);
  1164.     else {
  1165.     fprintf(shout, "%s is", zlecmds[func].name);
  1166.     for (i = 0; funcfound < MAXFOUND && i < 256; i++)
  1167.         if (mainbindtab[i] == func) {
  1168.         char ch = i;
  1169.         if (!funcfound++)
  1170.             fprintf(shout, " on");
  1171.         putc(' ', shout);
  1172.         printbind(&ch, 1, 1);
  1173.         }
  1174.     if (funcfound < MAXFOUND)
  1175.         scanhashtable(keybindtab, 1, 0, 0, printfuncbind, 0);
  1176.     if (!funcfound)
  1177.         fprintf(shout, " not bound to any key");
  1178.     }
  1179.     if (clearflag)
  1180.     putc('\r', shout), tcmultout(TCUP, TCMULTUP, nlnct);
  1181.     else
  1182.     putc('\n', shout);
  1183.     showinglist = 0;
  1184. }
  1185.  
  1186. /**/
  1187. void
  1188. trashzle(void)
  1189. {
  1190.     if (zleactive) {
  1191.     /* This refresh() is just to get the main editor display right and *
  1192.      * get the cursor in the right place.  For that reason, we disable *
  1193.      * list display (which would otherwise result in infinite          *
  1194.      * recursion [at least, it would if refresh() didn't have its      *
  1195.      * extra `inlist' check]).                                         */
  1196.     int sl = showinglist;
  1197.     showinglist = 0;
  1198.     refresh();
  1199.     showinglist = sl;
  1200.     moveto(nlnct, 0);
  1201.     if (clearflag && tccan(TCCLEAREOD)) {
  1202.         tcout(TCCLEAREOD);
  1203.         clearflag = 0;
  1204.     }
  1205.     if (postedit)
  1206.         fprintf(shout, "%s", postedit);
  1207.     fflush(shout);
  1208.     resetneeded = 1;
  1209.     settyinfo(&shttyinfo);
  1210.     }
  1211.     if (errflag)
  1212.     kungetct = 0;
  1213. }
  1214.