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