1 /* $Header: /src/pub/tcsh/ed.chared.c,v 3.63 2000/11/11 23:03:33 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.63 2000/11/11 23:03:33 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 void c_delafter __P((int)); 122 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 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 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) / sizeof(Char), &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 #ifdef IS_ASCII 1262 case '\r': /* Newline */ 1263 case '\n': 1264 #else 1265 case '\012': /* ASCII Line feed */ 1266 case '\015': /* ASCII (or EBCDIC) 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) / sizeof(Char), &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) / sizeof(Char), 1859 &hp->Hlex)); 1860 } 1861 hl = HistLit ? hp->histline : sprlex(sbuf, sizeof(sbuf) / sizeof(Char), 1862 &hp->Hlex); 1863 #ifdef SDEBUG 1864 xprintf("Comparing with \"%S\"\n", hl); 1865 #endif 1866 if ((Strncmp(hl, InputBuf, (size_t) (LastChar - InputBuf)) || 1867 hl[LastChar-InputBuf]) && c_hmatch(hl)) { 1868 found++; 1869 break; 1870 } 1871 h++; 1872 hp = hp->Hnext; 1873 } 1874 1875 if (!found) { 1876 #ifdef SDEBUG 1877 xprintf("not found\n"); 1878 #endif 1879 return(CC_ERROR); 1880 } 1881 1882 Hist_num = h; 1883 1884 return(c_get_histline()); 1885 } 1886 1887 /*ARGSUSED*/ 1888 CCRETVAL 1889 e_down_search_hist(c) 1890 int c; 1891 { 1892 struct Hist *hp; 1893 int h; 1894 bool found = 0; 1895 1896 USE(c); 1897 ActionFlag = TCSHOP_NOP; 1898 UndoAction = TCSHOP_NOP; 1899 *LastChar = '\0'; /* just in case */ 1900 1901 if (Hist_num == 0) 1902 return(CC_ERROR); 1903 1904 hp = Histlist.Hnext; 1905 if (hp == 0) 1906 return(CC_ERROR); 1907 1908 c_hsetpat(); /* Set search pattern !! */ 1909 1910 for (h = 1; h < Hist_num && hp; h++) { 1911 Char sbuf[INBUFSIZE], *hl; 1912 if (hp->histline == NULL) { 1913 hp->histline = Strsave(sprlex(sbuf, sizeof(sbuf) / sizeof(Char), 1914 &hp->Hlex)); 1915 } 1916 hl = HistLit ? hp->histline : sprlex(sbuf, sizeof(sbuf) / sizeof(Char), 1917 &hp->Hlex); 1918 #ifdef SDEBUG 1919 xprintf("Comparing with \"%S\"\n", hl); 1920 #endif 1921 if ((Strncmp(hl, InputBuf, (size_t) (LastChar - InputBuf)) || 1922 hl[LastChar-InputBuf]) && c_hmatch(hl)) 1923 found = h; 1924 hp = hp->Hnext; 1925 } 1926 1927 if (!found) { /* is it the current history number? */ 1928 if (!c_hmatch(HistBuf)) { 1929 #ifdef SDEBUG 1930 xprintf("not found\n"); 1931 #endif 1932 return(CC_ERROR); 1933 } 1934 } 1935 1936 Hist_num = found; 1937 1938 return(c_get_histline()); 1939 } 1940 1941 /*ARGSUSED*/ 1942 CCRETVAL 1943 e_helpme(c) 1944 int c; 1945 { 1946 USE(c); 1947 PastBottom(); 1948 *LastChar = '\0'; /* just in case */ 1949 return(CC_HELPME); 1950 } 1951 1952 /*ARGSUSED*/ 1953 CCRETVAL 1954 e_correct(c) 1955 int c; 1956 { 1957 USE(c); 1958 *LastChar = '\0'; /* just in case */ 1959 return(CC_CORRECT); 1960 } 1961 1962 /*ARGSUSED*/ 1963 CCRETVAL 1964 e_correctl(c) 1965 int c; 1966 { 1967 USE(c); 1968 *LastChar = '\0'; /* just in case */ 1969 return(CC_CORRECT_L); 1970 } 1971 1972 /*ARGSUSED*/ 1973 CCRETVAL 1974 e_run_fg_editor(c) 1975 int c; 1976 { 1977 register struct process *pp; 1978 extern bool tellwhat; 1979 1980 USE(c); 1981 if ((pp = find_stop_ed()) != NULL) { 1982 /* save our editor state so we can restore it */ 1983 tellwhat = 1; 1984 copyn(WhichBuf, InputBuf, INBUFSIZE); 1985 LastWhich = WhichBuf + (LastChar - InputBuf); 1986 CursWhich = WhichBuf + (Cursor - InputBuf); 1987 HistWhich = Hist_num; 1988 Hist_num = 0; /* for the history commands */ 1989 1990 /* put the tty in a sane mode */ 1991 PastBottom(); 1992 (void) Cookedmode(); /* make sure the tty is set up correctly */ 1993 1994 /* do it! */ 1995 fg_proc_entry(pp); 1996 1997 (void) Rawmode(); /* go on */ 1998 Refresh(); 1999 tellwhat = 0; 2000 } 2001 return(CC_NORM); 2002 } 2003 2004 /*ARGSUSED*/ 2005 CCRETVAL 2006 e_list_choices(c) 2007 int c; 2008 { 2009 USE(c); 2010 PastBottom(); 2011 *LastChar = '\0'; /* just in case */ 2012 return(CC_LIST_CHOICES); 2013 } 2014 2015 /*ARGSUSED*/ 2016 CCRETVAL 2017 e_list_all(c) 2018 int c; 2019 { 2020 USE(c); 2021 PastBottom(); 2022 *LastChar = '\0'; /* just in case */ 2023 return(CC_LIST_ALL); 2024 } 2025 2026 /*ARGSUSED*/ 2027 CCRETVAL 2028 e_list_glob(c) 2029 int c; 2030 { 2031 USE(c); 2032 PastBottom(); 2033 *LastChar = '\0'; /* just in case */ 2034 return(CC_LIST_GLOB); 2035 } 2036 2037 /*ARGSUSED*/ 2038 CCRETVAL 2039 e_expand_glob(c) 2040 int c; 2041 { 2042 USE(c); 2043 *LastChar = '\0'; /* just in case */ 2044 return(CC_EXPAND_GLOB); 2045 } 2046 2047 /*ARGSUSED*/ 2048 CCRETVAL 2049 e_normalize_path(c) 2050 int c; 2051 { 2052 USE(c); 2053 *LastChar = '\0'; /* just in case */ 2054 return(CC_NORMALIZE_PATH); 2055 } 2056 2057 /*ARGSUSED*/ 2058 CCRETVAL 2059 e_normalize_command(c) 2060 int c; 2061 { 2062 USE(c); 2063 *LastChar = '\0'; /* just in case */ 2064 return(CC_NORMALIZE_COMMAND); 2065 } 2066 2067 /*ARGSUSED*/ 2068 CCRETVAL 2069 e_expand_vars(c) 2070 int c; 2071 { 2072 USE(c); 2073 *LastChar = '\0'; /* just in case */ 2074 return(CC_EXPAND_VARS); 2075 } 2076 2077 /*ARGSUSED*/ 2078 CCRETVAL 2079 e_which(c) 2080 int c; 2081 { /* do a fast command line which(1) */ 2082 USE(c); 2083 PastBottom(); 2084 *LastChar = '\0'; /* just in case */ 2085 return(CC_WHICH); 2086 } 2087 2088 /*ARGSUSED*/ 2089 CCRETVAL 2090 e_last_item(c) 2091 int c; 2092 { /* insert the last element of the prev. cmd */ 2093 register Char *cp; 2094 register struct Hist *hp; 2095 register struct wordent *wp, *firstp; 2096 register int i; 2097 Char buf[INBUFSIZE]; 2098 2099 USE(c); 2100 if (Argument <= 0) 2101 return(CC_ERROR); 2102 2103 hp = Histlist.Hnext; 2104 if (hp == NULL) { /* this is only if no history */ 2105 return(CC_ERROR); 2106 } 2107 2108 wp = (hp->Hlex).prev; 2109 2110 if (wp->prev == (struct wordent *) NULL) 2111 return(CC_ERROR); /* an empty history entry */ 2112 2113 firstp = (hp->Hlex).next; 2114 2115 /* back up arg words in lex */ 2116 for (i = 0; i < Argument && wp != firstp; i++) { 2117 wp = wp->prev; 2118 } 2119 2120 cp = expand_lex(buf, INBUFSIZE, wp->prev, 0, i - 1); 2121 *cp = '\0'; 2122 if (InsertStr(buf)) 2123 return(CC_ERROR); 2124 2125 return(CC_REFRESH); 2126 } 2127 2128 /*ARGSUSED*/ 2129 CCRETVAL 2130 e_dabbrev_expand(c) 2131 int c; 2132 { /* expand to preceding word matching prefix */ 2133 register Char *cp, *ncp, *bp; 2134 register struct Hist *hp; 2135 register int arg = 0, len = 0, i; /* len = 0 to shut up gcc -Wall */ 2136 register bool found = 0; 2137 Char hbuf[INBUFSIZE]; 2138 static int oldevent, hist, word; 2139 static Char *start, *oldcursor; 2140 2141 USE(c); 2142 if (Argument <= 0) 2143 return(CC_ERROR); 2144 2145 cp = c_preword(Cursor, InputBuf, 1); 2146 if (cp == Cursor || Isspace(*cp)) 2147 return(CC_ERROR); 2148 2149 hp = Histlist.Hnext; 2150 bp = InputBuf; 2151 if (Argument == 1 && eventno == oldevent && cp == start && 2152 Cursor == oldcursor && patlen > 0 && Strncmp(patbuf, cp, patlen) == 0){ 2153 /* continue previous search - go to last match (hist/word) */ 2154 if (hist != 0) { /* need to move up history */ 2155 for (i = 1; i < hist && hp != NULL; i++) 2156 hp = hp->Hnext; 2157 if (hp == NULL) /* "can't happen" */ 2158 return(CC_ERROR); 2159 cp = expand_lex(hbuf, INBUFSIZE, &hp->Hlex, 0, NCARGS); 2160 *cp = '\0'; 2161 bp = hbuf; 2162 hp = hp->Hnext; 2163 } 2164 cp = c_preword(cp, bp, word); 2165 } else { /* starting new search */ 2166 oldevent = eventno; 2167 start = cp; 2168 patlen = (int) (Cursor - cp); 2169 (void) Strncpy(patbuf, cp, patlen); 2170 hist = 0; 2171 word = 0; 2172 } 2173 2174 while (!found) { 2175 ncp = c_preword(cp, bp, 1); 2176 if (ncp == cp || Isspace(*ncp)) { /* beginning of line */ 2177 hist++; 2178 word = 0; 2179 if (hp == NULL) 2180 return(CC_ERROR); 2181 cp = expand_lex(hbuf, INBUFSIZE, &hp->Hlex, 0, NCARGS); 2182 *cp = '\0'; 2183 bp = hbuf; 2184 hp = hp->Hnext; 2185 continue; 2186 } else { 2187 word++; 2188 len = (int) (c_endword(ncp-1, cp, 1) - ncp + 1); 2189 cp = ncp; 2190 } 2191 if (len > patlen && Strncmp(cp, patbuf, patlen) == 0) { 2192 /* We don't fully check distinct matches as Gnuemacs does: */ 2193 if (Argument > 1) { /* just count matches */ 2194 if (++arg >= Argument) 2195 found++; 2196 } else { /* match if distinct from previous */ 2197 if (len != Cursor - start || Strncmp(cp, start, len) != 0) 2198 found++; 2199 } 2200 } 2201 } 2202 2203 if (LastChar + len - (Cursor - start) >= InputLim) 2204 return(CC_ERROR); /* no room */ 2205 DeleteBack(Cursor - start); 2206 c_insert(len); 2207 while (len--) 2208 *Cursor++ = *cp++; 2209 oldcursor = Cursor; 2210 return(CC_REFRESH); 2211 } 2212 2213 /*ARGSUSED*/ 2214 CCRETVAL 2215 e_yank_kill(c) 2216 int c; 2217 { /* almost like GnuEmacs */ 2218 register Char *kp, *cp; 2219 2220 USE(c); 2221 if (LastKill == KillBuf) /* if zero content */ 2222 return(CC_ERROR); 2223 2224 if (LastChar + (LastKill - KillBuf) >= InputLim) 2225 return(CC_ERROR); /* end of buffer space */ 2226 2227 /* else */ 2228 Mark = Cursor; /* set the mark */ 2229 cp = Cursor; /* for speed */ 2230 2231 c_insert((int)(LastKill - KillBuf)); /* open the space, */ 2232 for (kp = KillBuf; kp < LastKill; kp++) /* copy the chars */ 2233 *cp++ = *kp; 2234 2235 if (Argument == 1) /* if an arg, cursor at beginning */ 2236 Cursor = cp; /* else cursor at end */ 2237 2238 return(CC_REFRESH); 2239 } 2240 2241 /*ARGSUSED*/ 2242 CCRETVAL 2243 v_delprev(c) /* Backspace key in insert mode */ 2244 int c; 2245 { 2246 int rc; 2247 2248 USE(c); 2249 rc = CC_ERROR; 2250 2251 if (InsertPos != 0) { 2252 if (Argument <= Cursor - InsertPos) { 2253 c_delbefore(Argument); /* delete before */ 2254 Cursor -= Argument; 2255 #if defined(DSPMBYTE) 2256 if (_enable_mbdisp && extdel) { 2257 Cursor--; 2258 e_redisp(c); 2259 } 2260 #endif 2261 rc = CC_REFRESH; 2262 } 2263 } 2264 return(rc); 2265 } /* v_delprev */ 2266 2267 /*ARGSUSED*/ 2268 CCRETVAL 2269 e_delprev(c) 2270 int c; 2271 { 2272 USE(c); 2273 if (Cursor > InputBuf) { 2274 c_delbefore(Argument); /* delete before dot */ 2275 if (Argument > Cursor - InputBuf) 2276 Cursor = InputBuf; /* bounds check */ 2277 else 2278 Cursor -= Argument; 2279 #if defined(DSPMBYTE) 2280 if (_enable_mbdisp && extdel && Cursor > InputBuf) { 2281 Cursor--; 2282 e_redisp(c); 2283 } 2284 #endif 2285 return(CC_REFRESH); 2286 } 2287 else { 2288 return(CC_ERROR); 2289 } 2290 } 2291 2292 /*ARGSUSED*/ 2293 CCRETVAL 2294 e_delwordprev(c) 2295 int c; 2296 { 2297 register Char *cp, *p, *kp; 2298 2299 USE(c); 2300 if (Cursor == InputBuf) 2301 return(CC_ERROR); 2302 /* else */ 2303 2304 cp = c_prev_word(Cursor, InputBuf, Argument); 2305 2306 for (p = cp, kp = KillBuf; p < Cursor; p++) /* save the text */ 2307 *kp++ = *p; 2308 LastKill = kp; 2309 2310 c_delbefore((int)(Cursor - cp)); /* delete before dot */ 2311 Cursor = cp; 2312 if (Cursor < InputBuf) 2313 Cursor = InputBuf; /* bounds check */ 2314 return(CC_REFRESH); 2315 } 2316 2317 /* DCS <dcs@neutron.chem.yale.edu>, 9 Oct 93 2318 * 2319 * Changed the names of some of the ^D family of editor functions to 2320 * correspond to what they actually do and created new e_delnext_list 2321 * for completeness. 2322 * 2323 * Old names: New names: 2324 * 2325 * delete-char delete-char-or-eof 2326 * F_DELNEXT F_DELNEXT_EOF 2327 * e_delnext e_delnext_eof 2328 * edelnxt edelnxteof 2329 * delete-char-or-eof delete-char 2330 * F_DELNEXT_EOF F_DELNEXT 2331 * e_delnext_eof e_delnext 2332 * edelnxteof edelnxt 2333 * delete-char-or-list delete-char-or-list-or-eof 2334 * F_LIST_DELNEXT F_DELNEXT_LIST_EOF 2335 * e_list_delnext e_delnext_list_eof 2336 * edellsteof 2337 * (no old equivalent) delete-char-or-list 2338 * F_DELNEXT_LIST 2339 * e_delnext_list 2340 * e_delnxtlst 2341 */ 2342 2343 /* added by mtk@ari.ncl.omron.co.jp (920818) */ 2344 /* rename e_delnext() -> e_delnext_eof() */ 2345 /*ARGSUSED*/ 2346 CCRETVAL 2347 e_delnext(c) 2348 int c; 2349 { 2350 USE(c); 2351 if (Cursor == LastChar) {/* if I'm at the end */ 2352 if (!VImode) { 2353 return(CC_ERROR); 2354 } 2355 else { 2356 if (Cursor != InputBuf) 2357 Cursor--; 2358 else 2359 return(CC_ERROR); 2360 } 2361 } 2362 c_delafter(Argument); /* delete after dot */ 2363 if (Cursor > LastChar) 2364 Cursor = LastChar; /* bounds check */ 2365 return(CC_REFRESH); 2366 } 2367 2368 2369 /*ARGSUSED*/ 2370 CCRETVAL 2371 e_delnext_eof(c) 2372 int c; 2373 { 2374 USE(c); 2375 if (Cursor == LastChar) {/* if I'm at the end */ 2376 if (!VImode) { 2377 if (Cursor == InputBuf) { 2378 /* if I'm also at the beginning */ 2379 so_write(STReof, 4);/* then do a EOF */ 2380 flush(); 2381 return(CC_EOF); 2382 } 2383 else 2384 return(CC_ERROR); 2385 } 2386 else { 2387 if (Cursor != InputBuf) 2388 Cursor--; 2389 else 2390 return(CC_ERROR); 2391 } 2392 } 2393 c_delafter(Argument); /* delete after dot */ 2394 if (Cursor > LastChar) 2395 Cursor = LastChar; /* bounds check */ 2396 return(CC_REFRESH); 2397 } 2398 2399 /*ARGSUSED*/ 2400 CCRETVAL 2401 e_delnext_list(c) 2402 int c; 2403 { 2404 USE(c); 2405 if (Cursor == LastChar) { /* if I'm at the end */ 2406 PastBottom(); 2407 *LastChar = '\0'; /* just in case */ 2408 return(CC_LIST_CHOICES); 2409 } 2410 else { 2411 c_delafter(Argument); /* delete after dot */ 2412 if (Cursor > LastChar) 2413 Cursor = LastChar; /* bounds check */ 2414 return(CC_REFRESH); 2415 } 2416 } 2417 2418 /*ARGSUSED*/ 2419 CCRETVAL 2420 e_delnext_list_eof(c) 2421 int c; 2422 { 2423 USE(c); 2424 if (Cursor == LastChar) { /* if I'm at the end */ 2425 if (Cursor == InputBuf) { /* if I'm also at the beginning */ 2426 so_write(STReof, 4);/* then do a EOF */ 2427 flush(); 2428 return(CC_EOF); 2429 } 2430 else { 2431 PastBottom(); 2432 *LastChar = '\0'; /* just in case */ 2433 return(CC_LIST_CHOICES); 2434 } 2435 } 2436 else { 2437 c_delafter(Argument); /* delete after dot */ 2438 if (Cursor > LastChar) 2439 Cursor = LastChar; /* bounds check */ 2440 return(CC_REFRESH); 2441 } 2442 } 2443 2444 /*ARGSUSED*/ 2445 CCRETVAL 2446 e_list_eof(c) 2447 int c; 2448 { 2449 CCRETVAL rv; 2450 2451 USE(c); 2452 if (Cursor == LastChar && Cursor == InputBuf) { 2453 so_write(STReof, 4); /* then do a EOF */ 2454 flush(); 2455 rv = CC_EOF; 2456 } 2457 else { 2458 PastBottom(); 2459 *LastChar = '\0'; /* just in case */ 2460 rv = CC_LIST_CHOICES; 2461 } 2462 return rv; 2463 } 2464 2465 /*ARGSUSED*/ 2466 CCRETVAL 2467 e_delwordnext(c) 2468 int c; 2469 { 2470 register Char *cp, *p, *kp; 2471 2472 USE(c); 2473 if (Cursor == LastChar) 2474 return(CC_ERROR); 2475 /* else */ 2476 2477 cp = c_next_word(Cursor, LastChar, Argument); 2478 2479 for (p = Cursor, kp = KillBuf; p < cp; p++) /* save the text */ 2480 *kp++ = *p; 2481 LastKill = kp; 2482 2483 c_delafter((int)(cp - Cursor)); /* delete after dot */ 2484 if (Cursor > LastChar) 2485 Cursor = LastChar; /* bounds check */ 2486 return(CC_REFRESH); 2487 } 2488 2489 /*ARGSUSED*/ 2490 CCRETVAL 2491 e_toend(c) 2492 int c; 2493 { 2494 USE(c); 2495 Cursor = LastChar; 2496 if (VImode) 2497 if (ActionFlag & TCSHOP_DELETE) { 2498 c_delfini(); 2499 return(CC_REFRESH); 2500 } 2501 RefCursor(); /* move the cursor */ 2502 return(CC_NORM); 2503 } 2504 2505 /*ARGSUSED*/ 2506 CCRETVAL 2507 e_tobeg(c) 2508 int c; 2509 { 2510 USE(c); 2511 Cursor = InputBuf; 2512 2513 if (VImode) { 2514 while (Isspace(*Cursor)) /* We want FIRST non space character */ 2515 Cursor++; 2516 if (ActionFlag & TCSHOP_DELETE) { 2517 c_delfini(); 2518 return(CC_REFRESH); 2519 } 2520 } 2521 2522 RefCursor(); /* move the cursor */ 2523 return(CC_NORM); 2524 } 2525 2526 /*ARGSUSED*/ 2527 CCRETVAL 2528 e_killend(c) 2529 int c; 2530 { 2531 register Char *kp, *cp; 2532 2533 USE(c); 2534 cp = Cursor; 2535 kp = KillBuf; 2536 while (cp < LastChar) 2537 *kp++ = *cp++; /* copy it */ 2538 LastKill = kp; 2539 LastChar = Cursor; /* zap! -- delete to end */ 2540 return(CC_REFRESH); 2541 } 2542 2543 2544 /*ARGSUSED*/ 2545 CCRETVAL 2546 e_killbeg(c) 2547 int c; 2548 { 2549 register Char *kp, *cp; 2550 2551 USE(c); 2552 cp = InputBuf; 2553 kp = KillBuf; 2554 while (cp < Cursor) 2555 *kp++ = *cp++; /* copy it */ 2556 LastKill = kp; 2557 c_delbefore((int)(Cursor - InputBuf)); 2558 Cursor = InputBuf; /* zap! */ 2559 return(CC_REFRESH); 2560 } 2561 2562 /*ARGSUSED*/ 2563 CCRETVAL 2564 e_killall(c) 2565 int c; 2566 { 2567 register Char *kp, *cp; 2568 2569 USE(c); 2570 cp = InputBuf; 2571 kp = KillBuf; 2572 while (cp < LastChar) 2573 *kp++ = *cp++; /* copy it */ 2574 LastKill = kp; 2575 LastChar = InputBuf; /* zap! -- delete all of it */ 2576 Cursor = InputBuf; 2577 return(CC_REFRESH); 2578 } 2579 2580 /*ARGSUSED*/ 2581 CCRETVAL 2582 e_killregion(c) 2583 int c; 2584 { 2585 register Char *kp, *cp; 2586 2587 USE(c); 2588 if (!Mark) 2589 return(CC_ERROR); 2590 2591 if (Mark > Cursor) { 2592 cp = Cursor; 2593 kp = KillBuf; 2594 while (cp < Mark) 2595 *kp++ = *cp++; /* copy it */ 2596 LastKill = kp; 2597 c_delafter((int)(cp - Cursor)); /* delete it - UNUSED BY VI mode */ 2598 } 2599 else { /* mark is before cursor */ 2600 cp = Mark; 2601 kp = KillBuf; 2602 while (cp < Cursor) 2603 *kp++ = *cp++; /* copy it */ 2604 LastKill = kp; 2605 c_delbefore((int)(cp - Mark)); 2606 Cursor = Mark; 2607 } 2608 return(CC_REFRESH); 2609 } 2610 2611 /*ARGSUSED*/ 2612 CCRETVAL 2613 e_copyregion(c) 2614 int c; 2615 { 2616 register Char *kp, *cp; 2617 2618 USE(c); 2619 if (!Mark) 2620 return(CC_ERROR); 2621 2622 if (Mark > Cursor) { 2623 cp = Cursor; 2624 kp = KillBuf; 2625 while (cp < Mark) 2626 *kp++ = *cp++; /* copy it */ 2627 LastKill = kp; 2628 } 2629 else { /* mark is before cursor */ 2630 cp = Mark; 2631 kp = KillBuf; 2632 while (cp < Cursor) 2633 *kp++ = *cp++; /* copy it */ 2634 LastKill = kp; 2635 } 2636 return(CC_NORM); /* don't even need to Refresh() */ 2637 } 2638 2639 /*ARGSUSED*/ 2640 CCRETVAL 2641 e_charswitch(cc) 2642 int cc; 2643 { 2644 register Char c; 2645 2646 USE(cc); 2647 2648 /* do nothing if we are at beginning of line or have only one char */ 2649 if (Cursor == &InputBuf[0] || LastChar == &InputBuf[1]) { 2650 return(CC_ERROR); 2651 } 2652 2653 if (Cursor < LastChar) { 2654 Cursor++; 2655 } 2656 c = Cursor[-2]; 2657 Cursor[-2] = Cursor[-1]; 2658 Cursor[-1] = c; 2659 return(CC_REFRESH); 2660 } 2661 2662 /*ARGSUSED*/ 2663 CCRETVAL 2664 e_gcharswitch(cc) 2665 int cc; 2666 { /* gosmacs style ^T */ 2667 register Char c; 2668 2669 USE(cc); 2670 if (Cursor > &InputBuf[1]) {/* must have at least two chars entered */ 2671 c = Cursor[-2]; 2672 Cursor[-2] = Cursor[-1]; 2673 Cursor[-1] = c; 2674 return(CC_REFRESH); 2675 } 2676 else { 2677 return(CC_ERROR); 2678 } 2679 } 2680 2681 #if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */ 2682 /*ARGSUSED*/ 2683 static void 2684 e_charback_mbyte(argument) 2685 int argument; 2686 { 2687 if (!_enable_mbdisp) { 2688 if (Argument > Cursor - InputBuf) 2689 Cursor = InputBuf; 2690 else 2691 Cursor -= Argument; 2692 } 2693 else { 2694 while (0 < argument && Cursor > InputBuf) { 2695 if (Cursor - 1 != InputBuf && 2696 Ismbyte1(*(Cursor - 2)) && Ismbyte2(*(Cursor - 1))) { 2697 Cursor--; 2698 } 2699 Cursor--; 2700 argument--; 2701 } 2702 } 2703 } 2704 #endif 2705 2706 /*ARGSUSED*/ 2707 CCRETVAL 2708 e_charback(c) 2709 int c; 2710 { 2711 USE(c); 2712 if (Cursor > InputBuf) { 2713 #if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */ 2714 e_charback_mbyte(Argument); 2715 #else 2716 if (Argument > Cursor - InputBuf) 2717 Cursor = InputBuf; 2718 else 2719 Cursor -= Argument; 2720 #endif 2721 2722 if (VImode) 2723 if (ActionFlag & TCSHOP_DELETE) { 2724 c_delfini(); 2725 return(CC_REFRESH); 2726 } 2727 2728 RefCursor(); 2729 return(CC_NORM); 2730 } 2731 else { 2732 return(CC_ERROR); 2733 } 2734 } 2735 2736 /*ARGSUSED*/ 2737 CCRETVAL 2738 v_wordback(c) 2739 int c; 2740 { 2741 USE(c); 2742 if (Cursor == InputBuf) 2743 return(CC_ERROR); 2744 /* else */ 2745 2746 Cursor = c_preword(Cursor, InputBuf, Argument); /* bounds check */ 2747 2748 if (ActionFlag & TCSHOP_DELETE) { 2749 c_delfini(); 2750 return(CC_REFRESH); 2751 } 2752 2753 RefCursor(); 2754 return(CC_NORM); 2755 } 2756 2757 /*ARGSUSED*/ 2758 CCRETVAL 2759 e_wordback(c) 2760 int c; 2761 { 2762 USE(c); 2763 if (Cursor == InputBuf) 2764 return(CC_ERROR); 2765 /* else */ 2766 2767 Cursor = c_prev_word(Cursor, InputBuf, Argument); /* bounds check */ 2768 2769 if (VImode) 2770 if (ActionFlag & TCSHOP_DELETE) { 2771 c_delfini(); 2772 return(CC_REFRESH); 2773 } 2774 2775 RefCursor(); 2776 return(CC_NORM); 2777 } 2778 2779 #if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */ 2780 /*ARGSUSED*/ 2781 static void 2782 e_charfwd_mbyte(argument) 2783 int argument; 2784 { 2785 if (!_enable_mbdisp) 2786 Cursor += argument; 2787 else 2788 while (0 < argument && Cursor < LastChar) { 2789 if (Cursor + 1 != LastChar && 2790 Ismbyte1(*Cursor) && Ismbyte2(*(Cursor + 1))) { 2791 Cursor++; 2792 } 2793 Cursor++; 2794 argument--; 2795 } 2796 } 2797 #endif 2798 2799 /*ARGSUSED*/ 2800 CCRETVAL 2801 e_charfwd(c) 2802 int c; 2803 { 2804 USE(c); 2805 if (Cursor < LastChar) { 2806 #if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */ 2807 e_charfwd_mbyte(Argument); 2808 #else 2809 Cursor += Argument; 2810 #endif 2811 if (Cursor > LastChar) 2812 Cursor = LastChar; 2813 2814 if (VImode) 2815 if (ActionFlag & TCSHOP_DELETE) { 2816 c_delfini(); 2817 return(CC_REFRESH); 2818 } 2819 2820 RefCursor(); 2821 return(CC_NORM); 2822 } 2823 else { 2824 return(CC_ERROR); 2825 } 2826 } 2827 2828 /*ARGSUSED*/ 2829 CCRETVAL 2830 e_wordfwd(c) 2831 int c; 2832 { 2833 USE(c); 2834 if (Cursor == LastChar) 2835 return(CC_ERROR); 2836 /* else */ 2837 2838 Cursor = c_next_word(Cursor, LastChar, Argument); 2839 2840 if (VImode) 2841 if (ActionFlag & TCSHOP_DELETE) { 2842 c_delfini(); 2843 return(CC_REFRESH); 2844 } 2845 2846 RefCursor(); 2847 return(CC_NORM); 2848 } 2849 2850 /*ARGSUSED*/ 2851 CCRETVAL 2852 v_wordfwd(c) 2853 int c; 2854 { 2855 USE(c); 2856 if (Cursor == LastChar) 2857 return(CC_ERROR); 2858 /* else */ 2859 2860 Cursor = c_nexword(Cursor, LastChar, Argument); 2861 2862 if (VImode) 2863 if (ActionFlag & TCSHOP_DELETE) { 2864 c_delfini(); 2865 return(CC_REFRESH); 2866 } 2867 2868 RefCursor(); 2869 return(CC_NORM); 2870 } 2871 2872 /*ARGSUSED*/ 2873 CCRETVAL 2874 v_wordbegnext(c) 2875 int c; 2876 { 2877 USE(c); 2878 if (Cursor == LastChar) 2879 return(CC_ERROR); 2880 /* else */ 2881 2882 Cursor = c_next_word(Cursor, LastChar, Argument); 2883 if (Cursor < LastChar) 2884 Cursor++; 2885 2886 if (VImode) 2887 if (ActionFlag & TCSHOP_DELETE) { 2888 c_delfini(); 2889 return(CC_REFRESH); 2890 } 2891 2892 RefCursor(); 2893 return(CC_NORM); 2894 } 2895 2896 /*ARGSUSED*/ 2897 static CCRETVAL 2898 v_repeat_srch(c) 2899 int c; 2900 { 2901 CCRETVAL rv = CC_ERROR; 2902 #ifdef SDEBUG 2903 xprintf("dir %d patlen %d patbuf %S\n", 2904 c, patlen, patbuf); 2905 #endif 2906 2907 LastCmd = (KEYCMD) c; /* Hack to stop c_hsetpat */ 2908 LastChar = InputBuf; 2909 switch (c) { 2910 case F_DOWN_SEARCH_HIST: 2911 rv = e_down_search_hist(0); 2912 break; 2913 case F_UP_SEARCH_HIST: 2914 rv = e_up_search_hist(0); 2915 break; 2916 default: 2917 break; 2918 } 2919 return rv; 2920 } 2921 2922 static CCRETVAL 2923 v_csearch_back(ch, count, tflag) 2924 int ch, count, tflag; 2925 { 2926 Char *cp; 2927 2928 cp = Cursor; 2929 while (count--) { 2930 if (*cp == ch) 2931 cp--; 2932 while (cp > InputBuf && *cp != ch) 2933 cp--; 2934 } 2935 2936 if (cp < InputBuf || (cp == InputBuf && *cp != ch)) 2937 return(CC_ERROR); 2938 2939 if (*cp == ch && tflag) 2940 cp++; 2941 2942 Cursor = cp; 2943 2944 if (ActionFlag & TCSHOP_DELETE) { 2945 Cursor++; 2946 c_delfini(); 2947 return(CC_REFRESH); 2948 } 2949 2950 RefCursor(); 2951 return(CC_NORM); 2952 } 2953 2954 static CCRETVAL 2955 v_csearch_fwd(ch, count, tflag) 2956 int ch, count, tflag; 2957 { 2958 Char *cp; 2959 2960 cp = Cursor; 2961 while (count--) { 2962 if(*cp == ch) 2963 cp++; 2964 while (cp < LastChar && *cp != ch) 2965 cp++; 2966 } 2967 2968 if (cp >= LastChar) 2969 return(CC_ERROR); 2970 2971 if (*cp == ch && tflag) 2972 cp--; 2973 2974 Cursor = cp; 2975 2976 if (ActionFlag & TCSHOP_DELETE) { 2977 Cursor++; 2978 c_delfini(); 2979 return(CC_REFRESH); 2980 } 2981 RefCursor(); 2982 return(CC_NORM); 2983 } 2984 2985 /*ARGSUSED*/ 2986 static CCRETVAL 2987 v_action(c) 2988 int c; 2989 { 2990 register Char *cp, *kp; 2991 2992 if (ActionFlag == TCSHOP_DELETE) { 2993 ActionFlag = TCSHOP_NOP; 2994 ActionPos = 0; 2995 2996 UndoSize = 0; 2997 kp = UndoBuf; 2998 for (cp = InputBuf; cp < LastChar; cp++) { 2999 *kp++ = *cp; 3000 UndoSize++; 3001 } 3002 3003 UndoAction = TCSHOP_INSERT; 3004 UndoPtr = InputBuf; 3005 LastChar = InputBuf; 3006 Cursor = InputBuf; 3007 if (c & TCSHOP_INSERT) 3008 c_alternativ_key_map(0); 3009 3010 return(CC_REFRESH); 3011 } 3012 #ifdef notdef 3013 else if (ActionFlag == TCSHOP_NOP) { 3014 #endif 3015 ActionPos = Cursor; 3016 ActionFlag = c; 3017 return(CC_ARGHACK); /* Do NOT clear out argument */ 3018 #ifdef notdef 3019 } 3020 else { 3021 ActionFlag = 0; 3022 ActionPos = 0; 3023 return(CC_ERROR); 3024 } 3025 #endif 3026 } 3027 3028 #ifdef COMMENT 3029 /* by: Brian Allison <uiucdcs!convex!allison@RUTGERS.EDU> */ 3030 static void 3031 c_get_word(begin, end) 3032 Char **begin; 3033 Char **end; 3034 { 3035 Char *cp; 3036 3037 cp = &Cursor[0]; 3038 while (Argument--) { 3039 while ((cp <= LastChar) && (isword(*cp))) 3040 cp++; 3041 *end = --cp; 3042 while ((cp >= InputBuf) && (isword(*cp))) 3043 cp--; 3044 *begin = ++cp; 3045 } 3046 } 3047 #endif /* COMMENT */ 3048 3049 /*ARGSUSED*/ 3050 CCRETVAL 3051 e_uppercase(c) 3052 int c; 3053 { 3054 Char *cp, *end; 3055 3056 USE(c); 3057 end = c_next_word(Cursor, LastChar, Argument); 3058 3059 for (cp = Cursor; cp < end; cp++) /* PWP: was cp=begin */ 3060 if (Islower(*cp)) 3061 *cp = Toupper(*cp); 3062 3063 Cursor = end; 3064 if (Cursor > LastChar) 3065 Cursor = LastChar; 3066 return(CC_REFRESH); 3067 } 3068 3069 3070 /*ARGSUSED*/ 3071 CCRETVAL 3072 e_capitolcase(c) 3073 int c; 3074 { 3075 Char *cp, *end; 3076 3077 USE(c); 3078 end = c_next_word(Cursor, LastChar, Argument); 3079 3080 cp = Cursor; 3081 for (; cp < end; cp++) { 3082 if (Isalpha(*cp)) { 3083 if (Islower(*cp)) 3084 *cp = Toupper(*cp); 3085 cp++; 3086 break; 3087 } 3088 } 3089 for (; cp < end; cp++) 3090 if (Isupper(*cp)) 3091 *cp = Tolower(*cp); 3092 3093 Cursor = end; 3094 if (Cursor > LastChar) 3095 Cursor = LastChar; 3096 return(CC_REFRESH); 3097 } 3098 3099 /*ARGSUSED*/ 3100 CCRETVAL 3101 e_lowercase(c) 3102 int c; 3103 { 3104 Char *cp, *end; 3105 3106 USE(c); 3107 end = c_next_word(Cursor, LastChar, Argument); 3108 3109 for (cp = Cursor; cp < end; cp++) 3110 if (Isupper(*cp)) 3111 *cp = Tolower(*cp); 3112 3113 Cursor = end; 3114 if (Cursor > LastChar) 3115 Cursor = LastChar; 3116 return(CC_REFRESH); 3117 } 3118 3119 3120 /*ARGSUSED*/ 3121 CCRETVAL 3122 e_set_mark(c) 3123 int c; 3124 { 3125 USE(c); 3126 Mark = Cursor; 3127 return(CC_NORM); 3128 } 3129 3130 /*ARGSUSED*/ 3131 CCRETVAL 3132 e_exchange_mark(c) 3133 int c; 3134 { 3135 register Char *cp; 3136 3137 USE(c); 3138 cp = Cursor; 3139 Cursor = Mark; 3140 Mark = cp; 3141 RefCursor(); 3142 return(CC_NORM); 3143 } 3144 3145 /*ARGSUSED*/ 3146 CCRETVAL 3147 e_argfour(c) 3148 int c; 3149 { /* multiply current argument by 4 */ 3150 USE(c); 3151 if (Argument > 1000000) 3152 return CC_ERROR; 3153 DoingArg = 1; 3154 Argument *= 4; 3155 return(CC_ARGHACK); 3156 } 3157 3158 /*ARGSUSED*/ 3159 CCRETVAL 3160 e_quote(c) 3161 int c; 3162 { 3163 Char ch; 3164 int num; 3165 3166 USE(c); 3167 QuoteModeOn(); 3168 num = GetNextChar(&ch); 3169 QuoteModeOff(); 3170 if (num == 1) 3171 return e_insert(ch); 3172 else 3173 return e_send_eof(0); 3174 } 3175 3176 /*ARGSUSED*/ 3177 CCRETVAL 3178 e_metanext(c) 3179 int c; 3180 { 3181 USE(c); 3182 MetaNext = 1; 3183 return(CC_ARGHACK); /* preserve argument */ 3184 } 3185 3186 #ifdef notdef 3187 /*ARGSUSED*/ 3188 CCRETVAL 3189 e_extendnext(c) 3190 int c; 3191 { 3192 CurrentKeyMap = CcAltMap; 3193 return(CC_ARGHACK); /* preserve argument */ 3194 } 3195 3196 #endif 3197 3198 /*ARGSUSED*/ 3199 CCRETVAL 3200 v_insbeg(c) 3201 int c; 3202 { /* move to beginning of line and start vi 3203 * insert mode */ 3204 USE(c); 3205 Cursor = InputBuf; 3206 InsertPos = Cursor; 3207 3208 UndoPtr = Cursor; 3209 UndoAction = TCSHOP_DELETE; 3210 3211 RefCursor(); /* move the cursor */ 3212 c_alternativ_key_map(0); 3213 return(CC_NORM); 3214 } 3215 3216 /*ARGSUSED*/ 3217 CCRETVAL 3218 v_replone(c) 3219 int c; 3220 { /* vi mode overwrite one character */ 3221 USE(c); 3222 c_alternativ_key_map(0); 3223 inputmode = MODE_REPLACE_1; 3224 UndoAction = TCSHOP_CHANGE; /* Set Up for VI undo command */ 3225 UndoPtr = Cursor; 3226 UndoSize = 0; 3227 return(CC_NORM); 3228 } 3229 3230 /*ARGSUSED*/ 3231 CCRETVAL 3232 v_replmode(c) 3233 int c; 3234 { /* vi mode start overwriting */ 3235 USE(c); 3236 c_alternativ_key_map(0); 3237 inputmode = MODE_REPLACE; 3238 UndoAction = TCSHOP_CHANGE; /* Set Up for VI undo command */ 3239 UndoPtr = Cursor; 3240 UndoSize = 0; 3241 return(CC_NORM); 3242 } 3243 3244 /*ARGSUSED*/ 3245 CCRETVAL 3246 v_substchar(c) 3247 int c; 3248 { /* vi mode substitute for one char */ 3249 USE(c); 3250 c_delafter(Argument); 3251 c_alternativ_key_map(0); 3252 return(CC_REFRESH); 3253 } 3254 3255 /*ARGSUSED*/ 3256 CCRETVAL 3257 v_substline(c) 3258 int c; 3259 { /* vi mode replace whole line */ 3260 USE(c); 3261 (void) e_killall(0); 3262 c_alternativ_key_map(0); 3263 return(CC_REFRESH); 3264 } 3265 3266 /*ARGSUSED*/ 3267 CCRETVAL 3268 v_chgtoend(c) 3269 int c; 3270 { /* vi mode change to end of line */ 3271 USE(c); 3272 (void) e_killend(0); 3273 c_alternativ_key_map(0); 3274 return(CC_REFRESH); 3275 } 3276 3277 /*ARGSUSED*/ 3278 CCRETVAL 3279 v_insert(c) 3280 int c; 3281 { /* vi mode start inserting */ 3282 USE(c); 3283 c_alternativ_key_map(0); 3284 3285 InsertPos = Cursor; 3286 UndoPtr = Cursor; 3287 UndoAction = TCSHOP_DELETE; 3288 3289 return(CC_NORM); 3290 } 3291 3292 /*ARGSUSED*/ 3293 CCRETVAL 3294 v_add(c) 3295 int c; 3296 { /* vi mode start adding */ 3297 USE(c); 3298 c_alternativ_key_map(0); 3299 if (Cursor < LastChar) 3300 { 3301 Cursor++; 3302 if (Cursor > LastChar) 3303 Cursor = LastChar; 3304 RefCursor(); 3305 } 3306 3307 InsertPos = Cursor; 3308 UndoPtr = Cursor; 3309 UndoAction = TCSHOP_DELETE; 3310 3311 return(CC_NORM); 3312 } 3313 3314 /*ARGSUSED*/ 3315 CCRETVAL 3316 v_addend(c) 3317 int c; 3318 { /* vi mode to add at end of line */ 3319 USE(c); 3320 c_alternativ_key_map(0); 3321 Cursor = LastChar; 3322 3323 InsertPos = LastChar; /* Mark where insertion begins */ 3324 UndoPtr = LastChar; 3325 UndoAction = TCSHOP_DELETE; 3326 3327 RefCursor(); 3328 return(CC_NORM); 3329 } 3330 3331 /*ARGSUSED*/ 3332 CCRETVAL 3333 v_change_case(cc) 3334 int cc; 3335 { 3336 char c; 3337 3338 USE(cc); 3339 if (Cursor < LastChar) { 3340 #ifndef WINNT_NATIVE 3341 c = *Cursor; 3342 #else 3343 c = CHAR & *Cursor; 3344 #endif /* WINNT_NATIVE */ 3345 if (Isupper(c)) 3346 *Cursor++ = Tolower(c); 3347 else if (Islower(c)) 3348 *Cursor++ = Toupper(c); 3349 else 3350 Cursor++; 3351 RefPlusOne(); /* fast refresh for one char */ 3352 return(CC_NORM); 3353 } 3354 return(CC_ERROR); 3355 } 3356 3357 /*ARGSUSED*/ 3358 CCRETVAL 3359 e_expand(c) 3360 int c; 3361 { 3362 register Char *p; 3363 extern bool justpr; 3364 3365 USE(c); 3366 for (p = InputBuf; Isspace(*p); p++) 3367 continue; 3368 if (p == LastChar) 3369 return(CC_ERROR); 3370 3371 justpr++; 3372 Expand++; 3373 return(e_newline(0)); 3374 } 3375 3376 /*ARGSUSED*/ 3377 CCRETVAL 3378 e_startover(c) 3379 int c; 3380 { /* erase all of current line, start again */ 3381 USE(c); 3382 ResetInLine(0); /* reset the input pointers */ 3383 return(CC_REFRESH); 3384 } 3385 3386 /*ARGSUSED*/ 3387 CCRETVAL 3388 e_redisp(c) 3389 int c; 3390 { 3391 USE(c); 3392 ClearLines(); 3393 ClearDisp(); 3394 return(CC_REFRESH); 3395 } 3396 3397 /*ARGSUSED*/ 3398 CCRETVAL 3399 e_cleardisp(c) 3400 int c; 3401 { 3402 USE(c); 3403 ClearScreen(); /* clear the whole real screen */ 3404 ClearDisp(); /* reset everything */ 3405 return(CC_REFRESH); 3406 } 3407 3408 /*ARGSUSED*/ 3409 CCRETVAL 3410 e_tty_int(c) 3411 int c; 3412 { 3413 USE(c); 3414 #if defined(_MINIX) || defined(WINNT_NATIVE) 3415 /* SAK PATCH: erase all of current line, start again */ 3416 ResetInLine(0); /* reset the input pointers */ 3417 xputchar('\n'); 3418 ClearDisp(); 3419 return (CC_REFRESH); 3420 #else /* !_MINIX && !WINNT_NATIVE */ 3421 /* do no editing */ 3422 return (CC_NORM); 3423 #endif /* _MINIX || WINNT_NATIVE */ 3424 } 3425 3426 /* 3427 * From: ghazi@cesl.rutgers.edu (Kaveh R. Ghazi) 3428 * Function to send a character back to the input stream in cooked 3429 * mode. Only works if we have TIOCSTI 3430 */ 3431 /*ARGSUSED*/ 3432 CCRETVAL 3433 e_stuff_char(c) 3434 int c; 3435 { 3436 #ifdef TIOCSTI 3437 extern int Tty_raw_mode; 3438 int was_raw = Tty_raw_mode; 3439 char ch = (char) c; 3440 3441 if (was_raw) 3442 (void) Cookedmode(); 3443 3444 (void) write(SHIN, "\n", 1); 3445 (void) ioctl(SHIN, TIOCSTI, (ioctl_t) &ch); 3446 3447 if (was_raw) 3448 (void) Rawmode(); 3449 return(e_redisp(c)); 3450 #else /* !TIOCSTI */ 3451 return(CC_ERROR); 3452 #endif /* !TIOCSTI */ 3453 } 3454 3455 /*ARGSUSED*/ 3456 CCRETVAL 3457 e_insovr(c) 3458 int c; 3459 { 3460 USE(c); 3461 inputmode = (inputmode == MODE_INSERT ? MODE_REPLACE : MODE_INSERT); 3462 return(CC_NORM); 3463 } 3464 3465 /*ARGSUSED*/ 3466 CCRETVAL 3467 e_tty_dsusp(c) 3468 int c; 3469 { 3470 USE(c); 3471 /* do no editing */ 3472 return(CC_NORM); 3473 } 3474 3475 /*ARGSUSED*/ 3476 CCRETVAL 3477 e_tty_flusho(c) 3478 int c; 3479 { 3480 USE(c); 3481 /* do no editing */ 3482 return(CC_NORM); 3483 } 3484 3485 /*ARGSUSED*/ 3486 CCRETVAL 3487 e_tty_quit(c) 3488 int c; 3489 { 3490 USE(c); 3491 /* do no editing */ 3492 return(CC_NORM); 3493 } 3494 3495 /*ARGSUSED*/ 3496 CCRETVAL 3497 e_tty_tsusp(c) 3498 int c; 3499 { 3500 USE(c); 3501 /* do no editing */ 3502 return(CC_NORM); 3503 } 3504 3505 /*ARGSUSED*/ 3506 CCRETVAL 3507 e_tty_stopo(c) 3508 int c; 3509 { 3510 USE(c); 3511 /* do no editing */ 3512 return(CC_NORM); 3513 } 3514 3515 /*ARGSUSED*/ 3516 CCRETVAL 3517 e_expand_history(c) 3518 int c; 3519 { 3520 USE(c); 3521 *LastChar = '\0'; /* just in case */ 3522 c_substitute(); 3523 return(CC_NORM); 3524 } 3525 3526 /*ARGSUSED*/ 3527 CCRETVAL 3528 e_magic_space(c) 3529 int c; 3530 { 3531 USE(c); 3532 *LastChar = '\0'; /* just in case */ 3533 c_substitute(); 3534 return(e_insert(' ')); 3535 } 3536 3537 /*ARGSUSED*/ 3538 CCRETVAL 3539 e_inc_fwd(c) 3540 int c; 3541 { 3542 USE(c); 3543 patlen = 0; 3544 return e_inc_search(F_DOWN_SEARCH_HIST); 3545 } 3546 3547 3548 /*ARGSUSED*/ 3549 CCRETVAL 3550 e_inc_back(c) 3551 int c; 3552 { 3553 USE(c); 3554 patlen = 0; 3555 return e_inc_search(F_UP_SEARCH_HIST); 3556 } 3557 3558 /*ARGSUSED*/ 3559 CCRETVAL 3560 e_copyprev(c) 3561 int c; 3562 { 3563 register Char *cp, *oldc, *dp; 3564 3565 USE(c); 3566 if (Cursor == InputBuf) 3567 return(CC_ERROR); 3568 /* else */ 3569 3570 oldc = Cursor; 3571 /* does a bounds check */ 3572 cp = c_prev_word(Cursor, InputBuf, Argument); 3573 3574 c_insert((int)(oldc - cp)); 3575 for (dp = oldc; cp < oldc && dp < LastChar; cp++) 3576 *dp++ = *cp; 3577 3578 Cursor = dp; /* put cursor at end */ 3579 3580 return(CC_REFRESH); 3581 } 3582 3583 /*ARGSUSED*/ 3584 CCRETVAL 3585 e_tty_starto(c) 3586 int c; 3587 { 3588 USE(c); 3589 /* do no editing */ 3590 return(CC_NORM); 3591 } 3592 3593 /*ARGSUSED*/ 3594 CCRETVAL 3595 e_load_average(c) 3596 int c; 3597 { 3598 USE(c); 3599 PastBottom(); 3600 #ifdef TIOCSTAT 3601 /* 3602 * Here we pass &c to the ioctl because some os's (NetBSD) expect it 3603 * there even if they don't use it. (lukem@netbsd.org) 3604 */ 3605 if (ioctl(SHIN, TIOCSTAT, (ioctl_t) &c) < 0) 3606 #endif 3607 xprintf(CGETS(5, 1, "Load average unavailable\n")); 3608 return(CC_REFRESH); 3609 } 3610 3611 /*ARGSUSED*/ 3612 CCRETVAL 3613 v_chgmeta(c) 3614 int c; 3615 { 3616 USE(c); 3617 /* 3618 * Delete with insert == change: first we delete and then we leave in 3619 * insert mode. 3620 */ 3621 return(v_action(TCSHOP_DELETE|TCSHOP_INSERT)); 3622 } 3623 3624 /*ARGSUSED*/ 3625 CCRETVAL 3626 v_delmeta(c) 3627 int c; 3628 { 3629 USE(c); 3630 return(v_action(TCSHOP_DELETE)); 3631 } 3632 3633 3634 /*ARGSUSED*/ 3635 CCRETVAL 3636 v_endword(c) 3637 int c; 3638 { 3639 USE(c); 3640 if (Cursor == LastChar) 3641 return(CC_ERROR); 3642 /* else */ 3643 3644 Cursor = c_endword(Cursor, LastChar, Argument); 3645 3646 if (ActionFlag & TCSHOP_DELETE) 3647 { 3648 Cursor++; 3649 c_delfini(); 3650 return(CC_REFRESH); 3651 } 3652 3653 RefCursor(); 3654 return(CC_NORM); 3655 } 3656 3657 /*ARGSUSED*/ 3658 CCRETVAL 3659 v_eword(c) 3660 int c; 3661 { 3662 USE(c); 3663 if (Cursor == LastChar) 3664 return(CC_ERROR); 3665 /* else */ 3666 3667 Cursor = c_eword(Cursor, LastChar, Argument); 3668 3669 if (ActionFlag & TCSHOP_DELETE) { 3670 Cursor++; 3671 c_delfini(); 3672 return(CC_REFRESH); 3673 } 3674 3675 RefCursor(); 3676 return(CC_NORM); 3677 } 3678 3679 /*ARGSUSED*/ 3680 CCRETVAL 3681 v_char_fwd(c) 3682 int c; 3683 { 3684 Char ch; 3685 3686 USE(c); 3687 if (GetNextChar(&ch) != 1) 3688 return e_send_eof(0); 3689 3690 srch_dir = CHAR_FWD; 3691 srch_char = ch; 3692 3693 return v_csearch_fwd(ch, Argument, 0); 3694 3695 } 3696 3697 /*ARGSUSED*/ 3698 CCRETVAL 3699 v_char_back(c) 3700 int c; 3701 { 3702 Char ch; 3703 3704 USE(c); 3705 if (GetNextChar(&ch) != 1) 3706 return e_send_eof(0); 3707 3708 srch_dir = CHAR_BACK; 3709 srch_char = ch; 3710 3711 return v_csearch_back(ch, Argument, 0); 3712 } 3713 3714 /*ARGSUSED*/ 3715 CCRETVAL 3716 v_charto_fwd(c) 3717 int c; 3718 { 3719 Char ch; 3720 3721 USE(c); 3722 if (GetNextChar(&ch) != 1) 3723 return e_send_eof(0); 3724 3725 return v_csearch_fwd(ch, Argument, 1); 3726 3727 } 3728 3729 /*ARGSUSED*/ 3730 CCRETVAL 3731 v_charto_back(c) 3732 int c; 3733 { 3734 Char ch; 3735 3736 USE(c); 3737 if (GetNextChar(&ch) != 1) 3738 return e_send_eof(0); 3739 3740 return v_csearch_back(ch, Argument, 1); 3741 } 3742 3743 /*ARGSUSED*/ 3744 CCRETVAL 3745 v_rchar_fwd(c) 3746 int c; 3747 { 3748 USE(c); 3749 if (srch_char == 0) 3750 return CC_ERROR; 3751 3752 return srch_dir == CHAR_FWD ? v_csearch_fwd(srch_char, Argument, 0) : 3753 v_csearch_back(srch_char, Argument, 0); 3754 } 3755 3756 /*ARGSUSED*/ 3757 CCRETVAL 3758 v_rchar_back(c) 3759 int c; 3760 { 3761 USE(c); 3762 if (srch_char == 0) 3763 return CC_ERROR; 3764 3765 return srch_dir == CHAR_BACK ? v_csearch_fwd(srch_char, Argument, 0) : 3766 v_csearch_back(srch_char, Argument, 0); 3767 } 3768 3769 /*ARGSUSED*/ 3770 CCRETVAL 3771 v_undo(c) 3772 int c; 3773 { 3774 register int loop; 3775 register Char *kp, *cp; 3776 Char temp; 3777 int size; 3778 3779 USE(c); 3780 switch (UndoAction) { 3781 case TCSHOP_DELETE|TCSHOP_INSERT: 3782 case TCSHOP_DELETE: 3783 if (UndoSize == 0) return(CC_NORM); 3784 cp = UndoPtr; 3785 kp = UndoBuf; 3786 for (loop=0; loop < UndoSize; loop++) /* copy the chars */ 3787 *kp++ = *cp++; /* into UndoBuf */ 3788 3789 for (cp = UndoPtr; cp <= LastChar; cp++) 3790 *cp = cp[UndoSize]; 3791 3792 LastChar -= UndoSize; 3793 Cursor = UndoPtr; 3794 3795 UndoAction = TCSHOP_INSERT; 3796 break; 3797 3798 case TCSHOP_INSERT: 3799 if (UndoSize == 0) return(CC_NORM); 3800 cp = UndoPtr; 3801 Cursor = UndoPtr; 3802 kp = UndoBuf; 3803 c_insert(UndoSize); /* open the space, */ 3804 for (loop = 0; loop < UndoSize; loop++) /* copy the chars */ 3805 *cp++ = *kp++; 3806 3807 UndoAction = TCSHOP_DELETE; 3808 break; 3809 3810 case TCSHOP_CHANGE: 3811 if (UndoSize == 0) return(CC_NORM); 3812 cp = UndoPtr; 3813 Cursor = UndoPtr; 3814 kp = UndoBuf; 3815 size = (int)(Cursor-LastChar); /* NOT NSL independant */ 3816 if (size < UndoSize) 3817 size = UndoSize; 3818 for(loop = 0; loop < size; loop++) { 3819 temp = *kp; 3820 *kp++ = *cp; 3821 *cp++ = temp; 3822 } 3823 break; 3824 3825 default: 3826 return(CC_ERROR); 3827 } 3828 3829 return(CC_REFRESH); 3830 } 3831 3832 /*ARGSUSED*/ 3833 CCRETVAL 3834 v_ush_meta(c) 3835 int c; 3836 { 3837 USE(c); 3838 return v_search(F_UP_SEARCH_HIST); 3839 } 3840 3841 /*ARGSUSED*/ 3842 CCRETVAL 3843 v_dsh_meta(c) 3844 int c; 3845 { 3846 USE(c); 3847 return v_search(F_DOWN_SEARCH_HIST); 3848 } 3849 3850 /*ARGSUSED*/ 3851 CCRETVAL 3852 v_rsrch_fwd(c) 3853 int c; 3854 { 3855 USE(c); 3856 if (patlen == 0) return(CC_ERROR); 3857 return(v_repeat_srch(searchdir)); 3858 } 3859 3860 /*ARGSUSED*/ 3861 CCRETVAL 3862 v_rsrch_back(c) 3863 int c; 3864 { 3865 USE(c); 3866 if (patlen == 0) return(CC_ERROR); 3867 return(v_repeat_srch(searchdir == F_UP_SEARCH_HIST ? 3868 F_DOWN_SEARCH_HIST : F_UP_SEARCH_HIST)); 3869 } 3870 3871 #ifndef WINNT_NATIVE 3872 /* Since ed.defns.h is generated from ed.defns.c, these empty 3873 functions will keep the F_NUM_FNS consistent 3874 */ 3875 CCRETVAL 3876 e_copy_to_clipboard(c) 3877 int c; 3878 { 3879 USE(c); 3880 return CC_ERROR; 3881 } 3882 3883 CCRETVAL 3884 e_paste_from_clipboard(c) 3885 int c; 3886 { 3887 USE(c); 3888 return (CC_ERROR); 3889 } 3890 3891 CCRETVAL 3892 e_dosify_next(c) 3893 int c; 3894 { 3895 USE(c); 3896 return (CC_ERROR); 3897 } 3898 CCRETVAL 3899 e_dosify_prev(c) 3900 int c; 3901 { 3902 USE(c); 3903 return (CC_ERROR); 3904 } 3905 CCRETVAL 3906 e_page_up(c) 3907 int c; 3908 { 3909 USE(c); 3910 return (CC_ERROR); 3911 } 3912 CCRETVAL 3913 e_page_down(c) 3914 int c; 3915 { 3916 USE(c); 3917 return (CC_ERROR); 3918 } 3919 #endif /* !WINNT_NATIVE */ 3920 3921 #ifdef notdef 3922 void 3923 MoveCursor(n) /* move cursor + right - left char */ 3924 int n; 3925 { 3926 Cursor = Cursor + n; 3927 if (Cursor < InputBuf) 3928 Cursor = InputBuf; 3929 if (Cursor > LastChar) 3930 Cursor = LastChar; 3931 return; 3932 } 3933 3934 Char * 3935 GetCursor() 3936 { 3937 return(Cursor); 3938 } 3939 3940 int 3941 PutCursor(p) 3942 Char *p; 3943 { 3944 if (p < InputBuf || p > LastChar) 3945 return 1; /* Error */ 3946 Cursor = p; 3947 return 0; 3948 } 3949 #endif 3950