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