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