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