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

Defined functions

DeleteBack defined in line 593; used 4 times
GetCursor defined in line 2005; never used
InsertStr defined in line 576; used 7 times
MoveCursor defined in line 1993; never used
PutCursor defined in line 2011; never used
c_alternativ_key_map defined in line 67; used 10 times
c_beg_next_word defined in line 167; used 1 times
c_copy defined in line 195; used 2 times
c_delafter defined in line 94; used 9 times
c_delbefore defined in line 112; used 5 times
c_excl defined in line 446; used 1 times
c_expand defined in line 256; used 1 times
c_get_word defined in line 1586; never used
c_hmatch defined in line 885; used 3 times
c_hsetpat defined in line 897; used 2 times
c_insert defined in line 78; used 6 times
c_next_word defined in line 150; used 5 times
c_number defined in line 224; used 2 times
c_prev_word defined in line 128; used 3 times
c_substitute defined in line 487; used 2 times
e_argdigit defined in line 638; never used
e_argfour defined in line 1692; never used
e_capitolcase defined in line 1625; never used
e_charback defined in line 1511; never used
e_charfwd defined in line 1541; never used
e_charswitch defined in line 1469; never used
e_cleardisp defined in line 1879; never used
e_complete defined in line 700; never used
e_copyprev defined in line 1962; never used
e_copyregion defined in line 1443; never used
e_corr defined in line 1063; never used
e_corrl defined in line 1071; never used
e_d_hist defined in line 822; never used
e_d_search_hist defined in line 983; never used
e_delnext defined in line 1263; never used
e_delprev defined in line 1224; never used
e_digit defined in line 608; never used
e_dwrdnext defined in line 1325; never used
e_dwrdprev defined in line 1240; never used
e_ex_glob defined in line 1127; never used
e_ex_history defined in line 1944; used 2 times
e_ex_vars defined in line 1135; never used
e_exchange_mark defined in line 1679; never used
e_expand defined in line 1846; never used
e_extendnext defined in line 1728; never used
e_gcharswitch defined in line 1494; never used
e_helpme defined in line 1054; never used
e_insert defined in line 535; used 2 times
e_insovr defined in line 1896; never used
e_killall defined in line 1398; used 1 times
e_killbeg defined in line 1382; never used
e_killend defined in line 1366; used 1 times
e_killregion defined in line 1414; never used
e_l_choices defined in line 1109; never used
e_l_delnext defined in line 1286; never used
e_l_eof defined in line 1309; never used
e_l_glob defined in line 1118; never used
e_last_item defined in line 1152; never used
e_lowercase defined in line 1652; never used
e_magic_space defined in line 1953; never used
e_metanext defined in line 1719; never used
e_newline defined in line 678; used 1 times
e_quote defined in line 1703; never used
e_redisp defined in line 1870; never used
e_run_fg_editor defined in line 1079; never used
e_send_eof defined in line 688; used 1 times
e_set_mark defined in line 1671; never used
e_startover defined in line 1862; never used
e_t_dsusp defined in line 1904; never used
e_t_flusho defined in line 1912; never used
e_t_int defined in line 1888; never used
e_t_quit defined in line 1920; never used
e_t_starto defined in line 1985; never used
e_t_stopo defined in line 1936; never used
e_t_tsusp defined in line 1928; never used
e_tobeg defined in line 1357; never used
e_toend defined in line 1348; never used
e_toggle_hist defined in line 718; never used
e_unassigned defined in line 526; used 4 times
e_up_hist defined in line 766; used 2 times
e_up_search_hist defined in line 914; never used
e_uppercase defined in line 1606; never used
e_which defined in line 1143; never used
e_wordback defined in line 1527; never used
e_wordfwd defined in line 1557; never used
e_yank_kill defined in line 1198; never used
rcsid defined in line 39; never used
v_add defined in line 1802; never used
v_addend defined in line 1816; never used
v_change_case defined in line 1826; never used
v_chgtoend defined in line 1785; never used
v_cm_complete defined in line 708; never used
v_cmd_mode defined in line 514; used 2 times
v_insbeg defined in line 1738; never used
v_insert defined in line 1794; never used
v_replmode defined in line 1758; never used
v_replone defined in line 1749; never used
v_s_char defined in line 1767; never used
v_s_line defined in line 1776; never used
v_wordbegnext defined in line 1571; never used
v_zero defined in line 660; never used

Defined variables

CCRETVAL defined in line 1571; never used
patbuf defined in line 880; used 5 times
patlen defined in line 881; used 7 times
Last modified: 1991-08-21
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 11114
Valid CSS Valid XHTML 1.0 Strict