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