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_hist.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-12-17  |  21.3 KB  |  1,157 lines

  1. /*
  2.  * $Id: zle_hist.c,v 2.24 1996/10/15 20:16:35 hzoli Exp $
  3.  *
  4.  * zle_hist.c - history editing
  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. #define ZLE
  33. #include "zsh.h"
  34.  
  35. /**/
  36. void
  37. remember_edits(void)
  38. {
  39.     if (histline == curhist) {
  40.     zsfree(curhistline);
  41.     curhistline = metafy((char *) line, ll, META_DUP);
  42.     }
  43.     else {
  44.     Histent ent = gethistent(histline);
  45.  
  46.     if (metadiffer(ent->zle_text ? ent->zle_text : ent->text,
  47.                (char *) line, ll)) {
  48.         zsfree(ent->zle_text);
  49.         ent->zle_text = metafy((char *) line, ll, META_DUP);
  50.     }
  51.     }
  52. }
  53.  
  54. /**/
  55. void
  56. forget_edits(void)
  57. {
  58.     int i;
  59.  
  60.     for (i = 0; i < histentct; i++) {
  61.     zsfree(histentarr[i].zle_text);
  62.     histentarr[i].zle_text = NULL;
  63.     }
  64. }
  65.  
  66. /**/
  67. void
  68. uphistory(void)
  69. {
  70.     char *s;
  71.  
  72.     if (zmult < 0) {
  73.     zmult = -zmult;
  74.     downhistory();
  75.     return;
  76.     }
  77.     remember_edits();
  78.     histline -= zmult;
  79.     if (!(s = zle_get_event(histline))) {
  80.     if (isset(HISTBEEP))
  81.         feep();
  82.     histline += zmult;
  83.     } else
  84.     setline(s);
  85. }
  86.  
  87. /**/
  88. void
  89. uplineorhistory(void)
  90. {
  91.     int ocs = cs;
  92.  
  93.     if (zmult < 0) {
  94.     zmult = -zmult;
  95.     downlineorhistory();
  96.     return;
  97.     }
  98.     if ((lastcmd & ZLE_LINEMOVE) != ZLE_LINEMOVE)
  99.     lastcol = cs - findbol();
  100.     cs = findbol();
  101.     while (zmult) {
  102.     if (!cs)
  103.         break;
  104.     cs--;
  105.     cs = findbol();
  106.     zmult--;
  107.     }
  108.     if (zmult) {
  109.     cs = ocs;
  110.     if (virangeflag || in_vared) {
  111.         feep();
  112.         return;
  113.     }
  114.     uphistory();
  115.     } else {
  116.     int x = findeol();
  117.  
  118.     if ((cs += lastcol) >= x) {
  119.         cs = x;
  120.         if (cs > findbol() && bindtab == altbindtab)
  121.         cs--;
  122.     }
  123.     }
  124. }
  125.  
  126. /**/
  127. void
  128. viuplineorhistory(void)
  129. {
  130.     int ocs = cs;
  131.  
  132.     if (zmult < 0) {
  133.     zmult = -zmult;
  134.     downlineorhistory();
  135.     return;
  136.     }
  137.     cs = findbol();
  138.     while (zmult) {
  139.     if (!cs)
  140.         break;
  141.     cs--;
  142.     cs = findbol();
  143.     zmult--;
  144.     }
  145.     if (zmult) {
  146.     cs = ocs;
  147.     if (virangeflag || in_vared) {
  148.         feep();
  149.         return;
  150.     }
  151.     uphistory();
  152.     }
  153.     vifirstnonblank();
  154.     lastcol = cs - findbol();
  155. }
  156.  
  157.  
  158. /**/
  159. void
  160. uplineorsearch(void)
  161. {
  162.     int ocs = cs;
  163.  
  164.     if (zmult < 0) {
  165.     zmult = -zmult;
  166.     downlineorsearch();
  167.     return;
  168.     }
  169.     if ((lastcmd & ZLE_LINEMOVE) != ZLE_LINEMOVE)
  170.     lastcol = cs - findbol();
  171.     cs = findbol();
  172.     while (zmult) {
  173.     if (!cs)
  174.         break;
  175.     cs--;
  176.     cs = findbol();
  177.     zmult--;
  178.     }
  179.     if (zmult) {
  180.     cs = ocs;
  181.     if (virangeflag || in_vared) {
  182.         feep();
  183.         return;
  184.     }
  185.     historysearchbackward();
  186.     } else {
  187.     int x = findeol();
  188.  
  189.     if ((cs += lastcol) >= x) {
  190.         cs = x;
  191.         if (cs && bindtab == altbindtab)
  192.         cs--;
  193.     }
  194.     }
  195. }
  196.  
  197. /**/
  198. void
  199. downlineorhistory(void)
  200. {
  201.     int ocs = cs;
  202.  
  203.     if (zmult < 0) {
  204.     zmult = -zmult;
  205.     uplineorhistory();
  206.     return;
  207.     }
  208.     if ((lastcmd & ZLE_LINEMOVE) != ZLE_LINEMOVE)
  209.     lastcol = cs - findbol();
  210.     while (zmult) {
  211.     int x = findeol();
  212.  
  213.     if (x == ll)
  214.         break;
  215.     cs = x + 1;
  216.     zmult--;
  217.     }
  218.     if (zmult) {
  219.     cs = ocs;
  220.     if (virangeflag || in_vared) {
  221.         feep();
  222.         return;
  223.     }
  224.     downhistory();
  225.     } else {
  226.     int x = findeol();
  227.  
  228.     if ((cs += lastcol) >= x) {
  229.         cs = x;
  230.         if (cs > findbol() && bindtab == altbindtab)
  231.         cs--;
  232.     }
  233.     }
  234. }
  235.  
  236. /**/
  237. void
  238. vidownlineorhistory(void)
  239. {
  240.     int ocs = cs;
  241.  
  242.     if (zmult < 0) {
  243.     zmult = -zmult;
  244.     uplineorhistory();
  245.     return;
  246.     }
  247.     while (zmult) {
  248.     int x = findeol();
  249.  
  250.     if (x == ll)
  251.         break;
  252.     cs = x + 1;
  253.     zmult--;
  254.     }
  255.     if (zmult) {
  256.     cs = ocs;
  257.     if (virangeflag || in_vared) {
  258.         feep();
  259.         return;
  260.     }
  261.     downhistory();
  262.     }
  263.     vifirstnonblank();
  264.     lastcol = cs - findbol();
  265. }
  266.  
  267. /**/
  268. void
  269. downlineorsearch(void)
  270. {
  271.     int ocs = cs;
  272.  
  273.     if (zmult < 0) {
  274.     zmult = -zmult;
  275.     uplineorsearch();
  276.     return;
  277.     }
  278.     if ((lastcmd & ZLE_LINEMOVE) != ZLE_LINEMOVE)
  279.     lastcol = cs - findbol();
  280.     while (zmult) {
  281.     int x = findeol();
  282.  
  283.     if (x == ll)
  284.         break;
  285.     cs = x + 1;
  286.     zmult--;
  287.     }
  288.     if (zmult) {
  289.     cs = ocs;
  290.     if (virangeflag || in_vared) {
  291.         feep();
  292.         return;
  293.     }
  294.     historysearchforward();
  295.     } else {
  296.     int x = findeol();
  297.  
  298.     if ((cs += lastcol) >= x) {
  299.         cs = x;
  300.         if (cs && bindtab == altbindtab)
  301.         cs--;
  302.     }
  303.     }
  304. }
  305.  
  306. /**/
  307. void
  308. acceptlineanddownhistory(void)
  309. {
  310.     char *s;
  311.  
  312.     if (!(s = zle_get_event(histline + 1))) {
  313.     feep();
  314.     return;
  315.     }
  316.     pushnode(bufstack, ztrdup(s));
  317.     done = 1;
  318.     stackhist = histline + 1;
  319. }
  320.  
  321. /**/
  322. void
  323. downhistory(void)
  324. {
  325.     char *s;
  326.  
  327.     if (zmult < 0) {
  328.     zmult = -zmult;
  329.     uphistory();
  330.     return;
  331.     }
  332.     remember_edits();
  333.     histline += zmult;
  334.     if (!(s = zle_get_event(histline))) {
  335.     if (isset(HISTBEEP))
  336.         feep();
  337.     histline -= zmult;
  338.     return;
  339.     }
  340.     setline(s);
  341. }
  342.  
  343. static int histpos;
  344.  
  345. /**/
  346. void
  347. historysearchbackward(void)
  348. {
  349.     int t0, ohistline = histline;
  350.     char *s;
  351.  
  352.     remember_edits();
  353.     if (lastcmd & ZLE_HISTSEARCH)
  354.     t0 = histpos;
  355.     else {
  356.     for (t0 = 0; t0 < ll && !iblank(line[t0]); t0++);
  357.     if (t0 < ll)
  358.         t0++;
  359.     histpos = t0;
  360.     }
  361.     for (;;) {
  362.     histline--;
  363.     if (!(s = zle_get_event(histline))) {
  364.         feep();
  365.         histline = ohistline;
  366.         return;
  367.     }
  368.     if (metadiffer(s, (char *) line, t0) < 0 &&
  369.         metadiffer(s, (char *) line, ll))
  370.         break;
  371.     }
  372.     setline(s);
  373. }
  374.  
  375. /**/
  376. void
  377. historysearchforward(void)
  378. {
  379.     int t0, ohistline = histline;
  380.     char *s;
  381.  
  382.     remember_edits();
  383.     if (lastcmd & ZLE_HISTSEARCH)
  384.     t0 = histpos;
  385.     else {
  386.     for (t0 = 0; t0 < ll && !iblank(line[t0]); t0++);
  387.     if (t0 < ll)
  388.         t0++;
  389.     histpos = t0;
  390.     }
  391.     for (;;) {
  392.     histline++;
  393.     if (!(s = zle_get_event(histline))) {
  394.         feep();
  395.         histline = ohistline;
  396.         return;
  397.     }
  398.     if (metadiffer(s, (char *) line, t0) < (histline == curhist) &&
  399.         metadiffer(s, (char *) line, ll))
  400.         break;
  401.     }
  402.     setline(s);
  403. }
  404.  
  405. /**/
  406. void
  407. beginningofbufferorhistory(void)
  408. {
  409.     if (findbol())
  410.     cs = 0;
  411.     else
  412.     beginningofhistory();
  413. }
  414.  
  415. /**/
  416. void
  417. beginningofhistory(void)
  418. {
  419.     char *s;
  420.  
  421.     remember_edits();
  422.     if (!(s = zle_get_event(firsthist()))) {
  423.     if (isset(HISTBEEP))
  424.         feep();
  425.     return;
  426.     }
  427.     histline = firsthist();
  428.     setline(s);
  429. }
  430.  
  431. /**/
  432. void
  433. endofbufferorhistory(void)
  434. {
  435.     if (findeol() != ll)
  436.     cs = ll;
  437.     else
  438.     endofhistory();
  439. }
  440.  
  441. /**/
  442. void
  443. endofhistory(void)
  444. {
  445.     if (histline == curhist) {
  446.     if (isset(HISTBEEP))
  447.         feep();
  448.     } else {
  449.     remember_edits();
  450.     histline = curhist;
  451.     setline(curhistline);
  452.     }
  453. }
  454.  
  455. /**/
  456. void
  457. insertlastword(void)
  458. {
  459.     char *s, *t;
  460.     int len;
  461.     Histent he;
  462.  
  463. /* multiple calls will now search back through the history, pem */
  464.     static char *lastinsert;
  465.     static int lasthist, lastpos;
  466.     int evhist = curhist - 1, save;
  467.  
  468.     if (lastinsert) {
  469.     int lastlen = strlen(lastinsert);
  470.     int pos = cs;
  471.  
  472.     if (lastpos <= pos &&
  473.         lastlen == pos - lastpos &&
  474.         memcmp(lastinsert, (char *)&line[lastpos], lastlen) == 0) {
  475.         evhist = --lasthist;
  476.         cs = lastpos;
  477.         foredel(pos - cs);
  478.     }
  479.     zsfree(lastinsert);
  480.     lastinsert = NULL;
  481.     }
  482.     if (!(he = quietgethist(evhist)) || !he->nwords) {
  483.     feep();
  484.     return;
  485.     }
  486.     if (zmult > 0) {
  487.     zmult = he->nwords - (zmult - 1);
  488.     } else {
  489.     zmult = 1 - zmult;
  490.     }
  491.     if (zmult < 1 || zmult > he->nwords) {
  492.     feep();
  493.     return;
  494.     }
  495.     s = he->text + he->words[2*zmult-2];
  496.     t = he->text + he->words[2*zmult-1];
  497.     save = *t;
  498.     *t = '\0';            /* ignore trailing whitespace */
  499.  
  500.     lasthist = evhist;
  501.     lastpos = cs;
  502.     lastinsert = ztrdup(s);
  503.     spaceinline(len = ztrlen(s));
  504.     while (len--) {
  505.     line[cs++] = *s == Meta ? *++s ^ 32 : *s;
  506.     s++;
  507.     }
  508.  
  509.     *t = save;
  510. }
  511.  
  512. /**/
  513. char *
  514. qgetevent(int ev)
  515. {
  516.     return ((ev == curhist) ? curhistline : quietgetevent(ev));
  517. }
  518.  
  519. /**/
  520. char *
  521. zle_get_event(int ev)
  522. {
  523.     Histent ent;
  524.  
  525.     if (ev == curhist)
  526.     return curhistline;
  527.     if (! (ent = quietgethist(ev)))
  528.     return NULL;
  529.     if (ent->zle_text)
  530.     return ent->zle_text;
  531.     return ent->text;
  532. }
  533.  
  534.     
  535.  
  536. /**/
  537. void
  538. pushline(void)
  539. {
  540.     if (zmult < 0)
  541.     return;
  542.     pushnode(bufstack, metafy((char *) line, ll, META_DUP));
  543.     while (--zmult)
  544.     pushnode(bufstack, ztrdup(""));
  545.     stackcs = cs;
  546.     *line = '\0';
  547.     ll = cs = 0;
  548. }
  549.  
  550. /**/
  551. void
  552. pushlineoredit(void)
  553. {
  554.     int ics;
  555.     unsigned char *s;
  556.     char *hline = hgetline();
  557.  
  558.     if (zmult < 0)
  559.     return;
  560.     if (hline && *hline) {
  561.     ics = ztrlen(hline);
  562.     sizeline(ics + ll + 1);
  563.     for (s = line + ll; --s >= line; *(s + ics) = *s);
  564.     for (s = line; *hline; hline++)
  565.         *s++ = *hline == Meta ? *++hline ^ 32 : *hline;
  566.     ll += ics;
  567.     cs += ics;
  568.     }
  569.     pushline();
  570.     if (!isfirstln) {
  571.     errflag = done = 1;
  572.     }
  573. }
  574.  
  575. /**/
  576. void
  577. pushinput(void)
  578. {
  579.     if (zmult < 0)
  580.     return;
  581.     if (!isfirstln)
  582.     zmult++;
  583.     pushlineoredit();
  584. }
  585.  
  586. /**/
  587. void
  588. getline(void)
  589. {
  590.     char *s = (char *)getlinknode(bufstack);
  591.  
  592.     if (!s)
  593.     feep();
  594.     else {
  595.     int cc;
  596.  
  597.     unmetafy(s, &cc);
  598.     spaceinline(cc);
  599.     memcpy((char *)line + cs, s, cc);
  600.     cs += cc;
  601.     free(s);
  602.     }
  603. }
  604.  
  605. /**/
  606. void
  607. historyincrementalsearchbackward(void)
  608. {
  609.     doisearch(-1);
  610. }
  611.  
  612. /**/
  613. void
  614. historyincrementalsearchforward(void)
  615. {
  616.     doisearch(1);
  617. }
  618.  
  619. static struct isrch_spot {
  620.     int hl;            /* This spot's histline */
  621.     unsigned short pos;        /* The search position in our metafied str */
  622.     unsigned short cs;        /* The visible search position to the user */
  623.     unsigned short len;        /* The search string's length */
  624.     unsigned short flags;    /* This spot's flags */
  625. #define ISS_FAILING    1
  626. #define ISS_FORWARD    2
  627. } *isrch_spots;
  628.  
  629. static int max_spot = 0;
  630.  
  631. static void
  632. set_isrch_spot(int num, int hl, int pos, int cs, int len, int dir, int nomatch)
  633. {
  634.     if (num >= max_spot) {
  635.     if (!isrch_spots) {
  636.         isrch_spots = (struct isrch_spot*)
  637.                 zalloc((max_spot = 64) * sizeof *isrch_spots);
  638.     } else {
  639.         isrch_spots = (struct isrch_spot*)realloc((char*)isrch_spots,
  640.                 (max_spot += 64) * sizeof *isrch_spots);
  641.     }
  642.     }
  643.  
  644.     isrch_spots[num].hl = hl;
  645.     isrch_spots[num].pos = (unsigned short)pos;
  646.     isrch_spots[num].cs = (unsigned short)cs;
  647.     isrch_spots[num].len = (unsigned short)len;
  648.     isrch_spots[num].flags = (dir > 0? ISS_FORWARD : 0)
  649.                + (nomatch? ISS_FAILING : 0);
  650. }
  651.  
  652. static void
  653. get_isrch_spot(int num, int *hlp, int *posp, int *csp, int *lenp, int *dirp, int *nomatch)
  654. {
  655.     *hlp = isrch_spots[num].hl;
  656.     *posp = (int)isrch_spots[num].pos;
  657.     *csp = (int)isrch_spots[num].cs;
  658.     *lenp = (int)isrch_spots[num].len;
  659.     *dirp = (isrch_spots[num].flags & ISS_FORWARD)? 1 : -1;
  660.     *nomatch = (isrch_spots[num].flags & ISS_FAILING);
  661. }
  662.  
  663. #define ISEARCH_PROMPT        "failing XXX-i-search: "
  664. #define NORM_PROMPT_POS        8
  665. #define FIRST_SEARCH_CHAR    (NORM_PROMPT_POS + 14)
  666.  
  667. /**/
  668. void
  669. doisearch(int dir)
  670. {
  671.     char *s, *ibuf = halloc(80), *sbuf = ibuf + FIRST_SEARCH_CHAR;
  672.     int sbptr = 0, cmd, top_spot = 0, pos, sibuf = 80;
  673.     int nomatch = 0, skip_line = 0, skip_pos = 0;
  674.     int odir = dir, *obindtab = bindtab, sens = zmult == 1 ? 3 : 1;
  675.     static char *previous_search = NULL;
  676.     static int previous_search_len = 0;
  677.  
  678.     strcpy(ibuf, ISEARCH_PROMPT);
  679.     memcpy(ibuf + NORM_PROMPT_POS, (dir == 1) ? "fwd" : "bck", 3);
  680.     remember_edits();
  681.     s = zle_get_event(histline);
  682.     bindtab = mainbindtab;
  683.     pos = metalen(s, cs);
  684.     for (;;) {
  685.     /* Remember the current values in case search fails (doesn't push). */
  686.     set_isrch_spot(top_spot, histline, pos, cs, sbptr, dir, nomatch);
  687.     if (sbptr == 1 && sbuf[0] == '^') {
  688.         cs = 0;
  689.             nomatch = 0;
  690.         statusline = ibuf + NORM_PROMPT_POS;
  691.     } else if (sbptr > 0) {
  692.         char *last_line = s;
  693.  
  694.         for (;;) {
  695.         char *t;
  696.  
  697.         if (skip_pos) {
  698.             if (dir < 0) {
  699.             if (pos == 0)
  700.                 skip_line = 1;
  701.             else
  702.                 pos -= 1 + (pos != 1 && s[pos-2] == Meta);
  703.             } else if (sbuf[0] != '^') {
  704.             if (pos >= strlen(s+1))
  705.                 skip_line = 1;
  706.             else
  707.                 pos += 1 + (s[pos] == Meta);
  708.             } else
  709.             skip_line = 1;
  710.             skip_pos = 0;
  711.         }
  712.         if (!skip_line && ((sbuf[0] == '^') ?
  713.             (t = metadiffer(s, sbuf + 1, sbptr - 1) < sens ? s : NULL) :
  714.             (t = hstrnstr(s, pos, sbuf, sbptr, dir, sens)))) {
  715.             setline(s);
  716.             pos = t - s;
  717.             cs = ztrsub(t, s) + (dir == 1? sbptr - (sbuf[0]=='^') : 0);
  718.                 nomatch = 0;
  719.             statusline = ibuf + NORM_PROMPT_POS;
  720.             break;
  721.         }
  722.         histline += dir;
  723.         if (!(s = zle_get_event(histline))) {
  724.             if (sbptr == (int)isrch_spots[top_spot-1].len
  725.              && (isrch_spots[top_spot-1].flags & ISS_FAILING))
  726.             top_spot--;
  727.             get_isrch_spot(top_spot, &histline, &pos, &cs, &sbptr,
  728.                    &dir, &nomatch);
  729.             if (!nomatch) {
  730.             feep();
  731.             nomatch = 1;
  732.             }
  733.             s = last_line;
  734.             skip_line = 0;
  735.             statusline = ibuf;
  736.             break;
  737.         }
  738.         pos = dir == 1? 0 : strlen(s);
  739.         skip_line = !strcmp(last_line, s);
  740.         }
  741.     } else {
  742.         top_spot = 0;
  743.             nomatch = 0;
  744.         statusline = ibuf + NORM_PROMPT_POS;
  745.     }
  746.     sbuf[sbptr] = '_';
  747.     statusll = sbuf - statusline + sbptr + 1;
  748.     ref:
  749.     refresh();
  750.     if ((cmd = getkeycmd()) < 0 || cmd == z_sendbreak) {
  751.         int i;
  752.         get_isrch_spot(0, &histline, &pos, &i, &sbptr, &dir, &nomatch);
  753.         s = zle_get_event(histline);
  754.         setline(s);
  755.         cs = i;
  756.         break;
  757.     }
  758.     switch (cmd) {
  759.     case z_clearscreen:
  760.         clearscreen();
  761.         goto ref;
  762.     case z_redisplay:
  763.         redisplay();
  764.         goto ref;
  765.     case z_vicmdmode:
  766.         bindtab = (bindtab == mainbindtab) ? altbindtab : mainbindtab;
  767.         goto ref;
  768.     case z_vibackwarddeletechar:
  769.     case z_backwarddeletechar:
  770.         if (top_spot)
  771.         get_isrch_spot(--top_spot, &histline, &pos, &cs, &sbptr,
  772.                    &dir, &nomatch);
  773.         else
  774.         feep();
  775.         if (nomatch) {
  776.         statusline = ibuf;
  777.         skip_pos = 1;
  778.         }
  779.         s = zle_get_event(histline);
  780.         if (nomatch || !sbptr || (sbptr == 1 && sbuf[0] == '^')) {
  781.         int i = cs;
  782.         setline(s);
  783.         cs = i;
  784.         }
  785.         memcpy(ibuf + NORM_PROMPT_POS, (dir == 1) ? "fwd" : "bck", 3);
  786.         continue;
  787.     case z_acceptandhold:
  788.         acceptandhold();
  789.         goto brk;
  790.     case z_acceptandinfernexthistory:
  791.         acceptandinfernexthistory();
  792.         goto brk;
  793.     case z_acceptlineanddownhistory:
  794.         acceptlineanddownhistory();
  795.         goto brk;
  796.     case z_acceptline:
  797.         acceptline();
  798.         goto brk;
  799.     case z_historyincrementalsearchbackward:
  800.         set_isrch_spot(top_spot++, histline, pos, cs, sbptr, dir, nomatch);
  801.         if (dir != -1)
  802.         dir = -1;
  803.         else
  804.         skip_pos = 1;
  805.         goto rpt;
  806.     case z_historyincrementalsearchforward:
  807.         set_isrch_spot(top_spot++, histline, pos, cs, sbptr, dir, nomatch);
  808.         if (dir != 1)
  809.         dir = 1;
  810.         else
  811.         skip_pos = 1;
  812.         goto rpt;
  813.     case z_virevrepeatsearch:
  814.         set_isrch_spot(top_spot++, histline, pos, cs, sbptr, dir, nomatch);
  815.         dir = -odir;
  816.         skip_pos = 1;
  817.         goto rpt;
  818.     case z_virepeatsearch:
  819.         set_isrch_spot(top_spot++, histline, pos, cs, sbptr, dir, nomatch);
  820.         dir = odir;
  821.         skip_pos = 1;
  822.     rpt:
  823.         if (!sbptr && previous_search_len) {
  824.         if (previous_search_len > sibuf - FIRST_SEARCH_CHAR - 2) {
  825.             ibuf = hrealloc(ibuf, sibuf, sibuf + previous_search_len);
  826.             sbuf = ibuf + FIRST_SEARCH_CHAR;
  827.             sibuf += previous_search_len;
  828.         }
  829.         memcpy(sbuf, previous_search, sbptr = previous_search_len);
  830.         }
  831.         memcpy(ibuf + NORM_PROMPT_POS, (dir == 1) ? "fwd" : "bck", 3);
  832.         continue;
  833.     case z_sendstring:
  834.         sendstring();
  835.         goto ref;
  836.     case z_viquotedinsert:
  837.         sbuf[sbptr] = '^';
  838.         refresh();
  839.     case z_quotedinsert:
  840.         if ((c = getkey(0)) == EOF) {
  841.         feep();
  842.         continue;
  843.         }
  844.         goto ins;
  845.     default:
  846.         if(cmd == z_selfinsertunmeta) {
  847.         c &= 0x7f;
  848.         if(c == '\r')
  849.             c = '\n';
  850.         } else if (cmd == z_magicspace)
  851.         c = ' ';
  852.         else if (cmd != z_selfinsert) {
  853.         ungetkeycmd();
  854.         if (cmd == z_sendbreak)
  855.             sbptr = 0;
  856.         goto brk;
  857.         }
  858.     ins:
  859.         if (sbptr == PATH_MAX) {
  860.         feep();
  861.         break;
  862.         }
  863.         set_isrch_spot(top_spot++, histline, pos, cs, sbptr, dir, nomatch);
  864.         if (sbptr == sibuf - FIRST_SEARCH_CHAR - 2) {
  865.         ibuf = hrealloc(ibuf, sibuf, sibuf * 2);
  866.         sbuf = ibuf + FIRST_SEARCH_CHAR;
  867.         sibuf *= 2;
  868.         }
  869.         sbuf[sbptr++] = c;
  870.     }
  871.     }
  872.   brk:
  873.     if (sbptr) {
  874.     zfree(previous_search, previous_search_len);
  875.     previous_search = zalloc(sbptr);
  876.     memcpy(previous_search, sbuf, previous_search_len = sbptr);
  877.     }
  878.     statusline = NULL;
  879.     bindtab = obindtab;
  880. }
  881.  
  882. /**/
  883. void
  884. acceptandinfernexthistory(void)
  885. {
  886.     int t0;
  887.     char *s;
  888.  
  889.     done = 1;
  890.     for (t0 = histline - 2;; t0--) {
  891.     if (!(s = qgetevent(t0)))
  892.         return;
  893.     if (!metadiffer(s, (char *) line, ll))
  894.         break;
  895.     }
  896.     if (!(s = qgetevent(t0 + 1)))
  897.     return;
  898.     pushnode(bufstack, ztrdup(s));
  899.     stackhist = t0 + 1;
  900. }
  901.  
  902. /**/
  903. void
  904. infernexthistory(void)
  905. {
  906.     int t0;
  907.     char *s;
  908.  
  909.     for (t0 = histline - 2;; t0--) {
  910.     if (!(s = qgetevent(t0))) {
  911.         feep();
  912.         return;
  913.     }
  914.     if (! metadiffer(s, (char *) line, ll))
  915.         break;
  916.     }
  917.     if (!(s = qgetevent(t0 + 1))) {
  918.     feep();
  919.     return;
  920.     }
  921.     remember_edits();
  922.     histline = t0 + 1;
  923.     setline(s);
  924. }
  925.  
  926. /**/
  927. void
  928. vifetchhistory(void)
  929. {
  930.     char *s;
  931.  
  932.     if (zmult < 0)
  933.     return;
  934.     if (histline == curhist) {
  935.     if (!gotmult) {
  936.         cs = ll;
  937.         cs = findbol();
  938.         return;
  939.     }
  940.     }
  941.     remember_edits();
  942.     if (!gotmult)
  943.     zmult = curhist;
  944.     if (!(s = qgetevent(zmult)))
  945.     feep();
  946.     else {
  947.     histline = zmult;
  948.     setline(s);
  949.     }
  950. }
  951.  
  952. /**/
  953. int
  954. getvisrchstr(void)
  955. {
  956.     char *sbuf = halloc(80);
  957.     int sptr = 1, cmd, ret = 0, ssbuf = 80;
  958.     int *obindtab = bindtab;
  959.  
  960.     if (visrchstr) {
  961.     zsfree(visrchstr);
  962.     visrchstr = NULL;
  963.     }
  964.     statusline = sbuf;
  965.     sbuf[0] = (visrchsense == -1) ? '?' : '/';
  966.     bindtab = mainbindtab;
  967.     while (sptr) {
  968.     sbuf[sptr] = '_';
  969.     statusll = sptr + 1;
  970.     refresh();
  971.     if ((cmd = getkeycmd()) < 0 || cmd == z_sendbreak) {
  972.         ret = 0;
  973.         break;
  974.     }
  975.     if(cmd == z_magicspace) {
  976.         c = ' ';
  977.         cmd = z_selfinsert;
  978.     }
  979.     switch(cmd) {
  980.       case z_redisplay:
  981.         redisplay();
  982.         break;
  983.       case z_clearscreen:
  984.         clearscreen();
  985.         break;
  986.       case z_acceptline:
  987.       case z_vicmdmode:
  988.         sbuf[sptr] = 0;
  989.         visrchstr = metafy(sbuf + 1, sptr - 1, META_DUP);
  990.         ret = 1;
  991.         sptr = 0;
  992.         break;
  993.       case z_backwarddeletechar:
  994.       case z_vibackwarddeletechar:
  995.         sptr--;
  996.         break;
  997.       case z_backwardkillword:
  998.       case z_vibackwardkillword:
  999.         while(sptr != 1 && iblank(sbuf[sptr - 1]))
  1000.         sptr--;
  1001.         if(iident(sbuf[sptr - 1]))
  1002.         while(sptr != 1 && iident(sbuf[sptr - 1]))
  1003.             sptr--;
  1004.         else
  1005.         while(sptr != 1 && !iident(sbuf[sptr - 1]) && !iblank(sbuf[sptr - 1]))
  1006.             sptr--;
  1007.         break;
  1008.       case z_sendstring:
  1009.         sendstring();
  1010.         break;
  1011.       case z_viquotedinsert:
  1012.         sbuf[sptr] = '^';
  1013.         refresh();
  1014.         /* fall through */
  1015.       case z_quotedinsert:
  1016.         if ((c = getkey(0)) == EOF) {
  1017.         feep();
  1018.         break;
  1019.         }
  1020.         goto ins;
  1021.       case z_selfinsertunmeta:
  1022.         c &= 0x7f;
  1023.         if(c == '\r')
  1024.         c = '\n';
  1025.       case z_selfinsert:
  1026.       ins:
  1027.         if(sptr == ssbuf - 1) {
  1028.         char *newbuf = halloc(ssbuf *= 2);
  1029.         strcpy(newbuf, sbuf);
  1030.         statusline = sbuf = newbuf;
  1031.         }
  1032.         sbuf[sptr++] = c;
  1033.         break;
  1034.       default:
  1035.         feep();
  1036.     }
  1037.     }
  1038.     statusline = NULL;
  1039.     bindtab = obindtab;
  1040.     return ret;
  1041. }
  1042.  
  1043. /**/
  1044. void
  1045. vihistorysearchforward(void)
  1046. {
  1047.     visrchsense = 1;
  1048.     if (getvisrchstr())
  1049.     virepeatsearch();
  1050. }
  1051.  
  1052. /**/
  1053. void
  1054. vihistorysearchbackward(void)
  1055. {
  1056.     visrchsense = -1;
  1057.     if (getvisrchstr())
  1058.     virepeatsearch();
  1059. }
  1060.  
  1061. /**/
  1062. void
  1063. virepeatsearch(void)
  1064. {
  1065.     int ohistline = histline, t0;
  1066.     char *s;
  1067.  
  1068.     if (!visrchstr) {
  1069.     feep();
  1070.     return;
  1071.     }
  1072.     t0 = strlen(visrchstr);
  1073.     remember_edits();
  1074.     for (;;) {
  1075.     histline += visrchsense;
  1076.     if (!(s = zle_get_event(histline))) {
  1077.         feep();
  1078.         histline = ohistline;
  1079.         return;
  1080.     }
  1081.     if (!metadiffer(s, (char *) line, ll))
  1082.         continue;
  1083.     if (*visrchstr == '^') {
  1084.         if (!strncmp(s, visrchstr + 1, t0 - 1))
  1085.         break;
  1086.     } else if (hstrnstr(s, 0, visrchstr, t0, 1, 1))
  1087.         break;
  1088.     }
  1089.     setline(s);
  1090. }
  1091.  
  1092. /**/
  1093. void
  1094. virevrepeatsearch(void)
  1095. {
  1096.     visrchsense = -visrchsense;
  1097.     virepeatsearch();
  1098.     visrchsense = -visrchsense;
  1099. }
  1100.  
  1101. /* Extra function added by A.R. Iano-Fletcher.    */
  1102. /*The extern variable "cs" is the position of the cursor. */
  1103. /* history-beginning-search-backward */
  1104.  
  1105. /**/
  1106. void
  1107. historybeginningsearchbackward(void)
  1108. {
  1109.     int cpos = cs;        /* save cursor position */
  1110.     int ohistline = histline;
  1111.     char *s;
  1112.  
  1113.     remember_edits();
  1114.     for (;;) {
  1115.     histline--;
  1116.     if (!(s = zle_get_event(histline))) {
  1117.         feep();
  1118.         histline = ohistline;
  1119.         return;
  1120.     }
  1121.     if (metadiffer(s, (char *)line, cs) < 0 &&
  1122.         metadiffer(s, (char *)line, ll))
  1123.         break;
  1124.     }
  1125.  
  1126.     setline(s);
  1127.     cs = cpos;
  1128. }
  1129.  
  1130. /* Extra function added by A.R. Iano-Fletcher.    */
  1131.  
  1132. /* history-beginning-search-forward */
  1133. /**/
  1134. void
  1135. historybeginningsearchforward(void)
  1136. {
  1137.     int cpos = cs;        /* save cursor position */
  1138.     int ohistline = histline;
  1139.     char *s;
  1140.  
  1141.     remember_edits();
  1142.     for (;;) {
  1143.     histline++;
  1144.     if (!(s = zle_get_event(histline))) {
  1145.         feep();
  1146.         histline = ohistline;
  1147.         return;
  1148.     }
  1149.     if (metadiffer(s, (char *)line, cs) < (histline == curhist) &&
  1150.         metadiffer(s, (char *)line, ll))
  1151.         break;
  1152.     }
  1153.  
  1154.     setline(s);
  1155.     cs = cpos;
  1156. }
  1157.