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