home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / shells / tcshsrc.zoo / tcsh / ed.chared.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-11  |  41.1 KB  |  2,107 lines

  1. /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.00/RCS/ed.chared.c,v 3.1 1991/07/15 19:37:24 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 "config.h"
  38. RCSID("$Id: ed.chared.c,v 3.1 1991/07/15 19:37:24 christos Exp $")
  39.  
  40. #include "sh.h"
  41. #include "ed.h"
  42. #include "tw.h"
  43. #include "ed.defns.h"
  44.  
  45. /* all routines that start with c_ are private to this set of routines */
  46. static    void     c_alternativ_key_map    __P((int));
  47. static    void     c_insert        __P((int));
  48. static    void     c_delafter        __P((int));
  49. static    void     c_delbefore        __P((int));
  50. static    Char    *c_prev_word        __P((Char *, Char *, int));
  51. static    Char    *c_next_word        __P((Char *, Char *, int));
  52. static    Char    *c_beg_next_word    __P((Char *, Char *, int));
  53. static    void     c_copy            __P((Char *, Char *, int));
  54. static    Char    *c_number        __P((Char *, int *, int));
  55. static    Char    *c_expand        __P((Char *));
  56. static    void     c_excl            __P((Char *));
  57. static    void     c_substitute        __P((void));
  58. static    int     c_hmatch        __P((Char *));
  59. static    void     c_hsetpat        __P((void));
  60. #ifdef COMMENT
  61. static    void     c_get_word        __P((Char **, Char **));
  62. #endif
  63.  
  64. static void
  65. c_alternativ_key_map(state)
  66.     int     state;
  67. {
  68.     AltKeyMap = state;
  69.     if (state)
  70.     CurrentKeyMap = CcAltMap;
  71.     else
  72.     CurrentKeyMap = CcKeyMap;
  73. }
  74.  
  75. static void
  76. c_insert(num)
  77.     register int num;
  78. {
  79.     register Char *cp;
  80.  
  81.     if (LastChar + num >= InputLim)
  82.     return;            /* can't go past end of buffer */
  83.  
  84.     if (Cursor < LastChar) {    /* if I must move chars */
  85.     for (cp = LastChar; cp >= Cursor; cp--)
  86.         cp[num] = *cp;
  87.     }
  88.     LastChar += num;
  89. }
  90.  
  91. static void
  92. c_delafter(num)            /* delete after dot, with bounds checking */
  93.     register int num;
  94. {
  95.     register Char *cp;
  96.  
  97.     if (Cursor + num > LastChar)
  98.     num = LastChar - Cursor;/* bounds check */
  99.  
  100.     if (num > 0) {        /* if I can delete anything */
  101.     for (cp = Cursor; cp <= LastChar; cp++)
  102.         *cp = cp[num];
  103.     LastChar -= num;
  104.     }
  105.     else
  106.     replacemode = 0;
  107. }
  108.  
  109. static void
  110. c_delbefore(num)        /* delete before dot, with bounds checking */
  111.     register int num;
  112. {
  113.     register Char *cp;
  114.  
  115.     if (Cursor - num < InputBuf)
  116.     num = Cursor - InputBuf;/* bounds check */
  117.  
  118.     if (num > 0) {        /* if I can delete anything */
  119.     for (cp = Cursor - num; cp <= LastChar; cp++)
  120.         *cp = cp[num];
  121.     LastChar -= num;
  122.     }
  123. }
  124.  
  125. static Char *
  126. c_prev_word(p, low, n)
  127.     register Char *p, *low;
  128.     register int n;
  129. {
  130.     /* to the beginning of the PREVIOUS word, not this one */
  131.     p--;
  132.  
  133.     while (n--) {
  134.     while ((p >= low) && (!(isword(*p))))
  135.         p--;
  136.     while ((p >= low) && (isword(*p)))
  137.         p--;
  138.     }
  139.     /* cp now points to one character before the word */
  140.     p++;
  141.     if (p < low)
  142.     p = low;
  143.     /* cp now points where we want it */
  144.     return (p);
  145. }
  146.  
  147. static Char *
  148. c_next_word(p, high, n)
  149.     register Char *p, *high;
  150.     register int n;
  151. {
  152.     while (n--) {
  153.     while ((p < high) && (!(isword(*p))))
  154.         p++;
  155.     while ((p < high) && (isword(*p)))
  156.         p++;
  157.     }
  158.     if (p > high)
  159.     p = high;
  160.     /* p now points where we want it */
  161.     return (p);
  162. }
  163.  
  164. static Char *
  165. c_beg_next_word(p, high, n)
  166.     register Char *p, *high;
  167.     register int n;
  168. {
  169.     while (n--) {
  170.     while ((p < high) && (isword(*p)))
  171.         p++;
  172.     while ((p < high) && (!(isword(*p))))
  173.         p++;
  174.     }
  175.     if (p > high)
  176.     p = high;
  177.     /* p now points where we want it */
  178.     return (p);
  179. }
  180.  
  181. /*
  182.  * Expand-History (originally "Magic-Space") code added by
  183.  * Ray Moody <ray@gibbs.physics.purdue.edu>
  184.  * this is a neat, but odd, addition.
  185.  */
  186.  
  187. /*
  188.  * c_copy is sorta like bcopy() except that we handle overlap between
  189.  * source and destination memory
  190.  */
  191.  
  192. static void
  193. c_copy(src, dst, length)
  194.     register Char *src, *dst;
  195.     register int length;
  196. {
  197.     if (src > dst) {
  198.     while (length--) {
  199.         *dst++ = *src++;
  200.     }
  201.     }
  202.     else {
  203.     src += length;
  204.     dst += length;
  205.     while (length--) {
  206.         *--dst = *--src;
  207.     }
  208.     }
  209. }
  210.  
  211. /*
  212.  * c_number: Ignore character p points to, return number appearing after that.
  213.  * A '$' by itself means a big number; "$-" is for negative; '^' means 1.
  214.  * Return p pointing to last char used.
  215.  */
  216.  
  217. /*
  218.  * dval is the number to subtract from for things like $-3
  219.  */
  220.  
  221. static Char *
  222. c_number(p, num, dval)
  223.     register Char *p;
  224.     register int *num;
  225.     register int dval;
  226. {
  227.     register int i;
  228.     register int sign = 1;
  229.  
  230.     if (*++p == '^') {
  231.     *num = 1;
  232.     return (p);
  233.     }
  234.     if (*p == '$') {
  235.     if (*++p != '-') {
  236.         *num = NCARGS;    /* Handle $ */
  237.         return (--p);
  238.     }
  239.     sign = -1;        /* Handle $- */
  240.     ++p;
  241.     }
  242.     for (i = 0; *p >= '0' && *p <= '9'; i = 10 * i + *p++ - '0');
  243.     *num = (sign < 0 ? dval - i : i);
  244.     return (--p);
  245. }
  246.  
  247. /*
  248.  * excl_expand: There is an excl to be expanded to p -- do the right thing
  249.  * with it and return a version of p advanced over the expanded stuff.  Also,
  250.  * update tsh_cur and related things as appropriate...
  251.  */
  252.  
  253. static Char *
  254. c_expand(p)
  255.     register Char *p;
  256. {
  257.     register Char *q;
  258.     register struct Hist *h = Histlist.Hnext;
  259.     register struct wordent *l;
  260.     int     i, from, to, dval;
  261.     bool    all_dig;
  262.     bool    been_once = 0;
  263.     Char   *op = p;
  264.     Char    buf[INBUFSIZ];
  265.     Char   *bend = buf;
  266.     Char   *modbuf, *omodbuf;
  267.  
  268.     if (!h)
  269.     goto excl_err;
  270. excl_sw:
  271.     switch (*(q = p + 1)) {
  272.  
  273.     case '^':
  274.     bend = expand_lex(buf, INBUFSIZ, &h->Hlex, 1, 1);
  275.     break;
  276.  
  277.     case '$':
  278.     if ((l = (h->Hlex).prev))
  279.         bend = expand_lex(buf, INBUFSIZ, l->prev->prev, 0, 0);
  280.     break;
  281.  
  282.     case '*':
  283.     bend = expand_lex(buf, INBUFSIZ, &h->Hlex, 1, NCARGS);
  284.     break;
  285.  
  286.     default:
  287.     if (been_once) {    /* unknown argument */
  288.         /* assume it's a modifier, e.g. !foo:h, and get whole cmd */
  289.         bend = expand_lex(buf, INBUFSIZ, &h->Hlex, 0, NCARGS);
  290.         q -= 2;
  291.         break;
  292.     }
  293.     been_once = 1;
  294.  
  295.     if (*q == ':')        /* short form: !:arg */
  296.         --q;
  297.  
  298.     if (*q != HIST) {
  299.         /*
  300.          * Search for a space, tab, or colon.  See if we have a number (as
  301.          * in !1234:xyz).  Remember the number.
  302.          */
  303.         for (i = 0, all_dig = 1; 
  304.          *q != ' ' && *q != '\t' && *q != ':' && q < Cursor; q++) {
  305.         /*
  306.          * PWP: !-4 is a valid history argument too, therefore the test
  307.          * is if not a digit, or not a - as the first character.
  308.          */
  309.         if ((*q < '0' || *q > '9') && (*q != '-' || q != p + 1))
  310.             all_dig = 0;
  311.         else if (*q == '-')
  312.             all_dig = 2;/* we are sneeky about this */
  313.         else
  314.             i = 10 * i + *q - '0';
  315.         }
  316.         --q;
  317.  
  318.         /*
  319.          * If we have a number, search for event i.  Otherwise, search for
  320.          * a named event (as in !foo).  (In this case, I is the length of
  321.          * the named event).
  322.          */
  323.         if (all_dig) {
  324.         if (all_dig == 2)
  325.             i = -i;    /* make it negitive */
  326.         if (i < 0)    /* if !-4 (for example) */
  327.             i = eventno + 1 + i;    /* remember: i is < 0 */
  328.         for (; h; h = h->Hnext) {
  329.             if (h->Hnum == i)
  330.             break;
  331.         }
  332.         }
  333.         else {
  334.         for (i = q - p; h; h = h->Hnext) {
  335.             if ((l = &h->Hlex)) {
  336.             if (!Strncmp(p + 1, l->next->word, i))
  337.                 break;
  338.             }
  339.         }
  340.         }
  341.     }
  342.     if (!h)
  343.         goto excl_err;
  344.     if (q[1] == ':' || q[1] == '-' || q[1] == '*' ||
  345.         q[1] == '$' || q[1] == '^') {    /* get some args */
  346.         p = q[1] == ':' ? ++q : q;
  347.         /*
  348.          * Go handle !foo:*
  349.          */
  350.         if ((q[1] < '0' || q[1] > '9') &&
  351.         q[1] != '-' && q[1] != '$' && q[1] != '^')
  352.         goto excl_sw;
  353.         /*
  354.          * Go handle !foo:$
  355.          */
  356.         if (q[1] == '$' && (q[2] != '-' || q[3] < '0' || q[3] > '9'))
  357.         goto excl_sw;
  358.         /*
  359.          * Count up the number of words in this event.  Store it in dval.
  360.          * Dval will be fed to number.
  361.          */
  362.         dval = 0;
  363.         if ((l = h->Hlex.prev)) {
  364.         for (l = l->prev; l != h->Hlex.next; l = l->prev, dval++);
  365.         }
  366.         if (!dval)
  367.         goto excl_err;
  368.         if (q[1] == '-')
  369.         from = 0;
  370.         else
  371.         q = c_number(q, &from, dval);
  372.         if (q[1] == '-') {
  373.         ++q;
  374.         if ((q[1] < '0' || q[1] > '9') && q[1] != '$')
  375.             to = dval - 1;
  376.         else
  377.             q = c_number(q, &to, dval);
  378.         }
  379.         else if (q[1] == '*') {
  380.         ++q;
  381.         to = NCARGS;
  382.         }
  383.         else {
  384.         to = from;
  385.         }
  386.         if (from < 0 || to < from)
  387.         goto excl_err;
  388.         bend = expand_lex(buf, INBUFSIZ, &h->Hlex, from, to);
  389.     }
  390.     else {            /* get whole cmd */
  391.         bend = expand_lex(buf, INBUFSIZ, &h->Hlex, 0, NCARGS);
  392.     }
  393.     break;
  394.     }
  395.  
  396.     /*
  397.      * Apply modifiers, if any.
  398.      */
  399.     if (q[1] == ':') {
  400.     *bend = '\0';
  401.     omodbuf = buf;
  402.     while (q[1] == ':' && (modbuf = domod(omodbuf, (int) q[2])) != NOSTR) {
  403.         if (omodbuf != buf)
  404.         xfree((ptr_t) omodbuf);
  405.         omodbuf = modbuf;
  406.         q += 2;
  407.     }
  408.     if (omodbuf != buf) {
  409.         (void) Strcpy(buf, omodbuf);
  410.         xfree((ptr_t) omodbuf);
  411.         bend = Strend(buf);
  412.     }
  413.     }
  414.  
  415.     /*
  416.      * Now replace the text from op to q inclusive with the text from buf to
  417.      * bend.
  418.      */
  419.     q++;
  420.  
  421.     /*
  422.      * Now replace text non-inclusively like a real CS major!
  423.      */
  424.     if (LastChar + (bend - buf) - (q - op) >= InputLim)
  425.     goto excl_err;
  426.     c_copy(q, q + (bend - buf) - (q - op), LastChar - q);
  427.     LastChar += (bend - buf) - (q - op);
  428.     Cursor += (bend - buf) - (q - op);
  429.     c_copy(buf, op, (bend - buf));
  430.     return (op + (bend - buf));
  431. excl_err:
  432.     Beep();
  433.     return (op + 1);
  434. }
  435.  
  436. /*
  437.  * c_excl: An excl has been found at point p -- back up and find some white
  438.  * space (or the beginning of the buffer) and properly expand all the excl's
  439.  * from there up to the current cursor position. We also avoid (trying to)
  440.  * expanding '>!'
  441.  */
  442.  
  443. static void
  444. c_excl(p)
  445.     register Char *p;
  446. {
  447.     register int i;
  448.     register Char *q;
  449.  
  450.     /*
  451.      * if />[SPC TAB]*![SPC TAB]/, back up p to just after the >. otherwise,
  452.      * back p up to just before the current word.
  453.      */
  454.     if ((p[1] == ' ' || p[1] == '\t') &&
  455.     (p[-1] == ' ' || p[-1] == '\t' || p[-1] == '>')) {
  456.     for (q = p - 1; q > InputBuf && (*q == ' ' || *q == '\t'); --q);
  457.     if (*q == '>')
  458.         ++p;
  459.     }
  460.     else {
  461.     while (*p != ' ' && *p != '\t' && p > InputBuf)
  462.         --p;
  463.     }
  464.  
  465.     /*
  466.      * Forever: Look for history char.  (Stop looking when we find the cursor.)
  467.      * Count backslashes.  Of odd, skip history char. Return if all done.
  468.      * Expand if even number of backslashes.
  469.      */
  470.     for (;;) {
  471.     while (*p != HIST && p < Cursor)
  472.         ++p;
  473. #ifdef ALTESC
  474.     for (i = 1; (p - i) >= InputBuf && p[-i] == escchar; i++);
  475. #else
  476.     for (i = 1; (p - i) >= InputBuf && p[-i] == '\\'; i++);
  477. #endif
  478.     if (i % 2 == 0)
  479.         ++p;
  480.     if (p >= Cursor)
  481.         return;
  482.     if (i % 2 == 1)
  483.         p = c_expand(p);
  484.     }
  485. }
  486.  
  487.  
  488. static void
  489. c_substitute()
  490. {
  491.     register Char *p;
  492.  
  493.     /*
  494.      * Start p out one character before the cursor.  Move it backwards looking
  495.      * for white space, the beginning of the line, or a history character.
  496.      */
  497.     for (p = Cursor - 1; 
  498.      p > InputBuf && *p != ' ' && *p != '\t' && *p != HIST; --p);
  499.  
  500.     /*
  501.      * If we found a history character, go expand it.
  502.      */
  503.     if (*p == HIST)
  504.     c_excl(p);
  505.     Refresh();
  506. }
  507.  
  508. /*
  509.  * demi-PUBLIC routines.  Any routine that is of type CCRETVAL is an
  510.  * entry point, called from the CcKeyMap indirected into the
  511.  * CcFuncTbl array.
  512.  */
  513.  
  514. /*ARGSUSED*/
  515. CCRETVAL
  516. v_cmd_mode(c)
  517.     int c;
  518. {
  519.     replacemode = 0;
  520.     c_alternativ_key_map(1);
  521.     if (Cursor > InputBuf)
  522.     Cursor--;
  523.     RefCursor();
  524.     return (CC_NORM);
  525. }
  526.  
  527. /*ARGSUSED*/
  528. CCRETVAL
  529. e_unassigned(c)
  530.     int c;
  531. {                /* bound to keys that arn't really assigned */
  532.     Beep();
  533.     flush();
  534.     return (CC_NORM);
  535. }
  536.  
  537. CCRETVAL
  538. e_insert(c)
  539.     register int c;
  540. {
  541. #ifndef SHORT_STRINGS
  542.     c &= ASCII;            /* no meta chars ever */
  543. #endif
  544.  
  545.     if (!c)
  546.     return (CC_ERROR);    /* no NULs in the input ever!! */
  547.  
  548.     if (LastChar + Argument >= InputLim)
  549.     return (CC_ERROR);    /* end of buffer space */
  550.  
  551.     if (Argument == 1) {    /* optimize */
  552.     if (replacemode == 1)
  553.         c_delafter(1);
  554.     else if (replacemode == 2)
  555.         c_delafter(1);
  556.     c_insert(1);
  557.     *Cursor++ = c;
  558.     DoingArg = 0;        /* just in case */
  559.     RefPlusOne();        /* fast refresh for one char. */
  560.     if (replacemode == 2)
  561.         (void) v_cmd_mode(0);
  562.     }
  563.     else {
  564.     if (replacemode == 1)
  565.         c_delafter(Argument);
  566.     else if (replacemode == 2)
  567.         c_delafter(Argument);
  568.     c_insert(Argument);
  569.     while (Argument--)
  570.         *Cursor++ = c;
  571.     Refresh();
  572.     if (replacemode == 2)
  573.         (void) v_cmd_mode(0);
  574.     }
  575.     return (CC_NORM);
  576. }
  577.  
  578. int
  579. InsertStr(s)            /* insert ASCIZ s at cursor (for complete) */
  580.     Char   *s;
  581. {
  582.     register int len;
  583.  
  584.     if ((len = Strlen(s)) <= 0)
  585.     return -1;
  586.     if (LastChar + len >= InputLim)
  587.     return -1;        /* end of buffer space */
  588.  
  589.     c_insert(len);
  590.     while (len--)
  591.     *Cursor++ = *s++;
  592.     return 0;
  593. }
  594.  
  595. void
  596. DeleteBack(n)            /* delete the n characters before . */
  597.     int     n;
  598. {
  599.     if (n <= 0)
  600.     return;
  601.     if (Cursor >= &InputBuf[n]) {
  602.     c_delbefore(n);        /* delete before dot */
  603.     Cursor -= n;
  604.     if (Cursor < InputBuf)
  605.         Cursor = InputBuf;    /* bounds check */
  606.     }
  607. }
  608.  
  609. CCRETVAL
  610. e_digit(c)            /* gray magic here */
  611.     register int c;
  612. {
  613.     if (!Isdigit(c))
  614.     return (CC_ERROR);    /* no NULs in the input ever!! */
  615.  
  616.     if (DoingArg) {        /* if doing an arg, add this in... */
  617.     if (LastCmd == F_ARGFOUR)    /* if last command was ^U */
  618.         Argument = c - '0';
  619.     else {
  620.         if (Argument > 1000000)
  621.         return CC_ERROR;
  622.         Argument = (Argument * 10) + (c - '0');
  623.     }
  624.     return (CC_ARGHACK);
  625.     }
  626.     else {
  627.     if (LastChar + 1 >= InputLim)
  628.         return CC_ERROR;    /* end of buffer space */
  629.  
  630.     c_insert(1);
  631.     *Cursor++ = c;
  632.     DoingArg = 0;        /* just in case */
  633.     RefPlusOne();        /* fast refresh for one char. */
  634.     }
  635.     return (CC_NORM);
  636. }
  637.  
  638. CCRETVAL
  639. e_argdigit(c)            /* for ESC-n */
  640.     register int c;
  641. {
  642.     c &= ASCII;
  643.  
  644.     if (!Isdigit(c))
  645.     return (CC_ERROR);    /* no NULs in the input ever!! */
  646.  
  647.     if (DoingArg) {        /* if doing an arg, add this in... */
  648.     if (Argument > 1000000)
  649.         return CC_ERROR;
  650.     Argument = (Argument * 10) + (c - '0');
  651.     }
  652.     else {            /* else starting an argument */
  653.     Argument = c - '0';
  654.     DoingArg = 1;
  655.     }
  656.     return (CC_ARGHACK);
  657. }
  658.  
  659. CCRETVAL
  660. v_zero(c)            /* command mode 0 for vi */
  661.     register int c;
  662. {
  663.     if (DoingArg) {        /* if doing an arg, add this in... */
  664.     if (Argument > 1000000)
  665.         return CC_ERROR;
  666.     Argument = (Argument * 10) + (c - '0');
  667.     return (CC_ARGHACK);
  668.     }
  669.     else {            /* else starting an argument */
  670.     Cursor = InputBuf;
  671.     RefCursor();        /* move the cursor */
  672.     return (CC_NORM);
  673.     }
  674. }
  675.  
  676. /*ARGSUSED*/
  677. CCRETVAL
  678. e_newline(c)
  679.     int c;
  680. {                /* always ignore argument */
  681.     PastBottom();
  682.     *LastChar++ = '\n';        /* for the benifit of CSH */
  683.     *LastChar = '\0';        /* just in case */
  684.     return (CC_NEWLINE);    /* we must do a ResetInLine later */
  685. }
  686.  
  687. /*ARGSUSED*/
  688. CCRETVAL
  689. e_send_eof(c)
  690.     int c;
  691. {                /* for when ^D is ONLY send-eof */
  692.     PastBottom();
  693.     *LastChar = '\0';        /* just in case */
  694. #ifdef notdef
  695.     ResetInLine();        /* reset the input pointers */
  696. #endif
  697.     return (CC_EOF);
  698. }
  699.  
  700. /*ARGSUSED*/
  701. CCRETVAL
  702. e_complete(c)
  703.     int c;
  704. {
  705.     *LastChar = '\0';        /* just in case */
  706.     return (CC_COMPLETE);
  707. }
  708.  
  709. /*ARGSUSED*/
  710. CCRETVAL
  711. v_cm_complete(c)
  712.     int c;
  713. {
  714.     if (Cursor < LastChar)
  715.     Cursor++;
  716.     *LastChar = '\0';        /* just in case */
  717.     return (CC_COMPLETE);
  718. }
  719.  
  720. /*ARGSUSED*/
  721. CCRETVAL
  722. e_toggle_hist(c)
  723.     int c;
  724. {
  725.     struct Hist *hp;
  726.     int     h;
  727.  
  728.     *LastChar = '\0';        /* just in case */
  729.  
  730.     if (Hist_num <= 0) {
  731.     return CC_ERROR;
  732.     }
  733.  
  734.     hp = Histlist.Hnext;
  735.     if (hp == NULL) {    /* this is only if no history */
  736.     return (CC_ERROR);
  737.     }
  738.  
  739.     for (h = 1; h < Hist_num; h++)
  740.     hp = hp->Hnext;
  741.  
  742.     if (!CurrentHistLit) {
  743.     if (hp->histline) {
  744.         copyn(InputBuf, hp->histline, INBUFSIZ);
  745.         CurrentHistLit = 1;
  746.     }
  747.     else {
  748.         return CC_ERROR;
  749.     }
  750.     }
  751.     else {
  752.     (void) sprlex(InputBuf, &hp->Hlex);
  753.     CurrentHistLit = 0;
  754.     }
  755.     LastChar = InputBuf + Strlen(InputBuf);
  756.     if (LastChar > InputBuf) {
  757.     if (LastChar[-1] == '\n')
  758.         LastChar--;
  759.     if (LastChar[-1] == ' ')
  760.         LastChar--;
  761.     if (LastChar < InputBuf)
  762.         LastChar = InputBuf;
  763.     }
  764.     Cursor = LastChar;
  765.  
  766.     return (CC_REFRESH);
  767. }
  768.  
  769. /*ARGSUSED*/
  770. CCRETVAL
  771. e_up_hist(c)
  772.     int c;
  773. {
  774.     struct Hist *hp;
  775.     int     hnumcntr;
  776.     Char    beep = 0;
  777.  
  778.     *LastChar = '\0';        /* just in case */
  779.  
  780.     if (Hist_num == 0) {    /* save the current buffer away */
  781.     copyn(HistBuf, InputBuf, INBUFSIZ);
  782.     LastHist = HistBuf + (LastChar - InputBuf);
  783.     }
  784.  
  785.     hp = Histlist.Hnext;
  786.     if (hp == NULL) {    /* this is only if no history */
  787.     return (CC_ERROR);
  788.     }
  789.  
  790.     Hist_num += Argument;
  791.     for (hnumcntr = 1; hnumcntr < Hist_num; hnumcntr++) {
  792.     if ((hp->Hnext) == NULL) {
  793.         Hist_num = hnumcntr;
  794.         beep = 1;
  795.         break;
  796.     }
  797.     hp = hp->Hnext;
  798.     }
  799.  
  800.     if (HistLit && hp->histline) {
  801.     copyn(InputBuf, hp->histline, INBUFSIZ);
  802.     CurrentHistLit = 1;
  803.     }
  804.     else {
  805.     (void) sprlex(InputBuf, &hp->Hlex);
  806.     CurrentHistLit = 0;
  807.     }
  808.     LastChar = InputBuf + Strlen(InputBuf);
  809.     if (LastChar > InputBuf) {
  810.     if (LastChar[-1] == '\n')
  811.         LastChar--;
  812.     if (LastChar[-1] == ' ')
  813.         LastChar--;
  814.     if (LastChar < InputBuf)
  815.         LastChar = InputBuf;
  816.     }
  817.     Cursor = LastChar;
  818.  
  819.     Refresh();
  820.     if (beep)
  821.     return (CC_ERROR);
  822.     else
  823.     return (CC_NORM);    /* was CC_UP_HIST */
  824. }
  825.  
  826. /*ARGSUSED*/
  827. CCRETVAL
  828. e_down_hist(c)
  829.     int c;
  830. {
  831.     struct Hist *hp;
  832.     int     hnumcntr;
  833.  
  834.     *LastChar = '\0';        /* just in case */
  835.  
  836.     Hist_num -= Argument;
  837.  
  838.     if (Hist_num < 0) {
  839.     Hist_num = 0;
  840.     return (CC_ERROR);    /* make it beep */
  841.     }
  842.  
  843.     if (Hist_num == 0) {    /* if really the current line */
  844.     copyn(InputBuf, HistBuf, INBUFSIZ);
  845.     LastChar = InputBuf + (LastHist - HistBuf);
  846.     Cursor = LastChar;
  847.     return (CC_REFRESH);
  848.     }
  849.  
  850.     hp = Histlist.Hnext;
  851.     if (hp == NULL)
  852.     return (CC_ERROR);
  853.  
  854.     for (hnumcntr = 1; hnumcntr < Hist_num; hnumcntr++) {
  855.     if ((hp->Hnext) == NULL) {
  856.         Hist_num = hnumcntr;
  857.         return (CC_ERROR);
  858.     }
  859.     hp = hp->Hnext;
  860.     }
  861.  
  862.     if (HistLit && hp->histline) {
  863.     copyn(InputBuf, hp->histline, INBUFSIZ);
  864.     CurrentHistLit = 1;
  865.     }
  866.     else {
  867.     (void) sprlex(InputBuf, &hp->Hlex);
  868.     CurrentHistLit = 0;
  869.     }
  870.     LastChar = InputBuf + Strlen(InputBuf);
  871.     if (LastChar > InputBuf) {
  872.     if (LastChar[-1] == '\n')
  873.         LastChar--;
  874.     if (LastChar[-1] == ' ')
  875.         LastChar--;
  876.     if (LastChar < InputBuf)
  877.         LastChar = InputBuf;
  878.     }
  879.     Cursor = LastChar;
  880.  
  881.     return (CC_REFRESH);
  882. }
  883.  
  884.  
  885.  
  886. static Char patbuf[INBUFSIZ];
  887. static int patlen = 0;
  888. /*
  889.  * c_hmatch() return True if the pattern matches the prefix
  890.  */
  891. static int
  892. c_hmatch(str)
  893. Char *str;
  894. {
  895.     if (Strncmp(patbuf, str, patlen) == 0)
  896.     return 1;
  897.     return Gmatch(str, patbuf);
  898. }
  899.  
  900. /*
  901.  * c_hsetpat(): Set the history seatch pattern
  902.  */
  903. static void
  904. c_hsetpat()
  905. {
  906.     if (LastCmd != F_UP_SEARCH_HIST && LastCmd != F_DOWN_SEARCH_HIST) {
  907.     patlen = Cursor - InputBuf;
  908.     if (patlen >= INBUFSIZ) patlen = INBUFSIZ -1;
  909.     (void) Strncpy(patbuf, InputBuf, patlen);
  910.     patbuf[patlen] = '\0';
  911.     }
  912. #ifdef SDEBUG
  913.     xprintf("\nHist_num = %d\n", Hist_num);
  914.     xprintf("patlen = %d\n", patlen);
  915.     xprintf("patbuf = \"%s\"\n", short2str(patbuf));
  916. #endif
  917. }
  918.  
  919. /*ARGSUSED*/
  920. CCRETVAL
  921. e_up_search_hist(c)
  922.     int c;
  923. {
  924.     struct Hist *hp;
  925.     int h;
  926.     bool    found = 0;
  927.  
  928.     *LastChar = '\0';        /* just in case */
  929.     if (Hist_num < 0) {
  930.     xprintf("tcsh: e_up_search_hist(): Hist_num < 0; resetting.\n");
  931.     Hist_num = 0;
  932.     return (CC_ERROR);
  933.     }
  934.  
  935.     if (Hist_num == 0) {
  936.     copyn(HistBuf, InputBuf, INBUFSIZ);
  937.     LastHist = HistBuf + (LastChar - InputBuf);
  938.     }
  939.  
  940.     hp = Histlist.Hnext;
  941.     if (hp == NULL)
  942.     return (CC_ERROR);
  943.  
  944.     c_hsetpat();
  945.     for (h = 1; h <= Hist_num; h++)
  946.     hp = hp->Hnext;
  947.  
  948.     while (hp != NULL) {
  949.     if (hp->histline == NULL) {
  950.         Char sbuf[BUFSIZ];
  951.         hp->histline = Strsave(sprlex(sbuf, &hp->Hlex));
  952.     }
  953. #ifdef SDEBUG
  954.     xprintf("Comparing with \"%s\"\n", short2str(hp->histline));
  955. #endif
  956.     if (c_hmatch(hp->histline)) {
  957.         found++;
  958.         break;
  959.     }
  960.     h++;
  961.     hp = hp->Hnext;
  962.     }
  963.     if (!found)
  964.     return (CC_ERROR);
  965.  
  966.     Hist_num = h;
  967.  
  968.     if (HistLit && hp->histline) {
  969.     copyn(InputBuf, hp->histline, INBUFSIZ);
  970.     CurrentHistLit = 1;
  971.     }
  972.     else {
  973.     (void) sprlex(InputBuf, &hp->Hlex);
  974.     CurrentHistLit = 0;
  975.     }
  976.     LastChar = InputBuf + Strlen(InputBuf);
  977.     if (LastChar > InputBuf) {
  978.     if (LastChar[-1] == '\n')
  979.         LastChar--;
  980.     if (LastChar[-1] == ' ')
  981.         LastChar--;
  982.     if (LastChar < InputBuf)
  983.         LastChar = InputBuf;
  984.     }
  985.     Cursor = LastChar;
  986.     return (CC_REFRESH);
  987. }
  988.  
  989. /*ARGSUSED*/
  990. CCRETVAL
  991. e_down_search_hist(c)
  992.     int c;
  993. {
  994.     struct Hist *hp, *hpt = NULL;
  995.     int h;
  996.     bool    found = 0;
  997.  
  998.     *LastChar = '\0';        /* just in case */
  999.  
  1000.     if (Hist_num == 0)
  1001.     return (CC_ERROR);
  1002.  
  1003.     hp = Histlist.Hnext;
  1004.     if (hp == 0)
  1005.     return (CC_ERROR);
  1006.  
  1007.     c_hsetpat();
  1008.  
  1009.     for (h = 1; h < Hist_num && hp; h++) {
  1010.     if (hp->histline == NULL) {
  1011.         Char sbuf[BUFSIZ];
  1012.         hp->histline = Strsave(sprlex(sbuf, &hp->Hlex));
  1013.     }
  1014. #ifdef SDEBUG
  1015.     xprintf("Comparing with \"%s\"\n", short2str(hp->histline));
  1016. #endif
  1017.     if (c_hmatch(hp->histline)) {
  1018.         found = h;
  1019.         hpt = hp;
  1020.     }
  1021.     hp = hp->Hnext;
  1022.     }
  1023.     if (!found) {        /* is it the current history number? */
  1024.     if (c_hmatch(HistBuf)) {
  1025.         copyn(InputBuf, HistBuf, INBUFSIZ);
  1026.         LastChar = InputBuf + (LastHist - HistBuf);
  1027.         Hist_num = 0;
  1028.         Cursor = LastChar;
  1029.         return (CC_REFRESH);
  1030.     }
  1031.     else {
  1032.         return (CC_ERROR);
  1033.     }
  1034.     }
  1035.  
  1036.     Hist_num = found;
  1037.     hp = hpt;
  1038.  
  1039.     if (HistLit && hp->histline) {
  1040.     copyn(InputBuf, hp->histline, INBUFSIZ);
  1041.     CurrentHistLit = 1;
  1042.     }
  1043.     else {
  1044.     (void) sprlex(InputBuf, &hp->Hlex);
  1045.     CurrentHistLit = 0;
  1046.     }
  1047.     LastChar = InputBuf + Strlen(InputBuf);
  1048.     if (LastChar > InputBuf) {
  1049.     if (LastChar[-1] == '\n')
  1050.         LastChar--;
  1051.     if (LastChar[-1] == ' ')
  1052.         LastChar--;
  1053.     if (LastChar < InputBuf)
  1054.         LastChar = InputBuf;
  1055.     }
  1056.     Cursor = LastChar;
  1057.  
  1058.     return (CC_REFRESH);
  1059. }
  1060.  
  1061. /*ARGSUSED*/
  1062. CCRETVAL
  1063. e_helpme(c)
  1064.     int c;
  1065. {
  1066.     PastBottom();
  1067.     *LastChar = '\0';        /* just in case */
  1068.     return (CC_HELPME);
  1069. }
  1070.  
  1071. /*ARGSUSED*/
  1072. CCRETVAL
  1073. e_correct(c)
  1074.     int c;
  1075. {
  1076.     *LastChar = '\0';        /* just in case */
  1077.     return (CC_CORRECT);
  1078. }
  1079.  
  1080. /*ARGSUSED*/
  1081. CCRETVAL
  1082. e_correctl(c)
  1083.     int c;
  1084. {
  1085.     *LastChar = '\0';        /* just in case */
  1086.     return (CC_CORRECT_L);
  1087. }
  1088.  
  1089. /*ARGSUSED*/
  1090. CCRETVAL
  1091. e_run_fg_editor(c)
  1092.     int c;
  1093. {
  1094.     register struct process *pp;
  1095.     extern bool tellwhat;
  1096.  
  1097.     if ((pp = find_stop_ed()) != PNULL) {
  1098.     /* save our editor state so we can restore it */
  1099.     tellwhat = 1;
  1100.     copyn(WhichBuf, InputBuf, INBUFSIZ);
  1101.     LastWhich = WhichBuf + (LastChar - InputBuf);
  1102.     CursWhich = WhichBuf + (Cursor - InputBuf);
  1103.     HistWhich = Hist_num;
  1104.     Hist_num = 0;        /* for the history commands */
  1105.  
  1106.     /* put the tty in a sane mode */
  1107.     PastBottom();
  1108.     (void) Cookedmode();    /* make sure the tty is set up correctly */
  1109.  
  1110.     /* do it! */
  1111.     fg_proc_entry(pp);
  1112.  
  1113.     (void) Rawmode();    /* go on */
  1114.     Refresh();
  1115.     tellwhat = 0;
  1116.     }
  1117.     return (CC_NORM);
  1118. }
  1119.  
  1120. /*ARGSUSED*/
  1121. CCRETVAL
  1122. e_list_choices(c)
  1123.     int c;
  1124. {
  1125.     PastBottom();
  1126.     *LastChar = '\0';        /* just in case */
  1127.     return (CC_LIST_CHOICES);
  1128. }
  1129.  
  1130. /*ARGSUSED*/
  1131. CCRETVAL
  1132. e_list_glob(c)
  1133.     int c;
  1134. {
  1135.     PastBottom();
  1136.     *LastChar = '\0';        /* just in case */
  1137.     return (CC_LIST_GLOB);
  1138. }
  1139.  
  1140. /*ARGSUSED*/
  1141. CCRETVAL
  1142. e_expand_glob(c)
  1143.     int c;
  1144. {
  1145.     *LastChar = '\0';        /* just in case */
  1146.     return (CC_EXPAND_GLOB);
  1147. }
  1148.  
  1149. /*ARGSUSED*/
  1150. CCRETVAL
  1151. e_expand_vars(c)
  1152.     int c;
  1153. {
  1154.     *LastChar = '\0';        /* just in case */
  1155.     return (CC_EXPAND_VARS);
  1156. }
  1157.  
  1158. /*ARGSUSED*/
  1159. CCRETVAL
  1160. e_which(c)
  1161.     int c;
  1162. {                /* do a fast command line which(1) */
  1163.     PastBottom();
  1164.     *LastChar = '\0';        /* just in case */
  1165.     return (CC_WHICH);
  1166. }
  1167.  
  1168. /*ARGSUSED*/
  1169. CCRETVAL
  1170. e_last_item(c)
  1171.     int c;
  1172. {                /* insert the last element of the prev. cmd */
  1173.     register Char *cp;
  1174.     register struct Hist *hp;
  1175.     register struct wordent *wp, *firstp;
  1176.     register int i;
  1177.  
  1178.     if (Argument <= 0)
  1179.     return (CC_ERROR);
  1180.  
  1181.     hp = Histlist.Hnext;
  1182.     if (hp == NULL) {    /* this is only if no history */
  1183.     return (CC_ERROR);
  1184.     }
  1185.  
  1186.     wp = (hp->Hlex).prev;
  1187.  
  1188.     if (wp->prev == (struct wordent *) NULL)
  1189.     return (CC_ERROR);    /* an empty history entry */
  1190.  
  1191.     firstp = (hp->Hlex).next;
  1192.  
  1193.     for (i = 0; i < Argument; i++) {    /* back up arg words in lex */
  1194.     wp = wp->prev;
  1195.     if (wp == firstp)
  1196.         break;
  1197.     }
  1198.  
  1199.     while (i > 0) {
  1200.     cp = wp->word;
  1201.  
  1202.     if (!cp)
  1203.         return (CC_ERROR);
  1204.  
  1205.     if (InsertStr(cp))
  1206.         return (CC_ERROR);
  1207.  
  1208.     wp = wp->next;
  1209.     i--;
  1210.     }
  1211.  
  1212.     return (CC_REFRESH);
  1213. }
  1214.  
  1215. /*ARGSUSED*/
  1216. CCRETVAL
  1217. e_yank_kill(c)
  1218.     int c;
  1219. {                /* almost like GnuEmacs */
  1220.     register Char *kp, *cp;
  1221.  
  1222.     if (LastKill == KillBuf)    /* if zero content */
  1223.     return (CC_ERROR);
  1224.  
  1225.     if (LastChar + (LastKill - KillBuf) >= InputLim)
  1226.     return (CC_ERROR);    /* end of buffer space */
  1227.  
  1228.     /* else */
  1229.     Mark = Cursor;        /* set the mark */
  1230.     cp = Cursor;        /* for speed */
  1231.  
  1232.     c_insert(LastKill - KillBuf);    /* open the space, */
  1233.     for (kp = KillBuf; kp < LastKill; kp++)    /* copy the chars */
  1234.     *cp++ = *kp;
  1235.  
  1236.     if (Argument == 1)        /* if an arg, cursor at beginning */
  1237.     Cursor = cp;        /* else cursor at end */
  1238.  
  1239.     return (CC_REFRESH);
  1240. }
  1241.  
  1242. /*ARGSUSED*/
  1243. CCRETVAL
  1244. e_delprev(c)
  1245.     int c;
  1246. {
  1247.     if (Cursor > InputBuf) {
  1248.     c_delbefore(Argument);    /* delete before dot */
  1249.     Cursor -= Argument;
  1250.     if (Cursor < InputBuf)
  1251.         Cursor = InputBuf;    /* bounds check */
  1252.     return (CC_REFRESH);
  1253.     }
  1254.     else {
  1255.     return (CC_ERROR);
  1256.     }
  1257. }
  1258.  
  1259. /*ARGSUSED*/
  1260. CCRETVAL
  1261. e_delwordprev(c)
  1262.     int c;
  1263. {
  1264.     register Char *cp, *p, *kp;
  1265.  
  1266.     if (Cursor == InputBuf)
  1267.     return (CC_ERROR);
  1268.     /* else */
  1269.  
  1270.     cp = c_prev_word(Cursor, InputBuf, Argument);
  1271.  
  1272.     for (p = cp, kp = KillBuf; p < Cursor; p++)    /* save the text */
  1273.     *kp++ = *p;
  1274.     LastKill = kp;
  1275.  
  1276.     c_delbefore(Cursor - cp);    /* delete before dot */
  1277.     Cursor = cp;
  1278.     if (Cursor < InputBuf)
  1279.     Cursor = InputBuf;    /* bounds check */
  1280.     return (CC_REFRESH);
  1281. }
  1282.  
  1283. /*ARGSUSED*/
  1284. CCRETVAL
  1285. e_delnext(c)
  1286.     int c;
  1287. {
  1288.     if (Cursor == LastChar) {    /* if I'm at the end */
  1289.     if (Cursor == InputBuf && !VImode) {    
  1290.         /* if I'm also at the beginning */
  1291.         so_write(STReof, 4);/* then do a EOF */
  1292.         flush();
  1293.         return (CC_EOF);
  1294.     }
  1295.     else {
  1296.         return (CC_ERROR);
  1297.     }
  1298.     }
  1299.     else {
  1300.     c_delafter(Argument);    /* delete after dot */
  1301.     if (Cursor > LastChar)
  1302.         Cursor = LastChar;    /* bounds check */
  1303.     return (CC_REFRESH);
  1304.     }
  1305. }
  1306.  
  1307. /*ARGSUSED*/
  1308. CCRETVAL
  1309. e_list_delnext(c)
  1310.     int c;
  1311. {
  1312.     if (Cursor == LastChar) {    /* if I'm at the end */
  1313.     if (Cursor == InputBuf) {    /* if I'm also at the beginning */
  1314.         so_write(STReof, 4);/* then do a EOF */
  1315.         flush();
  1316.         return (CC_EOF);
  1317.     }
  1318.     else {
  1319.         PastBottom();
  1320.         *LastChar = '\0';    /* just in case */
  1321.         return (CC_LIST_CHOICES);
  1322.     }
  1323.     }
  1324.     else {
  1325.     c_delafter(Argument);    /* delete after dot */
  1326.     if (Cursor > LastChar)
  1327.         Cursor = LastChar;    /* bounds check */
  1328.     return (CC_REFRESH);
  1329.     }
  1330. }
  1331.  
  1332. CCRETVAL
  1333. e_list_eof(c)
  1334.     int c;
  1335. {
  1336.     if (Cursor == LastChar && Cursor == InputBuf) {
  1337.     so_write(STReof, 4);    /* then do a EOF */
  1338.     flush();
  1339.     return (CC_EOF);
  1340.     }
  1341.     else {
  1342.     PastBottom();
  1343.     *LastChar = '\0';    /* just in case */
  1344.     return (CC_LIST_CHOICES);
  1345.     }
  1346. }
  1347.  
  1348. /*ARGSUSED*/
  1349. CCRETVAL
  1350. e_delwordnext(c)
  1351.     int c;
  1352. {
  1353.     register Char *cp, *p, *kp;
  1354.  
  1355.     if (Cursor == LastChar)
  1356.     return (CC_ERROR);
  1357.     /* else */
  1358.  
  1359.     cp = c_next_word(Cursor, LastChar, Argument);
  1360.  
  1361.     for (p = Cursor, kp = KillBuf; p < cp; p++)    /* save the text */
  1362.     *kp++ = *p;
  1363.     LastKill = kp;
  1364.  
  1365.     c_delafter(cp - Cursor);    /* delete after dot */
  1366.     /* Cursor = Cursor; */
  1367.     if (Cursor > LastChar)
  1368.     Cursor = LastChar;    /* bounds check */
  1369.     return (CC_REFRESH);
  1370. }
  1371.  
  1372. /*ARGSUSED*/
  1373. CCRETVAL
  1374. e_toend(c)
  1375.     int c;
  1376. {
  1377.     Cursor = LastChar;
  1378.     RefCursor();        /* move the cursor */
  1379.     return (CC_NORM);
  1380. }
  1381.  
  1382. /*ARGSUSED*/
  1383. CCRETVAL
  1384. e_tobeg(c)
  1385.     int c;
  1386. {
  1387.     Cursor = InputBuf;
  1388.     RefCursor();        /* move the cursor */
  1389.     return (CC_NORM);
  1390. }
  1391.  
  1392. /*ARGSUSED*/
  1393. CCRETVAL
  1394. e_killend(c)
  1395.     int c;
  1396. {
  1397.     register Char *kp, *cp;
  1398.  
  1399.     cp = Cursor;
  1400.     kp = KillBuf;
  1401.     while (cp < LastChar)
  1402.     *kp++ = *cp++;        /* copy it */
  1403.     LastKill = kp;
  1404.     LastChar = Cursor;        /* zap! -- delete to end */
  1405.     return (CC_REFRESH);
  1406. }
  1407.  
  1408.  
  1409. /*ARGSUSED*/
  1410. CCRETVAL
  1411. e_killbeg(c)
  1412.     int c;
  1413. {
  1414.     register Char *kp, *cp;
  1415.  
  1416.     cp = InputBuf;
  1417.     kp = KillBuf;
  1418.     while (cp < Cursor)
  1419.     *kp++ = *cp++;        /* copy it */
  1420.     LastKill = kp;
  1421.     c_delbefore(Cursor - InputBuf);
  1422.     Cursor = InputBuf;        /* zap! */
  1423.     return (CC_REFRESH);
  1424. }
  1425.  
  1426. /*ARGSUSED*/
  1427. CCRETVAL
  1428. e_killall(c)
  1429.     int c;
  1430. {
  1431.     register Char *kp, *cp;
  1432.  
  1433.     cp = InputBuf;
  1434.     kp = KillBuf;
  1435.     while (cp < LastChar)
  1436.     *kp++ = *cp++;        /* copy it */
  1437.     LastKill = kp;
  1438.     LastChar = InputBuf;    /* zap! -- delete all of it */
  1439.     Cursor = InputBuf;
  1440.     return (CC_REFRESH);
  1441. }
  1442.  
  1443. /*ARGSUSED*/
  1444. CCRETVAL
  1445. e_killregion(c)
  1446.     int c;
  1447. {
  1448.     register Char *kp, *cp;
  1449.  
  1450.     if (!Mark)
  1451.     return (CC_ERROR);
  1452.  
  1453.     if (Mark > Cursor) {
  1454.     cp = Cursor;
  1455.     kp = KillBuf;
  1456.     while (cp < Mark)
  1457.         *kp++ = *cp++;    /* copy it */
  1458.     LastKill = kp;
  1459.     c_delafter(cp - Cursor);/* delete it */
  1460.     }
  1461.     else {            /* mark is before cursor */
  1462.     cp = Mark;
  1463.     kp = KillBuf;
  1464.     while (cp < Cursor)
  1465.         *kp++ = *cp++;    /* copy it */
  1466.     LastKill = kp;
  1467.     c_delbefore(cp - Mark);
  1468.     Cursor = Mark;
  1469.     }
  1470.     return (CC_REFRESH);
  1471. }
  1472.  
  1473. /*ARGSUSED*/
  1474. CCRETVAL
  1475. e_copyregion(c)
  1476.     int c;
  1477. {
  1478.     register Char *kp, *cp;
  1479.  
  1480.     if (!Mark)
  1481.     return (CC_ERROR);
  1482.  
  1483.     if (Mark > Cursor) {
  1484.     cp = Cursor;
  1485.     kp = KillBuf;
  1486.     while (cp < Mark)
  1487.         *kp++ = *cp++;    /* copy it */
  1488.     LastKill = kp;
  1489.     }
  1490.     else {            /* mark is before cursor */
  1491.     cp = Mark;
  1492.     kp = KillBuf;
  1493.     while (cp < Cursor)
  1494.         *kp++ = *cp++;    /* copy it */
  1495.     LastKill = kp;
  1496.     }
  1497.     return (CC_NORM);        /* don't even need to Refresh() */
  1498. }
  1499.  
  1500. /*ARGSUSED*/
  1501. CCRETVAL
  1502. e_charswitch(cc)
  1503.     int cc;
  1504. {
  1505.     register Char c;
  1506.  
  1507.     if (Cursor < LastChar) {
  1508.     if (LastChar <= &InputBuf[1]) {
  1509.         return (CC_ERROR);
  1510.     }
  1511.     else {
  1512.         Cursor++;
  1513.     }
  1514.     }
  1515.     if (Cursor > &InputBuf[1]) {/* must have at least two chars entered */
  1516.     c = Cursor[-2];
  1517.     Cursor[-2] = Cursor[-1];
  1518.     Cursor[-1] = c;
  1519.     return (CC_REFRESH);
  1520.     }
  1521.     else {
  1522.     return (CC_ERROR);
  1523.     }
  1524. }
  1525.  
  1526. /*ARGSUSED*/
  1527. CCRETVAL
  1528. e_gcharswitch(cc)
  1529.     int cc;
  1530. {                /* gosmacs style ^T */
  1531.     register Char c;
  1532.  
  1533.     if (Cursor > &InputBuf[1]) {/* must have at least two chars entered */
  1534.     c = Cursor[-2];
  1535.     Cursor[-2] = Cursor[-1];
  1536.     Cursor[-1] = c;
  1537.     return (CC_REFRESH);
  1538.     }
  1539.     else {
  1540.     return (CC_ERROR);
  1541.     }
  1542. }
  1543.  
  1544. /*ARGSUSED*/
  1545. CCRETVAL
  1546. e_charback(c)
  1547.     int c;
  1548. {
  1549.     if (Cursor > InputBuf) {
  1550.     Cursor -= Argument;
  1551.     if (Cursor < InputBuf)
  1552.         Cursor = InputBuf;
  1553.     RefCursor();
  1554.     return (CC_NORM);
  1555.     }
  1556.     else {
  1557.     return (CC_ERROR);
  1558.     }
  1559. }
  1560.  
  1561. /*ARGSUSED*/
  1562. CCRETVAL
  1563. e_wordback(c)
  1564.     int c;
  1565. {
  1566.     if (Cursor == InputBuf)
  1567.     return (CC_ERROR);
  1568.     /* else */
  1569.  
  1570.     Cursor = c_prev_word(Cursor, InputBuf, Argument);    /* does a bounds check */
  1571.  
  1572.     RefCursor();
  1573.     return (CC_NORM);
  1574. }
  1575.  
  1576. /*ARGSUSED*/
  1577. CCRETVAL
  1578. e_charfwd(c)
  1579.     int c;
  1580. {
  1581.     if (Cursor < LastChar) {
  1582.     Cursor += Argument;
  1583.     if (Cursor > LastChar)
  1584.         Cursor = LastChar;
  1585.     RefCursor();
  1586.     return (CC_NORM);
  1587.     }
  1588.     else {
  1589.     return (CC_ERROR);
  1590.     }
  1591. }
  1592.  
  1593. /*ARGSUSED*/
  1594. CCRETVAL
  1595. e_wordfwd(c)
  1596.     int c;
  1597. {
  1598.     if (Cursor == LastChar)
  1599.     return (CC_ERROR);
  1600.     /* else */
  1601.  
  1602.     Cursor = c_next_word(Cursor, LastChar, Argument);
  1603.  
  1604.     RefCursor();
  1605.     return (CC_NORM);
  1606. }
  1607.  
  1608. /*ARGSUSED*/
  1609. CCRETVAL
  1610. v_wordbegnext(c)
  1611.     int c;
  1612. {
  1613.     if (Cursor == LastChar)
  1614.     return (CC_ERROR);
  1615.     /* else */
  1616.  
  1617.     Cursor = c_beg_next_word(Cursor, LastChar, Argument);
  1618.  
  1619.     RefCursor();
  1620.     return (CC_NORM);
  1621. }
  1622.  
  1623. #ifdef COMMENT
  1624. /* by: Brian Allison <uiucdcs!convex!allison@RUTGERS.EDU> */
  1625. static void
  1626. c_get_word(begin, end)
  1627.     Char  **begin;
  1628.     Char  **end;
  1629. {
  1630.     Char   *cp;
  1631.  
  1632.     cp = &Cursor[0];
  1633.     while (Argument--) {
  1634.     while ((cp <= LastChar) && (isword(*cp)))
  1635.         cp++;
  1636.     *end = --cp;
  1637.     while ((cp >= InputBuf) && (isword(*cp)))
  1638.         cp--;
  1639.     *begin = ++cp;
  1640.     }
  1641. }
  1642. #endif                /* COMMENT */
  1643.  
  1644. /*ARGSUSED*/
  1645. CCRETVAL
  1646. e_uppercase(c)
  1647.     int c;
  1648. {
  1649.     Char   *cp, *end;
  1650.  
  1651.     end = c_next_word(Cursor, LastChar, Argument);
  1652.  
  1653.     for (cp = Cursor; cp < end; cp++)    /* PWP: was cp=begin */
  1654.     if (Islower(*cp))
  1655.         *cp = Toupper(*cp);
  1656.  
  1657.     Cursor = end;
  1658.     if (Cursor > LastChar)
  1659.     Cursor = LastChar;
  1660.     return (CC_REFRESH);
  1661. }
  1662.  
  1663.  
  1664. /*ARGSUSED*/
  1665. CCRETVAL
  1666. e_capitolcase(c)
  1667.     int c;
  1668. {
  1669.     Char   *cp, *end;
  1670.  
  1671.     end = c_next_word(Cursor, LastChar, Argument);
  1672.  
  1673.     cp = Cursor;
  1674.     for (; cp < end; cp++) {
  1675.     if (Isalpha(*cp)) {
  1676.         if (Islower(*cp))
  1677.         *cp = Toupper(*cp);
  1678.         cp++;
  1679.         break;
  1680.     }
  1681.     }
  1682.     for (; cp < end; cp++)
  1683.     if (Isupper(*cp))
  1684.         *cp = Tolower(*cp);
  1685.  
  1686.     Cursor = end;
  1687.     if (Cursor > LastChar)
  1688.     Cursor = LastChar;
  1689.     return (CC_REFRESH);
  1690. }
  1691.  
  1692. /*ARGSUSED*/
  1693. CCRETVAL
  1694. e_lowercase(c)
  1695.     int c;
  1696. {
  1697.     Char   *cp, *end;
  1698.  
  1699.     end = c_next_word(Cursor, LastChar, Argument);
  1700.  
  1701.     for (cp = Cursor; cp < end; cp++)
  1702.     if (Isupper(*cp))
  1703.         *cp = Tolower(*cp);
  1704.  
  1705.     Cursor = end;
  1706.     if (Cursor > LastChar)
  1707.     Cursor = LastChar;
  1708.     return (CC_REFRESH);
  1709. }
  1710.  
  1711.  
  1712. /*ARGSUSED*/
  1713. CCRETVAL
  1714. e_set_mark(c)
  1715.     int c;
  1716. {
  1717.     Mark = Cursor;
  1718.     return (CC_NORM);
  1719. }
  1720.  
  1721. /*ARGSUSED*/
  1722. CCRETVAL
  1723. e_exchange_mark(c)
  1724.     int c;
  1725. {
  1726.     register Char *cp;
  1727.  
  1728.     cp = Cursor;
  1729.     Cursor = Mark;
  1730.     Mark = cp;
  1731.     RefCursor();
  1732.     return (CC_NORM);
  1733. }
  1734.  
  1735. /*ARGSUSED*/
  1736. CCRETVAL
  1737. e_argfour(c)
  1738.     int c;
  1739. {                /* multiply current argument by 4 */
  1740.     if (Argument > 1000000)
  1741.     return CC_ERROR;
  1742.     DoingArg = 1;
  1743.     Argument *= 4;
  1744.     return (CC_ARGHACK);
  1745. }
  1746.  
  1747. /*ARGSUSED*/
  1748. CCRETVAL
  1749. e_quote(c)
  1750.     int c;
  1751. {
  1752.     Char    ch;
  1753.     int     num;
  1754.  
  1755.     QuoteModeOn();
  1756.     num = GetNextChar(&ch);
  1757.     QuoteModeOff();
  1758.     if (num == 1)
  1759.     return e_insert(ch);
  1760.     else
  1761.     return e_send_eof(0);
  1762. }
  1763.  
  1764. /*ARGSUSED*/
  1765. CCRETVAL
  1766. e_metanext(c)
  1767.     int c;
  1768. {
  1769.     MetaNext = 1;
  1770.     return (CC_ARGHACK);    /* preserve argument */
  1771. }
  1772.  
  1773. #ifdef notdef
  1774. /*ARGSUSED*/
  1775. CCRETVAL
  1776. e_extendnext(c)
  1777.     int c;
  1778. {
  1779.     CurrentKeyMap = CcAltMap;
  1780.     return (CC_ARGHACK);    /* preserve argument */
  1781. }
  1782.  
  1783. #endif
  1784.  
  1785. /*ARGSUSED*/
  1786. CCRETVAL
  1787. v_insbeg(c)
  1788.     int c;
  1789. {                /* move to beginning of line and start vi
  1790.                  * insert mode */
  1791.     Cursor = InputBuf;
  1792.     RefCursor();        /* move the cursor */
  1793.     c_alternativ_key_map(0);
  1794.     return (CC_NORM);
  1795. }
  1796.  
  1797. /*ARGSUSED*/
  1798. CCRETVAL
  1799. v_replone(c)
  1800.     int c;
  1801. {                /* vi mode overwrite one character */
  1802.     c_alternativ_key_map(0);
  1803.     replacemode = 2;
  1804.     return (CC_NORM);
  1805. }
  1806.  
  1807. /*ARGSUSED*/
  1808. CCRETVAL
  1809. v_replmode(c)
  1810.     int c;
  1811. {                /* vi mode start overwriting */
  1812.     c_alternativ_key_map(0);
  1813.     replacemode = 1;
  1814.     return (CC_NORM);
  1815. }
  1816.  
  1817. /*ARGSUSED*/
  1818. CCRETVAL
  1819. v_substchar(c)
  1820.     int c;
  1821. {                /* vi mode substitute for one char */
  1822.     c_delafter(Argument);
  1823.     c_alternativ_key_map(0);
  1824.     return (CC_REFRESH);
  1825. }
  1826.  
  1827. /*ARGSUSED*/
  1828. CCRETVAL
  1829. v_substline(c)
  1830.     int c;
  1831. {                /* vi mode replace whole line */
  1832.     (void) e_killall(0);
  1833.     c_alternativ_key_map(0);
  1834.     return (CC_NORM);
  1835. }
  1836.  
  1837. /*ARGSUSED*/
  1838. CCRETVAL
  1839. v_chgtoend(c)
  1840.     int c;
  1841. {                /* vi mode change to end of line */
  1842.     (void) e_killend(0);
  1843.     c_alternativ_key_map(0);
  1844.     return (CC_REFRESH);
  1845. }
  1846.  
  1847. /*ARGSUSED*/
  1848. CCRETVAL
  1849. v_insert(c)
  1850.     int c;
  1851. {                /* vi mode start inserting */
  1852.     c_alternativ_key_map(0);
  1853.     return (CC_NORM);
  1854. }
  1855.  
  1856. /*ARGSUSED*/
  1857. CCRETVAL
  1858. v_add(c)
  1859.     int c;
  1860. {                /* vi mode start adding */
  1861.     c_alternativ_key_map(0);
  1862.     if (Cursor < LastChar) {
  1863.     Cursor++;
  1864.     if (Cursor > LastChar)
  1865.         Cursor = LastChar;
  1866.     RefCursor();
  1867.     }
  1868.     return (CC_NORM);
  1869. }
  1870.  
  1871. /*ARGSUSED*/
  1872. CCRETVAL
  1873. v_addend(c)
  1874.     int c;
  1875. {                /* vi mode to add at end of line */
  1876.     c_alternativ_key_map(0);
  1877.     Cursor = LastChar;
  1878.     RefCursor();
  1879.     return (CC_NORM);
  1880. }
  1881.  
  1882. /*ARGSUSED*/
  1883. CCRETVAL
  1884. v_change_case(cc)
  1885.     int cc;
  1886. {
  1887.     char    c;
  1888.  
  1889.     if (Cursor < LastChar) {
  1890.     c = *Cursor;
  1891.     if (Isupper(c))
  1892.         *Cursor++ = Tolower(c);
  1893.     else if (Islower(c))
  1894.         *Cursor++ = Toupper(c);
  1895.     else
  1896.         Cursor++;
  1897.     RefPlusOne();        /* fast refresh for one char */
  1898.     return (CC_NORM);
  1899.     }
  1900.     return (CC_ERROR);
  1901. }
  1902.  
  1903. /*ARGSUSED*/
  1904. CCRETVAL
  1905. e_expand(c)
  1906.     int c;
  1907. {
  1908.     register Char *p;
  1909.     extern bool justpr;
  1910.  
  1911.     for (p = InputBuf; Isspace(*p); p++);
  1912.     if (p == LastChar)
  1913.     return (CC_ERROR);
  1914.  
  1915.     justpr++;
  1916.     Expand++;
  1917.     return (e_newline(0));
  1918. }
  1919.  
  1920. /*ARGSUSED*/
  1921. CCRETVAL
  1922. e_startover(c)
  1923.     int c;
  1924. {                /* erase all of current line, start again */
  1925.     ResetInLine();        /* reset the input pointers */
  1926.     return (CC_REFRESH);
  1927. }
  1928.  
  1929. /*ARGSUSED*/
  1930. CCRETVAL
  1931. e_redisp(c)
  1932.     int c;
  1933. {
  1934.     ClearLines();
  1935.     ClearDisp();
  1936.     return (CC_REFRESH);
  1937. }
  1938.  
  1939. /*ARGSUSED*/
  1940. CCRETVAL
  1941. e_cleardisp(c)
  1942.     int c;
  1943. {
  1944.     ClearScreen();        /* clear the whole real screen */
  1945.     ClearDisp();        /* reset everything */
  1946.     return (CC_REFRESH);
  1947. }
  1948.  
  1949. /*ARGSUSED*/
  1950. CCRETVAL
  1951. e_tty_int(c)
  1952.     int c;
  1953. {
  1954.     /* do no editing */
  1955.     return (CC_NORM);
  1956. }
  1957.  
  1958. /*ARGSUSED*/
  1959. CCRETVAL
  1960. e_insovr(c)
  1961.     int c;
  1962. {
  1963.     replacemode = !replacemode;
  1964.     return (CC_NORM);
  1965. }
  1966.  
  1967. /*ARGSUSED*/
  1968. CCRETVAL
  1969. e_tty_dsusp(c)
  1970.     int c;
  1971. {
  1972.     /* do no editing */
  1973.     return (CC_NORM);
  1974. }
  1975.  
  1976. /*ARGSUSED*/
  1977. CCRETVAL
  1978. e_tty_flusho(c)
  1979.     int c;
  1980. {
  1981.     /* do no editing */
  1982.     return (CC_NORM);
  1983. }
  1984.  
  1985. /*ARGSUSED*/
  1986. CCRETVAL
  1987. e_tty_quit(c)
  1988.     int c;
  1989. {
  1990.     /* do no editing */
  1991.     return (CC_NORM);
  1992. }
  1993.  
  1994. /*ARGSUSED*/
  1995. CCRETVAL
  1996. e_tty_tsusp(c)
  1997.     int c;
  1998. {
  1999.     /* do no editing */
  2000.     return (CC_NORM);
  2001. }
  2002.  
  2003. /*ARGSUSED*/
  2004. CCRETVAL
  2005. e_tty_stopo(c)
  2006.     int c;
  2007. {
  2008.     /* do no editing */
  2009.     return (CC_NORM);
  2010. }
  2011.  
  2012. /*ARGSUSED*/
  2013. CCRETVAL
  2014. e_expand_history(c)
  2015.     int c;
  2016. {
  2017.     *LastChar = '\0';        /* just in case */
  2018.     c_substitute();
  2019.     return (CC_NORM);
  2020. }
  2021.  
  2022. /*ARGSUSED*/
  2023. CCRETVAL
  2024. e_magic_space(c)
  2025.     int c;
  2026. {
  2027.     *LastChar = '\0';        /* just in case */
  2028.     c_substitute();
  2029.     return (e_insert(' '));
  2030. }
  2031.  
  2032. /*ARGSUSED*/
  2033. CCRETVAL
  2034. e_copyprev(c)
  2035.     int c;
  2036. {
  2037.     register Char *cp, *oldc, *dp;
  2038.  
  2039.     if (Cursor == InputBuf)
  2040.     return (CC_ERROR);
  2041.     /* else */
  2042.  
  2043.     oldc = Cursor;
  2044.     /* does a bounds check */
  2045.     cp = c_prev_word(Cursor, InputBuf, Argument);    
  2046.  
  2047.     c_insert(oldc - cp);
  2048.     for (dp = oldc; cp < oldc && dp < LastChar; cp++)
  2049.     *dp++ = *cp;
  2050.  
  2051.     Cursor = dp;        /* put cursor at end */
  2052.  
  2053.     return (CC_REFRESH);
  2054. }
  2055.  
  2056. /*ARGSUSED*/
  2057. CCRETVAL
  2058. e_tty_starto(c)
  2059.     int c;
  2060. {
  2061.     /* do no editing */
  2062.     return (CC_NORM);
  2063. }
  2064.  
  2065. /*ARGSUSED*/
  2066. CCRETVAL
  2067. e_load_average(c)
  2068.     int c;
  2069. {
  2070.     PastBottom();
  2071. #ifdef TIOCSTAT
  2072.     if (ioctl(SHIN, TIOCSTAT, 0) < 0) 
  2073.     xprintf("Load average unavailable");
  2074. #endif
  2075.     return (CC_REFRESH);
  2076. }
  2077.  
  2078. #ifdef notdef
  2079. void
  2080. MoveCursor(n)            /* move cursor + right - left char */
  2081.     int     n;
  2082. {
  2083.     Cursor = Cursor + n;
  2084.     if (Cursor < InputBuf)
  2085.     Cursor = InputBuf;
  2086.     if (Cursor > LastChar)
  2087.     Cursor = LastChar;
  2088.     return;
  2089. }
  2090.  
  2091. Char   *
  2092. GetCursor()
  2093. {
  2094.     return (Cursor);
  2095. }
  2096.  
  2097. int
  2098. PutCursor(p)
  2099.     Char   *p;
  2100. {
  2101.     if (p < InputBuf || p > LastChar)
  2102.     return 1;        /* Error */
  2103.     Cursor = p;
  2104.     return 0;
  2105. }
  2106. #endif
  2107.