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