home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Unix / Shells / zsh / Source / src / zle_hist.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-07  |  14.3 KB  |  800 lines

  1. /*
  2.  *
  3.  * zle_hist.c - history editing
  4.  *
  5.  * This file is part of zsh, the Z shell.
  6.  *
  7.  * This software is Copyright 1992 by Paul Falstad
  8.  *
  9.  * Permission is hereby granted to copy, reproduce, redistribute or otherwise
  10.  * use this software as long as: there is no monetary profit gained
  11.  * specifically from the use or reproduction of this software, it is not
  12.  * sold, rented, traded or otherwise marketed, and this copyright notice is
  13.  * included prominently in any copy made.
  14.  *
  15.  * The author make no claims as to the fitness or correctness of this software
  16.  * for any use whatsoever, and it is provided as is. Any use of this software
  17.  * is at the user's own risk.
  18.  *
  19.  */
  20.  
  21. #define ZLE
  22. #include "zsh.h"
  23.  
  24. void toggleliteralhistory()
  25. {                /**/
  26.     char *s;
  27.  
  28.     if (histline == curhist) {
  29.     zsfree(curhistline);
  30.     curhistline = ztrdup(UTOSCP(line));
  31.     }
  32.     lithist ^= 1;
  33.     if (!(s = qgetevent(histline)))
  34.     feep();
  35.     else
  36.     sethistline(STOUCP(s));
  37. }
  38.  
  39. void uphistory()
  40. {                /**/
  41.     char *s;
  42.  
  43.     if (mult < 0) {
  44.     mult = -mult;
  45.     downhistory();
  46.     return;
  47.     }
  48.     if (histline == curhist) {
  49.     zsfree(curhistline);
  50.     curhistline = ztrdup(UTOSCP(line));
  51.     }
  52.     histline -= mult;
  53.     if (!(s = qgetevent(histline))) {
  54.     if (unset(NOHISTBEEP))
  55.         feep();
  56.     histline += mult;
  57.     } else
  58.     sethistline(STOUCP(s));
  59. }
  60.  
  61. void uplineorhistory()
  62. {                /**/
  63.     int ocs = cs;
  64.  
  65.     if (mult < 0) {
  66.     mult = -mult;
  67.     downlineorhistory();
  68.     return;
  69.     }
  70.     if ((lastcmd & ZLE_LINEMOVE) != ZLE_LINEMOVE)
  71.     lastcol = cs - findbol();
  72.     cs = findbol();
  73.     while (mult) {
  74.     if (!cs)
  75.         break;
  76.     cs--;
  77.     cs = findbol();
  78.     mult--;
  79.     }
  80.     if (mult) {
  81.     cs = ocs;
  82.     if (virangeflag) {
  83.         feep();
  84.         return;
  85.     }
  86.     uphistory();
  87.     } else {
  88.     int x = findeol();
  89.  
  90.     if ((cs += lastcol) > x)
  91.         cs = x;
  92.     }
  93. }
  94.  
  95. void uplineorsearch()
  96. {                /**/
  97.     int ocs = cs;
  98.  
  99.     if (mult < 0) {
  100.     mult = -mult;
  101.     downlineorsearch();
  102.     return;
  103.     }
  104.     if ((lastcmd & ZLE_LINEMOVE) != ZLE_LINEMOVE)
  105.     lastcol = cs - findbol();
  106.     cs = findbol();
  107.     while (mult) {
  108.     if (!cs)
  109.         break;
  110.     cs--;
  111.     cs = findbol();
  112.     mult--;
  113.     }
  114.     if (mult) {
  115.     cs = ocs;
  116.     if (virangeflag) {
  117.         feep();
  118.         return;
  119.     }
  120.     historysearchbackward();
  121.     } else {
  122.     int x = findeol();
  123.  
  124.     if ((cs += lastcol) > x)
  125.         cs = x;
  126.     }
  127. }
  128.  
  129. void downlineorhistory()
  130. {                /**/
  131.     int ocs = cs;
  132.  
  133.     if (mult < 0) {
  134.     mult = -mult;
  135.     uplineorhistory();
  136.     return;
  137.     }
  138.     if ((lastcmd & ZLE_LINEMOVE) != ZLE_LINEMOVE)
  139.     lastcol = cs - findbol();
  140.     while (mult) {
  141.     int x = findeol();
  142.  
  143.     if (x == ll)
  144.         break;
  145.     cs = x + 1;
  146.     mult--;
  147.     }
  148.     if (mult) {
  149.     cs = ocs;
  150.     if (virangeflag) {
  151.         feep();
  152.         return;
  153.     }
  154.     downhistory();
  155.     } else {
  156.     int x = findeol();
  157.  
  158.     if ((cs += lastcol) > x)
  159.         cs = x;
  160.     }
  161. }
  162.  
  163. void downlineorsearch()
  164. {                /**/
  165.     int ocs = cs;
  166.  
  167.     if (mult < 0) {
  168.     mult = -mult;
  169.     uplineorsearch();
  170.     return;
  171.     }
  172.     if ((lastcmd & ZLE_LINEMOVE) != ZLE_LINEMOVE)
  173.     lastcol = cs - findbol();
  174.     while (mult) {
  175.     int x = findeol();
  176.  
  177.     if (x == ll)
  178.         break;
  179.     cs = x + 1;
  180.     mult--;
  181.     }
  182.     if (mult) {
  183.     cs = ocs;
  184.     if (virangeflag) {
  185.         feep();
  186.         return;
  187.     }
  188.     historysearchforward();
  189.     } else {
  190.     int x = findeol();
  191.  
  192.     if ((cs += lastcol) > x)
  193.         cs = x;
  194.     }
  195. }
  196.  
  197. void acceptlineanddownhistory()
  198. {                /**/
  199.     char *s, *t;
  200.  
  201.     if (!(s = qgetevent(histline + 1))) {
  202.     feep();
  203.     return;
  204.     }
  205.     pushnode(bufstack, t = ztrdup(s));
  206.     for (; *t; t++)
  207.     if (*t == HISTSPACE)
  208.         *t = ' ';
  209.     done = 1;
  210.     stackhist = histline + 1;
  211. }
  212.  
  213. void downhistory()
  214. {                /**/
  215.     char *s;
  216.  
  217.     if (mult < 0) {
  218.     mult = -mult;
  219.     uphistory();
  220.     return;
  221.     }
  222.     histline += mult;
  223.     if (!(s = qgetevent(histline))) {
  224.     if (unset(NOHISTBEEP))
  225.         feep();
  226.     histline -= mult;
  227.     return;
  228.     }
  229.     sethistline(STOUCP(s));
  230. }
  231.  
  232. static int histpos;
  233.  
  234. void historysearchbackward()
  235. {                /**/
  236.     int t0, ohistline = histline;
  237.     char *s;
  238.  
  239.     if (histline == curhist) {
  240.     zsfree(curhistline);
  241.     curhistline = ztrdup(UTOSCP(line));
  242.     }
  243.     if (lastcmd & ZLE_HISTSEARCH)
  244.     t0 = histpos;
  245.     else
  246.     for (t0 = 0; line[t0] && !iblank(line[t0]); t0++);
  247.     histpos = t0;
  248.     for (;;) {
  249.     histline--;
  250.     if (!(s = qgetevent(histline))) {
  251.         feep();
  252.         histline = ohistline;
  253.         return;
  254.     }
  255.     if (!hstrncmp(s, UTOSCP(line), t0) && hstrcmp(s, UTOSCP(line)))
  256.         break;
  257.     }
  258.     sethistline(STOUCP(s));
  259. }
  260.  
  261. void historysearchforward()
  262. {                /**/
  263.     int t0, ohistline = histline;
  264.     char *s;
  265.  
  266.     if (histline == curhist) {
  267.     zsfree(curhistline);
  268.     curhistline = ztrdup(UTOSCP(line));
  269.     }
  270.     if (lastcmd & ZLE_HISTSEARCH)
  271.     t0 = histpos;
  272.     else
  273.     for (t0 = 0; line[t0] && !iblank(line[t0]); t0++);
  274.     histpos = t0;
  275.     for (;;) {
  276.     histline++;
  277.     if (!(s = qgetevent(histline))) {
  278.         feep();
  279.         histline = ohistline;
  280.         return;
  281.     }
  282.     if (!hstrncmp(s, UTOSCP(line), t0) && hstrcmp(s, UTOSCP(line)))
  283.         break;
  284.     }
  285.     sethistline(STOUCP(s));
  286. }
  287.  
  288. void beginningofbufferorhistory()
  289. {                /**/
  290.     if (findbol())
  291.     cs = 0;
  292.     else
  293.     beginningofhistory();
  294. }
  295.  
  296. void beginningofhistory()
  297. {                /**/
  298.     char *s;
  299.  
  300.     if (histline == curhist) {
  301.     zsfree(curhistline);
  302.     curhistline = ztrdup(UTOSCP(line));
  303.     }
  304.     if (!(s = qgetevent(firsthist()))) {
  305.     if (unset(NOHISTBEEP))
  306.         feep();
  307.     return;
  308.     }
  309.     histline = firsthist();
  310.     sethistline(STOUCP(s));
  311. }
  312.  
  313. void endofbufferorhistory()
  314. {                /**/
  315.     if (findeol() != ll)
  316.     cs = ll;
  317.     else
  318.     endofhistory();
  319. }
  320.  
  321. void endofhistory()
  322. {                /**/
  323.     if (histline == curhist) {
  324.     if (unset(NOHISTBEEP))
  325.         feep();
  326.     } else {
  327.     histline = curhist;
  328.     sethistline(STOUCP(curhistline));
  329.     }
  330. }
  331.  
  332. void insertlastword()
  333. {                /**/
  334.     char *s, *t;
  335.     int len, z = lithist;
  336.  
  337. /* multiple calls will now search back through the history, pem */
  338.     static char *lastinsert;
  339.     static int lasthist, lastpos;
  340.     int evhist = curhist - 1;
  341.  
  342.     if (lastinsert) {
  343.     int lastlen = strlen(lastinsert);
  344.     int pos = cs;
  345.  
  346.     if (lastpos <= pos &&
  347.         lastlen == pos - lastpos &&
  348.         strncmp(lastinsert, (char *)&line[lastpos], lastlen) == 0) {
  349.         evhist = --lasthist;
  350.         cs = lastpos;
  351.         foredel(pos - cs);
  352.     }
  353.     zsfree(lastinsert);
  354.     lastinsert = NULL;
  355.     }
  356.     lithist = 0;
  357.     if (!(s = qgetevent(evhist), lithist = z, s)) {
  358.     feep();
  359.     return;
  360.     }
  361.     for (t = s + strlen(s); t > s; t--)
  362.     if (*t == HISTSPACE)
  363.         break;
  364.     if (t != s)
  365.     t++;
  366.     lasthist = evhist;
  367.     lastpos = cs;
  368.     lastinsert = ztrdup(t);
  369.     spaceinline(len = strlen(t));
  370.     strncpy((char *)line + cs, t, len);
  371.     cs += len;
  372. }
  373.  
  374. char *qgetevent(ev)        /**/
  375. int ev;
  376. {
  377.     if (ev > curhist)
  378.     return NULL;
  379.     return ((ev == curhist) ? curhistline : quietgetevent(ev));
  380. }
  381.  
  382. void pushline()
  383. {                /**/
  384.     if (mult < 0)
  385.     return;
  386.     pushnode(bufstack, ztrdup(UTOSCP(line)));
  387.     while (--mult)
  388.     pushnode(bufstack, ztrdup(""));
  389.     stackcs = cs;
  390.     *line = '\0';
  391.     ll = cs = 0;
  392. }
  393.  
  394. void pushpopinput()
  395. {                /**/
  396.     int ics;
  397.     char *iline;
  398.     Histent curhistent = gethistent(curhist);
  399.  
  400.     if (mult < 0)
  401.     return;
  402.     if (*(curhistent->lit)) {
  403.     ics = strlen(curhistent->lit);
  404.     iline = (char *) zalloc(strlen((char *)line) + ics + 1);
  405.     strcpy(iline, curhistent->lit);
  406.     strcat(iline, (char *)line);
  407.     free(line);
  408.     line = (unsigned char *)iline;
  409.     cs += ics;
  410.     *(curhistent->lit) = '\0';
  411.     }
  412.     pushline();
  413.     if (!isfirstln) {
  414.     *(hptr = chline) = '\0';
  415.     errflag = done = 1;
  416.     }
  417. }
  418.  
  419. void pushinput()
  420. {                /**/
  421.     if (mult < 0)
  422.     return;
  423.     if (!isfirstln)
  424.     mult++;
  425.     pushpopinput();
  426. }
  427.  
  428. void getline()
  429. {                /**/
  430.     char *s = (char *)getnode(bufstack);
  431.  
  432.     if (!s)
  433.     feep();
  434.     else {
  435.     int cc;
  436.  
  437.     cc = strlen(s);
  438.     spaceinline(cc);
  439.     strncpy((char *)line + cs, s, cc);
  440.     cs += cc;
  441.     zsfree(s);
  442.     }
  443. }
  444.  
  445. void historyincrementalsearchbackward()
  446. {                /**/
  447.     doisearch(-1);
  448. }
  449.  
  450. void historyincrementalsearchforward()
  451. {                /**/
  452.     doisearch(1);
  453. }
  454.  
  455. extern int ungetok;
  456.  
  457. void doisearch(dir)        /**/
  458. int dir;
  459. {
  460.     char *s, *oldl;
  461.     char ibuf[256], *sbuf = ibuf + 14;
  462.     int sbptr = 0, cmd, ohl = histline, ocs = cs;
  463.     int nomatch, chequiv = 0;
  464.  
  465.     strcpy(ibuf, (dir == -1) ? "bck-i-search: " : "fwd-i-search: ");
  466.     statusline = ibuf;
  467.     oldl = ztrdup(UTOSCP(line));
  468.     if (histline == curhist) {
  469.     zsfree(curhistline);
  470.     curhistline = ztrdup(UTOSCP(line));
  471.     }
  472.     for (;;) {
  473.     nomatch = 0;
  474.     if (sbptr > 1 || (sbptr == 1 && sbuf[0] != '^')) {
  475.         int ohistline = histline;
  476.  
  477.         for (;;) {
  478.         char *t;
  479.  
  480.         if (!(s = qgetevent(histline))) {
  481.             feep();
  482.             nomatch = 1;
  483.             histline = ohistline;
  484.             break;
  485.         }
  486.         if ((sbuf[0] == '^') ?
  487.             (t = (hstrncmp(s, sbuf + 1, sbptr - 1)) ? NULL : s) :
  488.             (t = hstrnstr(s, sbuf, sbptr)))
  489.             if (!(chequiv && !hstrcmp(UTOSCP(line), s))) {
  490.             sethistline(STOUCP(s));
  491.             cs = t - s + sbptr - (sbuf[0] == '^');
  492.             break;
  493.             }
  494.         histline += dir;
  495.         }
  496.         chequiv = 0;
  497.     }
  498.     refresh();
  499.     if ((cmd = getkeycmd()) < 0 || cmd == z_sendbreak) {
  500.         setline(oldl);
  501.         cs = ocs;
  502.         histline = ohl;
  503.         break;
  504.     }
  505.     switch (cmd) {
  506.       case z_backwarddeletechar:
  507.         if (sbptr)
  508.         sbuf[--sbptr] = '\0';
  509.         else
  510.         feep();
  511.         histline = ohl;
  512.         continue;
  513.       case z_acceptandhold:
  514.         acceptandhold();
  515.         goto brk;
  516.       case z_acceptandinfernexthistory:
  517.         acceptandinfernexthistory();
  518.         goto brk;
  519.       case z_acceptlineanddownhistory:
  520.         acceptlineanddownhistory();
  521.         goto brk;
  522.       case z_acceptline:
  523.         acceptline();
  524.         goto brk;
  525.       case z_historyincrementalsearchbackward:
  526.         ohl = (histline += (dir = -1));
  527.         chequiv = 1;
  528.         memcpy(ibuf, "bck", 3);
  529.         refresh();
  530.         continue;
  531.       case z_historyincrementalsearchforward:
  532.         ohl = (histline += (dir = 1));
  533.         chequiv = 1;
  534.         memcpy(ibuf, "fwd", 3);
  535.         refresh();
  536.         continue;
  537.       case z_sendstring:
  538.         sendstring();
  539.         continue;
  540.       case z_quotedinsert:
  541.         if ((c = getkey(0)) == EOF)
  542.         goto brk;
  543.         else
  544.         cmd = z_selfinsert;
  545.      default:
  546.         if (cmd == z_magicspace)
  547.         c = ' ';
  548.         else if (cmd != z_selfinsert && cmd != z_selfinsertunmeta) {
  549.         if (ungetok)
  550.             ungetkey(c);
  551.         else
  552.             feep();
  553.         goto brk;
  554.         }
  555.         if (!nomatch && sbptr != 39) {
  556.         sbuf[sbptr++] = c;
  557.         sbuf[sbptr] = '\0';
  558.         }
  559.     }
  560.     }
  561.   brk:
  562.     free(oldl);
  563.     statusline = NULL;
  564. }
  565.  
  566. void acceptandinfernexthistory()
  567. {                /**/
  568.     int t0;
  569.     char *s, *t;
  570.  
  571.     done = 1;
  572.     for (t0 = histline - 2;; t0--) {
  573.     if (!(s = qgetevent(t0)))
  574.         return;
  575.     if (!hstrncmp(s, UTOSCP(line), ll))
  576.         break;
  577.     }
  578.     if (!(s = qgetevent(t0 + 1)))
  579.     return;
  580.     pushnode(bufstack, t = ztrdup(s));
  581.     for (; *t; t++)
  582.     if (*t == HISTSPACE)
  583.         *t = ' ';
  584.     stackhist = t0 + 1;
  585. }
  586.  
  587. void infernexthistory()
  588. {                /**/
  589.     int t0;
  590.     char *s, *t;
  591.  
  592.     if (!(t = qgetevent(histline - 1))) {
  593.     feep();
  594.     return;
  595.     }
  596.     for (t0 = histline - 2;; t0--) {
  597.     if (!(s = qgetevent(t0))) {
  598.         feep();
  599.         return;
  600.     }
  601.     if (!strcmp(s, t))
  602.         break;
  603.     }
  604.     if (!(s = qgetevent(t0 + 1))) {
  605.     feep();
  606.     return;
  607.     }
  608.     histline = t0 + 1;
  609.     sethistline(STOUCP(s));
  610. }
  611.  
  612. void vifetchhistory()
  613. {                /**/
  614.     char *s;
  615.  
  616.     if (mult < 0)
  617.     return;
  618.     if (histline == curhist) {
  619.     if (!(lastcmd & ZLE_ARG)) {
  620.         cs = ll;
  621.         cs = findbol();
  622.         return;
  623.     }
  624.     zsfree(curhistline);
  625.     curhistline = ztrdup(UTOSCP(line));
  626.     }
  627.     if (!(lastcmd & ZLE_ARG))
  628.     mult = curhist;
  629.     if (!(s = qgetevent(mult)))
  630.     feep();
  631.     else {
  632.     histline = mult;
  633.     sethistline(STOUCP(s));
  634.     }
  635. }
  636.  
  637. extern int viins_cur_bindtab[];
  638.  
  639. int getvisrchstr()
  640. {                /**/
  641.     static char sbuf[80] = "/";
  642.     int sptr = 1, cmd, ret = 0;
  643.     int *obindtab = NULL;
  644.  
  645.     if (visrchstr) {
  646.     zsfree(visrchstr);
  647.     visrchstr = NULL;
  648.     }
  649.     statusline = sbuf;
  650.     sbuf[1] = '\0';
  651.     if (bindtab == altbindtab) {
  652.     obindtab = bindtab;
  653.     bindtab = viins_cur_bindtab;
  654.     }
  655.     while (sptr) {
  656.     refresh();
  657.     if ((cmd = getkeycmd()) < 0 || cmd == z_sendbreak) {
  658.         ret = 0;
  659.         break;
  660.     } else if (cmd == z_acceptline || cmd == z_vicmdmode) {
  661.         visrchstr = ztrdup(sbuf + 1);
  662.         ret = 1;
  663.         break;
  664.     } else if (cmd == z_backwarddeletechar ||
  665.            cmd == z_vibackwarddeletechar) {
  666.         sbuf[--sptr] = '\0';
  667.         continue;
  668.     } else if (cmd == z_sendstring) {
  669.         sendstring();
  670.         continue;
  671.     } else if (cmd == z_quotedinsert) {
  672.         if ((c = getkey(0)) == EOF) {
  673.         feep();
  674.         continue;
  675.         }
  676.     } else if (cmd != z_selfinsert && cmd != z_selfinsertunmeta) {
  677.         feep();
  678.         continue;
  679.     }
  680.     if (sptr != 79) {
  681.         sbuf[sptr++] = c;
  682.         sbuf[sptr] = '\0';
  683.     }
  684.     }
  685.     statusline = NULL;
  686.     if (obindtab)
  687.     bindtab = obindtab;
  688.     return ret;
  689. }
  690.  
  691. void vihistorysearchforward()
  692. {                /**/
  693.     visrchsense = 1;
  694.     if (getvisrchstr())
  695.     virepeatsearch();
  696. }
  697.  
  698. void vihistorysearchbackward()
  699. {                /**/
  700.     visrchsense = -1;
  701.     if (getvisrchstr())
  702.     virepeatsearch();
  703. }
  704.  
  705. void virepeatsearch()
  706. {                /**/
  707.     int ohistline = histline, t0;
  708.     char *s;
  709.  
  710.     if (!visrchstr) {
  711.     feep();
  712.     return;
  713.     }
  714.     t0 = strlen(visrchstr);
  715.     if (histline == curhist) {
  716.     zsfree(curhistline);
  717.     curhistline = ztrdup(UTOSCP(line));
  718.     }
  719.     for (;;) {
  720.     histline += visrchsense;
  721.     if (!(s = qgetevent(histline))) {
  722.         feep();
  723.         histline = ohistline;
  724.         return;
  725.     }
  726.     if (!hstrcmp(UTOSCP(line), s))
  727.         continue;
  728.     if (*visrchstr == '^') {
  729.         if (!hstrncmp(s, visrchstr + 1, t0 - 1))
  730.         break;
  731.     } else if (hstrnstr(s, visrchstr, t0))
  732.         break;
  733.     }
  734.     sethistline(STOUCP(s));
  735. }
  736.  
  737. void virevrepeatsearch()
  738. {                /**/
  739.     visrchsense = -visrchsense;
  740.     virepeatsearch();
  741.     visrchsense = -visrchsense;
  742. }
  743.  
  744. /* Extra function added by A.R. Iano-Fletcher.    */
  745. /*The extern variable "cs" is the position of the cursor. */
  746. /* history-beginning-search-backward */
  747.  
  748. void historybeginningsearchbackward()
  749. {                /**/
  750.     int cpos = cs;        /* save cursor position */
  751.     int ohistline = histline;
  752.     char *s;
  753.  
  754.     if (histline == curhist) {
  755.     zsfree(curhistline);
  756.     curhistline = ztrdup((char *)line);
  757.     }
  758.     for (;;) {
  759.     histline--;
  760.     if (!(s = qgetevent(histline))) {
  761.         feep();
  762.         histline = ohistline;
  763.         return;
  764.     }
  765.     if (!hstrncmp(s, (char *)line, cs) && hstrcmp(s, (char *)line))
  766.         break;
  767.     }
  768.  
  769.     sethistline((unsigned char *)s);    /* update command line.        */
  770.     cs = cpos;            /* reset cursor position.    */
  771. }
  772.  
  773. /* Extra function added by A.R. Iano-Fletcher.    */
  774.  
  775. /* history-beginning-search-forward */
  776. void historybeginningsearchforward()
  777. {                /**/
  778.     int cpos = cs;        /* save cursor position */
  779.     int ohistline = histline;
  780.     char *s;
  781.  
  782.     if (histline == curhist) {
  783.     zsfree(curhistline);
  784.     curhistline = ztrdup((char *)line);
  785.     }
  786.     for (;;) {
  787.     histline++;
  788.     if (!(s = qgetevent(histline))) {
  789.         feep();
  790.         histline = ohistline;
  791.         return;
  792.     }
  793.     if (!hstrncmp(s, (char *)line, cs) && hstrcmp(s, (char *)line))
  794.         break;
  795.     }
  796.  
  797.     sethistline((unsigned char *)s);    /* update command line.        */
  798.     cs = cpos;            /* reset cursor position.    */
  799. }
  800.