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