home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Unix / Shells / tcsh / Source / ed.chared.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-21  |  58.3 KB  |  3,225 lines

  1. /* $Header: /u/christos/src/tcsh-6.03/RCS/ed.chared.c,v 3.31 1992/10/14 20:19:19 christos Exp $ */
  2. /*
  3.  * ed.chared.c: Character editing functions.
  4.  */
  5. /*-
  6.  * Copyright (c) 1980, 1991 The Regents of the University of California.
  7.  * All rights reserved.
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions
  11.  * are met:
  12.  * 1. Redistributions of source code must retain the above copyright
  13.  *    notice, this list of conditions and the following disclaimer.
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in the
  16.  *    documentation and/or other materials provided with the distribution.
  17.  * 3. All advertising materials mentioning features or use of this software
  18.  *    must display the following acknowledgement:
  19.  *    This product includes software developed by the University of
  20.  *    California, Berkeley and its contributors.
  21.  * 4. Neither the name of the University nor the names of its contributors
  22.  *    may be used to endorse or promote products derived from this software
  23.  *    without specific prior written permission.
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35.  * SUCH DAMAGE.
  36.  */
  37. #include "sh.h"
  38.  
  39. RCSID("$Id: ed.chared.c,v 3.31 1992/10/14 20:19:19 christos Exp $")
  40.  
  41. #include "ed.h"
  42. #include "tw.h"
  43. #include "ed.defns.h"
  44.  
  45. /* #define SDEBUG */
  46.  
  47. #define NOP          0x00
  48. #define DELETE       0x01
  49. #define INSERT       0x02
  50. #define CHANGE       0x04
  51.  
  52. #define CHAR_FWD    0
  53. #define CHAR_BACK    1
  54.  
  55. static Char *InsertPos = InputBuf; /* Where insertion starts */
  56. static Char *ActionPos = 0;       /* Where action begins  */
  57. static int  ActionFlag = NOP;       /* What delayed action to take */
  58. /*
  59.  * Word search state
  60.  */
  61. static int  searchdir = F_UP_SEARCH_HIST;     /* Direction of last search */
  62. static Char patbuf[INBUFSIZE];            /* Search target */
  63. static int patlen = 0;
  64. /*
  65.  * Char search state
  66.  */
  67. static int  srch_dir = CHAR_FWD;        /* Direction of last search */
  68. static Char srch_char = 0;            /* Search target */
  69.  
  70. /* all routines that start with c_ are private to this set of routines */
  71. static    void     c_alternativ_key_map    __P((int));
  72. static    void     c_insert        __P((int));
  73. static    void     c_delafter        __P((int));
  74. static    void     c_delbefore        __P((int));
  75. static    Char    *c_prev_word        __P((Char *, Char *, int));
  76. static    Char    *c_next_word        __P((Char *, Char *, int));
  77. static    Char    *c_number        __P((Char *, int *, int));
  78. static    Char    *c_expand        __P((Char *));
  79. static    void     c_excl            __P((Char *));
  80. static    void     c_substitute        __P((void));
  81. static    int     c_hmatch        __P((Char *));
  82. static    void     c_hsetpat        __P((void));
  83. #ifdef COMMENT
  84. static    void     c_get_word        __P((Char **, Char **));
  85. #endif
  86. static    Char    *c_preword        __P((Char *, Char *, int));
  87. static    Char    *c_nexword        __P((Char *, Char *, int));
  88. static    Char    *c_endword        __P((Char *, Char *, int));
  89. static    Char    *c_eword        __P((Char *, Char *, int));
  90. static  CCRETVAL c_get_histline        __P((void));
  91. static  CCRETVAL c_search_line        __P((Char *, int));
  92. static  CCRETVAL v_repeat_srch        __P((int));
  93. static    CCRETVAL e_inc_search        __P((int));
  94. static    CCRETVAL v_search        __P((int));
  95. static    CCRETVAL v_csearch_fwd        __P((int, int, int));
  96. static    CCRETVAL v_csearch_back        __P((int, int, int));
  97.  
  98. static void
  99. c_alternativ_key_map(state)
  100.     int     state;
  101. {
  102.     switch (state) {
  103.     case 0:
  104.     CurrentKeyMap = CcKeyMap;
  105.     break;
  106.     case 1:
  107.     CurrentKeyMap = CcAltMap;
  108.     break;
  109.     default:
  110.     return;
  111.     }
  112.  
  113.     AltKeyMap = state;
  114. }
  115.  
  116. static void
  117. c_insert(num)
  118.     register int num;
  119. {
  120.     register Char *cp;
  121.  
  122.     if (LastChar + num >= InputLim)
  123.     return;            /* can't go past end of buffer */
  124.  
  125.     if (Cursor < LastChar) {    /* if I must move chars */
  126.     for (cp = LastChar; cp >= Cursor; cp--)
  127.         cp[num] = *cp;
  128.     }
  129.     LastChar += num;
  130. }
  131.  
  132. static void
  133. c_delafter(num)    
  134.     register int num;
  135. {
  136.     register Char *cp, *kp;
  137.  
  138.     if (Cursor + num > LastChar)
  139.     num = LastChar - Cursor;    /* bounds check */
  140.  
  141.     if (num > 0) {            /* if I can delete anything */
  142.     if (VImode) {
  143.         kp = UndoBuf;        /* Set Up for VI undo command */
  144.         UndoAction = INSERT;
  145.         UndoSize = num;
  146.         UndoPtr  = Cursor;
  147.         for (cp = Cursor; cp <= LastChar; cp++) {
  148.         *kp++ = *cp;    /* Save deleted chars into undobuf */
  149.         *cp = cp[num];
  150.         }
  151.     }
  152.     else
  153.         for (cp = Cursor; cp <= LastChar; cp++)
  154.         *cp = cp[num];
  155.     LastChar -= num;
  156.     }
  157. #ifdef notdef
  158.     else {
  159.     /* 
  160.      * XXX: We don't want to do that. In emacs mode overwrite should be
  161.      * sticky. I am not sure how that affects vi mode 
  162.      */
  163.     inputmode = MODE_INSERT;
  164.     }
  165. #endif /* notdef */
  166. }
  167.  
  168. static void
  169. c_delbefore(num)        /* delete before dot, with bounds checking */
  170.     register int num;
  171. {
  172.     register Char *cp, *kp;
  173.  
  174.     if (Cursor - num < InputBuf)
  175.     num = Cursor - InputBuf;    /* bounds check */
  176.  
  177.     if (num > 0) {            /* if I can delete anything */
  178.     if (VImode) {
  179.         kp = UndoBuf;        /* Set Up for VI undo command */
  180.         UndoAction = INSERT;
  181.         UndoSize = num;
  182.         UndoPtr  = Cursor - num;
  183.         for (cp = Cursor - num; cp <= LastChar; cp++) {
  184.         *kp++ = *cp;
  185.         *cp = cp[num];
  186.         }
  187.     }
  188.     else
  189.         for (cp = Cursor - num; cp <= LastChar; cp++)
  190.         *cp = cp[num];
  191.     LastChar -= num;
  192.     }
  193. }
  194.  
  195. static Char *
  196. c_preword(p, low, n)
  197.     register Char *p, *low;
  198.     register int n;
  199. {
  200.     p--;
  201.  
  202.     while (n--) {
  203.     while ((p >= low) && Isspace(*p)) 
  204.         p--;
  205.     while ((p >= low) && !Isspace(*p)) 
  206.         p--;
  207.     }
  208.     /* cp now points to one character before the word */
  209.     p++;
  210.     if (p < low)
  211.     p = low;
  212.     /* cp now points where we want it */
  213.     return(p);
  214. }
  215.  
  216. static Char *
  217. c_prev_word(p, low, n)
  218.     register Char *p, *low;
  219.     register int n;
  220. {
  221.     p--;
  222.  
  223.     while (n--) {
  224.     while ((p >= low) && !isword(*p)) 
  225.         p--;
  226.     while ((p >= low) && isword(*p)) 
  227.         p--;
  228.     }
  229.  
  230.     /* cp now points to one character before the word */
  231.     p++;
  232.     if (p < low)
  233.     p = low;
  234.     /* cp now points where we want it */
  235.     return(p);
  236. }
  237.  
  238. static Char *
  239. c_next_word(p, high, n)
  240.     register Char *p, *high;
  241.     register int n;
  242. {
  243.     while (n--) {
  244.     while ((p < high) && !isword(*p)) 
  245.         p++;
  246.     while ((p < high) && isword(*p)) 
  247.         p++;
  248.     }
  249.     if (p > high)
  250.     p = high;
  251.     /* p now points where we want it */
  252.     return(p);
  253. }
  254.  
  255. static Char *
  256. c_nexword(p, high, n)
  257.     register Char *p, *high;
  258.     register int n;
  259. {
  260.     while (n--) {
  261.     while ((p < high) && !Isspace(*p)) 
  262.         p++;
  263.     while ((p < high) && Isspace(*p)) 
  264.         p++;
  265.     }
  266.  
  267.     if (p > high)
  268.     p = high;
  269.     /* p now points where we want it */
  270.     return(p);
  271. }
  272.  
  273. /*
  274.  * Expand-History (originally "Magic-Space") code added by
  275.  * Ray Moody <ray@gibbs.physics.purdue.edu>
  276.  * this is a neat, but odd, addition.
  277.  */
  278.  
  279. /*
  280.  * c_number: Ignore character p points to, return number appearing after that.
  281.  * A '$' by itself means a big number; "$-" is for negative; '^' means 1.
  282.  * Return p pointing to last char used.
  283.  */
  284.  
  285. /*
  286.  * dval is the number to subtract from for things like $-3
  287.  */
  288.  
  289. static Char *
  290. c_number(p, num, dval)
  291.     register Char *p;
  292.     register int *num;
  293.     register int dval;
  294. {
  295.     register int i;
  296.     register int sign = 1;
  297.  
  298.     if (*++p == '^') {
  299.     *num = 1;
  300.     return(p);
  301.     }
  302.     if (*p == '$') {
  303.     if (*++p != '-') {
  304.         *num = NCARGS;    /* Handle $ */
  305.         return(--p);
  306.     }
  307.     sign = -1;        /* Handle $- */
  308.     ++p;
  309.     }
  310.     for (i = 0; *p >= '0' && *p <= '9'; i = 10 * i + *p++ - '0')
  311.     continue;
  312.     *num = (sign < 0 ? dval - i : i);
  313.     return(--p);
  314. }
  315.  
  316. /*
  317.  * excl_expand: There is an excl to be expanded to p -- do the right thing
  318.  * with it and return a version of p advanced over the expanded stuff.  Also,
  319.  * update tsh_cur and related things as appropriate...
  320.  */
  321.  
  322. static Char *
  323. c_expand(p)
  324.     register Char *p;
  325. {
  326.     register Char *q;
  327.     register struct Hist *h = Histlist.Hnext;
  328.     register struct wordent *l;
  329.     int     i, from, to, dval;
  330.     bool    all_dig;
  331.     bool    been_once = 0;
  332.     Char   *op = p;
  333.     Char    buf[INBUFSIZE];
  334.     Char   *bend = buf;
  335.     Char   *modbuf, *omodbuf;
  336.  
  337.     if (!h)
  338.     goto excl_err;
  339. excl_sw:
  340.     switch (*(q = p + 1)) {
  341.  
  342.     case '^':
  343.     bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 1, 1);
  344.     break;
  345.  
  346.     case '$':
  347.     if ((l = (h->Hlex).prev) != 0)
  348.         bend = expand_lex(buf, INBUFSIZE, l->prev->prev, 0, 0);
  349.     break;
  350.  
  351.     case '*':
  352.     bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 1, NCARGS);
  353.     break;
  354.  
  355.     default:
  356.     if (been_once) {    /* unknown argument */
  357.         /* assume it's a modifier, e.g. !foo:h, and get whole cmd */
  358.         bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 0, NCARGS);
  359.         q -= 2;
  360.         break;
  361.     }
  362.     been_once = 1;
  363.  
  364.     if (*q == ':')        /* short form: !:arg */
  365.         --q;
  366.  
  367.     if (*q != HIST) {
  368.         /*
  369.          * Search for a space, tab, or colon.  See if we have a number (as
  370.          * in !1234:xyz).  Remember the number.
  371.          */
  372.         for (i = 0, all_dig = 1; 
  373.          *q != ' ' && *q != '\t' && *q != ':' && q < Cursor; q++) {
  374.         /*
  375.          * PWP: !-4 is a valid history argument too, therefore the test
  376.          * is if not a digit, or not a - as the first character.
  377.          */
  378.         if ((*q < '0' || *q > '9') && (*q != '-' || q != p + 1))
  379.             all_dig = 0;
  380.         else if (*q == '-')
  381.             all_dig = 2;/* we are sneeky about this */
  382.         else
  383.             i = 10 * i + *q - '0';
  384.         }
  385.         --q;
  386.  
  387.         /*
  388.          * If we have a number, search for event i.  Otherwise, search for
  389.          * a named event (as in !foo).  (In this case, I is the length of
  390.          * the named event).
  391.          */
  392.         if (all_dig) {
  393.         if (all_dig == 2)
  394.             i = -i;    /* make it negitive */
  395.         if (i < 0)    /* if !-4 (for example) */
  396.             i = eventno + 1 + i;    /* remember: i is < 0 */
  397.         for (; h; h = h->Hnext) {
  398.             if (h->Hnum == i)
  399.             break;
  400.         }
  401.         }
  402.         else {
  403.         for (i = q - p; h; h = h->Hnext) {
  404.             if ((l = &h->Hlex) != 0) {
  405.             if (!Strncmp(p + 1, l->next->word, i))
  406.                 break;
  407.             }
  408.         }
  409.         }
  410.     }
  411.     if (!h)
  412.         goto excl_err;
  413.     if (q[1] == ':' || q[1] == '-' || q[1] == '*' ||
  414.         q[1] == '$' || q[1] == '^') {    /* get some args */
  415.         p = q[1] == ':' ? ++q : q;
  416.         /*
  417.          * Go handle !foo:*
  418.          */
  419.         if ((q[1] < '0' || q[1] > '9') &&
  420.         q[1] != '-' && q[1] != '$' && q[1] != '^')
  421.         goto excl_sw;
  422.         /*
  423.          * Go handle !foo:$
  424.          */
  425.         if (q[1] == '$' && (q[2] != '-' || q[3] < '0' || q[3] > '9'))
  426.         goto excl_sw;
  427.         /*
  428.          * Count up the number of words in this event.  Store it in dval.
  429.          * Dval will be fed to number.
  430.          */
  431.         dval = 0;
  432.         if ((l = h->Hlex.prev) != 0) {
  433.         for (l = l->prev; l != h->Hlex.next; l = l->prev, dval++)
  434.             continue;
  435.         }
  436.         if (!dval)
  437.         goto excl_err;
  438.         if (q[1] == '-')
  439.         from = 0;
  440.         else
  441.         q = c_number(q, &from, dval);
  442.         if (q[1] == '-') {
  443.         ++q;
  444.         if ((q[1] < '0' || q[1] > '9') && q[1] != '$')
  445.             to = dval - 1;
  446.         else
  447.             q = c_number(q, &to, dval);
  448.         }
  449.         else if (q[1] == '*') {
  450.         ++q;
  451.         to = NCARGS;
  452.         }
  453.         else {
  454.         to = from;
  455.         }
  456.         if (from < 0 || to < from)
  457.         goto excl_err;
  458.         bend = expand_lex(buf, INBUFSIZE, &h->Hlex, from, to);
  459.     }
  460.     else {            /* get whole cmd */
  461.         bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 0, NCARGS);
  462.     }
  463.     break;
  464.     }
  465.  
  466.     /*
  467.      * Apply modifiers, if any.
  468.      */
  469.     if (q[1] == ':') {
  470.     *bend = '\0';
  471.     omodbuf = buf;
  472.     while (q[1] == ':' && (modbuf = domod(omodbuf, (int) q[2])) != NULL) {
  473.         if (omodbuf != buf)
  474.         xfree((ptr_t) omodbuf);
  475.         omodbuf = modbuf;
  476.         q += 2;
  477.     }
  478.     if (omodbuf != buf) {
  479.         (void) Strcpy(buf, omodbuf);
  480.         xfree((ptr_t) omodbuf);
  481.         bend = Strend(buf);
  482.     }
  483.     }
  484.  
  485.     /*
  486.      * Now replace the text from op to q inclusive with the text from buf to
  487.      * bend.
  488.      */
  489.     q++;
  490.  
  491.     /*
  492.      * Now replace text non-inclusively like a real CS major!
  493.      */
  494.     if (LastChar + (bend - buf) - (q - op) >= InputLim)
  495.     goto excl_err;
  496.     (void) memmove((ptr_t) (q + (bend - buf) - (q - op)), (ptr_t) q, 
  497.            (size_t) ((LastChar - q) * sizeof(Char)));
  498.     LastChar += (bend - buf) - (q - op);
  499.     Cursor += (bend - buf) - (q - op);
  500.     (void) memmove((ptr_t) op, (ptr_t) buf, 
  501.            (size_t) ((bend - buf) * sizeof(Char)));
  502.     *LastChar = '\0';
  503.     return(op + (bend - buf));
  504. excl_err:
  505.     Beep();
  506.     return(op + 1);
  507. }
  508.  
  509. /*
  510.  * c_excl: An excl has been found at point p -- back up and find some white
  511.  * space (or the beginning of the buffer) and properly expand all the excl's
  512.  * from there up to the current cursor position. We also avoid (trying to)
  513.  * expanding '>!'
  514.  */
  515.  
  516. static void
  517. c_excl(p)
  518.     register Char *p;
  519. {
  520.     register int i;
  521.     register Char *q;
  522.  
  523.     /*
  524.      * if />[SPC TAB]*![SPC TAB]/, back up p to just after the >. otherwise,
  525.      * back p up to just before the current word.
  526.      */
  527.     if ((p[1] == ' ' || p[1] == '\t') &&
  528.     (p[-1] == ' ' || p[-1] == '\t' || p[-1] == '>')) {
  529.     for (q = p - 1; q > InputBuf && (*q == ' ' || *q == '\t'); --q)
  530.         continue;
  531.     if (*q == '>')
  532.         ++p;
  533.     }
  534.     else {
  535.     while (*p != ' ' && *p != '\t' && p > InputBuf)
  536.         --p;
  537.     }
  538.  
  539.     /*
  540.      * Forever: Look for history char.  (Stop looking when we find the cursor.)
  541.      * Count backslashes.  Of odd, skip history char. Return if all done.
  542.      * Expand if even number of backslashes.
  543.      */
  544.     for (;;) {
  545.     while (*p != HIST && p < Cursor)
  546.         ++p;
  547.     for (i = 1; (p - i) >= InputBuf && p[-i] == '\\'; i++)
  548.         continue;
  549.     if (i % 2 == 0)
  550.         ++p;
  551.     if (p >= Cursor)
  552.         return;
  553.     if (i % 2 == 1)
  554.         p = c_expand(p);
  555.     }
  556. }
  557.  
  558.  
  559. static void
  560. c_substitute()
  561. {
  562.     register Char *p;
  563.  
  564.     /*
  565.      * Start p out one character before the cursor.  Move it backwards looking
  566.      * for white space, the beginning of the line, or a history character.
  567.      */
  568.     for (p = Cursor - 1; 
  569.      p > InputBuf && *p != ' ' && *p != '\t' && *p != HIST; --p)
  570.     continue;
  571.  
  572.     /*
  573.      * If we found a history character, go expand it.
  574.      */
  575.     if (*p == HIST)
  576.     c_excl(p);
  577.     Refresh();
  578. }
  579.  
  580. static void
  581. c_delfini()        /* Finish up delete action */
  582. {
  583.     register int Size;
  584.  
  585.     if (ActionFlag & INSERT)
  586.     c_alternativ_key_map(0);
  587.  
  588.     ActionFlag = NOP;
  589.  
  590.     if (ActionPos == 0) 
  591.     return;
  592.  
  593.     UndoAction = INSERT;
  594.  
  595.     if (Cursor > ActionPos) {
  596.     Size = (int) (Cursor-ActionPos);
  597.     c_delbefore(Size); 
  598.     Cursor = ActionPos;
  599.     RefCursor();
  600.     }
  601.     else if (Cursor < ActionPos) {
  602.     Size = (int)(ActionPos-Cursor);
  603.     c_delafter(Size);
  604.     }
  605.     else  {
  606.     Size = 1;
  607.     c_delafter(Size);
  608.     }
  609.     UndoPtr = Cursor;
  610.     UndoSize = Size;
  611. }
  612.  
  613. static Char *
  614. c_endword(p, high, n)
  615.     register Char *p, *high;
  616.     register int n;
  617. {
  618.     p++;
  619.  
  620.     while (n--) {
  621.     while ((p < high) && Isspace(*p))
  622.         p++;
  623.     while ((p < high) && !Isspace(*p)) 
  624.         p++;
  625.     }
  626.  
  627.     p--;
  628.     return(p);
  629. }
  630.  
  631.  
  632. static Char *
  633. c_eword(p, high, n)
  634.     register Char *p, *high;
  635.     register int n;
  636. {
  637.     p++;
  638.  
  639.     while (n--) {
  640.     while ((p < high) && Isspace(*p)) 
  641.         p++;
  642.  
  643.     if (Isalnum(*p))
  644.         while ((p < high) && Isalnum(*p)) 
  645.         p++;
  646.     else
  647.         while ((p < high) && !(Isspace(*p) || Isalnum(*p)))
  648.         p++;
  649.     }
  650.  
  651.     p--;
  652.     return(p);
  653. }
  654.  
  655. static CCRETVAL
  656. c_get_histline()
  657. {
  658.     struct Hist *hp;
  659.     int     h;
  660.  
  661.     if (Hist_num == 0) {    /* if really the current line */
  662.     copyn(InputBuf, HistBuf, INBUFSIZE);
  663.     LastChar = InputBuf + (LastHist - HistBuf);
  664.  
  665. #ifdef KSHVI
  666.     if (VImode)
  667.     Cursor = InputBuf;
  668.     else
  669. #endif /* KSHVI */
  670.     Cursor = LastChar;
  671.  
  672.     return(CC_REFRESH);
  673.     }
  674.  
  675.     hp = Histlist.Hnext;
  676.     if (hp == NULL)
  677.     return(CC_ERROR);
  678.  
  679.     for (h = 1; h < Hist_num; h++) {
  680.     if ((hp->Hnext) == NULL) {
  681.         Hist_num = h;
  682.         return(CC_ERROR);
  683.     }
  684.     hp = hp->Hnext;
  685.     }
  686.  
  687.     if (HistLit && hp->histline) {
  688.     copyn(InputBuf, hp->histline, INBUFSIZE);
  689.     CurrentHistLit = 1;
  690.     }
  691.     else {
  692.     (void) sprlex(InputBuf, &hp->Hlex);
  693.     CurrentHistLit = 0;
  694.     }
  695.     LastChar = InputBuf + Strlen(InputBuf);
  696.  
  697.     if (LastChar > InputBuf) {
  698.     if (LastChar[-1] == '\n')
  699.         LastChar--;
  700.     if (LastChar[-1] == ' ')
  701.         LastChar--;
  702.     if (LastChar < InputBuf)
  703.         LastChar = InputBuf;
  704.     }
  705.  
  706. #ifdef KSHVI
  707.     if (VImode)
  708.     Cursor = InputBuf;
  709.     else
  710. #endif /* KSHVI */
  711.     Cursor = LastChar;
  712.  
  713.     return(CC_REFRESH);
  714. }
  715.  
  716. static CCRETVAL
  717. c_search_line(pattern, dir)
  718. Char *pattern;
  719. int dir;
  720. {
  721.     Char *cp;
  722.     int len;
  723.  
  724.     len = Strlen(pattern);
  725.  
  726.     if (dir == F_UP_SEARCH_HIST) {
  727.     for (cp = Cursor; cp >= InputBuf; cp--)
  728.         if (Strncmp(cp, pattern, len) == 0 || Gmatch(cp, pattern)) {
  729.         Cursor = cp;
  730.         return(CC_NORM);
  731.         }
  732.     return(CC_ERROR);
  733.     } else {
  734.     for (cp = Cursor; *cp != '\0' && cp < InputLim; cp++)
  735.         if (Strncmp(cp, pattern, len) == 0 || Gmatch(cp, pattern)) {
  736.         Cursor = cp;
  737.         return(CC_NORM);
  738.         }
  739.     return(CC_ERROR);
  740.     }
  741. }
  742.  
  743. static CCRETVAL
  744. e_inc_search(dir)
  745.     int dir;
  746. {
  747.     static Char STRfwd[] = { 'f', 'w', 'd', '\0' },
  748.         STRbck[] = { 'b', 'c', 'k', '\0' };
  749.     static Char pchar = ':';    /* ':' = normal, '?' = failed */
  750.     static Char endcmd[2];
  751.     Char ch, *cp,
  752.     *oldCursor = Cursor,
  753.     oldpchar = pchar;
  754.     CCRETVAL ret = CC_NORM;
  755.     int oldHist_num = Hist_num,
  756.     oldpatlen = patlen,
  757.     newdir = dir,
  758.         done, redo;
  759.  
  760.     if (LastChar + sizeof(STRfwd)/sizeof(Char) + 2 + patlen >= InputLim)
  761.     return(CC_ERROR);
  762.  
  763.     for (;;) {
  764.  
  765.     if (patlen == 0) {    /* first round */
  766.         pchar = ':';
  767.         patbuf[patlen++] = '*';
  768.     }
  769.     done = redo = 0;
  770.     *LastChar++ = '\n';
  771.     for (cp = newdir == F_UP_SEARCH_HIST ? STRbck : STRfwd; 
  772.          *cp; *LastChar++ = *cp++)
  773.         continue;
  774.     *LastChar++ = pchar;
  775.     for (cp = &patbuf[1]; cp < &patbuf[patlen]; *LastChar++ = *cp++)
  776.         continue;
  777.     *LastChar = '\0';
  778.     Refresh();
  779.  
  780.     if (GetNextChar(&ch) != 1)
  781.         return(e_send_eof(0));
  782.  
  783.     switch (CurrentKeyMap[(unsigned char) ch]) {
  784.     case F_INSERT:
  785.     case F_DIGIT:
  786.     case F_MAGIC_SPACE:
  787.         if (patlen > INBUFSIZE - 3)
  788.         Beep();
  789.         else {
  790.         patbuf[patlen++] = ch;
  791.         *LastChar++ = ch;
  792.         *LastChar = '\0';
  793.         Refresh();
  794.         }
  795.         break;
  796.  
  797.     case F_INC_FWD:
  798.         newdir = F_DOWN_SEARCH_HIST;
  799.         redo++;
  800.         break;
  801.  
  802.     case F_INC_BACK:
  803.         newdir = F_UP_SEARCH_HIST;
  804.         redo++;
  805.         break;
  806.  
  807.     case F_DELPREV:
  808.         if (patlen > 1)
  809.         done++;
  810.         else 
  811.         Beep();
  812.         break;
  813.  
  814.     default:
  815.         switch (ch) {
  816.         case 0007:        /* ^G: Abort */
  817.         ret = CC_ERROR;
  818.         done++;
  819.         break;
  820.  
  821.         case 0027:        /* ^W: Append word */
  822.         /* No can do if globbing characters in pattern */
  823.         for (cp = &patbuf[1]; ; cp++)
  824.             if (cp >= &patbuf[patlen]) {
  825.             Cursor += patlen - 1;
  826.             cp = c_next_word(Cursor, LastChar, 1);
  827.             while (Cursor < cp && *Cursor != '\n') {
  828.                 if (patlen > INBUFSIZE - 3) {
  829.                 Beep();
  830.                 break;
  831.                 }
  832.                 patbuf[patlen++] = *Cursor;
  833.                 *LastChar++ = *Cursor++;
  834.             }
  835.             Cursor = oldCursor;
  836.             *LastChar = '\0';
  837.             Refresh();
  838.             break;
  839.             } else if (isglob(*cp)) {
  840.             Beep();
  841.             break;
  842.             }
  843.         break;
  844.         
  845.         default:        /* Terminate and execute cmd */
  846.         endcmd[0] = ch;
  847.         PushMacro(endcmd);
  848.         /*FALLTHROUGH*/
  849.  
  850.         case 0033:        /* ESC: Terminate */
  851.         ret = CC_REFRESH;
  852.         done++;
  853.         break;
  854.         }
  855.         break;
  856.     }
  857.  
  858.     while (LastChar > InputBuf && *LastChar != '\n')
  859.         *LastChar-- = '\0';
  860.     *LastChar = '\0';
  861.  
  862.     if (!done) {
  863.  
  864.         /* Can't search if unmatched '[' */
  865.         for (cp = &patbuf[patlen - 1], ch = ']'; cp > patbuf; cp--)
  866.         if (*cp == '[' || *cp == ']') {
  867.             ch = *cp;
  868.             break;
  869.         }
  870.  
  871.         if (patlen > 1 && ch != '[') {
  872.         if (redo && newdir == dir) {
  873.             if (pchar == '?') {    /* wrap around */
  874.             Hist_num = newdir == F_UP_SEARCH_HIST ? 0 : 0x7fffffff;
  875.             if (c_get_histline() == CC_ERROR)
  876.                 /* Hist_num was fixed by first call */
  877.                 (void) c_get_histline();
  878.             Cursor = newdir == F_UP_SEARCH_HIST ?
  879.                 LastChar : InputBuf;
  880.             } else
  881.             Cursor += newdir == F_UP_SEARCH_HIST ? -1 : 1;
  882.         }
  883.         patbuf[patlen++] = '*';
  884.         patbuf[patlen] = '\0';
  885.         if (Cursor < InputBuf || Cursor > LastChar ||
  886.             (ret = c_search_line(&patbuf[1], newdir)) == CC_ERROR) {
  887.             LastCmd = (KEYCMD) newdir; /* avoid c_hsetpat */
  888.             ret = newdir == F_UP_SEARCH_HIST ?
  889.             e_up_search_hist(0) : e_down_search_hist(0);
  890.             if (ret != CC_ERROR) {
  891.             Cursor = newdir == F_UP_SEARCH_HIST ?
  892.                 LastChar : InputBuf;
  893.             (void) c_search_line(&patbuf[1], newdir);
  894.             }
  895.         }
  896.         patbuf[--patlen] = '\0';
  897.         if (ret == CC_ERROR) {
  898.             Beep();
  899.             if (Hist_num != oldHist_num) {
  900.             Hist_num = oldHist_num;
  901.             if (c_get_histline() == CC_ERROR)
  902.                 return(CC_ERROR);
  903.             }
  904.             Cursor = oldCursor;
  905.             pchar = '?';
  906.         } else {
  907.             pchar = ':';
  908.         }
  909.         }
  910.  
  911.         ret = e_inc_search(newdir);
  912.  
  913.         if (ret == CC_ERROR && pchar == '?' && oldpchar == ':') {
  914.         /* break abort of failed search at last non-failed */
  915.         ret = CC_NORM;
  916.         }
  917.  
  918.     }
  919.  
  920.     if (ret == CC_NORM || (ret == CC_ERROR && oldpatlen == 0)) {
  921.         /* restore on normal return or error exit */
  922.         pchar = oldpchar;
  923.         patlen = oldpatlen;
  924.         if (Hist_num != oldHist_num) {
  925.         Hist_num = oldHist_num;
  926.         if (c_get_histline() == CC_ERROR)
  927.             return(CC_ERROR);
  928.         }
  929.         Cursor = oldCursor;
  930.         if (ret == CC_ERROR)
  931.         Refresh();
  932.     }
  933.     if (done || ret != CC_NORM)
  934.         return(ret);
  935.         
  936.     }
  937.  
  938. }
  939.  
  940. static CCRETVAL
  941. v_search(dir)
  942.     int dir;
  943. {
  944.     Char ch;
  945.     Char tmpbuf[INBUFSIZE];
  946.     Char oldbuf[INBUFSIZE];
  947.     Char *oldlc, *oldc;
  948.     int tmplen;
  949.  
  950.     copyn(oldbuf, InputBuf, INBUFSIZE);
  951.     oldlc = LastChar;
  952.     oldc = Cursor;
  953.     tmplen = 0;
  954.     tmpbuf[tmplen++] = '*';
  955.  
  956.     InputBuf[0] = '\0';
  957.     LastChar = InputBuf;
  958.     Cursor = InputBuf;
  959.     searchdir = dir;
  960.  
  961.     c_insert(2);    /* prompt + '\n' */
  962.     *Cursor++ = '\n';
  963.     *Cursor++ = dir == F_UP_SEARCH_HIST ? '?' : '/';
  964.     Refresh();
  965.     for (ch = 0;ch == 0;) {
  966.     if (GetNextChar(&ch) != 1)
  967.         return(e_send_eof(0));
  968.     switch (ch) {
  969.     case 0010:    /* Delete and backspace */
  970.     case 0177:
  971.         if (tmplen > 1) {
  972.         *Cursor-- = '\0';
  973.         LastChar = Cursor;
  974.         tmpbuf[tmplen--] = '\0';
  975.         }
  976.         else {
  977.         copyn(InputBuf, oldbuf, INBUFSIZE);
  978.         LastChar = oldlc;
  979.         Cursor = oldc;
  980.         return(CC_REFRESH);
  981.         }
  982.         Refresh();
  983.         ch = 0;
  984.         break;
  985.  
  986.     case 0033:    /* ESC */
  987.     case '\r':    /* Newline */
  988.     case '\n':
  989.         break;
  990.  
  991.     default:
  992.         if (tmplen >= INBUFSIZE)
  993.         Beep();
  994.         else {
  995.         tmpbuf[tmplen++] = ch;
  996.         *Cursor++ = ch;
  997.         LastChar = Cursor;
  998.         }
  999.         Refresh();
  1000.         ch = 0;
  1001.         break;
  1002.     }
  1003.     }
  1004.  
  1005.     if (tmplen == 1) {
  1006.     /*
  1007.      * Use the old pattern, but wild-card it.
  1008.      */
  1009.     if (patlen == 0) {
  1010.         InputBuf[0] = '\0';
  1011.         LastChar = InputBuf;
  1012.         Cursor = InputBuf;
  1013.         Refresh();
  1014.         return(CC_ERROR);
  1015.     }
  1016.     if (patbuf[0] != '*') {
  1017.         (void) Strcpy(tmpbuf, patbuf);
  1018.         patbuf[0] = '*';
  1019.         (void) Strcpy(&patbuf[1], tmpbuf);
  1020.         patlen++;
  1021.         patbuf[patlen++] = '*';
  1022.         patbuf[patlen] = '\0';
  1023.     }
  1024.     }
  1025.     else {
  1026.     tmpbuf[tmplen++] = '*';
  1027.     tmpbuf[tmplen] = '\0';
  1028.     (void) Strcpy(patbuf, tmpbuf);
  1029.     patlen = tmplen;
  1030.     }
  1031.     LastCmd = (KEYCMD) dir; /* avoid c_hsetpat */
  1032.     Cursor = LastChar = InputBuf;
  1033.     if ((dir == F_UP_SEARCH_HIST ? e_up_search_hist(0) : 
  1034.                    e_down_search_hist(0)) == CC_ERROR) {
  1035.     Refresh();
  1036.     return(CC_ERROR);
  1037.     }
  1038.     else {
  1039.     if (ch == 0033) {
  1040.         Refresh();
  1041.         *LastChar++ = '\n';
  1042.         *LastChar = '\0';
  1043.         PastBottom();
  1044.         return(CC_NEWLINE);
  1045.     }
  1046.     else
  1047.         return(CC_REFRESH);
  1048.     }
  1049. }
  1050.  
  1051. /*
  1052.  * semi-PUBLIC routines.  Any routine that is of type CCRETVAL is an
  1053.  * entry point, called from the CcKeyMap indirected into the
  1054.  * CcFuncTbl array.
  1055.  */
  1056.  
  1057. /*ARGSUSED*/
  1058. CCRETVAL
  1059. v_cmd_mode(c)
  1060.     int c;
  1061. {
  1062.  
  1063.     InsertPos = 0;
  1064.     ActionFlag = NOP;    /* [Esc] cancels pending action */
  1065.     ActionPos = 0;
  1066.     DoingArg = 0;
  1067.     if (UndoPtr > Cursor)
  1068.     UndoSize = (int)(UndoPtr - Cursor);
  1069.     else
  1070.     UndoSize = (int)(Cursor - UndoPtr);
  1071.  
  1072.     inputmode = MODE_INSERT;
  1073.     c_alternativ_key_map(1);
  1074. #ifdef notdef
  1075.     /*
  1076.      * We don't want to move the cursor, because all the editing
  1077.      * commands don't include the character under the cursor.
  1078.      */
  1079.     if (Cursor > InputBuf)
  1080.     Cursor--;
  1081. #endif
  1082.     RefCursor();
  1083.     return(CC_NORM);
  1084. }
  1085.  
  1086. /*ARGSUSED*/
  1087. CCRETVAL
  1088. e_unassigned(c)
  1089.     int c;
  1090. {                /* bound to keys that arn't really assigned */
  1091.     Beep();
  1092.     flush();
  1093.     return(CC_NORM);
  1094. }
  1095.  
  1096. CCRETVAL
  1097. e_insert(c)
  1098.     register int c;
  1099. {
  1100.     register int i;
  1101. #ifndef SHORT_STRINGS
  1102.     c &= ASCII;            /* no meta chars ever */
  1103. #endif
  1104.  
  1105.     if (!c)
  1106.     return(CC_ERROR);    /* no NULs in the input ever!! */
  1107.  
  1108.     if (LastChar + Argument >= InputLim)
  1109.     return(CC_ERROR);    /* end of buffer space */
  1110.  
  1111.     if (Argument == 1) {      /* How was this optimized ???? */
  1112.  
  1113.     if (inputmode != MODE_INSERT) {
  1114.         UndoBuf[UndoSize++] = *Cursor;
  1115.         UndoBuf[UndoSize] = '\0';
  1116.         c_delafter(1);   /* Do NOT use the saving ONE */
  1117.         }
  1118.  
  1119.         c_insert(1);
  1120.  
  1121.     *Cursor++ = c;
  1122.     DoingArg = 0;        /* just in case */
  1123.     RefPlusOne();        /* fast refresh for one char. */
  1124.     }
  1125.     else {
  1126.     if (inputmode != MODE_INSERT) {
  1127.  
  1128.         for(i=0;i<Argument;i++) 
  1129.         UndoBuf[UndoSize++] = *(Cursor+i);
  1130.  
  1131.         UndoBuf[UndoSize] = '\0';
  1132.         c_delafter(Argument);   /* Do NOT use the saving ONE */
  1133.         }
  1134.  
  1135.         c_insert(Argument);
  1136.  
  1137.     while (Argument--)
  1138.         *Cursor++ = c;
  1139.     Refresh();
  1140.     }
  1141.  
  1142.     if (inputmode == MODE_REPLACE_1)
  1143.     (void) v_cmd_mode(0);
  1144.  
  1145.     return(CC_NORM);
  1146. }
  1147.  
  1148. int
  1149. InsertStr(s)            /* insert ASCIZ s at cursor (for complete) */
  1150.     Char   *s;
  1151. {
  1152.     register int len;
  1153.  
  1154.     if ((len = Strlen(s)) <= 0)
  1155.     return -1;
  1156.     if (LastChar + len >= InputLim)
  1157.     return -1;        /* end of buffer space */
  1158.  
  1159.     c_insert(len);
  1160.     while (len--)
  1161.     *Cursor++ = *s++;
  1162.     return 0;
  1163. }
  1164.  
  1165. void
  1166. DeleteBack(n)            /* delete the n characters before . */
  1167.     int     n;
  1168. {
  1169.     if (n <= 0)
  1170.     return;
  1171.     if (Cursor >= &InputBuf[n]) {
  1172.     c_delbefore(n);        /* delete before dot */
  1173.     Cursor -= n;
  1174.     if (Cursor < InputBuf)
  1175.         Cursor = InputBuf;    /* bounds check */
  1176.     }
  1177. }
  1178.  
  1179. CCRETVAL
  1180. e_digit(c)            /* gray magic here */
  1181.     register int c;
  1182. {
  1183.     if (!Isdigit(c))
  1184.     return(CC_ERROR);    /* no NULs in the input ever!! */
  1185.  
  1186.     if (DoingArg) {        /* if doing an arg, add this in... */
  1187.     if (LastCmd == F_ARGFOUR)    /* if last command was ^U */
  1188.         Argument = c - '0';
  1189.     else {
  1190.         if (Argument > 1000000)
  1191.         return CC_ERROR;
  1192.         Argument = (Argument * 10) + (c - '0');
  1193.     }
  1194.     return(CC_ARGHACK);
  1195.     }
  1196.     else {
  1197.     if (LastChar + 1 >= InputLim)
  1198.         return CC_ERROR;    /* end of buffer space */
  1199.  
  1200.     if (inputmode != MODE_INSERT) {
  1201.         UndoBuf[UndoSize++] = *Cursor;
  1202.         UndoBuf[UndoSize] = '\0';
  1203.         c_delafter(1);   /* Do NOT use the saving ONE */
  1204.         }
  1205.     c_insert(1);
  1206.     *Cursor++ = c;
  1207.     DoingArg = 0;        /* just in case */
  1208.     RefPlusOne();        /* fast refresh for one char. */
  1209.     }
  1210.     return(CC_NORM);
  1211. }
  1212.  
  1213. CCRETVAL
  1214. e_argdigit(c)            /* for ESC-n */
  1215.     register int c;
  1216. {
  1217.     c &= ASCII;
  1218.  
  1219.     if (!Isdigit(c))
  1220.     return(CC_ERROR);    /* no NULs in the input ever!! */
  1221.  
  1222.     if (DoingArg) {        /* if doing an arg, add this in... */
  1223.     if (Argument > 1000000)
  1224.         return CC_ERROR;
  1225.     Argument = (Argument * 10) + (c - '0');
  1226.     }
  1227.     else {            /* else starting an argument */
  1228.     Argument = c - '0';
  1229.     DoingArg = 1;
  1230.     }
  1231.     return(CC_ARGHACK);
  1232. }
  1233.  
  1234. CCRETVAL
  1235. v_zero(c)            /* command mode 0 for vi */
  1236.     register int c;
  1237. {
  1238.     if (DoingArg) {        /* if doing an arg, add this in... */
  1239.     if (Argument > 1000000)
  1240.         return CC_ERROR;
  1241.     Argument = (Argument * 10) + (c - '0');
  1242.     return(CC_ARGHACK);
  1243.     }
  1244.     else {            /* else starting an argument */
  1245.     Cursor = InputBuf;
  1246.     if (ActionFlag & DELETE) {
  1247.        c_delfini();
  1248.        return(CC_REFRESH);
  1249.         }
  1250.     RefCursor();        /* move the cursor */
  1251.     return(CC_NORM);
  1252.     }
  1253. }
  1254.  
  1255. /*ARGSUSED*/
  1256. CCRETVAL
  1257. e_newline(c)
  1258.     int c;
  1259. {                /* always ignore argument */
  1260.     PastBottom();
  1261.     *LastChar++ = '\n';        /* for the benefit of CSH */
  1262.     *LastChar = '\0';        /* just in case */
  1263.     if (VImode)
  1264.     InsertPos = InputBuf;    /* Reset editing position */
  1265.     return(CC_NEWLINE);
  1266. }
  1267.  
  1268. /*ARGSUSED*/
  1269. CCRETVAL
  1270. e_send_eof(c)
  1271.     int c;
  1272. {                /* for when ^D is ONLY send-eof */
  1273.     PastBottom();
  1274.     *LastChar = '\0';        /* just in case */
  1275.     return(CC_EOF);
  1276. }
  1277.  
  1278. /*ARGSUSED*/
  1279. CCRETVAL
  1280. e_complete(c)
  1281.     int c;
  1282. {
  1283.     *LastChar = '\0';        /* just in case */
  1284.     return(CC_COMPLETE);
  1285. }
  1286.  
  1287. /*ARGSUSED*/
  1288. CCRETVAL
  1289. e_complete_all(c)
  1290.     int c;
  1291. {
  1292.     *LastChar = '\0';        /* just in case */
  1293.     return(CC_COMPLETE_ALL);
  1294. }
  1295.  
  1296. /*ARGSUSED*/
  1297. CCRETVAL
  1298. v_cm_complete(c)
  1299.     int c;
  1300. {
  1301.     if (Cursor < LastChar)
  1302.     Cursor++;
  1303.     *LastChar = '\0';        /* just in case */
  1304.     return(CC_COMPLETE);
  1305. }
  1306.  
  1307. /*ARGSUSED*/
  1308. CCRETVAL
  1309. e_toggle_hist(c)
  1310.     int c;
  1311. {
  1312.     struct Hist *hp;
  1313.     int     h;
  1314.  
  1315.     *LastChar = '\0';        /* just in case */
  1316.  
  1317.     if (Hist_num <= 0) {
  1318.     return CC_ERROR;
  1319.     }
  1320.  
  1321.     hp = Histlist.Hnext;
  1322.     if (hp == NULL) {    /* this is only if no history */
  1323.     return(CC_ERROR);
  1324.     }
  1325.  
  1326.     for (h = 1; h < Hist_num; h++)
  1327.     hp = hp->Hnext;
  1328.  
  1329.     if (!CurrentHistLit) {
  1330.     if (hp->histline) {
  1331.         copyn(InputBuf, hp->histline, INBUFSIZE);
  1332.         CurrentHistLit = 1;
  1333.     }
  1334.     else {
  1335.         return CC_ERROR;
  1336.     }
  1337.     }
  1338.     else {
  1339.     (void) sprlex(InputBuf, &hp->Hlex);
  1340.     CurrentHistLit = 0;
  1341.     }
  1342.  
  1343.     LastChar = InputBuf + Strlen(InputBuf);
  1344.     if (LastChar > InputBuf) {
  1345.     if (LastChar[-1] == '\n')
  1346.         LastChar--;
  1347.     if (LastChar[-1] == ' ')
  1348.         LastChar--;
  1349.     if (LastChar < InputBuf)
  1350.         LastChar = InputBuf;
  1351.     }
  1352.  
  1353. #ifdef KSHVI
  1354.     if (VImode)
  1355.     Cursor = InputBuf;
  1356.     else
  1357. #endif /* KSHVI */
  1358.     Cursor = LastChar;
  1359.  
  1360.     return(CC_REFRESH);
  1361. }
  1362.  
  1363. /*ARGSUSED*/
  1364. CCRETVAL
  1365. e_up_hist(c)
  1366.     int c;
  1367. {
  1368.     Char    beep = 0;
  1369.  
  1370.     UndoAction = NOP;
  1371.     *LastChar = '\0';        /* just in case */
  1372.  
  1373.     if (Hist_num == 0) {    /* save the current buffer away */
  1374.     copyn(HistBuf, InputBuf, INBUFSIZE);
  1375.     LastHist = HistBuf + (LastChar - InputBuf);
  1376.     }
  1377.  
  1378.     Hist_num += Argument;
  1379.  
  1380.     if (c_get_histline() == CC_ERROR) {
  1381.     beep = 1;
  1382.     (void) c_get_histline(); /* Hist_num was fixed by first call */
  1383.     }
  1384.  
  1385.     Refresh();
  1386.     if (beep)
  1387.     return(CC_ERROR);
  1388.     else
  1389.     return(CC_NORM);    /* was CC_UP_HIST */
  1390. }
  1391.  
  1392. /*ARGSUSED*/
  1393. CCRETVAL
  1394. e_down_hist(c)
  1395.     int c;
  1396. {
  1397.     UndoAction = NOP;
  1398.     *LastChar = '\0';        /* just in case */
  1399.  
  1400.     Hist_num -= Argument;
  1401.  
  1402.     if (Hist_num < 0) {
  1403.     Hist_num = 0;
  1404.     return(CC_ERROR);    /* make it beep */
  1405.     }
  1406.  
  1407.     return(c_get_histline());
  1408. }
  1409.  
  1410.  
  1411.  
  1412. /*
  1413.  * c_hmatch() return True if the pattern matches the prefix
  1414.  */
  1415. static int
  1416. c_hmatch(str)
  1417. Char *str;
  1418. {
  1419.     if (Strncmp(patbuf, str, patlen) == 0)
  1420.     return 1;
  1421.     return Gmatch(str, patbuf);
  1422. }
  1423.  
  1424. /*
  1425.  * c_hsetpat(): Set the history seatch pattern
  1426.  */
  1427. static void
  1428. c_hsetpat()
  1429. {
  1430.     if (LastCmd != F_UP_SEARCH_HIST && LastCmd != F_DOWN_SEARCH_HIST) {
  1431.     patlen = Cursor - InputBuf;
  1432.     if (patlen >= INBUFSIZE) patlen = INBUFSIZE -1;
  1433.     if (patlen >= 0)  {
  1434.         (void) Strncpy(patbuf, InputBuf, patlen);
  1435.         patbuf[patlen] = '\0';
  1436.     }
  1437.     else
  1438.         patlen = Strlen(patbuf);
  1439.     }
  1440. #ifdef SDEBUG
  1441.     xprintf("\nHist_num = %d\n", Hist_num);
  1442.     xprintf("patlen = %d\n", patlen);
  1443.     xprintf("patbuf = \"%S\"\n", patbuf);
  1444.     xprintf("Cursor %d LastChar %d\n", Cursor - InputBuf, LastChar - InputBuf);
  1445. #endif
  1446. }
  1447.  
  1448. /*ARGSUSED*/
  1449. CCRETVAL
  1450. e_up_search_hist(c)
  1451.     int c;
  1452. {
  1453.     struct Hist *hp;
  1454.     int h;
  1455.     bool    found = 0;
  1456.  
  1457.     ActionFlag = NOP;
  1458.     UndoAction = NOP;
  1459.     *LastChar = '\0';        /* just in case */
  1460.     if (Hist_num < 0) {
  1461. #ifdef DEBUG_EDIT
  1462.     xprintf("tcsh: e_up_search_hist(): Hist_num < 0; resetting.\n");
  1463. #endif
  1464.     Hist_num = 0;
  1465.     return(CC_ERROR);
  1466.     }
  1467.  
  1468.     if (Hist_num == 0)
  1469.     {
  1470.     copyn(HistBuf, InputBuf, INBUFSIZE);
  1471.     LastHist = HistBuf + (LastChar - InputBuf);
  1472.     }
  1473.  
  1474.  
  1475.     hp = Histlist.Hnext;
  1476.     if (hp == NULL)
  1477.     return(CC_ERROR);
  1478.  
  1479.     c_hsetpat();        /* Set search pattern !! */
  1480.  
  1481.     for (h = 1; h <= Hist_num; h++)
  1482.     hp = hp->Hnext;
  1483.  
  1484.     while (hp != NULL) {
  1485.     Char sbuf[BUFSIZE], *hl;
  1486.     if (hp->histline == NULL) {
  1487.         hp->histline = Strsave(sprlex(sbuf, &hp->Hlex));
  1488.     }
  1489.     hl = HistLit ? hp->histline : sprlex(sbuf, &hp->Hlex);
  1490. #ifdef SDEBUG
  1491.     xprintf("Comparing with \"%S\"\n", hl);
  1492. #endif
  1493.     if ((Strncmp(hl, InputBuf, LastChar-InputBuf) || 
  1494.          hl[LastChar-InputBuf]) && c_hmatch(hl)) {
  1495.         found++;
  1496.         break;
  1497.     }
  1498.     h++;
  1499.     hp = hp->Hnext;
  1500.     }
  1501.  
  1502.     if (!found) {
  1503. #ifdef SDEBUG
  1504.     xprintf("not found\n"); 
  1505. #endif
  1506.     return(CC_ERROR);
  1507.     }
  1508.  
  1509.     Hist_num = h;
  1510.  
  1511.     return(c_get_histline());
  1512. }
  1513.  
  1514. /*ARGSUSED*/
  1515. CCRETVAL
  1516. e_down_search_hist(c)
  1517.     int c;
  1518. {
  1519.     struct Hist *hp;
  1520.     int h;
  1521.     bool    found = 0;
  1522.  
  1523.     ActionFlag = NOP;
  1524.     UndoAction = NOP;
  1525.     *LastChar = '\0';        /* just in case */
  1526.  
  1527.     if (Hist_num == 0)
  1528.     return(CC_ERROR);
  1529.  
  1530.     hp = Histlist.Hnext;
  1531.     if (hp == 0)
  1532.     return(CC_ERROR);
  1533.  
  1534.     c_hsetpat();        /* Set search pattern !! */
  1535.  
  1536.     for (h = 1; h < Hist_num && hp; h++) {
  1537.     Char sbuf[BUFSIZE], *hl;
  1538.     if (hp->histline == NULL) {
  1539.         hp->histline = Strsave(sprlex(sbuf, &hp->Hlex));
  1540.     }
  1541.     hl = HistLit ? hp->histline : sprlex(sbuf, &hp->Hlex);
  1542. #ifdef SDEBUG
  1543.     xprintf("Comparing with \"%S\"\n", hl);
  1544. #endif
  1545.     if ((Strncmp(hl, InputBuf, LastChar-InputBuf) || 
  1546.          hl[LastChar-InputBuf]) && c_hmatch(hl))
  1547.         found = h;
  1548.     hp = hp->Hnext;
  1549.     }
  1550.  
  1551.     if (!found) {        /* is it the current history number? */
  1552.     if (!c_hmatch(HistBuf)) {
  1553. #ifdef SDEBUG
  1554.         xprintf("not found\n"); 
  1555. #endif
  1556.         return(CC_ERROR);
  1557.     }
  1558.     }
  1559.  
  1560.     Hist_num = found;
  1561.  
  1562.     return(c_get_histline());
  1563. }
  1564.  
  1565. /*ARGSUSED*/
  1566. CCRETVAL
  1567. e_helpme(c)
  1568.     int c;
  1569. {
  1570.     PastBottom();
  1571.     *LastChar = '\0';        /* just in case */
  1572.     return(CC_HELPME);
  1573. }
  1574.  
  1575. /*ARGSUSED*/
  1576. CCRETVAL
  1577. e_correct(c)
  1578.     int c;
  1579. {
  1580.     *LastChar = '\0';        /* just in case */
  1581.     return(CC_CORRECT);
  1582. }
  1583.  
  1584. /*ARGSUSED*/
  1585. CCRETVAL
  1586. e_correctl(c)
  1587.     int c;
  1588. {
  1589.     *LastChar = '\0';        /* just in case */
  1590.     return(CC_CORRECT_L);
  1591. }
  1592.  
  1593. /*ARGSUSED*/
  1594. CCRETVAL
  1595. e_run_fg_editor(c)
  1596.     int c;
  1597. {
  1598.     register struct process *pp;
  1599.     extern bool tellwhat;
  1600.  
  1601.     if ((pp = find_stop_ed()) != NULL) {
  1602.     /* save our editor state so we can restore it */
  1603.     tellwhat = 1;
  1604.     copyn(WhichBuf, InputBuf, INBUFSIZE);
  1605.     LastWhich = WhichBuf + (LastChar - InputBuf);
  1606.     CursWhich = WhichBuf + (Cursor - InputBuf);
  1607.     HistWhich = Hist_num;
  1608.     Hist_num = 0;        /* for the history commands */
  1609.  
  1610.     /* put the tty in a sane mode */
  1611.     PastBottom();
  1612.     (void) Cookedmode();    /* make sure the tty is set up correctly */
  1613.  
  1614.     /* do it! */
  1615.     fg_proc_entry(pp);
  1616.  
  1617.     (void) Rawmode();    /* go on */
  1618.     Refresh();
  1619.     tellwhat = 0;
  1620.     }
  1621.     return(CC_NORM);
  1622. }
  1623.  
  1624. /*ARGSUSED*/
  1625. CCRETVAL
  1626. e_list_choices(c)
  1627.     int c;
  1628. {
  1629.     PastBottom();
  1630.     *LastChar = '\0';        /* just in case */
  1631.     return(CC_LIST_CHOICES);
  1632. }
  1633.  
  1634. /*ARGSUSED*/
  1635. CCRETVAL
  1636. e_list_all(c)
  1637.     int c;
  1638. {
  1639.     PastBottom();
  1640.     *LastChar = '\0';        /* just in case */
  1641.     return(CC_LIST_ALL);
  1642. }
  1643.  
  1644. /*ARGSUSED*/
  1645. CCRETVAL
  1646. e_list_glob(c)
  1647.     int c;
  1648. {
  1649.     PastBottom();
  1650.     *LastChar = '\0';        /* just in case */
  1651.     return(CC_LIST_GLOB);
  1652. }
  1653.  
  1654. /*ARGSUSED*/
  1655. CCRETVAL
  1656. e_expand_glob(c)
  1657.     int c;
  1658. {
  1659.     *LastChar = '\0';        /* just in case */
  1660.     return(CC_EXPAND_GLOB);
  1661. }
  1662.  
  1663. /*ARGSUSED*/
  1664. CCRETVAL
  1665. e_normalize_path(c)
  1666.     int c;
  1667. {
  1668.     *LastChar = '\0';        /* just in case */
  1669.     return(CC_NORMALIZE_PATH);
  1670. }
  1671. /*ARGSUSED*/
  1672. CCRETVAL
  1673. e_expand_vars(c)
  1674.     int c;
  1675. {
  1676.     *LastChar = '\0';        /* just in case */
  1677.     return(CC_EXPAND_VARS);
  1678. }
  1679.  
  1680. /*ARGSUSED*/
  1681. CCRETVAL
  1682. e_which(c)
  1683.     int c;
  1684. {                /* do a fast command line which(1) */
  1685.     PastBottom();
  1686.     *LastChar = '\0';        /* just in case */
  1687.     return(CC_WHICH);
  1688. }
  1689.  
  1690. /*ARGSUSED*/
  1691. CCRETVAL
  1692. e_last_item(c)
  1693.     int c;
  1694. {                /* insert the last element of the prev. cmd */
  1695.     register Char *cp;
  1696.     register struct Hist *hp;
  1697.     register struct wordent *wp, *firstp;
  1698.     register int i;
  1699.  
  1700.     if (Argument <= 0)
  1701.     return(CC_ERROR);
  1702.  
  1703.     hp = Histlist.Hnext;
  1704.     if (hp == NULL) {    /* this is only if no history */
  1705.     return(CC_ERROR);
  1706.     }
  1707.  
  1708.     wp = (hp->Hlex).prev;
  1709.  
  1710.     if (wp->prev == (struct wordent *) NULL)
  1711.     return(CC_ERROR);    /* an empty history entry */
  1712.  
  1713.     firstp = (hp->Hlex).next;
  1714.  
  1715.     for (i = 0; i < Argument; i++) {    /* back up arg words in lex */
  1716.     wp = wp->prev;
  1717.     if (wp == firstp)
  1718.         break;
  1719.     }
  1720.  
  1721.     while (i > 0) {
  1722.     cp = wp->word;
  1723.  
  1724.     if (!cp)
  1725.         return(CC_ERROR);
  1726.  
  1727.     if (InsertStr(cp))
  1728.         return(CC_ERROR);
  1729.  
  1730.     wp = wp->next;
  1731.     i--;
  1732.     }
  1733.  
  1734.     return(CC_REFRESH);
  1735. }
  1736.  
  1737. /*ARGSUSED*/
  1738. CCRETVAL
  1739. e_yank_kill(c)
  1740.     int c;
  1741. {                /* almost like GnuEmacs */
  1742.     register Char *kp, *cp;
  1743.  
  1744.     if (LastKill == KillBuf)    /* if zero content */
  1745.     return(CC_ERROR);
  1746.  
  1747.     if (LastChar + (LastKill - KillBuf) >= InputLim)
  1748.     return(CC_ERROR);    /* end of buffer space */
  1749.  
  1750.     /* else */
  1751.     Mark = Cursor;        /* set the mark */
  1752.     cp = Cursor;        /* for speed */
  1753.  
  1754.     c_insert(LastKill - KillBuf);    /* open the space, */
  1755.     for (kp = KillBuf; kp < LastKill; kp++)    /* copy the chars */
  1756.     *cp++ = *kp;
  1757.  
  1758.     if (Argument == 1)        /* if an arg, cursor at beginning */
  1759.     Cursor = cp;        /* else cursor at end */
  1760.  
  1761.     return(CC_REFRESH);
  1762. }
  1763.  
  1764. /*ARGSUSED*/
  1765. CCRETVAL
  1766. v_delprev(c)         /* Backspace key in insert mode */
  1767.     int c;
  1768. {
  1769.     int rc;
  1770.  
  1771.     rc = CC_ERROR;
  1772.  
  1773.     if (InsertPos != 0) {
  1774.     if (InsertPos <= Cursor - Argument) {
  1775.         c_delbefore(Argument);    /* delete before */
  1776.         Cursor -= Argument;
  1777.         rc = CC_REFRESH;
  1778.     }
  1779.     }
  1780.     return(rc);
  1781. }   /* v_delprev  */
  1782.  
  1783. /*ARGSUSED*/
  1784. CCRETVAL
  1785. e_delprev(c)
  1786.     int c;
  1787. {
  1788.     if (Cursor > InputBuf) {
  1789.     c_delbefore(Argument);    /* delete before dot */
  1790.     Cursor -= Argument;
  1791.     if (Cursor < InputBuf)
  1792.         Cursor = InputBuf;    /* bounds check */
  1793.     return(CC_REFRESH);
  1794.     }
  1795.     else {
  1796.     return(CC_ERROR);
  1797.     }
  1798. }
  1799.  
  1800. /*ARGSUSED*/
  1801. CCRETVAL
  1802. e_delwordprev(c)
  1803.     int c;
  1804. {
  1805.     register Char *cp, *p, *kp;
  1806.  
  1807.     if (Cursor == InputBuf)
  1808.     return(CC_ERROR);
  1809.     /* else */
  1810.  
  1811.     cp = c_prev_word(Cursor, InputBuf, Argument);
  1812.  
  1813.     for (p = cp, kp = KillBuf; p < Cursor; p++)    /* save the text */
  1814.     *kp++ = *p;
  1815.     LastKill = kp;
  1816.  
  1817.     c_delbefore(Cursor - cp);    /* delete before dot */
  1818.     Cursor = cp;
  1819.     if (Cursor < InputBuf)
  1820.     Cursor = InputBuf;    /* bounds check */
  1821.     return(CC_REFRESH);
  1822. }
  1823.  
  1824. /* added by mtk@ari.ncl.omron.co.jp (920818) */
  1825. /* rename e_delnext() -> e_delnext_eof() */
  1826. /*ARGSUSED*/
  1827. CCRETVAL
  1828. e_delnext_eof(c)
  1829.     int c;
  1830. {
  1831.     if (Cursor == LastChar) {/* if I'm at the end */
  1832.     if (!VImode) {
  1833.         return(CC_ERROR);
  1834.     }
  1835.     else {
  1836.         if (Cursor != InputBuf)
  1837.         Cursor--;
  1838.         else
  1839.         return(CC_ERROR);
  1840.     }
  1841.     }
  1842.     c_delafter(Argument);    /* delete after dot */
  1843.     if (Cursor > LastChar)
  1844.     Cursor = LastChar;    /* bounds check */
  1845.     return(CC_REFRESH);
  1846. }
  1847.  
  1848.  
  1849. /*ARGSUSED*/
  1850. CCRETVAL
  1851. e_delnext(c)
  1852.     int c;
  1853. {
  1854.     if (Cursor == LastChar) {/* if I'm at the end */
  1855.     if (!VImode) {
  1856.         if (Cursor == InputBuf) {    
  1857.         /* if I'm also at the beginning */
  1858.         so_write(STReof, 4);/* then do a EOF */
  1859.         flush();
  1860.         return(CC_EOF);
  1861.         }
  1862.         else 
  1863.         return(CC_ERROR);
  1864.     }
  1865.     else {
  1866.         if (Cursor != InputBuf)
  1867.         Cursor--;
  1868.         else
  1869.         return(CC_ERROR);
  1870.     }
  1871.     }
  1872.     c_delafter(Argument);    /* delete after dot */
  1873.     if (Cursor > LastChar)
  1874.     Cursor = LastChar;    /* bounds check */
  1875.     return(CC_REFRESH);
  1876. }
  1877.  
  1878. /*ARGSUSED*/
  1879. CCRETVAL
  1880. e_list_delnext(c)
  1881.     int c;
  1882. {
  1883.     if (Cursor == LastChar) {    /* if I'm at the end */
  1884.     if (Cursor == InputBuf) {    /* if I'm also at the beginning */
  1885.         so_write(STReof, 4);/* then do a EOF */
  1886.         flush();
  1887.         return(CC_EOF);
  1888.     }
  1889.     else {
  1890.         PastBottom();
  1891.         *LastChar = '\0';    /* just in case */
  1892.         return(CC_LIST_CHOICES);
  1893.     }
  1894.     }
  1895.     else {
  1896.     c_delafter(Argument);    /* delete after dot */
  1897.     if (Cursor > LastChar)
  1898.         Cursor = LastChar;    /* bounds check */
  1899.     return(CC_REFRESH);
  1900.     }
  1901. }
  1902.  
  1903. /*ARGSUSED*/
  1904. CCRETVAL
  1905. e_list_eof(c)
  1906.     int c;
  1907. {
  1908.     if (Cursor == LastChar && Cursor == InputBuf) {
  1909.     so_write(STReof, 4);    /* then do a EOF */
  1910.     flush();
  1911.     return(CC_EOF);
  1912.     }
  1913.     else {
  1914.     PastBottom();
  1915.     *LastChar = '\0';    /* just in case */
  1916.     return(CC_LIST_CHOICES);
  1917.     }
  1918. }
  1919.  
  1920. /*ARGSUSED*/
  1921. CCRETVAL
  1922. e_delwordnext(c)
  1923.     int c;
  1924. {
  1925.     register Char *cp, *p, *kp;
  1926.  
  1927.     if (Cursor == LastChar)
  1928.     return(CC_ERROR);
  1929.     /* else */
  1930.  
  1931.     cp = c_next_word(Cursor, LastChar, Argument);
  1932.  
  1933.     for (p = Cursor, kp = KillBuf; p < cp; p++)    /* save the text */
  1934.     *kp++ = *p;
  1935.     LastKill = kp;
  1936.  
  1937.     c_delafter(cp - Cursor);    /* delete after dot */
  1938.     if (Cursor > LastChar)
  1939.     Cursor = LastChar;    /* bounds check */
  1940.     return(CC_REFRESH);
  1941. }
  1942.  
  1943. /*ARGSUSED*/
  1944. CCRETVAL
  1945. e_toend(c)
  1946.     int c;
  1947. {
  1948.     Cursor = LastChar;
  1949.     if (VImode)
  1950.     if (ActionFlag & DELETE) {
  1951.         c_delfini();
  1952.         return(CC_REFRESH);
  1953.     }
  1954.     RefCursor();        /* move the cursor */
  1955.     return(CC_NORM);
  1956. }
  1957.  
  1958. /*ARGSUSED*/
  1959. CCRETVAL
  1960. e_tobeg(c)
  1961.     int c;
  1962. {
  1963.     Cursor = InputBuf;
  1964.  
  1965.     if (VImode) {
  1966.        while (Isspace(*Cursor)) /* We want FIRST non space character */
  1967.     Cursor++;
  1968.     if (ActionFlag & DELETE) {
  1969.         c_delfini();
  1970.         return(CC_REFRESH);
  1971.     }
  1972.     }
  1973.  
  1974.     RefCursor();        /* move the cursor */
  1975.     return(CC_NORM);
  1976. }
  1977.  
  1978. /*ARGSUSED*/
  1979. CCRETVAL
  1980. e_killend(c)
  1981.     int c;
  1982. {
  1983.     register Char *kp, *cp;
  1984.  
  1985.     cp = Cursor;
  1986.     kp = KillBuf;
  1987.     while (cp < LastChar)
  1988.     *kp++ = *cp++;        /* copy it */
  1989.     LastKill = kp;
  1990.     LastChar = Cursor;        /* zap! -- delete to end */
  1991.     return(CC_REFRESH);
  1992. }
  1993.  
  1994.  
  1995. /*ARGSUSED*/
  1996. CCRETVAL
  1997. e_killbeg(c)
  1998.     int c;
  1999. {
  2000.     register Char *kp, *cp;
  2001.  
  2002.     cp = InputBuf;
  2003.     kp = KillBuf;
  2004.     while (cp < Cursor)
  2005.     *kp++ = *cp++;        /* copy it */
  2006.     LastKill = kp;
  2007.     c_delbefore(Cursor - InputBuf);
  2008.     Cursor = InputBuf;        /* zap! */
  2009.     return(CC_REFRESH);
  2010. }
  2011.  
  2012. /*ARGSUSED*/
  2013. CCRETVAL
  2014. e_killall(c)
  2015.     int c;
  2016. {
  2017.     register Char *kp, *cp;
  2018.  
  2019.     cp = InputBuf;
  2020.     kp = KillBuf;
  2021.     while (cp < LastChar)
  2022.     *kp++ = *cp++;        /* copy it */
  2023.     LastKill = kp;
  2024.     LastChar = InputBuf;    /* zap! -- delete all of it */
  2025.     Cursor = InputBuf;
  2026.     return(CC_REFRESH);
  2027. }
  2028.  
  2029. /*ARGSUSED*/
  2030. CCRETVAL
  2031. e_killregion(c)
  2032.     int c;
  2033. {
  2034.     register Char *kp, *cp;
  2035.  
  2036.     if (!Mark)
  2037.     return(CC_ERROR);
  2038.  
  2039.     if (Mark > Cursor) {
  2040.     cp = Cursor;
  2041.     kp = KillBuf;
  2042.     while (cp < Mark)
  2043.         *kp++ = *cp++;    /* copy it */
  2044.     LastKill = kp;
  2045.     c_delafter(cp - Cursor);/* delete it - UNUSED BY VI mode */
  2046.     }
  2047.     else {            /* mark is before cursor */
  2048.     cp = Mark;
  2049.     kp = KillBuf;
  2050.     while (cp < Cursor)
  2051.         *kp++ = *cp++;    /* copy it */
  2052.     LastKill = kp;
  2053.     c_delbefore(cp - Mark);
  2054.     Cursor = Mark;
  2055.     }
  2056.     return(CC_REFRESH);
  2057. }
  2058.  
  2059. /*ARGSUSED*/
  2060. CCRETVAL
  2061. e_copyregion(c)
  2062.     int c;
  2063. {
  2064.     register Char *kp, *cp;
  2065.  
  2066.     if (!Mark)
  2067.     return(CC_ERROR);
  2068.  
  2069.     if (Mark > Cursor) {
  2070.     cp = Cursor;
  2071.     kp = KillBuf;
  2072.     while (cp < Mark)
  2073.         *kp++ = *cp++;    /* copy it */
  2074.     LastKill = kp;
  2075.     }
  2076.     else {            /* mark is before cursor */
  2077.     cp = Mark;
  2078.     kp = KillBuf;
  2079.     while (cp < Cursor)
  2080.         *kp++ = *cp++;    /* copy it */
  2081.     LastKill = kp;
  2082.     }
  2083.     return(CC_NORM);        /* don't even need to Refresh() */
  2084. }
  2085.  
  2086. /*ARGSUSED*/
  2087. CCRETVAL
  2088. e_charswitch(cc)
  2089.     int cc;
  2090. {
  2091.     register Char c;
  2092.  
  2093.     if (Cursor < LastChar) {
  2094.     if (LastChar <= &InputBuf[1]) {
  2095.         return(CC_ERROR);
  2096.     }
  2097.     else {
  2098.         Cursor++;
  2099.     }
  2100.     }
  2101.     if (Cursor > &InputBuf[1]) {/* must have at least two chars entered */
  2102.     c = Cursor[-2];
  2103.     Cursor[-2] = Cursor[-1];
  2104.     Cursor[-1] = c;
  2105.     return(CC_REFRESH);
  2106.     }
  2107.     else {
  2108.     return(CC_ERROR);
  2109.     }
  2110. }
  2111.  
  2112. /*ARGSUSED*/
  2113. CCRETVAL
  2114. e_gcharswitch(cc)
  2115.     int cc;
  2116. {                /* gosmacs style ^T */
  2117.     register Char c;
  2118.  
  2119.     if (Cursor > &InputBuf[1]) {/* must have at least two chars entered */
  2120.     c = Cursor[-2];
  2121.     Cursor[-2] = Cursor[-1];
  2122.     Cursor[-1] = c;
  2123.     return(CC_REFRESH);
  2124.     }
  2125.     else {
  2126.     return(CC_ERROR);
  2127.     }
  2128. }
  2129.  
  2130. /*ARGSUSED*/
  2131. CCRETVAL
  2132. e_charback(c)
  2133.     int c;
  2134. {
  2135.     if (Cursor > InputBuf) {
  2136.     Cursor -= Argument;
  2137.     if (Cursor < InputBuf)
  2138.         Cursor = InputBuf;
  2139.  
  2140.     if (VImode)
  2141.         if (ActionFlag & DELETE) {
  2142.         c_delfini();
  2143.         return(CC_REFRESH);
  2144.         }
  2145.  
  2146.     RefCursor();
  2147.     return(CC_NORM);
  2148.     }
  2149.     else {
  2150.     return(CC_ERROR);
  2151.     }
  2152. }
  2153.  
  2154. /*ARGSUSED*/
  2155. CCRETVAL
  2156. v_wordback(c)
  2157.     int c;
  2158. {
  2159.     if (Cursor == InputBuf)
  2160.     return(CC_ERROR);
  2161.     /* else */
  2162.  
  2163.     Cursor = c_preword(Cursor, InputBuf, Argument); /* bounds check */
  2164.  
  2165.     if (ActionFlag & DELETE) {
  2166.     c_delfini();
  2167.     return(CC_REFRESH);
  2168.     }
  2169.  
  2170.     RefCursor();
  2171.     return(CC_NORM);
  2172. }
  2173.  
  2174. /*ARGSUSED*/
  2175. CCRETVAL
  2176. e_wordback(c)
  2177.     int c;
  2178. {
  2179.     if (Cursor == InputBuf)
  2180.     return(CC_ERROR);
  2181.     /* else */
  2182.  
  2183.     Cursor = c_prev_word(Cursor, InputBuf, Argument); /* bounds check */
  2184.  
  2185.     if (VImode) 
  2186.     if (ActionFlag & DELETE) {
  2187.         c_delfini();
  2188.         return(CC_REFRESH);
  2189.     }
  2190.  
  2191.     RefCursor();
  2192.     return(CC_NORM);
  2193. }
  2194.  
  2195. /*ARGSUSED*/
  2196. CCRETVAL
  2197. e_charfwd(c)
  2198.     int c;
  2199. {
  2200.     if (Cursor < LastChar) {
  2201.     Cursor += Argument;
  2202.     if (Cursor > LastChar)
  2203.         Cursor = LastChar;
  2204.  
  2205.     if (VImode)
  2206.         if (ActionFlag & DELETE) {
  2207.         c_delfini();
  2208.         return(CC_REFRESH);
  2209.         }
  2210.  
  2211.     RefCursor();
  2212.     return(CC_NORM);
  2213.     }
  2214.     else {
  2215.     return(CC_ERROR);
  2216.     }
  2217. }
  2218.  
  2219. /*ARGSUSED*/
  2220. CCRETVAL
  2221. e_wordfwd(c)
  2222.     int c;
  2223. {
  2224.     if (Cursor == LastChar)
  2225.     return(CC_ERROR);
  2226.     /* else */
  2227.  
  2228.     Cursor = c_next_word(Cursor, LastChar, Argument);
  2229.  
  2230.     if (VImode)
  2231.     if (ActionFlag & DELETE) {
  2232.         c_delfini();
  2233.         return(CC_REFRESH);
  2234.     }
  2235.  
  2236.     RefCursor();
  2237.     return(CC_NORM);
  2238. }
  2239.  
  2240. /*ARGSUSED*/
  2241. CCRETVAL
  2242. v_wordfwd(c)
  2243.     int c;
  2244. {
  2245.     if (Cursor == LastChar)
  2246.     return(CC_ERROR);
  2247.     /* else */
  2248.  
  2249.     Cursor = c_nexword(Cursor, LastChar, Argument);
  2250.  
  2251.     if (VImode)
  2252.     if (ActionFlag & DELETE) {
  2253.         c_delfini();
  2254.         return(CC_REFRESH);
  2255.     }
  2256.  
  2257.     RefCursor();
  2258.     return(CC_NORM);
  2259. }
  2260.  
  2261. /*ARGSUSED*/
  2262. CCRETVAL
  2263. v_wordbegnext(c)
  2264.     int c;
  2265. {
  2266.     if (Cursor == LastChar)
  2267.     return(CC_ERROR);
  2268.     /* else */
  2269.  
  2270.     Cursor = c_next_word(Cursor, LastChar, Argument);
  2271.     if (Cursor < LastChar)
  2272.     Cursor++;
  2273.  
  2274.     if (VImode)
  2275.     if (ActionFlag & DELETE) {
  2276.         c_delfini();
  2277.         return(CC_REFRESH);
  2278.     }
  2279.  
  2280.     RefCursor();
  2281.     return(CC_NORM);
  2282. }
  2283.  
  2284. /*ARGSUSED*/
  2285. static CCRETVAL
  2286. v_repeat_srch(c)
  2287.     int c;
  2288. {
  2289. #ifdef SDEBUG
  2290.     xprintf("dir %d patlen %d patbuf %S\n", 
  2291.         c, patlen, patbuf);
  2292. #endif
  2293.  
  2294.     LastCmd = (KEYCMD) c;  /* Hack to stop c_hsetpat */
  2295.     LastChar = InputBuf;
  2296.     switch (c) {
  2297.     case F_DOWN_SEARCH_HIST:
  2298.     return(e_down_search_hist(0));
  2299.     case F_UP_SEARCH_HIST:
  2300.     return(e_up_search_hist(0));
  2301.     default:
  2302.     return(CC_ERROR);
  2303.     }
  2304. }
  2305.  
  2306. static CCRETVAL
  2307. v_csearch_back(ch, count, tflag)
  2308.     int ch, count, tflag;
  2309. {
  2310.     Char *cp;
  2311.  
  2312.     cp = Cursor;
  2313.     while (count--) {
  2314.     if (*cp == ch) 
  2315.         cp--;
  2316.     while (cp > InputBuf && *cp != ch) 
  2317.         cp--;
  2318.     }
  2319.  
  2320.     if (cp < InputBuf || (cp == InputBuf && *cp != ch))
  2321.     return(CC_ERROR);
  2322.  
  2323.     if (*cp == ch && tflag)
  2324.     cp++;
  2325.  
  2326.     Cursor = cp;
  2327.  
  2328.     if (ActionFlag & DELETE) {
  2329.     Cursor++;
  2330.     c_delfini();
  2331.     return(CC_REFRESH);
  2332.     }
  2333.  
  2334.     RefCursor();
  2335.     return(CC_NORM);
  2336. }
  2337.  
  2338. static CCRETVAL
  2339. v_csearch_fwd(ch, count, tflag)
  2340.     int ch, count, tflag;
  2341. {
  2342.     Char *cp;
  2343.  
  2344.     cp = Cursor;
  2345.     while (count--) {
  2346.     if(*cp == ch) 
  2347.         cp++;
  2348.     while (cp < LastChar && *cp != ch) 
  2349.         cp++;
  2350.     }
  2351.  
  2352.     if (cp >= LastChar)
  2353.     return(CC_ERROR);
  2354.  
  2355.     if (*cp == ch && tflag)
  2356.     cp--;
  2357.  
  2358.     Cursor = cp;
  2359.  
  2360.     if (ActionFlag & DELETE) {
  2361.     Cursor++;
  2362.     c_delfini();
  2363.     return(CC_REFRESH);
  2364.     }
  2365.     RefCursor();
  2366.     return(CC_NORM);
  2367. }
  2368.  
  2369. /*ARGSUSED*/
  2370. static CCRETVAL
  2371. v_action(c)
  2372.     int c;
  2373. {
  2374.     register Char *cp, *kp;
  2375.  
  2376.     if (ActionFlag == DELETE) {
  2377.     ActionFlag = NOP;
  2378.     ActionPos = 0;
  2379.     
  2380.     UndoSize = 0;
  2381.     kp = UndoBuf;
  2382.     for (cp = InputBuf; cp < LastChar; cp++) {
  2383.         *kp++ = *cp;
  2384.         UndoSize++;
  2385.     }
  2386.         
  2387.     UndoAction = INSERT;
  2388.     UndoPtr  = InputBuf;
  2389.     LastChar = InputBuf;
  2390.     Cursor   = InputBuf;
  2391.     if (c & INSERT)
  2392.         c_alternativ_key_map(0);
  2393.         
  2394.     return(CC_REFRESH);
  2395.     }
  2396. #ifdef notdef
  2397.     else if (ActionFlag == NOP) {
  2398. #endif
  2399.     ActionPos = Cursor;
  2400.     ActionFlag = c;
  2401.     return(CC_ARGHACK);  /* Do NOT clear out argument */
  2402. #ifdef notdef
  2403.     }
  2404.     else {
  2405.     ActionFlag = 0;
  2406.     ActionPos = 0;
  2407.     return(CC_ERROR);
  2408.     }
  2409. #endif
  2410. }
  2411.  
  2412. #ifdef COMMENT
  2413. /* by: Brian Allison <uiucdcs!convex!allison@RUTGERS.EDU> */
  2414. static void
  2415. c_get_word(begin, end)
  2416.     Char  **begin;
  2417.     Char  **end;
  2418. {
  2419.     Char   *cp;
  2420.  
  2421.     cp = &Cursor[0];
  2422.     while (Argument--) {
  2423.     while ((cp <= LastChar) && (isword(*cp)))
  2424.         cp++;
  2425.     *end = --cp;
  2426.     while ((cp >= InputBuf) && (isword(*cp)))
  2427.         cp--;
  2428.     *begin = ++cp;
  2429.     }
  2430. }
  2431. #endif /* COMMENT */
  2432.  
  2433. /*ARGSUSED*/
  2434. CCRETVAL
  2435. e_uppercase(c)
  2436.     int c;
  2437. {
  2438.     Char   *cp, *end;
  2439.  
  2440.     end = c_next_word(Cursor, LastChar, Argument);
  2441.  
  2442.     for (cp = Cursor; cp < end; cp++)    /* PWP: was cp=begin */
  2443.     if (Islower(*cp))
  2444.         *cp = Toupper(*cp);
  2445.  
  2446.     Cursor = end;
  2447.     if (Cursor > LastChar)
  2448.     Cursor = LastChar;
  2449.     return(CC_REFRESH);
  2450. }
  2451.  
  2452.  
  2453. /*ARGSUSED*/
  2454. CCRETVAL
  2455. e_capitolcase(c)
  2456.     int c;
  2457. {
  2458.     Char   *cp, *end;
  2459.  
  2460.     end = c_next_word(Cursor, LastChar, Argument);
  2461.  
  2462.     cp = Cursor;
  2463.     for (; cp < end; cp++) {
  2464.     if (Isalpha(*cp)) {
  2465.         if (Islower(*cp))
  2466.         *cp = Toupper(*cp);
  2467.         cp++;
  2468.         break;
  2469.     }
  2470.     }
  2471.     for (; cp < end; cp++)
  2472.     if (Isupper(*cp))
  2473.         *cp = Tolower(*cp);
  2474.  
  2475.     Cursor = end;
  2476.     if (Cursor > LastChar)
  2477.     Cursor = LastChar;
  2478.     return(CC_REFRESH);
  2479. }
  2480.  
  2481. /*ARGSUSED*/
  2482. CCRETVAL
  2483. e_lowercase(c)
  2484.     int c;
  2485. {
  2486.     Char   *cp, *end;
  2487.  
  2488.     end = c_next_word(Cursor, LastChar, Argument);
  2489.  
  2490.     for (cp = Cursor; cp < end; cp++)
  2491.     if (Isupper(*cp))
  2492.         *cp = Tolower(*cp);
  2493.  
  2494.     Cursor = end;
  2495.     if (Cursor > LastChar)
  2496.     Cursor = LastChar;
  2497.     return(CC_REFRESH);
  2498. }
  2499.  
  2500.  
  2501. /*ARGSUSED*/
  2502. CCRETVAL
  2503. e_set_mark(c)
  2504.     int c;
  2505. {
  2506.     Mark = Cursor;
  2507.     return(CC_NORM);
  2508. }
  2509.  
  2510. /*ARGSUSED*/
  2511. CCRETVAL
  2512. e_exchange_mark(c)
  2513.     int c;
  2514. {
  2515.     register Char *cp;
  2516.  
  2517.     cp = Cursor;
  2518.     Cursor = Mark;
  2519.     Mark = cp;
  2520.     RefCursor();
  2521.     return(CC_NORM);
  2522. }
  2523.  
  2524. /*ARGSUSED*/
  2525. CCRETVAL
  2526. e_argfour(c)
  2527.     int c;
  2528. {                /* multiply current argument by 4 */
  2529.     if (Argument > 1000000)
  2530.     return CC_ERROR;
  2531.     DoingArg = 1;
  2532.     Argument *= 4;
  2533.     return(CC_ARGHACK);
  2534. }
  2535.  
  2536. /*ARGSUSED*/
  2537. CCRETVAL
  2538. e_quote(c)
  2539.     int c;
  2540. {
  2541.     Char    ch;
  2542.     int     num;
  2543.  
  2544.     QuoteModeOn();
  2545.     num = GetNextChar(&ch);
  2546.     QuoteModeOff();
  2547.     if (num == 1)
  2548.     return e_insert(ch);
  2549.     else
  2550.     return e_send_eof(0);
  2551. }
  2552.  
  2553. /*ARGSUSED*/
  2554. CCRETVAL
  2555. e_metanext(c)
  2556.     int c;
  2557. {
  2558.     MetaNext = 1;
  2559.     return(CC_ARGHACK);    /* preserve argument */
  2560. }
  2561.  
  2562. #ifdef notdef
  2563. /*ARGSUSED*/
  2564. CCRETVAL
  2565. e_extendnext(c)
  2566.     int c;
  2567. {
  2568.     CurrentKeyMap = CcAltMap;
  2569.     return(CC_ARGHACK);    /* preserve argument */
  2570. }
  2571.  
  2572. #endif
  2573.  
  2574. /*ARGSUSED*/
  2575. CCRETVAL
  2576. v_insbeg(c)
  2577.     int c;
  2578. {                /* move to beginning of line and start vi
  2579.                  * insert mode */
  2580.     Cursor = InputBuf;
  2581.     InsertPos = Cursor;
  2582.  
  2583.     UndoPtr  = Cursor;
  2584.     UndoAction = DELETE;
  2585.  
  2586.     RefCursor();        /* move the cursor */
  2587.     c_alternativ_key_map(0);
  2588.     return(CC_NORM);
  2589. }
  2590.  
  2591. /*ARGSUSED*/
  2592. CCRETVAL
  2593. v_replone(c)
  2594.     int c;
  2595. {                /* vi mode overwrite one character */
  2596.     c_alternativ_key_map(0);
  2597.     inputmode = MODE_REPLACE_1;
  2598.     UndoAction = CHANGE;    /* Set Up for VI undo command */
  2599.     UndoPtr = Cursor;
  2600.     UndoSize = 0;
  2601.     return(CC_NORM);
  2602. }
  2603.  
  2604. /*ARGSUSED*/
  2605. CCRETVAL
  2606. v_replmode(c)
  2607.     int c;
  2608. {                /* vi mode start overwriting */
  2609.     c_alternativ_key_map(0);
  2610.     inputmode = MODE_REPLACE;
  2611.     UndoAction = CHANGE;    /* Set Up for VI undo command */
  2612.     UndoPtr = Cursor;
  2613.     UndoSize = 0;
  2614.     return(CC_NORM);
  2615. }
  2616.  
  2617. /*ARGSUSED*/
  2618. CCRETVAL
  2619. v_substchar(c)
  2620.     int c;
  2621. {                /* vi mode substitute for one char */
  2622.     c_delafter(Argument);
  2623.     c_alternativ_key_map(0);
  2624.     return(CC_REFRESH);
  2625. }
  2626.  
  2627. /*ARGSUSED*/
  2628. CCRETVAL
  2629. v_substline(c)
  2630.     int c;
  2631. {                /* vi mode replace whole line */
  2632.     (void) e_killall(0);
  2633.     c_alternativ_key_map(0);
  2634.     return(CC_REFRESH);
  2635. }
  2636.  
  2637. /*ARGSUSED*/
  2638. CCRETVAL
  2639. v_chgtoend(c)
  2640.     int c;
  2641. {                /* vi mode change to end of line */
  2642.     (void) e_killend(0);
  2643.     c_alternativ_key_map(0);
  2644.     return(CC_REFRESH);
  2645. }
  2646.  
  2647. /*ARGSUSED*/
  2648. CCRETVAL
  2649. v_insert(c)
  2650.     int c;
  2651. {                /* vi mode start inserting */
  2652.     c_alternativ_key_map(0);
  2653.  
  2654.     InsertPos = Cursor;
  2655.     UndoPtr = Cursor;
  2656.     UndoAction = DELETE;
  2657.  
  2658.     return(CC_NORM);
  2659. }
  2660.  
  2661. /*ARGSUSED*/
  2662. CCRETVAL
  2663. v_add(c)
  2664.     int c;
  2665. {                /* vi mode start adding */
  2666.     c_alternativ_key_map(0);
  2667.     if (Cursor < LastChar)
  2668.     {
  2669.     Cursor++;
  2670.     if (Cursor > LastChar)
  2671.         Cursor = LastChar;
  2672.     RefCursor();
  2673.     }
  2674.  
  2675.     InsertPos = Cursor;
  2676.     UndoPtr = Cursor;
  2677.     UndoAction = DELETE;
  2678.  
  2679.     return(CC_NORM);
  2680. }
  2681.  
  2682. /*ARGSUSED*/
  2683. CCRETVAL
  2684. v_addend(c)
  2685.     int c;
  2686. {                /* vi mode to add at end of line */
  2687.     c_alternativ_key_map(0);
  2688.     Cursor = LastChar;
  2689.  
  2690.     InsertPos = LastChar;    /* Mark where insertion begins */
  2691.     UndoPtr = LastChar;
  2692.     UndoAction = DELETE;
  2693.  
  2694.     RefCursor();
  2695.     return(CC_NORM);
  2696. }
  2697.  
  2698. /*ARGSUSED*/
  2699. CCRETVAL
  2700. v_change_case(cc)
  2701.     int cc;
  2702. {
  2703.     char    c;
  2704.  
  2705.     if (Cursor < LastChar) {
  2706.     c = *Cursor;
  2707.     if (Isupper(c))
  2708.         *Cursor++ = Tolower(c);
  2709.     else if (Islower(c))
  2710.         *Cursor++ = Toupper(c);
  2711.     else
  2712.         Cursor++;
  2713.     RefPlusOne();        /* fast refresh for one char */
  2714.     return(CC_NORM);
  2715.     }
  2716.     return(CC_ERROR);
  2717. }
  2718.  
  2719. /*ARGSUSED*/
  2720. CCRETVAL
  2721. e_expand(c)
  2722.     int c;
  2723. {
  2724.     register Char *p;
  2725.     extern bool justpr;
  2726.  
  2727.     for (p = InputBuf; Isspace(*p); p++)
  2728.     continue;
  2729.     if (p == LastChar)
  2730.     return(CC_ERROR);
  2731.  
  2732.     justpr++;
  2733.     Expand++;
  2734.     return(e_newline(0));
  2735. }
  2736.  
  2737. /*ARGSUSED*/
  2738. CCRETVAL
  2739. e_startover(c)
  2740.     int c;
  2741. {                /* erase all of current line, start again */
  2742.     ResetInLine(0);        /* reset the input pointers */
  2743.     return(CC_REFRESH);
  2744. }
  2745.  
  2746. /*ARGSUSED*/
  2747. CCRETVAL
  2748. e_redisp(c)
  2749.     int c;
  2750. {
  2751.     ClearLines();
  2752.     ClearDisp();
  2753.     return(CC_REFRESH);
  2754. }
  2755.  
  2756. /*ARGSUSED*/
  2757. CCRETVAL
  2758. e_cleardisp(c)
  2759.     int c;
  2760. {
  2761.     ClearScreen();        /* clear the whole real screen */
  2762.     ClearDisp();        /* reset everything */
  2763.     return(CC_REFRESH);
  2764. }
  2765.  
  2766. /*ARGSUSED*/
  2767. CCRETVAL
  2768. e_tty_int(c)
  2769.     int c;
  2770. {            
  2771. #ifdef _MINIX
  2772.     /* SAK PATCH: erase all of current line, start again */
  2773.     ResetInLine(0);        /* reset the input pointers */
  2774.     xputchar('\n');
  2775.     ClearDisp();
  2776.     return (CC_REFRESH);
  2777. #else /* !_MINIX */
  2778.     /* do no editing */
  2779.     return (CC_NORM);
  2780. #endif /* _MINIX */
  2781. }
  2782.  
  2783. /*
  2784.  * From: ghazi@cesl.rutgers.edu (Kaveh R. Ghazi)
  2785.  * Function to send a character back to the input stream in cooked
  2786.  * mode. Only works if we have TIOCSTI
  2787.  */
  2788. /*ARGSUSED*/
  2789. CCRETVAL
  2790. e_stuff_char(c)
  2791.      int c;
  2792. {
  2793. #ifdef TIOCSTI
  2794.      extern int Tty_raw_mode;
  2795.      int was_raw = Tty_raw_mode;
  2796.      char ch = c;
  2797.  
  2798.      if (was_raw)
  2799.          Cookedmode();
  2800.  
  2801.      write(SHIN, "\n", 1);
  2802.      (void) ioctl(SHIN, TIOCSTI, (ioctl_t) &ch);
  2803.  
  2804.      if (was_raw)
  2805.          Rawmode();
  2806.      return(e_redisp(c));
  2807. #else /* !TIOCSTI */  
  2808.      return(CC_ERROR);
  2809. #endif /* !TIOCSTI */  
  2810. }
  2811.  
  2812. /*ARGSUSED*/
  2813. CCRETVAL
  2814. e_insovr(c)
  2815.     int c;
  2816. {
  2817.     inputmode = (inputmode == MODE_INSERT ? MODE_REPLACE : MODE_INSERT);
  2818.     return(CC_NORM);
  2819. }
  2820.  
  2821. /*ARGSUSED*/
  2822. CCRETVAL
  2823. e_tty_dsusp(c)
  2824.     int c;
  2825. {
  2826.     /* do no editing */
  2827.     return(CC_NORM);
  2828. }
  2829.  
  2830. /*ARGSUSED*/
  2831. CCRETVAL
  2832. e_tty_flusho(c)
  2833.     int c;
  2834. {
  2835.     /* do no editing */
  2836.     return(CC_NORM);
  2837. }
  2838.  
  2839. /*ARGSUSED*/
  2840. CCRETVAL
  2841. e_tty_quit(c)
  2842.     int c;
  2843. {
  2844.     /* do no editing */
  2845.     return(CC_NORM);
  2846. }
  2847.  
  2848. /*ARGSUSED*/
  2849. CCRETVAL
  2850. e_tty_tsusp(c)
  2851.     int c;
  2852. {
  2853.     /* do no editing */
  2854.     return(CC_NORM);
  2855. }
  2856.  
  2857. /*ARGSUSED*/
  2858. CCRETVAL
  2859. e_tty_stopo(c)
  2860.     int c;
  2861. {
  2862.     /* do no editing */
  2863.     return(CC_NORM);
  2864. }
  2865.  
  2866. /*ARGSUSED*/
  2867. CCRETVAL
  2868. e_expand_history(c)
  2869.     int c;
  2870. {
  2871.     *LastChar = '\0';        /* just in case */
  2872.     c_substitute();
  2873.     return(CC_NORM);
  2874. }
  2875.  
  2876. /*ARGSUSED*/
  2877. CCRETVAL
  2878. e_magic_space(c)
  2879.     int c;
  2880. {
  2881.     *LastChar = '\0';        /* just in case */
  2882.     c_substitute();
  2883.     return(e_insert(' '));
  2884. }
  2885.  
  2886. /*ARGSUSED*/
  2887. CCRETVAL
  2888. e_inc_fwd(c)
  2889.     int c;
  2890. {
  2891.     patlen = 0;
  2892.     return e_inc_search(F_DOWN_SEARCH_HIST);
  2893. }
  2894.  
  2895.  
  2896. /*ARGSUSED*/
  2897. CCRETVAL
  2898. e_inc_back(c)
  2899.     int c;
  2900. {
  2901.     patlen = 0;
  2902.     return e_inc_search(F_UP_SEARCH_HIST);
  2903. }
  2904.  
  2905. /*ARGSUSED*/
  2906. CCRETVAL
  2907. e_copyprev(c)
  2908.     int c;
  2909. {
  2910.     register Char *cp, *oldc, *dp;
  2911.  
  2912.     if (Cursor == InputBuf)
  2913.     return(CC_ERROR);
  2914.     /* else */
  2915.  
  2916.     oldc = Cursor;
  2917.     /* does a bounds check */
  2918.     cp = c_prev_word(Cursor, InputBuf, Argument);    
  2919.  
  2920.     c_insert(oldc - cp);
  2921.     for (dp = oldc; cp < oldc && dp < LastChar; cp++)
  2922.     *dp++ = *cp;
  2923.  
  2924.     Cursor = dp;        /* put cursor at end */
  2925.  
  2926.     return(CC_REFRESH);
  2927. }
  2928.  
  2929. /*ARGSUSED*/
  2930. CCRETVAL
  2931. e_tty_starto(c)
  2932.     int c;
  2933. {
  2934.     /* do no editing */
  2935.     return(CC_NORM);
  2936. }
  2937.  
  2938. /*ARGSUSED*/
  2939. CCRETVAL
  2940. e_load_average(c)
  2941.     int c;
  2942. {
  2943.     PastBottom();
  2944. #ifdef TIOCSTAT
  2945.     if (ioctl(SHIN, TIOCSTAT, 0) < 0) 
  2946. #endif
  2947.     xprintf("Load average unavailable\n");
  2948.     return(CC_REFRESH);
  2949. }
  2950.  
  2951. /*ARGSUSED*/
  2952. CCRETVAL
  2953. v_chgmeta(c)
  2954.     int c;
  2955. {
  2956.     /*
  2957.      * Delete with insert == change: first we delete and then we leave in
  2958.      * insert mode.
  2959.      */
  2960.     return(v_action(DELETE|INSERT));
  2961. }
  2962.  
  2963. /*ARGSUSED*/
  2964. CCRETVAL
  2965. v_delmeta(c)
  2966.     int c;
  2967. {
  2968.     return(v_action(DELETE));
  2969. }
  2970.  
  2971.  
  2972. /*ARGSUSED*/
  2973. CCRETVAL
  2974. v_endword(c)
  2975.     int c;
  2976. {
  2977.     if (Cursor == LastChar)
  2978.     return(CC_ERROR);
  2979.     /* else */
  2980.  
  2981.     Cursor = c_endword(Cursor, LastChar, Argument);
  2982.  
  2983.     if (ActionFlag & DELETE)
  2984.     {
  2985.     Cursor++;
  2986.     c_delfini();
  2987.     return(CC_REFRESH);
  2988.     }
  2989.  
  2990.     RefCursor();
  2991.     return(CC_NORM);
  2992. }
  2993.  
  2994. /*ARGSUSED*/
  2995. CCRETVAL
  2996. v_eword(c)
  2997.     int c;
  2998. {
  2999.     if (Cursor == LastChar)
  3000.     return(CC_ERROR);
  3001.     /* else */
  3002.  
  3003.     Cursor = c_eword(Cursor, LastChar, Argument);
  3004.  
  3005.     if (ActionFlag & DELETE) {
  3006.     Cursor++;
  3007.     c_delfini();
  3008.     return(CC_REFRESH);
  3009.     }
  3010.  
  3011.     RefCursor();
  3012.     return(CC_NORM);
  3013. }
  3014.  
  3015. /*ARGSUSED*/
  3016. CCRETVAL
  3017. v_char_fwd(c)
  3018.     int c;
  3019. {
  3020.     Char ch;
  3021.  
  3022.     if (GetNextChar(&ch) != 1)
  3023.     return e_send_eof(0);
  3024.  
  3025.     srch_dir = CHAR_FWD;
  3026.     srch_char = ch;
  3027.  
  3028.     return v_csearch_fwd(ch, Argument, 0);
  3029.  
  3030. }
  3031.  
  3032. /*ARGSUSED*/
  3033. CCRETVAL
  3034. v_char_back(c)
  3035.     int c;
  3036. {
  3037.     Char ch;
  3038.  
  3039.     if (GetNextChar(&ch) != 1)
  3040.     return e_send_eof(0);
  3041.  
  3042.     srch_dir = CHAR_BACK;
  3043.     srch_char = ch;
  3044.  
  3045.     return v_csearch_back(ch, Argument, 0);
  3046. }
  3047.  
  3048. /*ARGSUSED*/
  3049. CCRETVAL
  3050. v_charto_fwd(c)
  3051.     int c;
  3052. {
  3053.     Char ch;
  3054.  
  3055.     if (GetNextChar(&ch) != 1)
  3056.     return e_send_eof(0);
  3057.  
  3058.     return v_csearch_fwd(ch, Argument, 1);
  3059.  
  3060. }
  3061.  
  3062. /*ARGSUSED*/
  3063. CCRETVAL
  3064. v_charto_back(c)
  3065.     int c;
  3066. {
  3067.     Char ch;
  3068.  
  3069.     if (GetNextChar(&ch) != 1)
  3070.     return e_send_eof(0);
  3071.  
  3072.     return v_csearch_back(ch, Argument, 1);
  3073. }
  3074.  
  3075. /*ARGSUSED*/
  3076. CCRETVAL
  3077. v_rchar_fwd(c)
  3078.     int c;
  3079. {
  3080.     if (srch_char == 0)
  3081.     return CC_ERROR;
  3082.  
  3083.     return srch_dir == CHAR_FWD ? v_csearch_fwd(srch_char, Argument, 0) : 
  3084.                       v_csearch_back(srch_char, Argument, 0);
  3085. }
  3086.  
  3087. /*ARGSUSED*/
  3088. CCRETVAL
  3089. v_rchar_back(c)
  3090.     int c;
  3091. {
  3092.     if (srch_char == 0)
  3093.     return CC_ERROR;
  3094.  
  3095.     return srch_dir == CHAR_BACK ? v_csearch_fwd(srch_char, Argument, 0) : 
  3096.                        v_csearch_back(srch_char, Argument, 0);
  3097. }
  3098.  
  3099. /*ARGSUSED*/
  3100. CCRETVAL
  3101. v_undo(c)
  3102.     int c;
  3103. {
  3104.     register int  loop;
  3105.     register Char *kp, *cp;
  3106.     Char temp;
  3107.     int     size;
  3108.  
  3109.     switch (UndoAction) {
  3110.     case DELETE|INSERT:
  3111.     case DELETE:
  3112.     if (UndoSize == 0) return(CC_NORM);
  3113.     cp = UndoPtr;
  3114.     kp = UndoBuf;
  3115.     for (loop=0; loop < UndoSize; loop++)    /* copy the chars */
  3116.         *kp++ = *cp++;            /* into UndoBuf   */
  3117.  
  3118.     for (cp = UndoPtr; cp <= LastChar; cp++)
  3119.         *cp = cp[UndoSize];
  3120.  
  3121.     LastChar -= UndoSize;
  3122.     Cursor   =  UndoPtr;
  3123.     
  3124.     UndoAction = INSERT;
  3125.     break;
  3126.  
  3127.     case INSERT:
  3128.     if (UndoSize == 0) return(CC_NORM);
  3129.     cp = UndoPtr;
  3130.     Cursor = UndoPtr;
  3131.     kp = UndoBuf;
  3132.     c_insert(UndoSize);        /* open the space, */
  3133.     for (loop = 0; loop < UndoSize; loop++)    /* copy the chars */
  3134.         *cp++ = *kp++;
  3135.  
  3136.     UndoAction = DELETE;
  3137.     break;
  3138.  
  3139.     case CHANGE:
  3140.     if (UndoSize == 0) return(CC_NORM);
  3141.     cp = UndoPtr;
  3142.     Cursor = UndoPtr;
  3143.     kp = UndoBuf;
  3144.     size = (int)(Cursor-LastChar); /*  NOT NSL independant */
  3145.     if (size < UndoSize)
  3146.         size = UndoSize;
  3147.     for(loop = 0; loop < size; loop++) {
  3148.         temp = *kp;
  3149.         *kp++ = *cp;
  3150.         *cp++ = temp;
  3151.     }
  3152.     break;
  3153.  
  3154.     default:
  3155.     return(CC_ERROR);
  3156.     }
  3157.  
  3158.     return(CC_REFRESH);
  3159. }
  3160.  
  3161. /*ARGSUSED*/
  3162. CCRETVAL
  3163. v_ush_meta(c)
  3164.     int c;
  3165. {
  3166.     return v_search(F_UP_SEARCH_HIST);
  3167. }
  3168.  
  3169. /*ARGSUSED*/
  3170. CCRETVAL
  3171. v_dsh_meta(c)
  3172.     int c;
  3173. {
  3174.     return v_search(F_DOWN_SEARCH_HIST);
  3175. }
  3176.  
  3177. /*ARGSUSED*/
  3178. CCRETVAL
  3179. v_rsrch_fwd(c)
  3180.     int c;
  3181. {
  3182.     if (patlen == 0) return(CC_ERROR);
  3183.     return(v_repeat_srch(searchdir));
  3184. }
  3185.  
  3186. /*ARGSUSED*/
  3187. CCRETVAL
  3188. v_rsrch_back(c)
  3189.     int c;
  3190. {
  3191.     if (patlen == 0) return(CC_ERROR);
  3192.     return(v_repeat_srch(searchdir == F_UP_SEARCH_HIST ? 
  3193.              F_DOWN_SEARCH_HIST : F_UP_SEARCH_HIST));
  3194. }
  3195.  
  3196. #ifdef notdef
  3197. void
  3198. MoveCursor(n)            /* move cursor + right - left char */
  3199.     int     n;
  3200. {
  3201.     Cursor = Cursor + n;
  3202.     if (Cursor < InputBuf)
  3203.     Cursor = InputBuf;
  3204.     if (Cursor > LastChar)
  3205.     Cursor = LastChar;
  3206.     return;
  3207. }
  3208.  
  3209. Char   *
  3210. GetCursor()
  3211. {
  3212.     return(Cursor);
  3213. }
  3214.  
  3215. int
  3216. PutCursor(p)
  3217.     Char   *p;
  3218. {
  3219.     if (p < InputBuf || p > LastChar)
  3220.     return 1;        /* Error */
  3221.     Cursor = p;
  3222.     return 0;
  3223. }
  3224. #endif
  3225.