1 /* $Header: /src/pub/tcsh/ed.chared.c,v 3.59 1999/08/13 16:34:57 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 /* 38 Bjorn Knutsson @ Thu Jun 24 19:02:17 1999 39 40 e_dabbrev_expand() did not do proper completion if quoted spaces were present 41 in the string being completed. Exemple: 42 43 # echo hello\ world 44 hello world 45 # echo h<press key bound to dabbrev-expande> 46 # echo hello\<cursor> 47 48 Correct behavior is: 49 # echo h<press key bound to dabbrev-expande> 50 # echo hello\ world<cursor> 51 52 The same problem occured if spaces were present in a string withing quotation 53 marks. Example: 54 55 # echo "hello world" 56 hello world 57 # echo "h<press key bound to dabbrev-expande> 58 # echo "hello<cursor> 59 60 The former problem could be solved with minor modifications of c_preword() 61 and c_endword(). The latter, however, required a significant rewrite of 62 c_preword(), since quoted strings must be parsed from start to end to 63 determine if a given character is inside or outside the quotation marks. 64 65 Compare the following two strings: 66 67 # echo \"" 'foo \' bar\" 68 " 'foo \' bar\ 69 # echo '\"" 'foo \' bar\" 70 \"" foo ' bar" 71 72 The only difference between the two echo lines is in the first character 73 after the echo command. The result is either one or three arguments. 74 75 */ 76 77 #include "sh.h" 78 79 RCSID("$Id: ed.chared.c,v 3.59 1999/08/13 16:34:57 christos Exp $") 80 81 #include "ed.h" 82 #include "tw.h" 83 #include "ed.defns.h" 84 85 /* #define SDEBUG */ 86 87 #define TCSHOP_NOP 0x00 88 #define TCSHOP_DELETE 0x01 89 #define TCSHOP_INSERT 0x02 90 #define TCSHOP_CHANGE 0x04 91 92 #define CHAR_FWD 0 93 #define CHAR_BACK 1 94 95 /* 96 * vi word treatment 97 * from: Gert-Jan Vons <vons@cesar.crbca1.sinet.slb.com> 98 */ 99 #define C_CLASS_WHITE 1 100 #define C_CLASS_ALNUM 2 101 #define C_CLASS_OTHER 3 102 103 static Char *InsertPos = InputBuf; /* Where insertion starts */ 104 static Char *ActionPos = 0; /* Where action begins */ 105 static int ActionFlag = TCSHOP_NOP; /* What delayed action to take */ 106 /* 107 * Word search state 108 */ 109 static int searchdir = F_UP_SEARCH_HIST; /* Direction of last search */ 110 static Char patbuf[INBUFSIZE]; /* Search target */ 111 static int patlen = 0; 112 /* 113 * Char search state 114 */ 115 static int srch_dir = CHAR_FWD; /* Direction of last search */ 116 static Char srch_char = 0; /* Search target */ 117 118 /* all routines that start with c_ are private to this set of routines */ 119 static void c_alternativ_key_map __P((int)); 120 static void c_insert __P((int)); 121 static void c_delafter __P((int)); 122 static void c_delbefore __P((int)); 123 static int c_to_class __P((int)); 124 static Char *c_prev_word __P((Char *, Char *, int)); 125 static Char *c_next_word __P((Char *, Char *, int)); 126 static Char *c_number __P((Char *, int *, int)); 127 static Char *c_expand __P((Char *)); 128 static void c_excl __P((Char *)); 129 static void c_substitute __P((void)); 130 static void c_delfini __P((void)); 131 static int c_hmatch __P((Char *)); 132 static void c_hsetpat __P((void)); 133 #ifdef COMMENT 134 static void c_get_word __P((Char **, Char **)); 135 #endif 136 static Char *c_preword __P((Char *, Char *, int)); 137 static Char *c_nexword __P((Char *, Char *, int)); 138 static Char *c_endword __P((Char *, Char *, int)); 139 static Char *c_eword __P((Char *, Char *, int)); 140 static CCRETVAL c_get_histline __P((void)); 141 static CCRETVAL c_search_line __P((Char *, int)); 142 static CCRETVAL v_repeat_srch __P((int)); 143 static CCRETVAL e_inc_search __P((int)); 144 static CCRETVAL v_search __P((int)); 145 static CCRETVAL v_csearch_fwd __P((int, int, int)); 146 static CCRETVAL v_action __P((int)); 147 static CCRETVAL v_csearch_back __P((int, int, int)); 148 149 #if defined(DSPMBYTE) 150 static void e_charfwd_mbyte __P((int)); 151 static void e_charback_mbyte __P((int)); 152 static int extdel; 153 static int extins = 0; 154 #endif 155 156 static void 157 c_alternativ_key_map(state) 158 int state; 159 { 160 switch (state) { 161 case 0: 162 CurrentKeyMap = CcKeyMap; 163 break; 164 case 1: 165 CurrentKeyMap = CcAltMap; 166 break; 167 default: 168 return; 169 } 170 171 AltKeyMap = (Char) state; 172 } 173 174 static void 175 c_insert(num) 176 register int num; 177 { 178 register Char *cp; 179 180 if (LastChar + num >= InputLim) 181 return; /* can't go past end of buffer */ 182 183 if (Cursor < LastChar) { /* if I must move chars */ 184 for (cp = LastChar; cp >= Cursor; cp--) 185 cp[num] = *cp; 186 } 187 LastChar += num; 188 } 189 190 static void 191 c_delafter(num) 192 register int num; 193 { 194 register Char *cp, *kp = NULL; 195 196 #if defined(DSPMBYTE) 197 Char *wkcp; 198 199 extdel = 0; 200 #endif 201 202 if (num > LastChar - Cursor) 203 num = (int) (LastChar - Cursor); /* bounds check */ 204 205 if (num > 0) { /* if I can delete anything */ 206 #if defined(DSPMBYTE) 207 /* check for code of deleted character */ 208 if (_enable_mbdisp) { 209 for (wkcp = Cursor ; wkcp < Cursor + num; wkcp++) { 210 if (extdel == 0) 211 extdel = Ismbyte1(*wkcp); /* check to 1st. byte */ 212 else 213 extdel = 0; /* if 2nd. byte, force set to 0 */ 214 } 215 } 216 #endif 217 if (VImode) { 218 kp = UndoBuf; /* Set Up for VI undo command */ 219 UndoAction = TCSHOP_INSERT; 220 UndoSize = num; 221 UndoPtr = Cursor; 222 for (cp = Cursor; cp <= LastChar; cp++) { 223 *kp++ = *cp; /* Save deleted chars into undobuf */ 224 *cp = cp[num]; 225 } 226 } 227 else 228 for (cp = Cursor; cp <= LastChar; cp++) 229 *cp = cp[num]; 230 LastChar -= num; 231 #if defined(DSPMBYTE) 232 if (_enable_mbdisp && extdel && Ismbyte2(*Cursor)) { 233 if( VImode ) { 234 UndoSize++; 235 *kp++ = *Cursor; /* Save deleted chars into undobuf */ 236 } 237 for (cp = Cursor; cp <= LastChar; cp++) 238 *cp = cp[1]; 239 LastChar--; 240 e_redisp( 1 ); 241 } 242 else 243 extdel = 0; 244 #endif 245 } 246 #ifdef notdef 247 else { 248 /* 249 * XXX: We don't want to do that. In emacs mode overwrite should be 250 * sticky. I am not sure how that affects vi mode 251 */ 252 inputmode = MODE_INSERT; 253 } 254 #endif /* notdef */ 255 } 256 257 static void 258 c_delbefore(num) /* delete before dot, with bounds checking */ 259 register int num; 260 { 261 register Char *cp, *kp = NULL; 262 263 #if defined(DSPMBYTE) 264 Char *nowcur, *wkcp; 265 Char delc; 266 267 extdel = 0; 268 #endif 269 270 if (num > Cursor - InputBuf) 271 num = (int) (Cursor - InputBuf); /* bounds check */ 272 273 if (num > 0) { /* if I can delete anything */ 274 #if defined(DSPMBYTE) 275 nowcur = Cursor - num; 276 delc = *nowcur; 277 #endif 278 if (VImode) { 279 kp = UndoBuf; /* Set Up for VI undo command */ 280 UndoAction = TCSHOP_INSERT; 281 UndoSize = num; 282 UndoPtr = Cursor - num; 283 for (cp = Cursor - num; cp <= LastChar; cp++) { 284 *kp++ = *cp; 285 *cp = cp[num]; 286 } 287 } 288 else 289 for (cp = Cursor - num; cp <= LastChar; cp++) 290 *cp = cp[num]; 291 LastChar -= num; 292 #if defined(DSPMBYTE) 293 if (_enable_mbdisp) { 294 for (wkcp = InputBuf; wkcp < nowcur; wkcp++) { 295 if(extdel == 0) 296 extdel = Ismbyte1(*wkcp); /* check to 1st. byte */ 297 else 298 extdel = 0; /* if 2nd. byte, force set to 0 */ 299 } 300 if (extdel && Ismbyte2(delc)) { 301 if( VImode ) { 302 UndoSize++; 303 UndoPtr--; 304 *kp++ = *(nowcur-1); 305 /* Save deleted chars into undobuf */ 306 } 307 for (cp = nowcur - 1; cp <= LastChar; cp++) 308 *cp = cp[1]; 309 LastChar--; 310 } 311 } 312 else 313 extdel = 0; 314 #endif 315 } 316 } 317 318 static Char * 319 c_preword(p, low, n) 320 register Char *p, *low; 321 register int n; 322 { 323 while (n--) { 324 register Char *prev = low; 325 register Char *new; 326 327 while (prev < p) { /* Skip initial spaces */ 328 if (!Isspace(*prev) || (Isspace(*prev) && *(prev-1) == (Char)'\\')) 329 break; 330 prev++; 331 } 332 333 new = prev; 334 335 while (new < p) { 336 prev = new; 337 new = c_endword(prev-1, p, 1); /* Skip to next space */ 338 new++; /* Step away from end of word */ 339 while (new <= p) { /* Skip trailing spaces */ 340 if (!Isspace(*new) || (Isspace(*new) && *(new-1) == (Char)'\\')) 341 break; 342 new++; 343 } 344 } 345 346 p = prev; /* Set to previous word start */ 347 348 } 349 if (p < low) 350 p = low; 351 return (p); 352 } 353 354 /* 355 * c_to_class() returns the class of the given character. 356 * 357 * This is used to make the c_prev_word() and c_next_word() functions 358 * work like vi's, which classify characters. A word is a sequence of 359 * characters belonging to the same class, classes being defined as 360 * follows: 361 * 362 * 1/ whitespace 363 * 2/ alphanumeric chars, + underscore 364 * 3/ others 365 */ 366 static int 367 c_to_class(ch) 368 register int ch; 369 { 370 if (Isspace(ch)) 371 return C_CLASS_WHITE; 372 373 if (Isdigit(ch) || Isalpha(ch) || ch == '_') 374 return C_CLASS_ALNUM; 375 376 return C_CLASS_OTHER; 377 } 378 379 static Char * 380 c_prev_word(p, low, n) 381 register Char *p, *low; 382 register int n; 383 { 384 p--; 385 386 if (!VImode) { 387 while (n--) { 388 while ((p >= low) && !isword(*p)) 389 p--; 390 while ((p >= low) && isword(*p)) 391 p--; 392 } 393 394 /* cp now points to one character before the word */ 395 p++; 396 if (p < low) 397 p = low; 398 /* cp now points where we want it */ 399 return(p); 400 } 401 402 while (n--) { 403 register int c_class; 404 405 if (p < low) 406 break; 407 408 /* scan until beginning of current word (may be all whitespace!) */ 409 c_class = c_to_class(*p); 410 while ((p >= low) && c_class == c_to_class(*p)) 411 p--; 412 413 /* if this was a non_whitespace word, we're ready */ 414 if (c_class != C_CLASS_WHITE) 415 continue; 416 417 /* otherwise, move back to beginning of the word just found */ 418 c_class = c_to_class(*p); 419 while ((p >= low) && c_class == c_to_class(*p)) 420 p--; 421 } 422 423 p++; /* correct overshoot */ 424 425 return (p); 426 } 427 428 static Char * 429 c_next_word(p, high, n) 430 register Char *p, *high; 431 register int n; 432 { 433 if (!VImode) { 434 while (n--) { 435 while ((p < high) && !isword(*p)) 436 p++; 437 while ((p < high) && isword(*p)) 438 p++; 439 } 440 if (p > high) 441 p = high; 442 /* p now points where we want it */ 443 return(p); 444 } 445 446 while (n--) { 447 register int c_class; 448 449 if (p >= high) 450 break; 451 452 /* scan until end of current word (may be all whitespace!) */ 453 c_class = c_to_class(*p); 454 while ((p < high) && c_class == c_to_class(*p)) 455 p++; 456 457 /* if this was all whitespace, we're ready */ 458 if (c_class == C_CLASS_WHITE) 459 continue; 460 461 /* if we've found white-space at the end of the word, skip it */ 462 while ((p < high) && c_to_class(*p) == C_CLASS_WHITE) 463 p++; 464 } 465 466 p--; /* correct overshoot */ 467 468 return (p); 469 } 470 471 static Char * 472 c_nexword(p, high, n) 473 register Char *p, *high; 474 register int n; 475 { 476 while (n--) { 477 while ((p < high) && !Isspace(*p)) 478 p++; 479 while ((p < high) && Isspace(*p)) 480 p++; 481 } 482 483 if (p > high) 484 p = high; 485 /* p now points where we want it */ 486 return(p); 487 } 488 489 /* 490 * Expand-History (originally "Magic-Space") code added by 491 * Ray Moody <ray@gibbs.physics.purdue.edu> 492 * this is a neat, but odd, addition. 493 */ 494 495 /* 496 * c_number: Ignore character p points to, return number appearing after that. 497 * A '$' by itself means a big number; "$-" is for negative; '^' means 1. 498 * Return p pointing to last char used. 499 */ 500 501 /* 502 * dval is the number to subtract from for things like $-3 503 */ 504 505 static Char * 506 c_number(p, num, dval) 507 register Char *p; 508 register int *num; 509 register int dval; 510 { 511 register int i; 512 register int sign = 1; 513 514 if (*++p == '^') { 515 *num = 1; 516 return(p); 517 } 518 if (*p == '$') { 519 if (*++p != '-') { 520 *num = NCARGS; /* Handle $ */ 521 return(--p); 522 } 523 sign = -1; /* Handle $- */ 524 ++p; 525 } 526 for (i = 0; *p >= '0' && *p <= '9'; i = 10 * i + *p++ - '0') 527 continue; 528 *num = (sign < 0 ? dval - i : i); 529 return(--p); 530 } 531 532 /* 533 * excl_expand: There is an excl to be expanded to p -- do the right thing 534 * with it and return a version of p advanced over the expanded stuff. Also, 535 * update tsh_cur and related things as appropriate... 536 */ 537 538 static Char * 539 c_expand(p) 540 register Char *p; 541 { 542 register Char *q; 543 register struct Hist *h = Histlist.Hnext; 544 register struct wordent *l; 545 int i, from, to, dval; 546 bool all_dig; 547 bool been_once = 0; 548 Char *op = p; 549 Char buf[INBUFSIZE]; 550 Char *bend = buf; 551 Char *modbuf, *omodbuf; 552 553 if (!h) 554 goto excl_err; 555 excl_sw: 556 switch (*(q = p + 1)) { 557 558 case '^': 559 bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 1, 1); 560 break; 561 562 case '$': 563 if ((l = (h->Hlex).prev) != 0) 564 bend = expand_lex(buf, INBUFSIZE, l->prev->prev, 0, 0); 565 break; 566 567 case '*': 568 bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 1, NCARGS); 569 break; 570 571 default: 572 if (been_once) { /* unknown argument */ 573 /* assume it's a modifier, e.g. !foo:h, and get whole cmd */ 574 bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 0, NCARGS); 575 q -= 2; 576 break; 577 } 578 been_once = 1; 579 580 if (*q == ':') /* short form: !:arg */ 581 --q; 582 583 if (*q != HIST) { 584 /* 585 * Search for a space, tab, or colon. See if we have a number (as 586 * in !1234:xyz). Remember the number. 587 */ 588 for (i = 0, all_dig = 1; 589 *q != ' ' && *q != '\t' && *q != ':' && q < Cursor; q++) { 590 /* 591 * PWP: !-4 is a valid history argument too, therefore the test 592 * is if not a digit, or not a - as the first character. 593 */ 594 if ((*q < '0' || *q > '9') && (*q != '-' || q != p + 1)) 595 all_dig = 0; 596 else if (*q == '-') 597 all_dig = 2;/* we are sneeky about this */ 598 else 599 i = 10 * i + *q - '0'; 600 } 601 --q; 602 603 /* 604 * If we have a number, search for event i. Otherwise, search for 605 * a named event (as in !foo). (In this case, I is the length of 606 * the named event). 607 */ 608 if (all_dig) { 609 if (all_dig == 2) 610 i = -i; /* make it negitive */ 611 if (i < 0) /* if !-4 (for example) */ 612 i = eventno + 1 + i; /* remember: i is < 0 */ 613 for (; h; h = h->Hnext) { 614 if (h->Hnum == i) 615 break; 616 } 617 } 618 else { 619 for (i = (int) (q - p); h; h = h->Hnext) { 620 if ((l = &h->Hlex) != 0) { 621 if (!Strncmp(p + 1, l->next->word, (size_t) i)) 622 break; 623 } 624 } 625 } 626 } 627 if (!h) 628 goto excl_err; 629 if (q[1] == ':' || q[1] == '-' || q[1] == '*' || 630 q[1] == '$' || q[1] == '^') { /* get some args */ 631 p = q[1] == ':' ? ++q : q; 632 /* 633 * Go handle !foo:* 634 */ 635 if ((q[1] < '0' || q[1] > '9') && 636 q[1] != '-' && q[1] != '$' && q[1] != '^') 637 goto excl_sw; 638 /* 639 * Go handle !foo:$ 640 */ 641 if (q[1] == '$' && (q[2] != '-' || q[3] < '0' || q[3] > '9')) 642 goto excl_sw; 643 /* 644 * Count up the number of words in this event. Store it in dval. 645 * Dval will be fed to number. 646 */ 647 dval = 0; 648 if ((l = h->Hlex.prev) != 0) { 649 for (l = l->prev; l != h->Hlex.next; l = l->prev, dval++) 650 continue; 651 } 652 if (!dval) 653 goto excl_err; 654 if (q[1] == '-') 655 from = 0; 656 else 657 q = c_number(q, &from, dval); 658 if (q[1] == '-') { 659 ++q; 660 if ((q[1] < '0' || q[1] > '9') && q[1] != '$') 661 to = dval - 1; 662 else 663 q = c_number(q, &to, dval); 664 } 665 else if (q[1] == '*') { 666 ++q; 667 to = NCARGS; 668 } 669 else { 670 to = from; 671 } 672 if (from < 0 || to < from) 673 goto excl_err; 674 bend = expand_lex(buf, INBUFSIZE, &h->Hlex, from, to); 675 } 676 else { /* get whole cmd */ 677 bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 0, NCARGS); 678 } 679 break; 680 } 681 682 /* 683 * Apply modifiers, if any. 684 */ 685 if (q[1] == ':') { 686 *bend = '\0'; 687 modbuf = omodbuf = buf; 688 while (q[1] == ':' && modbuf != NULL) { 689 switch (q[2]) { 690 case 'r': 691 case 'e': 692 case 'h': 693 case 't': 694 case 'q': 695 case 'x': 696 case 'u': 697 case 'l': 698 if ((modbuf = domod(omodbuf, (int) q[2])) != NULL) { 699 if (omodbuf != buf) 700 xfree((ptr_t) omodbuf); 701 omodbuf = modbuf; 702 } 703 ++q; 704 break; 705 706 case 'a': 707 case 'g': 708 /* Not implemented; this needs to be done before expanding 709 * lex. We don't have the words available to us anymore. 710 */ 711 ++q; 712 break; 713 714 case 'p': 715 /* Ok */ 716 ++q; 717 break; 718 719 case '\0': 720 break; 721 722 default: 723 ++q; 724 break; 725 } 726 if (q[1]) 727 ++q; 728 } 729 if (omodbuf != buf) { 730 (void) Strcpy(buf, omodbuf); 731 xfree((ptr_t) omodbuf); 732 bend = Strend(buf); 733 } 734 } 735 736 /* 737 * Now replace the text from op to q inclusive with the text from buf to 738 * bend. 739 */ 740 q++; 741 742 /* 743 * Now replace text non-inclusively like a real CS major! 744 */ 745 if (LastChar + (bend - buf) - (q - op) >= InputLim) 746 goto excl_err; 747 (void) memmove((ptr_t) (q + (bend - buf) - (q - op)), (ptr_t) q, 748 (size_t) ((LastChar - q) * sizeof(Char))); 749 LastChar += (bend - buf) - (q - op); 750 Cursor += (bend - buf) - (q - op); 751 (void) memmove((ptr_t) op, (ptr_t) buf, 752 (size_t) ((bend - buf) * sizeof(Char))); 753 *LastChar = '\0'; 754 return(op + (bend - buf)); 755 excl_err: 756 SoundBeep(); 757 return(op + 1); 758 } 759 760 /* 761 * c_excl: An excl has been found at point p -- back up and find some white 762 * space (or the beginning of the buffer) and properly expand all the excl's 763 * from there up to the current cursor position. We also avoid (trying to) 764 * expanding '>!' 765 */ 766 767 static void 768 c_excl(p) 769 register Char *p; 770 { 771 register int i; 772 register Char *q; 773 774 /* 775 * if />[SPC TAB]*![SPC TAB]/, back up p to just after the >. otherwise, 776 * back p up to just before the current word. 777 */ 778 if ((p[1] == ' ' || p[1] == '\t') && 779 (p[-1] == ' ' || p[-1] == '\t' || p[-1] == '>')) { 780 for (q = p - 1; q > InputBuf && (*q == ' ' || *q == '\t'); --q) 781 continue; 782 if (*q == '>') 783 ++p; 784 } 785 else { 786 while (*p != ' ' && *p != '\t' && p > InputBuf) 787 --p; 788 } 789 790 /* 791 * Forever: Look for history char. (Stop looking when we find the cursor.) 792 * Count backslashes. Of odd, skip history char. Return if all done. 793 * Expand if even number of backslashes. 794 */ 795 for (;;) { 796 while (*p != HIST && p < Cursor) 797 ++p; 798 for (i = 1; (p - i) >= InputBuf && p[-i] == '\\'; i++) 799 continue; 800 if (i % 2 == 0) 801 ++p; 802 if (p >= Cursor) 803 return; 804 if (i % 2 == 1) 805 p = c_expand(p); 806 } 807 } 808 809 810 static void 811 c_substitute() 812 { 813 register Char *p; 814 815 /* 816 * Start p out one character before the cursor. Move it backwards looking 817 * for white space, the beginning of the line, or a history character. 818 */ 819 for (p = Cursor - 1; 820 p > InputBuf && *p != ' ' && *p != '\t' && *p != HIST; --p) 821 continue; 822 823 /* 824 * If we found a history character, go expand it. 825 */ 826 if (*p == HIST) 827 c_excl(p); 828 Refresh(); 829 } 830 831 static void 832 c_delfini() /* Finish up delete action */ 833 { 834 register int Size; 835 836 if (ActionFlag & TCSHOP_INSERT) 837 c_alternativ_key_map(0); 838 839 ActionFlag = TCSHOP_NOP; 840 841 if (ActionPos == 0) 842 return; 843 844 UndoAction = TCSHOP_INSERT; 845 846 if (Cursor > ActionPos) { 847 Size = (int) (Cursor-ActionPos); 848 c_delbefore(Size); 849 Cursor = ActionPos; 850 #if defined(DSPMBYTE) 851 if (_enable_mbdisp && extdel) { 852 Cursor--; 853 e_redisp(1); 854 } 855 #endif 856 RefCursor(); 857 } 858 else if (Cursor < ActionPos) { 859 Size = (int)(ActionPos-Cursor); 860 c_delafter(Size); 861 } 862 else { 863 Size = 1; 864 c_delafter(Size); 865 } 866 UndoPtr = Cursor; 867 UndoSize = Size; 868 } 869 870 static Char * 871 c_endword(p, high, n) 872 register Char *p, *high; 873 register int n; 874 { 875 register int inquote = 0; 876 p++; 877 878 while (n--) { 879 while (p < high) { /* Skip spaces */ 880 if (!Isspace(*p) || (Isspace(*p) && *(p-1) == (Char)'\\')) 881 break; 882 p++; 883 } 884 while (p < high) { /* Skip string */ 885 if ((*p == (Char)'\'' || *p == (Char)'"')) { /* Quotation marks? */ 886 if ((!inquote && *(p-1) != (Char)'\\') || inquote) { /* Should it be honored? */ 887 if (inquote == 0) inquote = *p; 888 else if (inquote == *p) inquote = 0; 889 } 890 } 891 if (!inquote && (Isspace(*p) && *(p-1) != (Char)'\\')) /* Break if unquoted space */ 892 break; 893 p++; 894 } 895 } 896 897 p--; 898 return(p); 899 } 900 901 902 static Char * 903 c_eword(p, high, n) 904 register Char *p, *high; 905 register int n; 906 { 907 p++; 908 909 while (n--) { 910 while ((p < high) && Isspace(*p)) 911 p++; 912 913 if (Isalnum(*p)) 914 while ((p < high) && Isalnum(*p)) 915 p++; 916 else 917 while ((p < high) && !(Isspace(*p) || Isalnum(*p))) 918 p++; 919 } 920 921 p--; 922 return(p); 923 } 924 925 static CCRETVAL 926 c_get_histline() 927 { 928 struct Hist *hp; 929 int h; 930 931 if (Hist_num == 0) { /* if really the current line */ 932 copyn(InputBuf, HistBuf, INBUFSIZE); 933 LastChar = InputBuf + (LastHist - HistBuf); 934 935 #ifdef KSHVI 936 if (VImode) 937 Cursor = InputBuf; 938 else 939 #endif /* KSHVI */ 940 Cursor = LastChar; 941 942 return(CC_REFRESH); 943 } 944 945 hp = Histlist.Hnext; 946 if (hp == NULL) 947 return(CC_ERROR); 948 949 for (h = 1; h < Hist_num; h++) { 950 if ((hp->Hnext) == NULL) { 951 Hist_num = h; 952 return(CC_ERROR); 953 } 954 hp = hp->Hnext; 955 } 956 957 if (HistLit && hp->histline) { 958 copyn(InputBuf, hp->histline, INBUFSIZE); 959 CurrentHistLit = 1; 960 } 961 else { 962 (void) sprlex(InputBuf, sizeof(InputBuf), &hp->Hlex); 963 CurrentHistLit = 0; 964 } 965 LastChar = InputBuf + Strlen(InputBuf); 966 967 if (LastChar > InputBuf) { 968 if (LastChar[-1] == '\n') 969 LastChar--; 970 #if 0 971 if (LastChar[-1] == ' ') 972 LastChar--; 973 #endif 974 if (LastChar < InputBuf) 975 LastChar = InputBuf; 976 } 977 978 #ifdef KSHVI 979 if (VImode) 980 Cursor = InputBuf; 981 else 982 #endif /* KSHVI */ 983 Cursor = LastChar; 984 985 return(CC_REFRESH); 986 } 987 988 static CCRETVAL 989 c_search_line(pattern, dir) 990 Char *pattern; 991 int dir; 992 { 993 Char *cp; 994 int len; 995 996 len = (int) Strlen(pattern); 997 998 if (dir == F_UP_SEARCH_HIST) { 999 for (cp = Cursor; cp >= InputBuf; cp--) 1000 if (Strncmp(cp, pattern, (size_t) len) == 0 || 1001 Gmatch(cp, pattern)) { 1002 Cursor = cp; 1003 return(CC_NORM); 1004 } 1005 return(CC_ERROR); 1006 } else { 1007 for (cp = Cursor; *cp != '\0' && cp < InputLim; cp++) 1008 if (Strncmp(cp, pattern, (size_t) len) == 0 || 1009 Gmatch(cp, pattern)) { 1010 Cursor = cp; 1011 return(CC_NORM); 1012 } 1013 return(CC_ERROR); 1014 } 1015 } 1016 1017 static CCRETVAL 1018 e_inc_search(dir) 1019 int dir; 1020 { 1021 static Char STRfwd[] = { 'f', 'w', 'd', '\0' }, 1022 STRbck[] = { 'b', 'c', 'k', '\0' }; 1023 static Char pchar = ':'; /* ':' = normal, '?' = failed */ 1024 static Char endcmd[2]; 1025 Char ch, *cp, 1026 *oldCursor = Cursor, 1027 oldpchar = pchar; 1028 CCRETVAL ret = CC_NORM; 1029 int oldHist_num = Hist_num, 1030 oldpatlen = patlen, 1031 newdir = dir, 1032 done, redo; 1033 1034 if (LastChar + sizeof(STRfwd)/sizeof(Char) + 2 + patlen >= InputLim) 1035 return(CC_ERROR); 1036 1037 for (;;) { 1038 1039 if (patlen == 0) { /* first round */ 1040 pchar = ':'; 1041 patbuf[patlen++] = '*'; 1042 } 1043 done = redo = 0; 1044 *LastChar++ = '\n'; 1045 for (cp = newdir == F_UP_SEARCH_HIST ? STRbck : STRfwd; 1046 *cp; *LastChar++ = *cp++) 1047 continue; 1048 *LastChar++ = pchar; 1049 for (cp = &patbuf[1]; cp < &patbuf[patlen]; *LastChar++ = *cp++) 1050 continue; 1051 *LastChar = '\0'; 1052 Refresh(); 1053 1054 if (GetNextChar(&ch) != 1) 1055 return(e_send_eof(0)); 1056 1057 switch (CurrentKeyMap[(unsigned char) ch]) { 1058 case F_INSERT: 1059 case F_DIGIT: 1060 case F_MAGIC_SPACE: 1061 if (patlen > INBUFSIZE - 3) 1062 SoundBeep(); 1063 else { 1064 patbuf[patlen++] = ch; 1065 *LastChar++ = ch; 1066 *LastChar = '\0'; 1067 Refresh(); 1068 } 1069 break; 1070 1071 case F_INC_FWD: 1072 newdir = F_DOWN_SEARCH_HIST; 1073 redo++; 1074 break; 1075 1076 case F_INC_BACK: 1077 newdir = F_UP_SEARCH_HIST; 1078 redo++; 1079 break; 1080 1081 case F_DELPREV: 1082 if (patlen > 1) 1083 done++; 1084 else 1085 SoundBeep(); 1086 break; 1087 1088 default: 1089 switch (ch) { 1090 case 0007: /* ^G: Abort */ 1091 ret = CC_ERROR; 1092 done++; 1093 break; 1094 1095 case 0027: /* ^W: Append word */ 1096 /* No can do if globbing characters in pattern */ 1097 for (cp = &patbuf[1]; ; cp++) 1098 if (cp >= &patbuf[patlen]) { 1099 Cursor += patlen - 1; 1100 cp = c_next_word(Cursor, LastChar, 1); 1101 while (Cursor < cp && *Cursor != '\n') { 1102 if (patlen > INBUFSIZE - 3) { 1103 SoundBeep(); 1104 break; 1105 } 1106 patbuf[patlen++] = *Cursor; 1107 *LastChar++ = *Cursor++; 1108 } 1109 Cursor = oldCursor; 1110 *LastChar = '\0'; 1111 Refresh(); 1112 break; 1113 } else if (isglob(*cp)) { 1114 SoundBeep(); 1115 break; 1116 } 1117 break; 1118 1119 default: /* Terminate and execute cmd */ 1120 endcmd[0] = ch; 1121 PushMacro(endcmd); 1122 /*FALLTHROUGH*/ 1123 1124 case 0033: /* ESC: Terminate */ 1125 ret = CC_REFRESH; 1126 done++; 1127 break; 1128 } 1129 break; 1130 } 1131 1132 while (LastChar > InputBuf && *LastChar != '\n') 1133 *LastChar-- = '\0'; 1134 *LastChar = '\0'; 1135 1136 if (!done) { 1137 1138 /* Can't search if unmatched '[' */ 1139 for (cp = &patbuf[patlen - 1], ch = ']'; cp > patbuf; cp--) 1140 if (*cp == '[' || *cp == ']') { 1141 ch = *cp; 1142 break; 1143 } 1144 1145 if (patlen > 1 && ch != '[') { 1146 if (redo && newdir == dir) { 1147 if (pchar == '?') { /* wrap around */ 1148 Hist_num = newdir == F_UP_SEARCH_HIST ? 0 : 0x7fffffff; 1149 if (c_get_histline() == CC_ERROR) 1150 /* Hist_num was fixed by first call */ 1151 (void) c_get_histline(); 1152 Cursor = newdir == F_UP_SEARCH_HIST ? 1153 LastChar : InputBuf; 1154 } else 1155 Cursor += newdir == F_UP_SEARCH_HIST ? -1 : 1; 1156 } 1157 patbuf[patlen++] = '*'; 1158 patbuf[patlen] = '\0'; 1159 if (Cursor < InputBuf || Cursor > LastChar || 1160 (ret = c_search_line(&patbuf[1], newdir)) == CC_ERROR) { 1161 LastCmd = (KEYCMD) newdir; /* avoid c_hsetpat */ 1162 ret = newdir == F_UP_SEARCH_HIST ? 1163 e_up_search_hist(0) : e_down_search_hist(0); 1164 if (ret != CC_ERROR) { 1165 Cursor = newdir == F_UP_SEARCH_HIST ? 1166 LastChar : InputBuf; 1167 (void) c_search_line(&patbuf[1], newdir); 1168 } 1169 } 1170 patbuf[--patlen] = '\0'; 1171 if (ret == CC_ERROR) { 1172 SoundBeep(); 1173 if (Hist_num != oldHist_num) { 1174 Hist_num = oldHist_num; 1175 if (c_get_histline() == CC_ERROR) 1176 return(CC_ERROR); 1177 } 1178 Cursor = oldCursor; 1179 pchar = '?'; 1180 } else { 1181 pchar = ':'; 1182 } 1183 } 1184 1185 ret = e_inc_search(newdir); 1186 1187 if (ret == CC_ERROR && pchar == '?' && oldpchar == ':') { 1188 /* break abort of failed search at last non-failed */ 1189 ret = CC_NORM; 1190 } 1191 1192 } 1193 1194 if (ret == CC_NORM || (ret == CC_ERROR && oldpatlen == 0)) { 1195 /* restore on normal return or error exit */ 1196 pchar = oldpchar; 1197 patlen = oldpatlen; 1198 if (Hist_num != oldHist_num) { 1199 Hist_num = oldHist_num; 1200 if (c_get_histline() == CC_ERROR) 1201 return(CC_ERROR); 1202 } 1203 Cursor = oldCursor; 1204 if (ret == CC_ERROR) 1205 Refresh(); 1206 } 1207 if (done || ret != CC_NORM) 1208 return(ret); 1209 1210 } 1211 1212 } 1213 1214 static CCRETVAL 1215 v_search(dir) 1216 int dir; 1217 { 1218 Char ch; 1219 Char tmpbuf[INBUFSIZE]; 1220 Char oldbuf[INBUFSIZE]; 1221 Char *oldlc, *oldc; 1222 int tmplen; 1223 1224 copyn(oldbuf, InputBuf, INBUFSIZE); 1225 oldlc = LastChar; 1226 oldc = Cursor; 1227 tmplen = 0; 1228 tmpbuf[tmplen++] = '*'; 1229 1230 InputBuf[0] = '\0'; 1231 LastChar = InputBuf; 1232 Cursor = InputBuf; 1233 searchdir = dir; 1234 1235 c_insert(2); /* prompt + '\n' */ 1236 *Cursor++ = '\n'; 1237 *Cursor++ = dir == F_UP_SEARCH_HIST ? '?' : '/'; 1238 Refresh(); 1239 for (ch = 0;ch == 0;) { 1240 if (GetNextChar(&ch) != 1) 1241 return(e_send_eof(0)); 1242 switch (ASC(ch)) { 1243 case 0010: /* Delete and backspace */ 1244 case 0177: 1245 if (tmplen > 1) { 1246 *Cursor-- = '\0'; 1247 LastChar = Cursor; 1248 tmpbuf[tmplen--] = '\0'; 1249 } 1250 else { 1251 copyn(InputBuf, oldbuf, INBUFSIZE); 1252 LastChar = oldlc; 1253 Cursor = oldc; 1254 return(CC_REFRESH); 1255 } 1256 Refresh(); 1257 ch = 0; 1258 break; 1259 1260 case 0033: /* ESC */ 1261 #ifndef _OSD_POSIX 1262 case '\r': /* Newline */ 1263 case '\n': 1264 #else 1265 case '\012': /* Newline */ 1266 case '\015': /* Return */ 1267 #endif 1268 break; 1269 1270 default: 1271 if (tmplen >= INBUFSIZE) 1272 SoundBeep(); 1273 else { 1274 tmpbuf[tmplen++] = ch; 1275 *Cursor++ = ch; 1276 LastChar = Cursor; 1277 } 1278 Refresh(); 1279 ch = 0; 1280 break; 1281 } 1282 } 1283 1284 if (tmplen == 1) { 1285 /* 1286 * Use the old pattern, but wild-card it. 1287 */ 1288 if (patlen == 0) { 1289 InputBuf[0] = '\0'; 1290 LastChar = InputBuf; 1291 Cursor = InputBuf; 1292 Refresh(); 1293 return(CC_ERROR); 1294 } 1295 if (patbuf[0] != '*') { 1296 (void) Strcpy(tmpbuf, patbuf); 1297 patbuf[0] = '*'; 1298 (void) Strcpy(&patbuf[1], tmpbuf); 1299 patlen++; 1300 patbuf[patlen++] = '*'; 1301 patbuf[patlen] = '\0'; 1302 } 1303 } 1304 else { 1305 tmpbuf[tmplen++] = '*'; 1306 tmpbuf[tmplen] = '\0'; 1307 (void) Strcpy(patbuf, tmpbuf); 1308 patlen = tmplen; 1309 } 1310 LastCmd = (KEYCMD) dir; /* avoid c_hsetpat */ 1311 Cursor = LastChar = InputBuf; 1312 if ((dir == F_UP_SEARCH_HIST ? e_up_search_hist(0) : 1313 e_down_search_hist(0)) == CC_ERROR) { 1314 Refresh(); 1315 return(CC_ERROR); 1316 } 1317 else { 1318 if (ch == 0033) { 1319 Refresh(); 1320 *LastChar++ = '\n'; 1321 *LastChar = '\0'; 1322 PastBottom(); 1323 return(CC_NEWLINE); 1324 } 1325 else 1326 return(CC_REFRESH); 1327 } 1328 } 1329 1330 /* 1331 * semi-PUBLIC routines. Any routine that is of type CCRETVAL is an 1332 * entry point, called from the CcKeyMap indirected into the 1333 * CcFuncTbl array. 1334 */ 1335 1336 /*ARGSUSED*/ 1337 CCRETVAL 1338 v_cmd_mode(c) 1339 int c; 1340 { 1341 USE(c); 1342 InsertPos = 0; 1343 ActionFlag = TCSHOP_NOP; /* [Esc] cancels pending action */ 1344 ActionPos = 0; 1345 DoingArg = 0; 1346 if (UndoPtr > Cursor) 1347 UndoSize = (int)(UndoPtr - Cursor); 1348 else 1349 UndoSize = (int)(Cursor - UndoPtr); 1350 1351 inputmode = MODE_INSERT; 1352 c_alternativ_key_map(1); 1353 #ifdef notdef 1354 /* 1355 * We don't want to move the cursor, because all the editing 1356 * commands don't include the character under the cursor. 1357 */ 1358 if (Cursor > InputBuf) 1359 Cursor--; 1360 #endif 1361 RefCursor(); 1362 return(CC_NORM); 1363 } 1364 1365 /*ARGSUSED*/ 1366 CCRETVAL 1367 e_unassigned(c) 1368 int c; 1369 { /* bound to keys that arn't really assigned */ 1370 USE(c); 1371 SoundBeep(); 1372 flush(); 1373 return(CC_NORM); 1374 } 1375 1376 CCRETVAL 1377 e_insert(c) 1378 register int c; 1379 { 1380 register int i; 1381 #if defined(DSPMBYTE) 1382 CCRETVAL ret; 1383 static Char savec; 1384 static int exterr = 0; 1385 #endif 1386 #ifndef SHORT_STRINGS 1387 c &= ASCII; /* no meta chars ever */ 1388 #endif 1389 #if defined(DSPMBYTE) 1390 ret = (CCRETVAL) CC_NORM; 1391 #endif 1392 1393 if (!c) 1394 return(CC_ERROR); /* no NULs in the input ever!! */ 1395 1396 if (LastChar + Argument >= InputLim) 1397 return(CC_ERROR); /* end of buffer space */ 1398 1399 if (Argument == 1) { /* How was this optimized ???? */ 1400 1401 #if defined(DSPMBYTE) 1402 if(_enable_mbdisp && extins && exterr && Ismbyte2(c)) { 1403 extins = 0; 1404 exterr = 0; 1405 return(CC_ERROR); 1406 } 1407 #endif 1408 if (inputmode != MODE_INSERT) { 1409 UndoBuf[UndoSize++] = *Cursor; 1410 UndoBuf[UndoSize] = '\0'; 1411 c_delafter(1); /* Do NOT use the saving ONE */ 1412 } 1413 1414 c_insert(1); 1415 1416 #if defined(DSPMBYTE) 1417 /* 1st. byte is store to special buffer, and replace space */ 1418 if(_enable_mbdisp && extins == 0 && Ismbyte1(c)) { 1419 extins++; 1420 savec = (Char) c; 1421 *Cursor++ = (Char) ' '; 1422 } 1423 else if (_enable_mbdisp && extins && Ismbyte2(c)) { 1424 *(Cursor-1) = savec; 1425 *Cursor++ = (Char) c; 1426 extins = 0; 1427 e_redisp(1); 1428 Refresh(); 1429 ret = CC_REFRESH; 1430 } 1431 else 1432 *Cursor++ = (Char) c; 1433 DoingArg = 0; /* just in case */ 1434 if (ret != CC_REFRESH) 1435 RefPlusOne(); /* fast refresh for one char. */ 1436 #else 1437 *Cursor++ = (Char) c; 1438 DoingArg = 0; /* just in case */ 1439 RefPlusOne(); /* fast refresh for one char. */ 1440 #endif 1441 } 1442 else { 1443 #if defined(DSPMBYTE) 1444 /* Cannot use ESC-(number) for multi-byte */ 1445 if (_enable_mbdisp && extins == 0 && Ismbyte1(c)) { 1446 extins++; 1447 exterr++; 1448 return(CC_ERROR); 1449 } 1450 else if (_enable_mbdisp && extins && exterr && Ismbyte2(c)) 1451 { 1452 extins = 0; 1453 exterr = 0; 1454 return(CC_ERROR); 1455 } 1456 #endif 1457 if (inputmode != MODE_INSERT) { 1458 1459 for(i=0;i<Argument;i++) 1460 UndoBuf[UndoSize++] = *(Cursor+i); 1461 1462 UndoBuf[UndoSize] = '\0'; 1463 c_delafter(Argument); /* Do NOT use the saving ONE */ 1464 } 1465 1466 c_insert(Argument); 1467 1468 while (Argument--) 1469 *Cursor++ = (Char) c; 1470 Refresh(); 1471 } 1472 1473 if (inputmode == MODE_REPLACE_1) 1474 (void) v_cmd_mode(0); 1475 1476 #if defined(DSPMBYTE) 1477 return(ret); 1478 #else 1479 return(CC_NORM); 1480 #endif 1481 } 1482 1483 int 1484 InsertStr(s) /* insert ASCIZ s at cursor (for complete) */ 1485 Char *s; 1486 { 1487 register int len; 1488 1489 if ((len = (int) Strlen(s)) <= 0) 1490 return -1; 1491 if (LastChar + len >= InputLim) 1492 return -1; /* end of buffer space */ 1493 1494 c_insert(len); 1495 while (len--) 1496 *Cursor++ = *s++; 1497 return 0; 1498 } 1499 1500 void 1501 DeleteBack(n) /* delete the n characters before . */ 1502 int n; 1503 { 1504 if (n <= 0) 1505 return; 1506 if (Cursor >= &InputBuf[n]) { 1507 c_delbefore(n); /* delete before dot */ 1508 if (n > Cursor - InputBuf) 1509 Cursor = InputBuf; /* bounds check */ 1510 else 1511 Cursor -= n; 1512 #if defined(DSPMBYTE) 1513 if(_enable_mbdisp && extdel && Cursor > InputBuf) { 1514 Cursor--; 1515 e_redisp(1); 1516 } 1517 #endif 1518 } 1519 } 1520 1521 CCRETVAL 1522 e_digit(c) /* gray magic here */ 1523 register int c; 1524 { 1525 if (!Isdigit(c)) 1526 return(CC_ERROR); /* no NULs in the input ever!! */ 1527 1528 if (DoingArg) { /* if doing an arg, add this in... */ 1529 if (LastCmd == F_ARGFOUR) /* if last command was ^U */ 1530 Argument = c - '0'; 1531 else { 1532 if (Argument > 1000000) 1533 return CC_ERROR; 1534 Argument = (Argument * 10) + (c - '0'); 1535 } 1536 return(CC_ARGHACK); 1537 } 1538 else { 1539 if (LastChar + 1 >= InputLim) 1540 return CC_ERROR; /* end of buffer space */ 1541 1542 if (inputmode != MODE_INSERT) { 1543 UndoBuf[UndoSize++] = *Cursor; 1544 UndoBuf[UndoSize] = '\0'; 1545 c_delafter(1); /* Do NOT use the saving ONE */ 1546 } 1547 c_insert(1); 1548 *Cursor++ = (Char) c; 1549 DoingArg = 0; /* just in case */ 1550 RefPlusOne(); /* fast refresh for one char. */ 1551 } 1552 return(CC_NORM); 1553 } 1554 1555 CCRETVAL 1556 e_argdigit(c) /* for ESC-n */ 1557 register int c; 1558 { 1559 c &= ASCII; 1560 1561 if (!Isdigit(c)) 1562 return(CC_ERROR); /* no NULs in the input ever!! */ 1563 1564 if (DoingArg) { /* if doing an arg, add this in... */ 1565 if (Argument > 1000000) 1566 return CC_ERROR; 1567 Argument = (Argument * 10) + (c - '0'); 1568 } 1569 else { /* else starting an argument */ 1570 Argument = c - '0'; 1571 DoingArg = 1; 1572 } 1573 return(CC_ARGHACK); 1574 } 1575 1576 CCRETVAL 1577 v_zero(c) /* command mode 0 for vi */ 1578 register int c; 1579 { 1580 if (DoingArg) { /* if doing an arg, add this in... */ 1581 if (Argument > 1000000) 1582 return CC_ERROR; 1583 Argument = (Argument * 10) + (c - '0'); 1584 return(CC_ARGHACK); 1585 } 1586 else { /* else starting an argument */ 1587 Cursor = InputBuf; 1588 if (ActionFlag & TCSHOP_DELETE) { 1589 c_delfini(); 1590 return(CC_REFRESH); 1591 } 1592 RefCursor(); /* move the cursor */ 1593 return(CC_NORM); 1594 } 1595 } 1596 1597 /*ARGSUSED*/ 1598 CCRETVAL 1599 e_newline(c) 1600 int c; 1601 { /* always ignore argument */ 1602 USE(c); 1603 /* PastBottom(); NOW done in ed.inputl.c */ 1604 *LastChar++ = '\n'; /* for the benefit of CSH */ 1605 *LastChar = '\0'; /* just in case */ 1606 if (VImode) 1607 InsertPos = InputBuf; /* Reset editing position */ 1608 return(CC_NEWLINE); 1609 } 1610 1611 /*ARGSUSED*/ 1612 CCRETVAL 1613 e_send_eof(c) 1614 int c; 1615 { /* for when ^D is ONLY send-eof */ 1616 USE(c); 1617 PastBottom(); 1618 *LastChar = '\0'; /* just in case */ 1619 return(CC_EOF); 1620 } 1621 1622 /*ARGSUSED*/ 1623 CCRETVAL 1624 e_complete(c) 1625 int c; 1626 { 1627 USE(c); 1628 *LastChar = '\0'; /* just in case */ 1629 return(CC_COMPLETE); 1630 } 1631 1632 /*ARGSUSED*/ 1633 CCRETVAL 1634 e_complete_back(c) 1635 int c; 1636 { 1637 USE(c); 1638 *LastChar = '\0'; /* just in case */ 1639 return(CC_COMPLETE_BACK); 1640 } 1641 1642 /*ARGSUSED*/ 1643 CCRETVAL 1644 e_complete_fwd(c) 1645 int c; 1646 { 1647 USE(c); 1648 *LastChar = '\0'; /* just in case */ 1649 return(CC_COMPLETE_FWD); 1650 } 1651 1652 /*ARGSUSED*/ 1653 CCRETVAL 1654 e_complete_all(c) 1655 int c; 1656 { 1657 USE(c); 1658 *LastChar = '\0'; /* just in case */ 1659 return(CC_COMPLETE_ALL); 1660 } 1661 1662 /*ARGSUSED*/ 1663 CCRETVAL 1664 v_cm_complete(c) 1665 int c; 1666 { 1667 USE(c); 1668 if (Cursor < LastChar) 1669 Cursor++; 1670 *LastChar = '\0'; /* just in case */ 1671 return(CC_COMPLETE); 1672 } 1673 1674 /*ARGSUSED*/ 1675 CCRETVAL 1676 e_toggle_hist(c) 1677 int c; 1678 { 1679 struct Hist *hp; 1680 int h; 1681 1682 USE(c); 1683 *LastChar = '\0'; /* just in case */ 1684 1685 if (Hist_num <= 0) { 1686 return CC_ERROR; 1687 } 1688 1689 hp = Histlist.Hnext; 1690 if (hp == NULL) { /* this is only if no history */ 1691 return(CC_ERROR); 1692 } 1693 1694 for (h = 1; h < Hist_num; h++) 1695 hp = hp->Hnext; 1696 1697 if (!CurrentHistLit) { 1698 if (hp->histline) { 1699 copyn(InputBuf, hp->histline, INBUFSIZE); 1700 CurrentHistLit = 1; 1701 } 1702 else { 1703 return CC_ERROR; 1704 } 1705 } 1706 else { 1707 (void) sprlex(InputBuf, sizeof(InputBuf), &hp->Hlex); 1708 CurrentHistLit = 0; 1709 } 1710 1711 LastChar = InputBuf + Strlen(InputBuf); 1712 if (LastChar > InputBuf) { 1713 if (LastChar[-1] == '\n') 1714 LastChar--; 1715 if (LastChar[-1] == ' ') 1716 LastChar--; 1717 if (LastChar < InputBuf) 1718 LastChar = InputBuf; 1719 } 1720 1721 #ifdef KSHVI 1722 if (VImode) 1723 Cursor = InputBuf; 1724 else 1725 #endif /* KSHVI */ 1726 Cursor = LastChar; 1727 1728 return(CC_REFRESH); 1729 } 1730 1731 /*ARGSUSED*/ 1732 CCRETVAL 1733 e_up_hist(c) 1734 int c; 1735 { 1736 Char beep = 0; 1737 1738 USE(c); 1739 UndoAction = TCSHOP_NOP; 1740 *LastChar = '\0'; /* just in case */ 1741 1742 if (Hist_num == 0) { /* save the current buffer away */ 1743 copyn(HistBuf, InputBuf, INBUFSIZE); 1744 LastHist = HistBuf + (LastChar - InputBuf); 1745 } 1746 1747 Hist_num += Argument; 1748 1749 if (c_get_histline() == CC_ERROR) { 1750 beep = 1; 1751 (void) c_get_histline(); /* Hist_num was fixed by first call */ 1752 } 1753 1754 Refresh(); 1755 if (beep) 1756 return(CC_ERROR); 1757 else 1758 return(CC_NORM); /* was CC_UP_HIST */ 1759 } 1760 1761 /*ARGSUSED*/ 1762 CCRETVAL 1763 e_down_hist(c) 1764 int c; 1765 { 1766 USE(c); 1767 UndoAction = TCSHOP_NOP; 1768 *LastChar = '\0'; /* just in case */ 1769 1770 Hist_num -= Argument; 1771 1772 if (Hist_num < 0) { 1773 Hist_num = 0; 1774 return(CC_ERROR); /* make it beep */ 1775 } 1776 1777 return(c_get_histline()); 1778 } 1779 1780 1781 1782 /* 1783 * c_hmatch() return True if the pattern matches the prefix 1784 */ 1785 static int 1786 c_hmatch(str) 1787 Char *str; 1788 { 1789 if (Strncmp(patbuf, str, (size_t) patlen) == 0) 1790 return 1; 1791 return Gmatch(str, patbuf); 1792 } 1793 1794 /* 1795 * c_hsetpat(): Set the history seatch pattern 1796 */ 1797 static void 1798 c_hsetpat() 1799 { 1800 if (LastCmd != F_UP_SEARCH_HIST && LastCmd != F_DOWN_SEARCH_HIST) { 1801 patlen = (int) (Cursor - InputBuf); 1802 if (patlen >= INBUFSIZE) patlen = INBUFSIZE -1; 1803 if (patlen >= 0) { 1804 (void) Strncpy(patbuf, InputBuf, (size_t) patlen); 1805 patbuf[patlen] = '\0'; 1806 } 1807 else 1808 patlen = (int) Strlen(patbuf); 1809 } 1810 #ifdef SDEBUG 1811 xprintf("\nHist_num = %d\n", Hist_num); 1812 xprintf("patlen = %d\n", patlen); 1813 xprintf("patbuf = \"%S\"\n", patbuf); 1814 xprintf("Cursor %d LastChar %d\n", Cursor - InputBuf, LastChar - InputBuf); 1815 #endif 1816 } 1817 1818 /*ARGSUSED*/ 1819 CCRETVAL 1820 e_up_search_hist(c) 1821 int c; 1822 { 1823 struct Hist *hp; 1824 int h; 1825 bool found = 0; 1826 1827 USE(c); 1828 ActionFlag = TCSHOP_NOP; 1829 UndoAction = TCSHOP_NOP; 1830 *LastChar = '\0'; /* just in case */ 1831 if (Hist_num < 0) { 1832 #ifdef DEBUG_EDIT 1833 xprintf("%s: e_up_search_hist(): Hist_num < 0; resetting.\n", progname); 1834 #endif 1835 Hist_num = 0; 1836 return(CC_ERROR); 1837 } 1838 1839 if (Hist_num == 0) 1840 { 1841 copyn(HistBuf, InputBuf, INBUFSIZE); 1842 LastHist = HistBuf + (LastChar - InputBuf); 1843 } 1844 1845 1846 hp = Histlist.Hnext; 1847 if (hp == NULL) 1848 return(CC_ERROR); 1849 1850 c_hsetpat(); /* Set search pattern !! */ 1851 1852 for (h = 1; h <= Hist_num; h++) 1853 hp = hp->Hnext; 1854 1855 while (hp != NULL) { 1856 Char sbuf[INBUFSIZE], *hl; 1857 if (hp->histline == NULL) { 1858 hp->histline = Strsave(sprlex(sbuf, sizeof(sbuf), &hp->Hlex)); 1859 } 1860 hl = HistLit ? hp->histline : sprlex(sbuf, sizeof(sbuf), &hp->Hlex); 1861 #ifdef SDEBUG 1862 xprintf("Comparing with \"%S\"\n", hl); 1863 #endif 1864 if ((Strncmp(hl, InputBuf, (size_t) (LastChar - InputBuf)) || 1865 hl[LastChar-InputBuf]) && c_hmatch(hl)) { 1866 found++; 1867 break; 1868 } 1869 h++; 1870 hp = hp->Hnext; 1871 } 1872 1873 if (!found) { 1874 #ifdef SDEBUG 1875 xprintf("not found\n"); 1876 #endif 1877 return(CC_ERROR); 1878 } 1879 1880 Hist_num = h; 1881 1882 return(c_get_histline()); 1883 } 1884 1885 /*ARGSUSED*/ 1886 CCRETVAL 1887 e_down_search_hist(c) 1888 int c; 1889 { 1890 struct Hist *hp; 1891 int h; 1892 bool found = 0; 1893 1894 USE(c); 1895 ActionFlag = TCSHOP_NOP; 1896 UndoAction = TCSHOP_NOP; 1897 *LastChar = '\0'; /* just in case */ 1898 1899 if (Hist_num == 0) 1900 return(CC_ERROR); 1901 1902 hp = Histlist.Hnext; 1903 if (hp == 0) 1904 return(CC_ERROR); 1905 1906 c_hsetpat(); /* Set search pattern !! */ 1907 1908 for (h = 1; h < Hist_num && hp; h++) { 1909 Char sbuf[INBUFSIZE], *hl; 1910 if (hp->histline == NULL) { 1911 hp->histline = Strsave(sprlex(sbuf, sizeof(sbuf), &hp->Hlex)); 1912 } 1913 hl = HistLit ? hp->histline : sprlex(sbuf, sizeof(sbuf), &hp->Hlex); 1914 #ifdef SDEBUG 1915 xprintf("Comparing with \"%S\"\n", hl); 1916 #endif 1917 if ((Strncmp(hl, InputBuf, (size_t) (LastChar - InputBuf)) || 1918 hl[LastChar-InputBuf]) && c_hmatch(hl)) 1919 found = h; 1920 hp = hp->Hnext; 1921 } 1922 1923 if (!found) { /* is it the current history number? */ 1924 if (!c_hmatch(HistBuf)) { 1925 #ifdef SDEBUG 1926 xprintf("not found\n"); 1927 #endif 1928 return(CC_ERROR); 1929 } 1930 } 1931 1932 Hist_num = found; 1933 1934 return(c_get_histline()); 1935 } 1936 1937 /*ARGSUSED*/ 1938 CCRETVAL 1939 e_helpme(c) 1940 int c; 1941 { 1942 USE(c); 1943 PastBottom(); 1944 *LastChar = '\0'; /* just in case */ 1945 return(CC_HELPME); 1946 } 1947 1948 /*ARGSUSED*/ 1949 CCRETVAL 1950 e_correct(c) 1951 int c; 1952 { 1953 USE(c); 1954 *LastChar = '\0'; /* just in case */ 1955 return(CC_CORRECT); 1956 } 1957 1958 /*ARGSUSED*/ 1959 CCRETVAL 1960 e_correctl(c) 1961 int c; 1962 { 1963 USE(c); 1964 *LastChar = '\0'; /* just in case */ 1965 return(CC_CORRECT_L); 1966 } 1967 1968 /*ARGSUSED*/ 1969 CCRETVAL 1970 e_run_fg_editor(c) 1971 int c; 1972 { 1973 register struct process *pp; 1974 extern bool tellwhat; 1975 1976 USE(c); 1977 if ((pp = find_stop_ed()) != NULL) { 1978 /* save our editor state so we can restore it */ 1979 tellwhat = 1; 1980 copyn(WhichBuf, InputBuf, INBUFSIZE); 1981 LastWhich = WhichBuf + (LastChar - InputBuf); 1982 CursWhich = WhichBuf + (Cursor - InputBuf); 1983 HistWhich = Hist_num; 1984 Hist_num = 0; /* for the history commands */ 1985 1986 /* put the tty in a sane mode */ 1987 PastBottom(); 1988 (void) Cookedmode(); /* make sure the tty is set up correctly */ 1989 1990 /* do it! */ 1991 fg_proc_entry(pp); 1992 1993 (void) Rawmode(); /* go on */ 1994 Refresh(); 1995 tellwhat = 0; 1996 } 1997 return(CC_NORM); 1998 } 1999 2000 /*ARGSUSED*/ 2001 CCRETVAL 2002 e_list_choices(c) 2003 int c; 2004 { 2005 USE(c); 2006 PastBottom(); 2007 *LastChar = '\0'; /* just in case */ 2008 return(CC_LIST_CHOICES); 2009 } 2010 2011 /*ARGSUSED*/ 2012 CCRETVAL 2013 e_list_all(c) 2014 int c; 2015 { 2016 USE(c); 2017 PastBottom(); 2018 *LastChar = '\0'; /* just in case */ 2019 return(CC_LIST_ALL); 2020 } 2021 2022 /*ARGSUSED*/ 2023 CCRETVAL 2024 e_list_glob(c) 2025 int c; 2026 { 2027 USE(c); 2028 PastBottom(); 2029 *LastChar = '\0'; /* just in case */ 2030 return(CC_LIST_GLOB); 2031 } 2032 2033 /*ARGSUSED*/ 2034 CCRETVAL 2035 e_expand_glob(c) 2036 int c; 2037 { 2038 USE(c); 2039 *LastChar = '\0'; /* just in case */ 2040 return(CC_EXPAND_GLOB); 2041 } 2042 2043 /*ARGSUSED*/ 2044 CCRETVAL 2045 e_normalize_path(c) 2046 int c; 2047 { 2048 USE(c); 2049 *LastChar = '\0'; /* just in case */ 2050 return(CC_NORMALIZE_PATH); 2051 } 2052 2053 /*ARGSUSED*/ 2054 CCRETVAL 2055 e_normalize_command(c) 2056 int c; 2057 { 2058 USE(c); 2059 *LastChar = '\0'; /* just in case */ 2060 return(CC_NORMALIZE_COMMAND); 2061 } 2062 2063 /*ARGSUSED*/ 2064 CCRETVAL 2065 e_expand_vars(c) 2066 int c; 2067 { 2068 USE(c); 2069 *LastChar = '\0'; /* just in case */ 2070 return(CC_EXPAND_VARS); 2071 } 2072 2073 /*ARGSUSED*/ 2074 CCRETVAL 2075 e_which(c) 2076 int c; 2077 { /* do a fast command line which(1) */ 2078 USE(c); 2079 PastBottom(); 2080 *LastChar = '\0'; /* just in case */ 2081 return(CC_WHICH); 2082 } 2083 2084 /*ARGSUSED*/ 2085 CCRETVAL 2086 e_last_item(c) 2087 int c; 2088 { /* insert the last element of the prev. cmd */ 2089 register Char *cp; 2090 register struct Hist *hp; 2091 register struct wordent *wp, *firstp; 2092 register int i; 2093 Char buf[INBUFSIZE]; 2094 2095 USE(c); 2096 if (Argument <= 0) 2097 return(CC_ERROR); 2098 2099 hp = Histlist.Hnext; 2100 if (hp == NULL) { /* this is only if no history */ 2101 return(CC_ERROR); 2102 } 2103 2104 wp = (hp->Hlex).prev; 2105 2106 if (wp->prev == (struct wordent *) NULL) 2107 return(CC_ERROR); /* an empty history entry */ 2108 2109 firstp = (hp->Hlex).next; 2110 2111 /* back up arg words in lex */ 2112 for (i = 0; i < Argument && wp != firstp; i++) { 2113 wp = wp->prev; 2114 } 2115 2116 cp = expand_lex(buf, INBUFSIZE, wp->prev, 0, i - 1); 2117 *cp = '\0'; 2118 if (InsertStr(buf)) 2119 return(CC_ERROR); 2120 2121 return(CC_REFRESH); 2122 } 2123 2124 /*ARGSUSED*/ 2125 CCRETVAL 2126 e_dabbrev_expand(c) 2127 int c; 2128 { /* expand to preceding word matching prefix */ 2129 register Char *cp, *ncp, *bp; 2130 register struct Hist *hp; 2131 register int arg = 0, len = 0, i; /* len = 0 to shut up gcc -Wall */ 2132 register bool found = 0; 2133 Char hbuf[INBUFSIZE]; 2134 static int oldevent, hist, word; 2135 static Char *start, *oldcursor; 2136 2137 USE(c); 2138 if (Argument <= 0) 2139 return(CC_ERROR); 2140 2141 cp = c_preword(Cursor, InputBuf, 1); 2142 if (cp == Cursor || Isspace(*cp)) 2143 return(CC_ERROR); 2144 2145 hp = Histlist.Hnext; 2146 bp = InputBuf; 2147 if (Argument == 1 && eventno == oldevent && cp == start && 2148 Cursor == oldcursor && patlen > 0 && Strncmp(patbuf, cp, patlen) == 0){ 2149 /* continue previous search - go to last match (hist/word) */ 2150 if (hist != 0) { /* need to move up history */ 2151 for (i = 1; i < hist && hp != NULL; i++) 2152 hp = hp->Hnext; 2153 if (hp == NULL) /* "can't happen" */ 2154 return(CC_ERROR); 2155 cp = expand_lex(hbuf, INBUFSIZE, &hp->Hlex, 0, NCARGS); 2156 *cp = '\0'; 2157 bp = hbuf; 2158 hp = hp->Hnext; 2159 } 2160 cp = c_preword(cp, bp, word); 2161 } else { /* starting new search */ 2162 oldevent = eventno; 2163 start = cp; 2164 patlen = (int) (Cursor - cp); 2165 (void) Strncpy(patbuf, cp, patlen); 2166 hist = 0; 2167 word = 0; 2168 } 2169 2170 while (!found) { 2171 ncp = c_preword(cp, bp, 1); 2172 if (ncp == cp || Isspace(*ncp)) { /* beginning of line */ 2173 hist++; 2174 word = 0; 2175 if (hp == NULL) 2176 return(CC_ERROR); 2177 cp = expand_lex(hbuf, INBUFSIZE, &hp->Hlex, 0, NCARGS); 2178 *cp = '\0'; 2179 bp = hbuf; 2180 hp = hp->Hnext; 2181 continue; 2182 } else { 2183 word++; 2184 len = (int) (c_endword(ncp-1, cp, 1) - ncp + 1); 2185 cp = ncp; 2186 } 2187 if (len > patlen && Strncmp(cp, patbuf, patlen) == 0) { 2188 /* We don't fully check distinct matches as Gnuemacs does: */ 2189 if (Argument > 1) { /* just count matches */ 2190 if (++arg >= Argument) 2191 found++; 2192 } else { /* match if distinct from previous */ 2193 if (len != Cursor - start || Strncmp(cp, start, len) != 0) 2194 found++; 2195 } 2196 } 2197 } 2198 2199 if (LastChar + len - (Cursor - start) >= InputLim) 2200 return(CC_ERROR); /* no room */ 2201 DeleteBack(Cursor - start); 2202 c_insert(len); 2203 while (len--) 2204 *Cursor++ = *cp++; 2205 oldcursor = Cursor; 2206 return(CC_REFRESH); 2207 } 2208 2209 /*ARGSUSED*/ 2210 CCRETVAL 2211 e_yank_kill(c) 2212 int c; 2213 { /* almost like GnuEmacs */ 2214 register Char *kp, *cp; 2215 2216 USE(c); 2217 if (LastKill == KillBuf) /* if zero content */ 2218 return(CC_ERROR); 2219 2220 if (LastChar + (LastKill - KillBuf) >= InputLim) 2221 return(CC_ERROR); /* end of buffer space */ 2222 2223 /* else */ 2224 Mark = Cursor; /* set the mark */ 2225 cp = Cursor; /* for speed */ 2226 2227 c_insert((int)(LastKill - KillBuf)); /* open the space, */ 2228 for (kp = KillBuf; kp < LastKill; kp++) /* copy the chars */ 2229 *cp++ = *kp; 2230 2231 if (Argument == 1) /* if an arg, cursor at beginning */ 2232 Cursor = cp; /* else cursor at end */ 2233 2234 return(CC_REFRESH); 2235 } 2236 2237 /*ARGSUSED*/ 2238 CCRETVAL 2239 v_delprev(c) /* Backspace key in insert mode */ 2240 int c; 2241 { 2242 int rc; 2243 2244 USE(c); 2245 rc = CC_ERROR; 2246 2247 if (InsertPos != 0) { 2248 if (Argument <= Cursor - InsertPos) { 2249 c_delbefore(Argument); /* delete before */ 2250 Cursor -= Argument; 2251 #if defined(DSPMBYTE) 2252 if (_enable_mbdisp && extdel) { 2253 Cursor--; 2254 e_redisp(c); 2255 } 2256 #endif 2257 rc = CC_REFRESH; 2258 } 2259 } 2260 return(rc); 2261 } /* v_delprev */ 2262 2263 /*ARGSUSED*/ 2264 CCRETVAL 2265 e_delprev(c) 2266 int c; 2267 { 2268 USE(c); 2269 if (Cursor > InputBuf) { 2270 c_delbefore(Argument); /* delete before dot */ 2271 if (Argument > Cursor - InputBuf) 2272 Cursor = InputBuf; /* bounds check */ 2273 else 2274 Cursor -= Argument; 2275 #if defined(DSPMBYTE) 2276 if (_enable_mbdisp && extdel && Cursor > InputBuf) { 2277 Cursor--; 2278 e_redisp(c); 2279 } 2280 #endif 2281 return(CC_REFRESH); 2282 } 2283 else { 2284 return(CC_ERROR); 2285 } 2286 } 2287 2288 /*ARGSUSED*/ 2289 CCRETVAL 2290 e_delwordprev(c) 2291 int c; 2292 { 2293 register Char *cp, *p, *kp; 2294 2295 USE(c); 2296 if (Cursor == InputBuf) 2297 return(CC_ERROR); 2298 /* else */ 2299 2300 cp = c_prev_word(Cursor, InputBuf, Argument); 2301 2302 for (p = cp, kp = KillBuf; p < Cursor; p++) /* save the text */ 2303 *kp++ = *p; 2304 LastKill = kp; 2305 2306 c_delbefore((int)(Cursor - cp)); /* delete before dot */ 2307 Cursor = cp; 2308 if (Cursor < InputBuf) 2309 Cursor = InputBuf; /* bounds check */ 2310 return(CC_REFRESH); 2311 } 2312 2313 /* DCS <dcs@neutron.chem.yale.edu>, 9 Oct 93 2314 * 2315 * Changed the names of some of the ^D family of editor functions to 2316 * correspond to what they actually do and created new e_delnext_list 2317 * for completeness. 2318 * 2319 * Old names: New names: 2320 * 2321 * delete-char delete-char-or-eof 2322 * F_DELNEXT F_DELNEXT_EOF 2323 * e_delnext e_delnext_eof 2324 * edelnxt edelnxteof 2325 * delete-char-or-eof delete-char 2326 * F_DELNEXT_EOF F_DELNEXT 2327 * e_delnext_eof e_delnext 2328 * edelnxteof edelnxt 2329 * delete-char-or-list delete-char-or-list-or-eof 2330 * F_LIST_DELNEXT F_DELNEXT_LIST_EOF 2331 * e_list_delnext e_delnext_list_eof 2332 * edellsteof 2333 * (no old equivalent) delete-char-or-list 2334 * F_DELNEXT_LIST 2335 * e_delnext_list 2336 * e_delnxtlst 2337 */ 2338 2339 /* added by mtk@ari.ncl.omron.co.jp (920818) */ 2340 /* rename e_delnext() -> e_delnext_eof() */ 2341 /*ARGSUSED*/ 2342 CCRETVAL 2343 e_delnext(c) 2344 int c; 2345 { 2346 USE(c); 2347 if (Cursor == LastChar) {/* if I'm at the end */ 2348 if (!VImode) { 2349 return(CC_ERROR); 2350 } 2351 else { 2352 if (Cursor != InputBuf) 2353 Cursor--; 2354 else 2355 return(CC_ERROR); 2356 } 2357 } 2358 c_delafter(Argument); /* delete after dot */ 2359 if (Cursor > LastChar) 2360 Cursor = LastChar; /* bounds check */ 2361 return(CC_REFRESH); 2362 } 2363 2364 2365 /*ARGSUSED*/ 2366 CCRETVAL 2367 e_delnext_eof(c) 2368 int c; 2369 { 2370 USE(c); 2371 if (Cursor == LastChar) {/* if I'm at the end */ 2372 if (!VImode) { 2373 if (Cursor == InputBuf) { 2374 /* if I'm also at the beginning */ 2375 so_write(STReof, 4);/* then do a EOF */ 2376 flush(); 2377 return(CC_EOF); 2378 } 2379 else 2380 return(CC_ERROR); 2381 } 2382 else { 2383 if (Cursor != InputBuf) 2384 Cursor--; 2385 else 2386 return(CC_ERROR); 2387 } 2388 } 2389 c_delafter(Argument); /* delete after dot */ 2390 if (Cursor > LastChar) 2391 Cursor = LastChar; /* bounds check */ 2392 return(CC_REFRESH); 2393 } 2394 2395 /*ARGSUSED*/ 2396 CCRETVAL 2397 e_delnext_list(c) 2398 int c; 2399 { 2400 USE(c); 2401 if (Cursor == LastChar) { /* if I'm at the end */ 2402 PastBottom(); 2403 *LastChar = '\0'; /* just in case */ 2404 return(CC_LIST_CHOICES); 2405 } 2406 else { 2407 c_delafter(Argument); /* delete after dot */ 2408 if (Cursor > LastChar) 2409 Cursor = LastChar; /* bounds check */ 2410 return(CC_REFRESH); 2411 } 2412 } 2413 2414 /*ARGSUSED*/ 2415 CCRETVAL 2416 e_delnext_list_eof(c) 2417 int c; 2418 { 2419 USE(c); 2420 if (Cursor == LastChar) { /* if I'm at the end */ 2421 if (Cursor == InputBuf) { /* if I'm also at the beginning */ 2422 so_write(STReof, 4);/* then do a EOF */ 2423 flush(); 2424 return(CC_EOF); 2425 } 2426 else { 2427 PastBottom(); 2428 *LastChar = '\0'; /* just in case */ 2429 return(CC_LIST_CHOICES); 2430 } 2431 } 2432 else { 2433 c_delafter(Argument); /* delete after dot */ 2434 if (Cursor > LastChar) 2435 Cursor = LastChar; /* bounds check */ 2436 return(CC_REFRESH); 2437 } 2438 } 2439 2440 /*ARGSUSED*/ 2441 CCRETVAL 2442 e_list_eof(c) 2443 int c; 2444 { 2445 CCRETVAL rv; 2446 2447 USE(c); 2448 if (Cursor == LastChar && Cursor == InputBuf) { 2449 so_write(STReof, 4); /* then do a EOF */ 2450 flush(); 2451 rv = CC_EOF; 2452 } 2453 else { 2454 PastBottom(); 2455 *LastChar = '\0'; /* just in case */ 2456 rv = CC_LIST_CHOICES; 2457 } 2458 return rv; 2459 } 2460 2461 /*ARGSUSED*/ 2462 CCRETVAL 2463 e_delwordnext(c) 2464 int c; 2465 { 2466 register Char *cp, *p, *kp; 2467 2468 USE(c); 2469 if (Cursor == LastChar) 2470 return(CC_ERROR); 2471 /* else */ 2472 2473 cp = c_next_word(Cursor, LastChar, Argument); 2474 2475 for (p = Cursor, kp = KillBuf; p < cp; p++) /* save the text */ 2476 *kp++ = *p; 2477 LastKill = kp; 2478 2479 c_delafter((int)(cp - Cursor)); /* delete after dot */ 2480 if (Cursor > LastChar) 2481 Cursor = LastChar; /* bounds check */ 2482 return(CC_REFRESH); 2483 } 2484 2485 /*ARGSUSED*/ 2486 CCRETVAL 2487 e_toend(c) 2488 int c; 2489 { 2490 USE(c); 2491 Cursor = LastChar; 2492 if (VImode) 2493 if (ActionFlag & TCSHOP_DELETE) { 2494 c_delfini(); 2495 return(CC_REFRESH); 2496 } 2497 RefCursor(); /* move the cursor */ 2498 return(CC_NORM); 2499 } 2500 2501 /*ARGSUSED*/ 2502 CCRETVAL 2503 e_tobeg(c) 2504 int c; 2505 { 2506 USE(c); 2507 Cursor = InputBuf; 2508 2509 if (VImode) { 2510 while (Isspace(*Cursor)) /* We want FIRST non space character */ 2511 Cursor++; 2512 if (ActionFlag & TCSHOP_DELETE) { 2513 c_delfini(); 2514 return(CC_REFRESH); 2515 } 2516 } 2517 2518 RefCursor(); /* move the cursor */ 2519 return(CC_NORM); 2520 } 2521 2522 /*ARGSUSED*/ 2523 CCRETVAL 2524 e_killend(c) 2525 int c; 2526 { 2527 register Char *kp, *cp; 2528 2529 USE(c); 2530 cp = Cursor; 2531 kp = KillBuf; 2532 while (cp < LastChar) 2533 *kp++ = *cp++; /* copy it */ 2534 LastKill = kp; 2535 LastChar = Cursor; /* zap! -- delete to end */ 2536 return(CC_REFRESH); 2537 } 2538 2539 2540 /*ARGSUSED*/ 2541 CCRETVAL 2542 e_killbeg(c) 2543 int c; 2544 { 2545 register Char *kp, *cp; 2546 2547 USE(c); 2548 cp = InputBuf; 2549 kp = KillBuf; 2550 while (cp < Cursor) 2551 *kp++ = *cp++; /* copy it */ 2552 LastKill = kp; 2553 c_delbefore((int)(Cursor - InputBuf)); 2554 Cursor = InputBuf; /* zap! */ 2555 return(CC_REFRESH); 2556 } 2557 2558 /*ARGSUSED*/ 2559 CCRETVAL 2560 e_killall(c) 2561 int c; 2562 { 2563 register Char *kp, *cp; 2564 2565 USE(c); 2566 cp = InputBuf; 2567 kp = KillBuf; 2568 while (cp < LastChar) 2569 *kp++ = *cp++; /* copy it */ 2570 LastKill = kp; 2571 LastChar = InputBuf; /* zap! -- delete all of it */ 2572 Cursor = InputBuf; 2573 return(CC_REFRESH); 2574 } 2575 2576 /*ARGSUSED*/ 2577 CCRETVAL 2578 e_killregion(c) 2579 int c; 2580 { 2581 register Char *kp, *cp; 2582 2583 USE(c); 2584 if (!Mark) 2585 return(CC_ERROR); 2586 2587 if (Mark > Cursor) { 2588 cp = Cursor; 2589 kp = KillBuf; 2590 while (cp < Mark) 2591 *kp++ = *cp++; /* copy it */ 2592 LastKill = kp; 2593 c_delafter((int)(cp - Cursor)); /* delete it - UNUSED BY VI mode */ 2594 } 2595 else { /* mark is before cursor */ 2596 cp = Mark; 2597 kp = KillBuf; 2598 while (cp < Cursor) 2599 *kp++ = *cp++; /* copy it */ 2600 LastKill = kp; 2601 c_delbefore((int)(cp - Mark)); 2602 Cursor = Mark; 2603 } 2604 return(CC_REFRESH); 2605 } 2606 2607 /*ARGSUSED*/ 2608 CCRETVAL 2609 e_copyregion(c) 2610 int c; 2611 { 2612 register Char *kp, *cp; 2613 2614 USE(c); 2615 if (!Mark) 2616 return(CC_ERROR); 2617 2618 if (Mark > Cursor) { 2619 cp = Cursor; 2620 kp = KillBuf; 2621 while (cp < Mark) 2622 *kp++ = *cp++; /* copy it */ 2623 LastKill = kp; 2624 } 2625 else { /* mark is before cursor */ 2626 cp = Mark; 2627 kp = KillBuf; 2628 while (cp < Cursor) 2629 *kp++ = *cp++; /* copy it */ 2630 LastKill = kp; 2631 } 2632 return(CC_NORM); /* don't even need to Refresh() */ 2633 } 2634 2635 /*ARGSUSED*/ 2636 CCRETVAL 2637 e_charswitch(cc) 2638 int cc; 2639 { 2640 register Char c; 2641 2642 USE(cc); 2643 2644 /* do nothing if we are at beginning of line or have only one char */ 2645 if (Cursor == &InputBuf[0] || LastChar == &InputBuf[1]) { 2646 return(CC_ERROR); 2647 } 2648 2649 if (Cursor < LastChar) { 2650 Cursor++; 2651 } 2652 c = Cursor[-2]; 2653 Cursor[-2] = Cursor[-1]; 2654 Cursor[-1] = c; 2655 return(CC_REFRESH); 2656 } 2657 2658 /*ARGSUSED*/ 2659 CCRETVAL 2660 e_gcharswitch(cc) 2661 int cc; 2662 { /* gosmacs style ^T */ 2663 register Char c; 2664 2665 USE(cc); 2666 if (Cursor > &InputBuf[1]) {/* must have at least two chars entered */ 2667 c = Cursor[-2]; 2668 Cursor[-2] = Cursor[-1]; 2669 Cursor[-1] = c; 2670 return(CC_REFRESH); 2671 } 2672 else { 2673 return(CC_ERROR); 2674 } 2675 } 2676 2677 #if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */ 2678 /*ARGSUSED*/ 2679 static void 2680 e_charback_mbyte(argument) 2681 int argument; 2682 { 2683 if (!_enable_mbdisp) { 2684 if (Argument > Cursor - InputBuf) 2685 Cursor = InputBuf; 2686 else 2687 Cursor -= Argument; 2688 } 2689 else { 2690 while (0 < argument && Cursor > InputBuf) { 2691 if (Cursor - 1 != InputBuf && 2692 Ismbyte1(*(Cursor - 2)) && Ismbyte2(*(Cursor - 1))) { 2693 Cursor--; 2694 } 2695 Cursor--; 2696 argument--; 2697 } 2698 } 2699 } 2700 #endif 2701 2702 /*ARGSUSED*/ 2703 CCRETVAL 2704 e_charback(c) 2705 int c; 2706 { 2707 USE(c); 2708 if (Cursor > InputBuf) { 2709 #if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */ 2710 e_charback_mbyte(Argument); 2711 #else 2712 if (Argument > Cursor - InputBuf) 2713 Cursor = InputBuf; 2714 else 2715 Cursor -= Argument; 2716 #endif 2717 2718 if (VImode) 2719 if (ActionFlag & TCSHOP_DELETE) { 2720 c_delfini(); 2721 return(CC_REFRESH); 2722 } 2723 2724 RefCursor(); 2725 return(CC_NORM); 2726 } 2727 else { 2728 return(CC_ERROR); 2729 } 2730 } 2731 2732 /*ARGSUSED*/ 2733 CCRETVAL 2734 v_wordback(c) 2735 int c; 2736 { 2737 USE(c); 2738 if (Cursor == InputBuf) 2739 return(CC_ERROR); 2740 /* else */ 2741 2742 Cursor = c_preword(Cursor, InputBuf, Argument); /* bounds check */ 2743 2744 if (ActionFlag & TCSHOP_DELETE) { 2745 c_delfini(); 2746 return(CC_REFRESH); 2747 } 2748 2749 RefCursor(); 2750 return(CC_NORM); 2751 } 2752 2753 /*ARGSUSED*/ 2754 CCRETVAL 2755 e_wordback(c) 2756 int c; 2757 { 2758 USE(c); 2759 if (Cursor == InputBuf) 2760 return(CC_ERROR); 2761 /* else */ 2762 2763 Cursor = c_prev_word(Cursor, InputBuf, Argument); /* bounds check */ 2764 2765 if (VImode) 2766 if (ActionFlag & TCSHOP_DELETE) { 2767 c_delfini(); 2768 return(CC_REFRESH); 2769 } 2770 2771 RefCursor(); 2772 return(CC_NORM); 2773 } 2774 2775 #if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */ 2776 /*ARGSUSED*/ 2777 static void 2778 e_charfwd_mbyte(argument) 2779 int argument; 2780 { 2781 if (!_enable_mbdisp) 2782 Cursor += argument; 2783 else 2784 while (0 < argument && Cursor < LastChar) { 2785 if (Cursor + 1 != LastChar && 2786 Ismbyte1(*Cursor) && Ismbyte2(*(Cursor + 1))) { 2787 Cursor++; 2788 } 2789 Cursor++; 2790 argument--; 2791 } 2792 } 2793 #endif 2794 2795 /*ARGSUSED*/ 2796 CCRETVAL 2797 e_charfwd(c) 2798 int c; 2799 { 2800 USE(c); 2801 if (Cursor < LastChar) { 2802 #if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */ 2803 e_charfwd_mbyte(Argument); 2804 #else 2805 Cursor += Argument; 2806 #endif 2807 if (Cursor > LastChar) 2808 Cursor = LastChar; 2809 2810 if (VImode) 2811 if (ActionFlag & TCSHOP_DELETE) { 2812 c_delfini(); 2813 return(CC_REFRESH); 2814 } 2815 2816 RefCursor(); 2817 return(CC_NORM); 2818 } 2819 else { 2820 return(CC_ERROR); 2821 } 2822 } 2823 2824 /*ARGSUSED*/ 2825 CCRETVAL 2826 e_wordfwd(c) 2827 int c; 2828 { 2829 USE(c); 2830 if (Cursor == LastChar) 2831 return(CC_ERROR); 2832 /* else */ 2833 2834 Cursor = c_next_word(Cursor, LastChar, Argument); 2835 2836 if (VImode) 2837 if (ActionFlag & TCSHOP_DELETE) { 2838 c_delfini(); 2839 return(CC_REFRESH); 2840 } 2841 2842 RefCursor(); 2843 return(CC_NORM); 2844 } 2845 2846 /*ARGSUSED*/ 2847 CCRETVAL 2848 v_wordfwd(c) 2849 int c; 2850 { 2851 USE(c); 2852 if (Cursor == LastChar) 2853 return(CC_ERROR); 2854 /* else */ 2855 2856 Cursor = c_nexword(Cursor, LastChar, Argument); 2857 2858 if (VImode) 2859 if (ActionFlag & TCSHOP_DELETE) { 2860 c_delfini(); 2861 return(CC_REFRESH); 2862 } 2863 2864 RefCursor(); 2865 return(CC_NORM); 2866 } 2867 2868 /*ARGSUSED*/ 2869 CCRETVAL 2870 v_wordbegnext(c) 2871 int c; 2872 { 2873 USE(c); 2874 if (Cursor == LastChar) 2875 return(CC_ERROR); 2876 /* else */ 2877 2878 Cursor = c_next_word(Cursor, LastChar, Argument); 2879 if (Cursor < LastChar) 2880 Cursor++; 2881 2882 if (VImode) 2883 if (ActionFlag & TCSHOP_DELETE) { 2884 c_delfini(); 2885 return(CC_REFRESH); 2886 } 2887 2888 RefCursor(); 2889 return(CC_NORM); 2890 } 2891 2892 /*ARGSUSED*/ 2893 static CCRETVAL 2894 v_repeat_srch(c) 2895 int c; 2896 { 2897 CCRETVAL rv = CC_ERROR; 2898 #ifdef SDEBUG 2899 xprintf("dir %d patlen %d patbuf %S\n", 2900 c, patlen, patbuf); 2901 #endif 2902 2903 LastCmd = (KEYCMD) c; /* Hack to stop c_hsetpat */ 2904 LastChar = InputBuf; 2905 switch (c) { 2906 case F_DOWN_SEARCH_HIST: 2907 rv = e_down_search_hist(0); 2908 break; 2909 case F_UP_SEARCH_HIST: 2910 rv = e_up_search_hist(0); 2911 break; 2912 default: 2913 break; 2914 } 2915 return rv; 2916 } 2917 2918 static CCRETVAL 2919 v_csearch_back(ch, count, tflag) 2920 int ch, count, tflag; 2921 { 2922 Char *cp; 2923 2924 cp = Cursor; 2925 while (count--) { 2926 if (*cp == ch) 2927 cp--; 2928 while (cp > InputBuf && *cp != ch) 2929 cp--; 2930 } 2931 2932 if (cp < InputBuf || (cp == InputBuf && *cp != ch)) 2933 return(CC_ERROR); 2934 2935 if (*cp == ch && tflag) 2936 cp++; 2937 2938 Cursor = cp; 2939 2940 if (ActionFlag & TCSHOP_DELETE) { 2941 Cursor++; 2942 c_delfini(); 2943 return(CC_REFRESH); 2944 } 2945 2946 RefCursor(); 2947 return(CC_NORM); 2948 } 2949 2950 static CCRETVAL 2951 v_csearch_fwd(ch, count, tflag) 2952 int ch, count, tflag; 2953 { 2954 Char *cp; 2955 2956 cp = Cursor; 2957 while (count--) { 2958 if(*cp == ch) 2959 cp++; 2960 while (cp < LastChar && *cp != ch) 2961 cp++; 2962 } 2963 2964 if (cp >= LastChar) 2965 return(CC_ERROR); 2966 2967 if (*cp == ch && tflag) 2968 cp--; 2969 2970 Cursor = cp; 2971 2972 if (ActionFlag & TCSHOP_DELETE) { 2973 Cursor++; 2974 c_delfini(); 2975 return(CC_REFRESH); 2976 } 2977 RefCursor(); 2978 return(CC_NORM); 2979 } 2980 2981 /*ARGSUSED*/ 2982 static CCRETVAL 2983 v_action(c) 2984 int c; 2985 { 2986 register Char *cp, *kp; 2987 2988 if (ActionFlag == TCSHOP_DELETE) { 2989 ActionFlag = TCSHOP_NOP; 2990 ActionPos = 0; 2991 2992 UndoSize = 0; 2993 kp = UndoBuf; 2994 for (cp = InputBuf; cp < LastChar; cp++) { 2995 *kp++ = *cp; 2996 UndoSize++; 2997 } 2998 2999 UndoAction = TCSHOP_INSERT; 3000 UndoPtr = InputBuf; 3001 LastChar = InputBuf; 3002 Cursor = InputBuf; 3003 if (c & TCSHOP_INSERT) 3004 c_alternativ_key_map(0); 3005 3006 return(CC_REFRESH); 3007 } 3008 #ifdef notdef 3009 else if (ActionFlag == TCSHOP_NOP) { 3010 #endif 3011 ActionPos = Cursor; 3012 ActionFlag = c; 3013 return(CC_ARGHACK); /* Do NOT clear out argument */ 3014 #ifdef notdef 3015 } 3016 else { 3017 ActionFlag = 0; 3018 ActionPos = 0; 3019 return(CC_ERROR); 3020 } 3021 #endif 3022 } 3023 3024 #ifdef COMMENT 3025 /* by: Brian Allison <uiucdcs!convex!allison@RUTGERS.EDU> */ 3026 static void 3027 c_get_word(begin, end) 3028 Char **begin; 3029 Char **end; 3030 { 3031 Char *cp; 3032 3033 cp = &Cursor[0]; 3034 while (Argument--) { 3035 while ((cp <= LastChar) && (isword(*cp))) 3036 cp++; 3037 *end = --cp; 3038 while ((cp >= InputBuf) && (isword(*cp))) 3039 cp--; 3040 *begin = ++cp; 3041 } 3042 } 3043 #endif /* COMMENT */ 3044 3045 /*ARGSUSED*/ 3046 CCRETVAL 3047 e_uppercase(c) 3048 int c; 3049 { 3050 Char *cp, *end; 3051 3052 USE(c); 3053 end = c_next_word(Cursor, LastChar, Argument); 3054 3055 for (cp = Cursor; cp < end; cp++) /* PWP: was cp=begin */ 3056 if (Islower(*cp)) 3057 *cp = Toupper(*cp); 3058 3059 Cursor = end; 3060 if (Cursor > LastChar) 3061 Cursor = LastChar; 3062 return(CC_REFRESH); 3063 } 3064 3065 3066 /*ARGSUSED*/ 3067 CCRETVAL 3068 e_capitolcase(c) 3069 int c; 3070 { 3071 Char *cp, *end; 3072 3073 USE(c); 3074 end = c_next_word(Cursor, LastChar, Argument); 3075 3076 cp = Cursor; 3077 for (; cp < end; cp++) { 3078 if (Isalpha(*cp)) { 3079 if (Islower(*cp)) 3080 *cp = Toupper(*cp); 3081 cp++; 3082 break; 3083 } 3084 } 3085 for (; cp < end; cp++) 3086 if (Isupper(*cp)) 3087 *cp = Tolower(*cp); 3088 3089 Cursor = end; 3090 if (Cursor > LastChar) 3091 Cursor = LastChar; 3092 return(CC_REFRESH); 3093 } 3094 3095 /*ARGSUSED*/ 3096 CCRETVAL 3097 e_lowercase(c) 3098 int c; 3099 { 3100 Char *cp, *end; 3101 3102 USE(c); 3103 end = c_next_word(Cursor, LastChar, Argument); 3104 3105 for (cp = Cursor; cp < end; cp++) 3106 if (Isupper(*cp)) 3107 *cp = Tolower(*cp); 3108 3109 Cursor = end; 3110 if (Cursor > LastChar) 3111 Cursor = LastChar; 3112 return(CC_REFRESH); 3113 } 3114 3115 3116 /*ARGSUSED*/ 3117 CCRETVAL 3118 e_set_mark(c) 3119 int c; 3120 { 3121 USE(c); 3122 Mark = Cursor; 3123 return(CC_NORM); 3124 } 3125 3126 /*ARGSUSED*/ 3127 CCRETVAL 3128 e_exchange_mark(c) 3129 int c; 3130 { 3131 register Char *cp; 3132 3133 USE(c); 3134 cp = Cursor; 3135 Cursor = Mark; 3136 Mark = cp; 3137 RefCursor(); 3138 return(CC_NORM); 3139 } 3140 3141 /*ARGSUSED*/ 3142 CCRETVAL 3143 e_argfour(c) 3144 int c; 3145 { /* multiply current argument by 4 */ 3146 USE(c); 3147 if (Argument > 1000000) 3148 return CC_ERROR; 3149 DoingArg = 1; 3150 Argument *= 4; 3151 return(CC_ARGHACK); 3152 } 3153 3154 /*ARGSUSED*/ 3155 CCRETVAL 3156 e_quote(c) 3157 int c; 3158 { 3159 Char ch; 3160 int num; 3161 3162 USE(c); 3163 QuoteModeOn(); 3164 num = GetNextChar(&ch); 3165 QuoteModeOff(); 3166 if (num == 1) 3167 return e_insert(ch); 3168 else 3169 return e_send_eof(0); 3170 } 3171 3172 /*ARGSUSED*/ 3173 CCRETVAL 3174 e_metanext(c) 3175 int c; 3176 { 3177 USE(c); 3178 MetaNext = 1; 3179 return(CC_ARGHACK); /* preserve argument */ 3180 } 3181 3182 #ifdef notdef 3183 /*ARGSUSED*/ 3184 CCRETVAL 3185 e_extendnext(c) 3186 int c; 3187 { 3188 CurrentKeyMap = CcAltMap; 3189 return(CC_ARGHACK); /* preserve argument */ 3190 } 3191 3192 #endif 3193 3194 /*ARGSUSED*/ 3195 CCRETVAL 3196 v_insbeg(c) 3197 int c; 3198 { /* move to beginning of line and start vi 3199 * insert mode */ 3200 USE(c); 3201 Cursor = InputBuf; 3202 InsertPos = Cursor; 3203 3204 UndoPtr = Cursor; 3205 UndoAction = TCSHOP_DELETE; 3206 3207 RefCursor(); /* move the cursor */ 3208 c_alternativ_key_map(0); 3209 return(CC_NORM); 3210 } 3211 3212 /*ARGSUSED*/ 3213 CCRETVAL 3214 v_replone(c) 3215 int c; 3216 { /* vi mode overwrite one character */ 3217 USE(c); 3218 c_alternativ_key_map(0); 3219 inputmode = MODE_REPLACE_1; 3220 UndoAction = TCSHOP_CHANGE; /* Set Up for VI undo command */ 3221 UndoPtr = Cursor; 3222 UndoSize = 0; 3223 return(CC_NORM); 3224 } 3225 3226 /*ARGSUSED*/ 3227 CCRETVAL 3228 v_replmode(c) 3229 int c; 3230 { /* vi mode start overwriting */ 3231 USE(c); 3232 c_alternativ_key_map(0); 3233 inputmode = MODE_REPLACE; 3234 UndoAction = TCSHOP_CHANGE; /* Set Up for VI undo command */ 3235 UndoPtr = Cursor; 3236 UndoSize = 0; 3237 return(CC_NORM); 3238 } 3239 3240 /*ARGSUSED*/ 3241 CCRETVAL 3242 v_substchar(c) 3243 int c; 3244 { /* vi mode substitute for one char */ 3245 USE(c); 3246 c_delafter(Argument); 3247 c_alternativ_key_map(0); 3248 return(CC_REFRESH); 3249 } 3250 3251 /*ARGSUSED*/ 3252 CCRETVAL 3253 v_substline(c) 3254 int c; 3255 { /* vi mode replace whole line */ 3256 USE(c); 3257 (void) e_killall(0); 3258 c_alternativ_key_map(0); 3259 return(CC_REFRESH); 3260 } 3261 3262 /*ARGSUSED*/ 3263 CCRETVAL 3264 v_chgtoend(c) 3265 int c; 3266 { /* vi mode change to end of line */ 3267 USE(c); 3268 (void) e_killend(0); 3269 c_alternativ_key_map(0); 3270 return(CC_REFRESH); 3271 } 3272 3273 /*ARGSUSED*/ 3274 CCRETVAL 3275 v_insert(c) 3276 int c; 3277 { /* vi mode start inserting */ 3278 USE(c); 3279 c_alternativ_key_map(0); 3280 3281 InsertPos = Cursor; 3282 UndoPtr = Cursor; 3283 UndoAction = TCSHOP_DELETE; 3284 3285 return(CC_NORM); 3286 } 3287 3288 /*ARGSUSED*/ 3289 CCRETVAL 3290 v_add(c) 3291 int c; 3292 { /* vi mode start adding */ 3293 USE(c); 3294 c_alternativ_key_map(0); 3295 if (Cursor < LastChar) 3296 { 3297 Cursor++; 3298 if (Cursor > LastChar) 3299 Cursor = LastChar; 3300 RefCursor(); 3301 } 3302 3303 InsertPos = Cursor; 3304 UndoPtr = Cursor; 3305 UndoAction = TCSHOP_DELETE; 3306 3307 return(CC_NORM); 3308 } 3309 3310 /*ARGSUSED*/ 3311 CCRETVAL 3312 v_addend(c) 3313 int c; 3314 { /* vi mode to add at end of line */ 3315 USE(c); 3316 c_alternativ_key_map(0); 3317 Cursor = LastChar; 3318 3319 InsertPos = LastChar; /* Mark where insertion begins */ 3320 UndoPtr = LastChar; 3321 UndoAction = TCSHOP_DELETE; 3322 3323 RefCursor(); 3324 return(CC_NORM); 3325 } 3326 3327 /*ARGSUSED*/ 3328 CCRETVAL 3329 v_change_case(cc) 3330 int cc; 3331 { 3332 char c; 3333 3334 USE(cc); 3335 if (Cursor < LastChar) { 3336 #ifndef WINNT 3337 c = *Cursor; 3338 #else 3339 c = CHAR & *Cursor; 3340 #endif /* WINNT */ 3341 if (Isupper(c)) 3342 *Cursor++ = Tolower(c); 3343 else if (Islower(c)) 3344 *Cursor++ = Toupper(c); 3345 else 3346 Cursor++; 3347 RefPlusOne(); /* fast refresh for one char */ 3348 return(CC_NORM); 3349 } 3350 return(CC_ERROR); 3351 } 3352 3353 /*ARGSUSED*/ 3354 CCRETVAL 3355 e_expand(c) 3356 int c; 3357 { 3358 register Char *p; 3359 extern bool justpr; 3360 3361 USE(c); 3362 for (p = InputBuf; Isspace(*p); p++) 3363 continue; 3364 if (p == LastChar) 3365 return(CC_ERROR); 3366 3367 justpr++; 3368 Expand++; 3369 return(e_newline(0)); 3370 } 3371 3372 /*ARGSUSED*/ 3373 CCRETVAL 3374 e_startover(c) 3375 int c; 3376 { /* erase all of current line, start again */ 3377 USE(c); 3378 ResetInLine(0); /* reset the input pointers */ 3379 return(CC_REFRESH); 3380 } 3381 3382 /*ARGSUSED*/ 3383 CCRETVAL 3384 e_redisp(c) 3385 int c; 3386 { 3387 USE(c); 3388 ClearLines(); 3389 ClearDisp(); 3390 return(CC_REFRESH); 3391 } 3392 3393 /*ARGSUSED*/ 3394 CCRETVAL 3395 e_cleardisp(c) 3396 int c; 3397 { 3398 USE(c); 3399 ClearScreen(); /* clear the whole real screen */ 3400 ClearDisp(); /* reset everything */ 3401 return(CC_REFRESH); 3402 } 3403 3404 /*ARGSUSED*/ 3405 CCRETVAL 3406 e_tty_int(c) 3407 int c; 3408 { 3409 USE(c); 3410 #if defined(_MINIX) || defined(WINNT) 3411 /* SAK PATCH: erase all of current line, start again */ 3412 ResetInLine(0); /* reset the input pointers */ 3413 xputchar('\n'); 3414 ClearDisp(); 3415 return (CC_REFRESH); 3416 #else /* !_MINIX && !WINNT */ 3417 /* do no editing */ 3418 return (CC_NORM); 3419 #endif /* _MINIX || WINNT */ 3420 } 3421 3422 /* 3423 * From: ghazi@cesl.rutgers.edu (Kaveh R. Ghazi) 3424 * Function to send a character back to the input stream in cooked 3425 * mode. Only works if we have TIOCSTI 3426 */ 3427 /*ARGSUSED*/ 3428 CCRETVAL 3429 e_stuff_char(c) 3430 int c; 3431 { 3432 #ifdef TIOCSTI 3433 extern int Tty_raw_mode; 3434 int was_raw = Tty_raw_mode; 3435 char ch = (char) c; 3436 3437 if (was_raw) 3438 (void) Cookedmode(); 3439 3440 (void) write(SHIN, "\n", 1); 3441 (void) ioctl(SHIN, TIOCSTI, (ioctl_t) &ch); 3442 3443 if (was_raw) 3444 (void) Rawmode(); 3445 return(e_redisp(c)); 3446 #else /* !TIOCSTI */ 3447 return(CC_ERROR); 3448 #endif /* !TIOCSTI */ 3449 } 3450 3451 /*ARGSUSED*/ 3452 CCRETVAL 3453 e_insovr(c) 3454 int c; 3455 { 3456 USE(c); 3457 inputmode = (inputmode == MODE_INSERT ? MODE_REPLACE : MODE_INSERT); 3458 return(CC_NORM); 3459 } 3460 3461 /*ARGSUSED*/ 3462 CCRETVAL 3463 e_tty_dsusp(c) 3464 int c; 3465 { 3466 USE(c); 3467 /* do no editing */ 3468 return(CC_NORM); 3469 } 3470 3471 /*ARGSUSED*/ 3472 CCRETVAL 3473 e_tty_flusho(c) 3474 int c; 3475 { 3476 USE(c); 3477 /* do no editing */ 3478 return(CC_NORM); 3479 } 3480 3481 /*ARGSUSED*/ 3482 CCRETVAL 3483 e_tty_quit(c) 3484 int c; 3485 { 3486 USE(c); 3487 /* do no editing */ 3488 return(CC_NORM); 3489 } 3490 3491 /*ARGSUSED*/ 3492 CCRETVAL 3493 e_tty_tsusp(c) 3494 int c; 3495 { 3496 USE(c); 3497 /* do no editing */ 3498 return(CC_NORM); 3499 } 3500 3501 /*ARGSUSED*/ 3502 CCRETVAL 3503 e_tty_stopo(c) 3504 int c; 3505 { 3506 USE(c); 3507 /* do no editing */ 3508 return(CC_NORM); 3509 } 3510 3511 /*ARGSUSED*/ 3512 CCRETVAL 3513 e_expand_history(c) 3514 int c; 3515 { 3516 USE(c); 3517 *LastChar = '\0'; /* just in case */ 3518 c_substitute(); 3519 return(CC_NORM); 3520 } 3521 3522 /*ARGSUSED*/ 3523 CCRETVAL 3524 e_magic_space(c) 3525 int c; 3526 { 3527 USE(c); 3528 *LastChar = '\0'; /* just in case */ 3529 c_substitute(); 3530 return(e_insert(' ')); 3531 } 3532 3533 /*ARGSUSED*/ 3534 CCRETVAL 3535 e_inc_fwd(c) 3536 int c; 3537 { 3538 USE(c); 3539 patlen = 0; 3540 return e_inc_search(F_DOWN_SEARCH_HIST); 3541 } 3542 3543 3544 /*ARGSUSED*/ 3545 CCRETVAL 3546 e_inc_back(c) 3547 int c; 3548 { 3549 USE(c); 3550 patlen = 0; 3551 return e_inc_search(F_UP_SEARCH_HIST); 3552 } 3553 3554 /*ARGSUSED*/ 3555 CCRETVAL 3556 e_copyprev(c) 3557 int c; 3558 { 3559 register Char *cp, *oldc, *dp; 3560 3561 USE(c); 3562 if (Cursor == InputBuf) 3563 return(CC_ERROR); 3564 /* else */ 3565 3566 oldc = Cursor; 3567 /* does a bounds check */ 3568 cp = c_prev_word(Cursor, InputBuf, Argument); 3569 3570 c_insert((int)(oldc - cp)); 3571 for (dp = oldc; cp < oldc && dp < LastChar; cp++) 3572 *dp++ = *cp; 3573 3574 Cursor = dp; /* put cursor at end */ 3575 3576 return(CC_REFRESH); 3577 } 3578 3579 /*ARGSUSED*/ 3580 CCRETVAL 3581 e_tty_starto(c) 3582 int c; 3583 { 3584 USE(c); 3585 /* do no editing */ 3586 return(CC_NORM); 3587 } 3588 3589 /*ARGSUSED*/ 3590 CCRETVAL 3591 e_load_average(c) 3592 int c; 3593 { 3594 USE(c); 3595 PastBottom(); 3596 #ifdef TIOCSTAT 3597 /* 3598 * Here we pass &c to the ioctl because some os's (NetBSD) expect it 3599 * there even if they don't use it. (lukem@netbsd.org) 3600 */ 3601 if (ioctl(SHIN, TIOCSTAT, (ioctl_t) &c) < 0) 3602 #endif 3603 xprintf(CGETS(5, 1, "Load average unavailable\n")); 3604 return(CC_REFRESH); 3605 } 3606 3607 /*ARGSUSED*/ 3608 CCRETVAL 3609 v_chgmeta(c) 3610 int c; 3611 { 3612 USE(c); 3613 /* 3614 * Delete with insert == change: first we delete and then we leave in 3615 * insert mode. 3616 */ 3617 return(v_action(TCSHOP_DELETE|TCSHOP_INSERT)); 3618 } 3619 3620 /*ARGSUSED*/ 3621 CCRETVAL 3622 v_delmeta(c) 3623 int c; 3624 { 3625 USE(c); 3626 return(v_action(TCSHOP_DELETE)); 3627 } 3628 3629 3630 /*ARGSUSED*/ 3631 CCRETVAL 3632 v_endword(c) 3633 int c; 3634 { 3635 USE(c); 3636 if (Cursor == LastChar) 3637 return(CC_ERROR); 3638 /* else */ 3639 3640 Cursor = c_endword(Cursor, LastChar, Argument); 3641 3642 if (ActionFlag & TCSHOP_DELETE) 3643 { 3644 Cursor++; 3645 c_delfini(); 3646 return(CC_REFRESH); 3647 } 3648 3649 RefCursor(); 3650 return(CC_NORM); 3651 } 3652 3653 /*ARGSUSED*/ 3654 CCRETVAL 3655 v_eword(c) 3656 int c; 3657 { 3658 USE(c); 3659 if (Cursor == LastChar) 3660 return(CC_ERROR); 3661 /* else */ 3662 3663 Cursor = c_eword(Cursor, LastChar, Argument); 3664 3665 if (ActionFlag & TCSHOP_DELETE) { 3666 Cursor++; 3667 c_delfini(); 3668 return(CC_REFRESH); 3669 } 3670 3671 RefCursor(); 3672 return(CC_NORM); 3673 } 3674 3675 /*ARGSUSED*/ 3676 CCRETVAL 3677 v_char_fwd(c) 3678 int c; 3679 { 3680 Char ch; 3681 3682 USE(c); 3683 if (GetNextChar(&ch) != 1) 3684 return e_send_eof(0); 3685 3686 srch_dir = CHAR_FWD; 3687 srch_char = ch; 3688 3689 return v_csearch_fwd(ch, Argument, 0); 3690 3691 } 3692 3693 /*ARGSUSED*/ 3694 CCRETVAL 3695 v_char_back(c) 3696 int c; 3697 { 3698 Char ch; 3699 3700 USE(c); 3701 if (GetNextChar(&ch) != 1) 3702 return e_send_eof(0); 3703 3704 srch_dir = CHAR_BACK; 3705 srch_char = ch; 3706 3707 return v_csearch_back(ch, Argument, 0); 3708 } 3709 3710 /*ARGSUSED*/ 3711 CCRETVAL 3712 v_charto_fwd(c) 3713 int c; 3714 { 3715 Char ch; 3716 3717 USE(c); 3718 if (GetNextChar(&ch) != 1) 3719 return e_send_eof(0); 3720 3721 return v_csearch_fwd(ch, Argument, 1); 3722 3723 } 3724 3725 /*ARGSUSED*/ 3726 CCRETVAL 3727 v_charto_back(c) 3728 int c; 3729 { 3730 Char ch; 3731 3732 USE(c); 3733 if (GetNextChar(&ch) != 1) 3734 return e_send_eof(0); 3735 3736 return v_csearch_back(ch, Argument, 1); 3737 } 3738 3739 /*ARGSUSED*/ 3740 CCRETVAL 3741 v_rchar_fwd(c) 3742 int c; 3743 { 3744 USE(c); 3745 if (srch_char == 0) 3746 return CC_ERROR; 3747 3748 return srch_dir == CHAR_FWD ? v_csearch_fwd(srch_char, Argument, 0) : 3749 v_csearch_back(srch_char, Argument, 0); 3750 } 3751 3752 /*ARGSUSED*/ 3753 CCRETVAL 3754 v_rchar_back(c) 3755 int c; 3756 { 3757 USE(c); 3758 if (srch_char == 0) 3759 return CC_ERROR; 3760 3761 return srch_dir == CHAR_BACK ? v_csearch_fwd(srch_char, Argument, 0) : 3762 v_csearch_back(srch_char, Argument, 0); 3763 } 3764 3765 /*ARGSUSED*/ 3766 CCRETVAL 3767 v_undo(c) 3768 int c; 3769 { 3770 register int loop; 3771 register Char *kp, *cp; 3772 Char temp; 3773 int size; 3774 3775 USE(c); 3776 switch (UndoAction) { 3777 case TCSHOP_DELETE|TCSHOP_INSERT: 3778 case TCSHOP_DELETE: 3779 if (UndoSize == 0) return(CC_NORM); 3780 cp = UndoPtr; 3781 kp = UndoBuf; 3782 for (loop=0; loop < UndoSize; loop++) /* copy the chars */ 3783 *kp++ = *cp++; /* into UndoBuf */ 3784 3785 for (cp = UndoPtr; cp <= LastChar; cp++) 3786 *cp = cp[UndoSize]; 3787 3788 LastChar -= UndoSize; 3789 Cursor = UndoPtr; 3790 3791 UndoAction = TCSHOP_INSERT; 3792 break; 3793 3794 case TCSHOP_INSERT: 3795 if (UndoSize == 0) return(CC_NORM); 3796 cp = UndoPtr; 3797 Cursor = UndoPtr; 3798 kp = UndoBuf; 3799 c_insert(UndoSize); /* open the space, */ 3800 for (loop = 0; loop < UndoSize; loop++) /* copy the chars */ 3801 *cp++ = *kp++; 3802 3803 UndoAction = TCSHOP_DELETE; 3804 break; 3805 3806 case TCSHOP_CHANGE: 3807 if (UndoSize == 0) return(CC_NORM); 3808 cp = UndoPtr; 3809 Cursor = UndoPtr; 3810 kp = UndoBuf; 3811 size = (int)(Cursor-LastChar); /* NOT NSL independant */ 3812 if (size < UndoSize) 3813 size = UndoSize; 3814 for(loop = 0; loop < size; loop++) { 3815 temp = *kp; 3816 *kp++ = *cp; 3817 *cp++ = temp; 3818 } 3819 break; 3820 3821 default: 3822 return(CC_ERROR); 3823 } 3824 3825 return(CC_REFRESH); 3826 } 3827 3828 /*ARGSUSED*/ 3829 CCRETVAL 3830 v_ush_meta(c) 3831 int c; 3832 { 3833 USE(c); 3834 return v_search(F_UP_SEARCH_HIST); 3835 } 3836 3837 /*ARGSUSED*/ 3838 CCRETVAL 3839 v_dsh_meta(c) 3840 int c; 3841 { 3842 USE(c); 3843 return v_search(F_DOWN_SEARCH_HIST); 3844 } 3845 3846 /*ARGSUSED*/ 3847 CCRETVAL 3848 v_rsrch_fwd(c) 3849 int c; 3850 { 3851 USE(c); 3852 if (patlen == 0) return(CC_ERROR); 3853 return(v_repeat_srch(searchdir)); 3854 } 3855 3856 /*ARGSUSED*/ 3857 CCRETVAL 3858 v_rsrch_back(c) 3859 int c; 3860 { 3861 USE(c); 3862 if (patlen == 0) return(CC_ERROR); 3863 return(v_repeat_srch(searchdir == F_UP_SEARCH_HIST ? 3864 F_DOWN_SEARCH_HIST : F_UP_SEARCH_HIST)); 3865 } 3866 3867 #ifndef WINNT 3868 /* Since ed.defns.h is generated from ed.defns.c, these empty 3869 functions will keep the F_NUM_FNS consistent 3870 */ 3871 CCRETVAL 3872 e_copy_to_clipboard(c) 3873 int c; 3874 { 3875 USE(c); 3876 return CC_ERROR; 3877 } 3878 3879 CCRETVAL 3880 e_paste_from_clipboard(c) 3881 int c; 3882 { 3883 USE(c); 3884 return (CC_ERROR); 3885 } 3886 3887 CCRETVAL 3888 e_dosify_next(c) 3889 int c; 3890 { 3891 USE(c); 3892 return (CC_ERROR); 3893 } 3894 CCRETVAL 3895 e_dosify_prev(c) 3896 int c; 3897 { 3898 USE(c); 3899 return (CC_ERROR); 3900 } 3901 #else /* WINNT */ 3902 /*ARGSUSED*/ 3903 CCRETVAL 3904 e_dosify_next(c) 3905 int c; 3906 { 3907 register Char *cp, *p, *kp; 3908 3909 USE(c); 3910 if (Cursor == LastChar) 3911 return(CC_ERROR); 3912 /* else */ 3913 3914 cp = Cursor; 3915 while( cp < LastChar) { 3916 if ( (*cp & CHAR == ' ') && (cp[-1] & CHAR != '\\') ) 3917 break; 3918 cp++; 3919 } 3920 3921 for (p = Cursor, kp = KillBuf; p < cp; p++) {/* save the text */ 3922 if ( ( *p & CHAR ) == '/') { 3923 *kp++ = '\\'; 3924 *kp++ = '\\'; 3925 } 3926 else 3927 *kp++ = *p; 3928 } 3929 LastKill = kp; 3930 3931 c_delafter((int)(cp - Cursor)); /* delete after dot */ 3932 if (Cursor > LastChar) 3933 Cursor = LastChar; /* bounds check */ 3934 return (e_yank_kill(c)); 3935 } 3936 /*ARGSUSED*/ 3937 CCRETVAL 3938 e_dosify_prev(c) 3939 int c; 3940 { 3941 register Char *cp, *p, *kp; 3942 3943 USE(c); 3944 if (Cursor == InputBuf) 3945 return(CC_ERROR); 3946 /* else */ 3947 3948 cp = Cursor-1; 3949 /* Skip trailing spaces */ 3950 while ((cp > InputBuf) && ( (*cp & CHAR) == ' ')) 3951 cp--; 3952 3953 while (cp > InputBuf) { 3954 if ( ((*cp & CHAR) == ' ') && ((cp[-1] & CHAR) != '\\') ) 3955 break; 3956 cp--; 3957 } 3958 3959 for (p = cp, kp = KillBuf; p < Cursor; p++) {/* save the text */ 3960 if ( ( *p & CHAR ) == '/') { 3961 *kp++ = '\\'; 3962 *kp++ = '\\'; 3963 } 3964 else 3965 *kp++ = *p; 3966 } 3967 LastKill = kp; 3968 3969 c_delbefore((int)(Cursor - cp)); /* delete before dot */ 3970 Cursor = cp; 3971 if (Cursor < InputBuf) 3972 Cursor = InputBuf; /* bounds check */ 3973 return(e_yank_kill(c)); 3974 } 3975 #endif /* !WINNT */ 3976 3977 #ifdef notdef 3978 void 3979 MoveCursor(n) /* move cursor + right - left char */ 3980 int n; 3981 { 3982 Cursor = Cursor + n; 3983 if (Cursor < InputBuf) 3984 Cursor = InputBuf; 3985 if (Cursor > LastChar) 3986 Cursor = LastChar; 3987 return; 3988 } 3989 3990 Char * 3991 GetCursor() 3992 { 3993 return(Cursor); 3994 } 3995 3996 int 3997 PutCursor(p) 3998 Char *p; 3999 { 4000 if (p < InputBuf || p > LastChar) 4001 return 1; /* Error */ 4002 Cursor = p; 4003 return 0; 4004 } 4005 #endif 4006