1 /* $NetBSD: common.c,v 1.29 2012/03/24 20:08:43 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 1992, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Christos Zoulas of Cornell University. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #include "config.h" 36 #if !defined(lint) && !defined(SCCSID) 37 #if 0 38 static char sccsid[] = "@(#)common.c 8.1 (Berkeley) 6/4/93"; 39 #else 40 __RCSID("$NetBSD: common.c,v 1.29 2012/03/24 20:08:43 christos Exp $"); 41 #endif 42 #endif /* not lint && not SCCSID */ 43 44 /* 45 * common.c: Common Editor functions 46 */ 47 #include "el.h" 48 49 /* ed_end_of_file(): 50 * Indicate end of file 51 * [^D] 52 */ 53 protected el_action_t 54 /*ARGSUSED*/ 55 ed_end_of_file(EditLine *el, Int c __attribute__((__unused__))) 56 { 57 58 re_goto_bottom(el); 59 *el->el_line.lastchar = '\0'; 60 return CC_EOF; 61 } 62 63 64 /* ed_insert(): 65 * Add character to the line 66 * Insert a character [bound to all insert keys] 67 */ 68 protected el_action_t 69 ed_insert(EditLine *el, Int c) 70 { 71 int count = el->el_state.argument; 72 73 if (c == '\0') 74 return CC_ERROR; 75 76 if (el->el_line.lastchar + el->el_state.argument >= 77 el->el_line.limit) { 78 /* end of buffer space, try to allocate more */ 79 if (!ch_enlargebufs(el, (size_t) count)) 80 return CC_ERROR; /* error allocating more */ 81 } 82 83 if (count == 1) { 84 if (el->el_state.inputmode == MODE_INSERT 85 || el->el_line.cursor >= el->el_line.lastchar) 86 c_insert(el, 1); 87 88 *el->el_line.cursor++ = c; 89 re_fastaddc(el); /* fast refresh for one char. */ 90 } else { 91 if (el->el_state.inputmode != MODE_REPLACE_1) 92 c_insert(el, el->el_state.argument); 93 94 while (count-- && el->el_line.cursor < el->el_line.lastchar) 95 *el->el_line.cursor++ = c; 96 re_refresh(el); 97 } 98 99 if (el->el_state.inputmode == MODE_REPLACE_1) 100 return vi_command_mode(el, 0); 101 102 return CC_NORM; 103 } 104 105 106 /* ed_delete_prev_word(): 107 * Delete from beginning of current word to cursor 108 * [M-^?] [^W] 109 */ 110 protected el_action_t 111 /*ARGSUSED*/ 112 ed_delete_prev_word(EditLine *el, Int c __attribute__((__unused__))) 113 { 114 Char *cp, *p, *kp; 115 116 if (el->el_line.cursor == el->el_line.buffer) 117 return CC_ERROR; 118 119 cp = c__prev_word(el->el_line.cursor, el->el_line.buffer, 120 el->el_state.argument, ce__isword); 121 122 for (p = cp, kp = el->el_chared.c_kill.buf; p < el->el_line.cursor; p++) 123 *kp++ = *p; 124 el->el_chared.c_kill.last = kp; 125 126 c_delbefore(el, (int)(el->el_line.cursor - cp));/* delete before dot */ 127 el->el_line.cursor = cp; 128 if (el->el_line.cursor < el->el_line.buffer) 129 el->el_line.cursor = el->el_line.buffer; /* bounds check */ 130 return CC_REFRESH; 131 } 132 133 134 /* ed_delete_next_char(): 135 * Delete character under cursor 136 * [^D] [x] 137 */ 138 protected el_action_t 139 /*ARGSUSED*/ 140 ed_delete_next_char(EditLine *el, Int c __attribute__((__unused__))) 141 { 142 #ifdef DEBUG_EDIT 143 #define EL el->el_line 144 (void) fprintf(el->el_errlfile, 145 "\nD(b: %x(%s) c: %x(%s) last: %x(%s) limit: %x(%s)\n", 146 EL.buffer, EL.buffer, EL.cursor, EL.cursor, EL.lastchar, 147 EL.lastchar, EL.limit, EL.limit); 148 #endif 149 if (el->el_line.cursor == el->el_line.lastchar) { 150 /* if I'm at the end */ 151 if (el->el_map.type == MAP_VI) { 152 if (el->el_line.cursor == el->el_line.buffer) { 153 /* if I'm also at the beginning */ 154 #ifdef KSHVI 155 return CC_ERROR; 156 #else 157 /* then do an EOF */ 158 terminal_writec(el, c); 159 return CC_EOF; 160 #endif 161 } else { 162 #ifdef KSHVI 163 el->el_line.cursor--; 164 #else 165 return CC_ERROR; 166 #endif 167 } 168 } else 169 return CC_ERROR; 170 } 171 c_delafter(el, el->el_state.argument); /* delete after dot */ 172 if (el->el_map.type == MAP_VI && 173 el->el_line.cursor >= el->el_line.lastchar && 174 el->el_line.cursor > el->el_line.buffer) 175 /* bounds check */ 176 el->el_line.cursor = el->el_line.lastchar - 1; 177 return CC_REFRESH; 178 } 179 180 181 /* ed_kill_line(): 182 * Cut to the end of line 183 * [^K] [^K] 184 */ 185 protected el_action_t 186 /*ARGSUSED*/ 187 ed_kill_line(EditLine *el, Int c __attribute__((__unused__))) 188 { 189 Char *kp, *cp; 190 191 cp = el->el_line.cursor; 192 kp = el->el_chared.c_kill.buf; 193 while (cp < el->el_line.lastchar) 194 *kp++ = *cp++; /* copy it */ 195 el->el_chared.c_kill.last = kp; 196 /* zap! -- delete to end */ 197 el->el_line.lastchar = el->el_line.cursor; 198 return CC_REFRESH; 199 } 200 201 202 /* ed_move_to_end(): 203 * Move cursor to the end of line 204 * [^E] [^E] 205 */ 206 protected el_action_t 207 /*ARGSUSED*/ 208 ed_move_to_end(EditLine *el, Int c __attribute__((__unused__))) 209 { 210 211 el->el_line.cursor = el->el_line.lastchar; 212 if (el->el_map.type == MAP_VI) { 213 if (el->el_chared.c_vcmd.action != NOP) { 214 cv_delfini(el); 215 return CC_REFRESH; 216 } 217 #ifdef VI_MOVE 218 el->el_line.cursor--; 219 #endif 220 } 221 return CC_CURSOR; 222 } 223 224 225 /* ed_move_to_beg(): 226 * Move cursor to the beginning of line 227 * [^A] [^A] 228 */ 229 protected el_action_t 230 /*ARGSUSED*/ 231 ed_move_to_beg(EditLine *el, Int c __attribute__((__unused__))) 232 { 233 234 el->el_line.cursor = el->el_line.buffer; 235 236 if (el->el_map.type == MAP_VI) { 237 /* We want FIRST non space character */ 238 while (Isspace(*el->el_line.cursor)) 239 el->el_line.cursor++; 240 if (el->el_chared.c_vcmd.action != NOP) { 241 cv_delfini(el); 242 return CC_REFRESH; 243 } 244 } 245 return CC_CURSOR; 246 } 247 248 249 /* ed_transpose_chars(): 250 * Exchange the character to the left of the cursor with the one under it 251 * [^T] [^T] 252 */ 253 protected el_action_t 254 ed_transpose_chars(EditLine *el, Int c) 255 { 256 257 if (el->el_line.cursor < el->el_line.lastchar) { 258 if (el->el_line.lastchar <= &el->el_line.buffer[1]) 259 return CC_ERROR; 260 else 261 el->el_line.cursor++; 262 } 263 if (el->el_line.cursor > &el->el_line.buffer[1]) { 264 /* must have at least two chars entered */ 265 c = el->el_line.cursor[-2]; 266 el->el_line.cursor[-2] = el->el_line.cursor[-1]; 267 el->el_line.cursor[-1] = c; 268 return CC_REFRESH; 269 } else 270 return CC_ERROR; 271 } 272 273 274 /* ed_next_char(): 275 * Move to the right one character 276 * [^F] [^F] 277 */ 278 protected el_action_t 279 /*ARGSUSED*/ 280 ed_next_char(EditLine *el, Int c __attribute__((__unused__))) 281 { 282 Char *lim = el->el_line.lastchar; 283 284 if (el->el_line.cursor >= lim || 285 (el->el_line.cursor == lim - 1 && 286 el->el_map.type == MAP_VI && 287 el->el_chared.c_vcmd.action == NOP)) 288 return CC_ERROR; 289 290 el->el_line.cursor += el->el_state.argument; 291 if (el->el_line.cursor > lim) 292 el->el_line.cursor = lim; 293 294 if (el->el_map.type == MAP_VI) 295 if (el->el_chared.c_vcmd.action != NOP) { 296 cv_delfini(el); 297 return CC_REFRESH; 298 } 299 return CC_CURSOR; 300 } 301 302 303 /* ed_prev_word(): 304 * Move to the beginning of the current word 305 * [M-b] [b] 306 */ 307 protected el_action_t 308 /*ARGSUSED*/ 309 ed_prev_word(EditLine *el, Int c __attribute__((__unused__))) 310 { 311 312 if (el->el_line.cursor == el->el_line.buffer) 313 return CC_ERROR; 314 315 el->el_line.cursor = c__prev_word(el->el_line.cursor, 316 el->el_line.buffer, 317 el->el_state.argument, 318 ce__isword); 319 320 if (el->el_map.type == MAP_VI) 321 if (el->el_chared.c_vcmd.action != NOP) { 322 cv_delfini(el); 323 return CC_REFRESH; 324 } 325 return CC_CURSOR; 326 } 327 328 329 /* ed_prev_char(): 330 * Move to the left one character 331 * [^B] [^B] 332 */ 333 protected el_action_t 334 /*ARGSUSED*/ 335 ed_prev_char(EditLine *el, Int c __attribute__((__unused__))) 336 { 337 338 if (el->el_line.cursor > el->el_line.buffer) { 339 el->el_line.cursor -= el->el_state.argument; 340 if (el->el_line.cursor < el->el_line.buffer) 341 el->el_line.cursor = el->el_line.buffer; 342 343 if (el->el_map.type == MAP_VI) 344 if (el->el_chared.c_vcmd.action != NOP) { 345 cv_delfini(el); 346 return CC_REFRESH; 347 } 348 return CC_CURSOR; 349 } else 350 return CC_ERROR; 351 } 352 353 354 /* ed_quoted_insert(): 355 * Add the next character typed verbatim 356 * [^V] [^V] 357 */ 358 protected el_action_t 359 ed_quoted_insert(EditLine *el, Int c) 360 { 361 int num; 362 Char tc; 363 364 tty_quotemode(el); 365 num = FUN(el,getc)(el, &tc); 366 c = tc; 367 tty_noquotemode(el); 368 if (num == 1) 369 return ed_insert(el, c); 370 else 371 return ed_end_of_file(el, 0); 372 } 373 374 375 /* ed_digit(): 376 * Adds to argument or enters a digit 377 */ 378 protected el_action_t 379 ed_digit(EditLine *el, Int c) 380 { 381 382 if (!Isdigit(c)) 383 return CC_ERROR; 384 385 if (el->el_state.doingarg) { 386 /* if doing an arg, add this in... */ 387 if (el->el_state.lastcmd == EM_UNIVERSAL_ARGUMENT) 388 el->el_state.argument = c - '0'; 389 else { 390 if (el->el_state.argument > 1000000) 391 return CC_ERROR; 392 el->el_state.argument = 393 (el->el_state.argument * 10) + (c - '0'); 394 } 395 return CC_ARGHACK; 396 } 397 398 return ed_insert(el, c); 399 } 400 401 402 /* ed_argument_digit(): 403 * Digit that starts argument 404 * For ESC-n 405 */ 406 protected el_action_t 407 ed_argument_digit(EditLine *el, Int c) 408 { 409 410 if (!Isdigit(c)) 411 return CC_ERROR; 412 413 if (el->el_state.doingarg) { 414 if (el->el_state.argument > 1000000) 415 return CC_ERROR; 416 el->el_state.argument = (el->el_state.argument * 10) + 417 (c - '0'); 418 } else { /* else starting an argument */ 419 el->el_state.argument = c - '0'; 420 el->el_state.doingarg = 1; 421 } 422 return CC_ARGHACK; 423 } 424 425 426 /* ed_unassigned(): 427 * Indicates unbound character 428 * Bound to keys that are not assigned 429 */ 430 protected el_action_t 431 /*ARGSUSED*/ 432 ed_unassigned(EditLine *el __attribute__((__unused__)), 433 Int c __attribute__((__unused__))) 434 { 435 436 return CC_ERROR; 437 } 438 439 440 /** 441 ** TTY key handling. 442 **/ 443 444 /* ed_tty_sigint(): 445 * Tty interrupt character 446 * [^C] 447 */ 448 protected el_action_t 449 /*ARGSUSED*/ 450 ed_tty_sigint(EditLine *el __attribute__((__unused__)), 451 Int c __attribute__((__unused__))) 452 { 453 454 return CC_NORM; 455 } 456 457 458 /* ed_tty_dsusp(): 459 * Tty delayed suspend character 460 * [^Y] 461 */ 462 protected el_action_t 463 /*ARGSUSED*/ 464 ed_tty_dsusp(EditLine *el __attribute__((__unused__)), 465 Int c __attribute__((__unused__))) 466 { 467 468 return CC_NORM; 469 } 470 471 472 /* ed_tty_flush_output(): 473 * Tty flush output characters 474 * [^O] 475 */ 476 protected el_action_t 477 /*ARGSUSED*/ 478 ed_tty_flush_output(EditLine *el __attribute__((__unused__)), 479 Int c __attribute__((__unused__))) 480 { 481 482 return CC_NORM; 483 } 484 485 486 /* ed_tty_sigquit(): 487 * Tty quit character 488 * [^\] 489 */ 490 protected el_action_t 491 /*ARGSUSED*/ 492 ed_tty_sigquit(EditLine *el __attribute__((__unused__)), 493 Int c __attribute__((__unused__))) 494 { 495 496 return CC_NORM; 497 } 498 499 500 /* ed_tty_sigtstp(): 501 * Tty suspend character 502 * [^Z] 503 */ 504 protected el_action_t 505 /*ARGSUSED*/ 506 ed_tty_sigtstp(EditLine *el __attribute__((__unused__)), 507 Int c __attribute__((__unused__))) 508 { 509 510 return CC_NORM; 511 } 512 513 514 /* ed_tty_stop_output(): 515 * Tty disallow output characters 516 * [^S] 517 */ 518 protected el_action_t 519 /*ARGSUSED*/ 520 ed_tty_stop_output(EditLine *el __attribute__((__unused__)), 521 Int c __attribute__((__unused__))) 522 { 523 524 return CC_NORM; 525 } 526 527 528 /* ed_tty_start_output(): 529 * Tty allow output characters 530 * [^Q] 531 */ 532 protected el_action_t 533 /*ARGSUSED*/ 534 ed_tty_start_output(EditLine *el __attribute__((__unused__)), 535 Int c __attribute__((__unused__))) 536 { 537 538 return CC_NORM; 539 } 540 541 542 /* ed_newline(): 543 * Execute command 544 * [^J] 545 */ 546 protected el_action_t 547 /*ARGSUSED*/ 548 ed_newline(EditLine *el, Int c __attribute__((__unused__))) 549 { 550 551 re_goto_bottom(el); 552 *el->el_line.lastchar++ = '\n'; 553 *el->el_line.lastchar = '\0'; 554 return CC_NEWLINE; 555 } 556 557 558 /* ed_delete_prev_char(): 559 * Delete the character to the left of the cursor 560 * [^?] 561 */ 562 protected el_action_t 563 /*ARGSUSED*/ 564 ed_delete_prev_char(EditLine *el, Int c __attribute__((__unused__))) 565 { 566 567 if (el->el_line.cursor <= el->el_line.buffer) 568 return CC_ERROR; 569 570 c_delbefore(el, el->el_state.argument); 571 el->el_line.cursor -= el->el_state.argument; 572 if (el->el_line.cursor < el->el_line.buffer) 573 el->el_line.cursor = el->el_line.buffer; 574 return CC_REFRESH; 575 } 576 577 578 /* ed_clear_screen(): 579 * Clear screen leaving current line at the top 580 * [^L] 581 */ 582 protected el_action_t 583 /*ARGSUSED*/ 584 ed_clear_screen(EditLine *el, Int c __attribute__((__unused__))) 585 { 586 587 terminal_clear_screen(el); /* clear the whole real screen */ 588 re_clear_display(el); /* reset everything */ 589 return CC_REFRESH; 590 } 591 592 593 /* ed_redisplay(): 594 * Redisplay everything 595 * ^R 596 */ 597 protected el_action_t 598 /*ARGSUSED*/ 599 ed_redisplay(EditLine *el __attribute__((__unused__)), 600 Int c __attribute__((__unused__))) 601 { 602 603 return CC_REDISPLAY; 604 } 605 606 607 /* ed_start_over(): 608 * Erase current line and start from scratch 609 * [^G] 610 */ 611 protected el_action_t 612 /*ARGSUSED*/ 613 ed_start_over(EditLine *el, Int c __attribute__((__unused__))) 614 { 615 616 ch_reset(el, 0); 617 return CC_REFRESH; 618 } 619 620 621 /* ed_sequence_lead_in(): 622 * First character in a bound sequence 623 * Placeholder for external keys 624 */ 625 protected el_action_t 626 /*ARGSUSED*/ 627 ed_sequence_lead_in(EditLine *el __attribute__((__unused__)), 628 Int c __attribute__((__unused__))) 629 { 630 631 return CC_NORM; 632 } 633 634 635 /* ed_prev_history(): 636 * Move to the previous history line 637 * [^P] [k] 638 */ 639 protected el_action_t 640 /*ARGSUSED*/ 641 ed_prev_history(EditLine *el, Int c __attribute__((__unused__))) 642 { 643 char beep = 0; 644 int sv_event = el->el_history.eventno; 645 646 el->el_chared.c_undo.len = -1; 647 *el->el_line.lastchar = '\0'; /* just in case */ 648 649 if (el->el_history.eventno == 0) { /* save the current buffer 650 * away */ 651 (void) Strncpy(el->el_history.buf, el->el_line.buffer, 652 EL_BUFSIZ); 653 el->el_history.last = el->el_history.buf + 654 (el->el_line.lastchar - el->el_line.buffer); 655 } 656 el->el_history.eventno += el->el_state.argument; 657 658 if (hist_get(el) == CC_ERROR) { 659 if (el->el_map.type == MAP_VI) { 660 el->el_history.eventno = sv_event; 661 662 } 663 beep = 1; 664 /* el->el_history.eventno was fixed by first call */ 665 (void) hist_get(el); 666 } 667 if (beep) 668 return CC_REFRESH_BEEP; 669 return CC_REFRESH; 670 } 671 672 673 /* ed_next_history(): 674 * Move to the next history line 675 * [^N] [j] 676 */ 677 protected el_action_t 678 /*ARGSUSED*/ 679 ed_next_history(EditLine *el, Int c __attribute__((__unused__))) 680 { 681 el_action_t beep = CC_REFRESH, rval; 682 683 el->el_chared.c_undo.len = -1; 684 *el->el_line.lastchar = '\0'; /* just in case */ 685 686 el->el_history.eventno -= el->el_state.argument; 687 688 if (el->el_history.eventno < 0) { 689 el->el_history.eventno = 0; 690 beep = CC_REFRESH_BEEP; 691 } 692 rval = hist_get(el); 693 if (rval == CC_REFRESH) 694 return beep; 695 return rval; 696 697 } 698 699 700 /* ed_search_prev_history(): 701 * Search previous in history for a line matching the current 702 * next search history [M-P] [K] 703 */ 704 protected el_action_t 705 /*ARGSUSED*/ 706 ed_search_prev_history(EditLine *el, Int c __attribute__((__unused__))) 707 { 708 const Char *hp; 709 int h; 710 bool_t found = 0; 711 712 el->el_chared.c_vcmd.action = NOP; 713 el->el_chared.c_undo.len = -1; 714 *el->el_line.lastchar = '\0'; /* just in case */ 715 if (el->el_history.eventno < 0) { 716 #ifdef DEBUG_EDIT 717 (void) fprintf(el->el_errfile, 718 "e_prev_search_hist(): eventno < 0;\n"); 719 #endif 720 el->el_history.eventno = 0; 721 return CC_ERROR; 722 } 723 if (el->el_history.eventno == 0) { 724 (void) Strncpy(el->el_history.buf, el->el_line.buffer, 725 EL_BUFSIZ); 726 el->el_history.last = el->el_history.buf + 727 (el->el_line.lastchar - el->el_line.buffer); 728 } 729 if (el->el_history.ref == NULL) 730 return CC_ERROR; 731 732 hp = HIST_FIRST(el); 733 if (hp == NULL) 734 return CC_ERROR; 735 736 c_setpat(el); /* Set search pattern !! */ 737 738 for (h = 1; h <= el->el_history.eventno; h++) 739 hp = HIST_NEXT(el); 740 741 while (hp != NULL) { 742 #ifdef SDEBUG 743 (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp); 744 #endif 745 if ((Strncmp(hp, el->el_line.buffer, (size_t) 746 (el->el_line.lastchar - el->el_line.buffer)) || 747 hp[el->el_line.lastchar - el->el_line.buffer]) && 748 c_hmatch(el, hp)) { 749 found++; 750 break; 751 } 752 h++; 753 hp = HIST_NEXT(el); 754 } 755 756 if (!found) { 757 #ifdef SDEBUG 758 (void) fprintf(el->el_errfile, "not found\n"); 759 #endif 760 return CC_ERROR; 761 } 762 el->el_history.eventno = h; 763 764 return hist_get(el); 765 } 766 767 768 /* ed_search_next_history(): 769 * Search next in history for a line matching the current 770 * [M-N] [J] 771 */ 772 protected el_action_t 773 /*ARGSUSED*/ 774 ed_search_next_history(EditLine *el, Int c __attribute__((__unused__))) 775 { 776 const Char *hp; 777 int h; 778 bool_t found = 0; 779 780 el->el_chared.c_vcmd.action = NOP; 781 el->el_chared.c_undo.len = -1; 782 *el->el_line.lastchar = '\0'; /* just in case */ 783 784 if (el->el_history.eventno == 0) 785 return CC_ERROR; 786 787 if (el->el_history.ref == NULL) 788 return CC_ERROR; 789 790 hp = HIST_FIRST(el); 791 if (hp == NULL) 792 return CC_ERROR; 793 794 c_setpat(el); /* Set search pattern !! */ 795 796 for (h = 1; h < el->el_history.eventno && hp; h++) { 797 #ifdef SDEBUG 798 (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp); 799 #endif 800 if ((Strncmp(hp, el->el_line.buffer, (size_t) 801 (el->el_line.lastchar - el->el_line.buffer)) || 802 hp[el->el_line.lastchar - el->el_line.buffer]) && 803 c_hmatch(el, hp)) 804 found = h; 805 hp = HIST_NEXT(el); 806 } 807 808 if (!found) { /* is it the current history number? */ 809 if (!c_hmatch(el, el->el_history.buf)) { 810 #ifdef SDEBUG 811 (void) fprintf(el->el_errfile, "not found\n"); 812 #endif 813 return CC_ERROR; 814 } 815 } 816 el->el_history.eventno = found; 817 818 return hist_get(el); 819 } 820 821 822 /* ed_prev_line(): 823 * Move up one line 824 * Could be [k] [^p] 825 */ 826 protected el_action_t 827 /*ARGSUSED*/ 828 ed_prev_line(EditLine *el, Int c __attribute__((__unused__))) 829 { 830 Char *ptr; 831 int nchars = c_hpos(el); 832 833 /* 834 * Move to the line requested 835 */ 836 if (*(ptr = el->el_line.cursor) == '\n') 837 ptr--; 838 839 for (; ptr >= el->el_line.buffer; ptr--) 840 if (*ptr == '\n' && --el->el_state.argument <= 0) 841 break; 842 843 if (el->el_state.argument > 0) 844 return CC_ERROR; 845 846 /* 847 * Move to the beginning of the line 848 */ 849 for (ptr--; ptr >= el->el_line.buffer && *ptr != '\n'; ptr--) 850 continue; 851 852 /* 853 * Move to the character requested 854 */ 855 for (ptr++; 856 nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n'; 857 ptr++) 858 continue; 859 860 el->el_line.cursor = ptr; 861 return CC_CURSOR; 862 } 863 864 865 /* ed_next_line(): 866 * Move down one line 867 * Could be [j] [^n] 868 */ 869 protected el_action_t 870 /*ARGSUSED*/ 871 ed_next_line(EditLine *el, Int c __attribute__((__unused__))) 872 { 873 Char *ptr; 874 int nchars = c_hpos(el); 875 876 /* 877 * Move to the line requested 878 */ 879 for (ptr = el->el_line.cursor; ptr < el->el_line.lastchar; ptr++) 880 if (*ptr == '\n' && --el->el_state.argument <= 0) 881 break; 882 883 if (el->el_state.argument > 0) 884 return CC_ERROR; 885 886 /* 887 * Move to the character requested 888 */ 889 for (ptr++; 890 nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n'; 891 ptr++) 892 continue; 893 894 el->el_line.cursor = ptr; 895 return CC_CURSOR; 896 } 897 898 899 /* ed_command(): 900 * Editline extended command 901 * [M-X] [:] 902 */ 903 protected el_action_t 904 /*ARGSUSED*/ 905 ed_command(EditLine *el, Int c __attribute__((__unused__))) 906 { 907 Char tmpbuf[EL_BUFSIZ]; 908 int tmplen; 909 910 tmplen = c_gets(el, tmpbuf, STR("\n: ")); 911 terminal__putc(el, '\n'); 912 913 if (tmplen < 0 || (tmpbuf[tmplen] = 0, parse_line(el, tmpbuf)) == -1) 914 terminal_beep(el); 915 916 el->el_map.current = el->el_map.key; 917 re_clear_display(el); 918 return CC_REFRESH; 919 } 920