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