common.c revision 1.8
1/* $OpenBSD: common.c,v 1.8 2010/06/30 00:05:35 nicm 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 */ 47protected el_action_t 48/*ARGSUSED*/ 49ed_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 */ 62protected el_action_t 63ed_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 */ 104protected el_action_t 105/*ARGSUSED*/ 106ed_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 */ 132protected el_action_t 133/*ARGSUSED*/ 134ed_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 term_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 */ 182protected el_action_t 183/*ARGSUSED*/ 184ed_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 */ 203protected el_action_t 204/*ARGSUSED*/ 205ed_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 */ 226protected el_action_t 227/*ARGSUSED*/ 228ed_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 */ 250protected el_action_t 251ed_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 */ 275protected el_action_t 276/*ARGSUSED*/ 277ed_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 */ 304protected el_action_t 305/*ARGSUSED*/ 306ed_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 */ 330protected el_action_t 331/*ARGSUSED*/ 332ed_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 */ 355protected el_action_t 356ed_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 */ 375protected el_action_t 376ed_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 */ 403protected el_action_t 404ed_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 */ 427protected el_action_t 428/*ARGSUSED*/ 429ed_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 */ 444protected el_action_t 445/*ARGSUSED*/ 446ed_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 */ 458protected el_action_t 459/*ARGSUSED*/ 460ed_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 */ 472protected el_action_t 473/*ARGSUSED*/ 474ed_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 */ 486protected el_action_t 487/*ARGSUSED*/ 488ed_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 */ 500protected el_action_t 501/*ARGSUSED*/ 502ed_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 */ 514protected el_action_t 515/*ARGSUSED*/ 516ed_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 */ 528protected el_action_t 529/*ARGSUSED*/ 530ed_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 */ 542protected el_action_t 543/*ARGSUSED*/ 544ed_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 */ 558protected el_action_t 559/*ARGSUSED*/ 560ed_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 */ 578protected el_action_t 579/*ARGSUSED*/ 580ed_clear_screen(EditLine *el, Int c __attribute__((__unused__))) 581{ 582 583 term_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 */ 593protected el_action_t 594/*ARGSUSED*/ 595ed_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 */ 607protected el_action_t 608/*ARGSUSED*/ 609ed_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 */ 621protected el_action_t 622/*ARGSUSED*/ 623ed_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 */ 635protected el_action_t 636/*ARGSUSED*/ 637ed_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 */ 673protected el_action_t 674/*ARGSUSED*/ 675ed_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 */ 700protected el_action_t 701/*ARGSUSED*/ 702ed_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 */ 768protected el_action_t 769/*ARGSUSED*/ 770ed_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 */ 822protected el_action_t 823/*ARGSUSED*/ 824ed_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 */ 865protected el_action_t 866/*ARGSUSED*/ 867ed_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 */ 899protected el_action_t 900/*ARGSUSED*/ 901ed_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 term__putc(el, '\n'); 908 909 if (tmplen < 0 || (tmpbuf[tmplen] = 0, parse_line(el, tmpbuf)) == -1) 910 term_beep(el); 911 912 el->el_map.current = el->el_map.key; 913 re_clear_display(el); 914 return CC_REFRESH; 915} 916