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