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