ed.chared.c revision 59243
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 79RCSID("$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 103static Char *InsertPos = InputBuf; /* Where insertion starts */ 104static Char *ActionPos = 0; /* Where action begins */ 105static int ActionFlag = TCSHOP_NOP; /* What delayed action to take */ 106/* 107 * Word search state 108 */ 109static int searchdir = F_UP_SEARCH_HIST; /* Direction of last search */ 110static Char patbuf[INBUFSIZE]; /* Search target */ 111static int patlen = 0; 112/* 113 * Char search state 114 */ 115static int srch_dir = CHAR_FWD; /* Direction of last search */ 116static Char srch_char = 0; /* Search target */ 117 118/* all routines that start with c_ are private to this set of routines */ 119static void c_alternativ_key_map __P((int)); 120static void c_insert __P((int)); 121static void c_delafter __P((int)); 122static void c_delbefore __P((int)); 123static int c_to_class __P((int)); 124static Char *c_prev_word __P((Char *, Char *, int)); 125static Char *c_next_word __P((Char *, Char *, int)); 126static Char *c_number __P((Char *, int *, int)); 127static Char *c_expand __P((Char *)); 128static void c_excl __P((Char *)); 129static void c_substitute __P((void)); 130static void c_delfini __P((void)); 131static int c_hmatch __P((Char *)); 132static void c_hsetpat __P((void)); 133#ifdef COMMENT 134static void c_get_word __P((Char **, Char **)); 135#endif 136static Char *c_preword __P((Char *, Char *, int)); 137static Char *c_nexword __P((Char *, Char *, int)); 138static Char *c_endword __P((Char *, Char *, int)); 139static Char *c_eword __P((Char *, Char *, int)); 140static CCRETVAL c_get_histline __P((void)); 141static CCRETVAL c_search_line __P((Char *, int)); 142static CCRETVAL v_repeat_srch __P((int)); 143static CCRETVAL e_inc_search __P((int)); 144static CCRETVAL v_search __P((int)); 145static CCRETVAL v_csearch_fwd __P((int, int, int)); 146static CCRETVAL v_action __P((int)); 147static CCRETVAL v_csearch_back __P((int, int, int)); 148 149#if defined(DSPMBYTE) 150static void e_charfwd_mbyte __P((int)); 151static void e_charback_mbyte __P((int)); 152static int extdel; 153static int extins = 0; 154#endif 155 156static void 157c_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 174static void 175c_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 190static void 191c_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 257static void 258c_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 318static Char * 319c_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 */ 366static int 367c_to_class(ch) 368register 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 379static Char * 380c_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 428static Char * 429c_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 471static Char * 472c_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 505static Char * 506c_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 538static Char * 539c_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; 555excl_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)); 755excl_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 767static void 768c_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 810static void 811c_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 831static void 832c_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 870static Char * 871c_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 902static Char * 903c_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 925static CCRETVAL 926c_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 988static CCRETVAL 989c_search_line(pattern, dir) 990Char *pattern; 991int 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 1017static CCRETVAL 1018e_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 1214static CCRETVAL 1215v_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*/ 1337CCRETVAL 1338v_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*/ 1366CCRETVAL 1367e_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 1376CCRETVAL 1377e_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 1483int 1484InsertStr(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 1500void 1501DeleteBack(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 1521CCRETVAL 1522e_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 1555CCRETVAL 1556e_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 1576CCRETVAL 1577v_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*/ 1598CCRETVAL 1599e_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*/ 1612CCRETVAL 1613e_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*/ 1623CCRETVAL 1624e_complete(c) 1625 int c; 1626{ 1627 USE(c); 1628 *LastChar = '\0'; /* just in case */ 1629 return(CC_COMPLETE); 1630} 1631 1632/*ARGSUSED*/ 1633CCRETVAL 1634e_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*/ 1643CCRETVAL 1644e_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*/ 1653CCRETVAL 1654e_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*/ 1663CCRETVAL 1664v_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*/ 1675CCRETVAL 1676e_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*/ 1732CCRETVAL 1733e_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*/ 1762CCRETVAL 1763e_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 */ 1785static int 1786c_hmatch(str) 1787Char *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 */ 1797static void 1798c_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*/ 1819CCRETVAL 1820e_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*/ 1886CCRETVAL 1887e_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*/ 1938CCRETVAL 1939e_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*/ 1949CCRETVAL 1950e_correct(c) 1951 int c; 1952{ 1953 USE(c); 1954 *LastChar = '\0'; /* just in case */ 1955 return(CC_CORRECT); 1956} 1957 1958/*ARGSUSED*/ 1959CCRETVAL 1960e_correctl(c) 1961 int c; 1962{ 1963 USE(c); 1964 *LastChar = '\0'; /* just in case */ 1965 return(CC_CORRECT_L); 1966} 1967 1968/*ARGSUSED*/ 1969CCRETVAL 1970e_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*/ 2001CCRETVAL 2002e_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*/ 2012CCRETVAL 2013e_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*/ 2023CCRETVAL 2024e_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*/ 2034CCRETVAL 2035e_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*/ 2044CCRETVAL 2045e_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*/ 2054CCRETVAL 2055e_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*/ 2064CCRETVAL 2065e_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*/ 2074CCRETVAL 2075e_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*/ 2085CCRETVAL 2086e_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*/ 2125CCRETVAL 2126e_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*/ 2210CCRETVAL 2211e_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*/ 2238CCRETVAL 2239v_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*/ 2264CCRETVAL 2265e_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*/ 2289CCRETVAL 2290e_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*/ 2342CCRETVAL 2343e_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*/ 2366CCRETVAL 2367e_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*/ 2396CCRETVAL 2397e_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*/ 2415CCRETVAL 2416e_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*/ 2441CCRETVAL 2442e_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*/ 2462CCRETVAL 2463e_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*/ 2486CCRETVAL 2487e_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*/ 2502CCRETVAL 2503e_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*/ 2523CCRETVAL 2524e_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*/ 2541CCRETVAL 2542e_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*/ 2559CCRETVAL 2560e_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*/ 2577CCRETVAL 2578e_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*/ 2608CCRETVAL 2609e_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*/ 2636CCRETVAL 2637e_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*/ 2659CCRETVAL 2660e_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*/ 2679static void 2680e_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*/ 2703CCRETVAL 2704e_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*/ 2733CCRETVAL 2734v_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*/ 2754CCRETVAL 2755e_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*/ 2777static void 2778e_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*/ 2796CCRETVAL 2797e_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*/ 2825CCRETVAL 2826e_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*/ 2847CCRETVAL 2848v_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*/ 2869CCRETVAL 2870v_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*/ 2893static CCRETVAL 2894v_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 2918static CCRETVAL 2919v_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 2950static CCRETVAL 2951v_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*/ 2982static CCRETVAL 2983v_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> */ 3026static void 3027c_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*/ 3046CCRETVAL 3047e_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*/ 3067CCRETVAL 3068e_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*/ 3096CCRETVAL 3097e_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*/ 3117CCRETVAL 3118e_set_mark(c) 3119 int c; 3120{ 3121 USE(c); 3122 Mark = Cursor; 3123 return(CC_NORM); 3124} 3125 3126/*ARGSUSED*/ 3127CCRETVAL 3128e_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*/ 3142CCRETVAL 3143e_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*/ 3155CCRETVAL 3156e_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*/ 3173CCRETVAL 3174e_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*/ 3184CCRETVAL 3185e_extendnext(c) 3186 int c; 3187{ 3188 CurrentKeyMap = CcAltMap; 3189 return(CC_ARGHACK); /* preserve argument */ 3190} 3191 3192#endif 3193 3194/*ARGSUSED*/ 3195CCRETVAL 3196v_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*/ 3213CCRETVAL 3214v_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*/ 3227CCRETVAL 3228v_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*/ 3241CCRETVAL 3242v_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*/ 3252CCRETVAL 3253v_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*/ 3263CCRETVAL 3264v_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*/ 3274CCRETVAL 3275v_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*/ 3289CCRETVAL 3290v_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*/ 3311CCRETVAL 3312v_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*/ 3328CCRETVAL 3329v_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*/ 3354CCRETVAL 3355e_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*/ 3373CCRETVAL 3374e_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*/ 3383CCRETVAL 3384e_redisp(c) 3385 int c; 3386{ 3387 USE(c); 3388 ClearLines(); 3389 ClearDisp(); 3390 return(CC_REFRESH); 3391} 3392 3393/*ARGSUSED*/ 3394CCRETVAL 3395e_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*/ 3405CCRETVAL 3406e_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*/ 3428CCRETVAL 3429e_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*/ 3452CCRETVAL 3453e_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*/ 3462CCRETVAL 3463e_tty_dsusp(c) 3464 int c; 3465{ 3466 USE(c); 3467 /* do no editing */ 3468 return(CC_NORM); 3469} 3470 3471/*ARGSUSED*/ 3472CCRETVAL 3473e_tty_flusho(c) 3474 int c; 3475{ 3476 USE(c); 3477 /* do no editing */ 3478 return(CC_NORM); 3479} 3480 3481/*ARGSUSED*/ 3482CCRETVAL 3483e_tty_quit(c) 3484 int c; 3485{ 3486 USE(c); 3487 /* do no editing */ 3488 return(CC_NORM); 3489} 3490 3491/*ARGSUSED*/ 3492CCRETVAL 3493e_tty_tsusp(c) 3494 int c; 3495{ 3496 USE(c); 3497 /* do no editing */ 3498 return(CC_NORM); 3499} 3500 3501/*ARGSUSED*/ 3502CCRETVAL 3503e_tty_stopo(c) 3504 int c; 3505{ 3506 USE(c); 3507 /* do no editing */ 3508 return(CC_NORM); 3509} 3510 3511/*ARGSUSED*/ 3512CCRETVAL 3513e_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*/ 3523CCRETVAL 3524e_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*/ 3534CCRETVAL 3535e_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*/ 3545CCRETVAL 3546e_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*/ 3555CCRETVAL 3556e_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*/ 3580CCRETVAL 3581e_tty_starto(c) 3582 int c; 3583{ 3584 USE(c); 3585 /* do no editing */ 3586 return(CC_NORM); 3587} 3588 3589/*ARGSUSED*/ 3590CCRETVAL 3591e_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*/ 3608CCRETVAL 3609v_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*/ 3621CCRETVAL 3622v_delmeta(c) 3623 int c; 3624{ 3625 USE(c); 3626 return(v_action(TCSHOP_DELETE)); 3627} 3628 3629 3630/*ARGSUSED*/ 3631CCRETVAL 3632v_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*/ 3654CCRETVAL 3655v_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*/ 3676CCRETVAL 3677v_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*/ 3694CCRETVAL 3695v_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*/ 3711CCRETVAL 3712v_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*/ 3726CCRETVAL 3727v_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*/ 3740CCRETVAL 3741v_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*/ 3753CCRETVAL 3754v_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*/ 3766CCRETVAL 3767v_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*/ 3829CCRETVAL 3830v_ush_meta(c) 3831 int c; 3832{ 3833 USE(c); 3834 return v_search(F_UP_SEARCH_HIST); 3835} 3836 3837/*ARGSUSED*/ 3838CCRETVAL 3839v_dsh_meta(c) 3840 int c; 3841{ 3842 USE(c); 3843 return v_search(F_DOWN_SEARCH_HIST); 3844} 3845 3846/*ARGSUSED*/ 3847CCRETVAL 3848v_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*/ 3857CCRETVAL 3858v_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 */ 3871CCRETVAL 3872e_copy_to_clipboard(c) 3873 int c; 3874{ 3875 USE(c); 3876 return CC_ERROR; 3877} 3878 3879CCRETVAL 3880e_paste_from_clipboard(c) 3881 int c; 3882{ 3883 USE(c); 3884 return (CC_ERROR); 3885} 3886 3887CCRETVAL 3888e_dosify_next(c) 3889 int c; 3890{ 3891 USE(c); 3892 return (CC_ERROR); 3893} 3894CCRETVAL 3895e_dosify_prev(c) 3896 int c; 3897{ 3898 USE(c); 3899 return (CC_ERROR); 3900} 3901#else /* WINNT */ 3902/*ARGSUSED*/ 3903CCRETVAL 3904e_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*/ 3937CCRETVAL 3938e_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 3978void 3979MoveCursor(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 3990Char * 3991GetCursor() 3992{ 3993 return(Cursor); 3994} 3995 3996int 3997PutCursor(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