common.c revision 1.19
1/* $OpenBSD: common.c,v 1.19 2016/04/11 20:43:33 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 <ctype.h> 42#include <string.h> 43 44#include "el.h" 45#include "common.h" 46#include "parse.h" 47#include "vi.h" 48 49/* ed_end_of_file(): 50 * Indicate end of file 51 * [^D] 52 */ 53protected el_action_t 54/*ARGSUSED*/ 55ed_end_of_file(EditLine *el, wint_t c __attribute__((__unused__))) 56{ 57 58 re_goto_bottom(el); 59 *el->el_line.lastchar = '\0'; 60 return CC_EOF; 61} 62 63 64/* ed_insert(): 65 * Add character to the line 66 * Insert a character [bound to all insert keys] 67 */ 68protected el_action_t 69ed_insert(EditLine *el, wint_t c) 70{ 71 int count = el->el_state.argument; 72 73 if (c == '\0') 74 return CC_ERROR; 75 76 if (el->el_line.lastchar + el->el_state.argument >= 77 el->el_line.limit) { 78 /* end of buffer space, try to allocate more */ 79 if (!ch_enlargebufs(el, (size_t) count)) 80 return CC_ERROR; /* error allocating more */ 81 } 82 83 if (count == 1) { 84 if (el->el_state.inputmode == MODE_INSERT 85 || el->el_line.cursor >= el->el_line.lastchar) 86 c_insert(el, 1); 87 88 *el->el_line.cursor++ = c; 89 re_fastaddc(el); /* fast refresh for one char. */ 90 } else { 91 if (el->el_state.inputmode != MODE_REPLACE_1) 92 c_insert(el, el->el_state.argument); 93 94 while (count-- && el->el_line.cursor < el->el_line.lastchar) 95 *el->el_line.cursor++ = c; 96 re_refresh(el); 97 } 98 99 if (el->el_state.inputmode == MODE_REPLACE_1) 100 return vi_command_mode(el, 0); 101 102 return CC_NORM; 103} 104 105 106/* ed_delete_prev_word(): 107 * Delete from beginning of current word to cursor 108 * [M-^?] [^W] 109 */ 110protected el_action_t 111/*ARGSUSED*/ 112ed_delete_prev_word(EditLine *el, wint_t c __attribute__((__unused__))) 113{ 114 wchar_t *cp, *p, *kp; 115 116 if (el->el_line.cursor == el->el_line.buffer) 117 return CC_ERROR; 118 119 cp = c__prev_word(el->el_line.cursor, el->el_line.buffer, 120 el->el_state.argument, ce__isword); 121 122 for (p = cp, kp = el->el_chared.c_kill.buf; p < el->el_line.cursor; p++) 123 *kp++ = *p; 124 el->el_chared.c_kill.last = kp; 125 126 c_delbefore(el, (int)(el->el_line.cursor - cp));/* delete before dot */ 127 el->el_line.cursor = cp; 128 if (el->el_line.cursor < el->el_line.buffer) 129 el->el_line.cursor = el->el_line.buffer; /* bounds check */ 130 return CC_REFRESH; 131} 132 133 134/* ed_delete_next_char(): 135 * Delete character under cursor 136 * [^D] [x] 137 */ 138protected el_action_t 139/*ARGSUSED*/ 140ed_delete_next_char(EditLine *el, wint_t c) 141{ 142#ifdef notdef /* XXX */ 143#define EL el->el_line 144 (void) fprintf(el->el_errfile, 145 "\nD(b: %p(%ls) c: %p(%ls) last: %p(%ls) limit: %p(%ls)\n", 146 EL.buffer, EL.buffer, EL.cursor, EL.cursor, EL.lastchar, 147 EL.lastchar, EL.limit, EL.limit); 148#endif 149 if (el->el_line.cursor == el->el_line.lastchar) { 150 /* if I'm at the end */ 151 if (el->el_map.type == MAP_VI) { 152 if (el->el_line.cursor == el->el_line.buffer) { 153 /* if I'm also at the beginning */ 154#ifdef KSHVI 155 return CC_ERROR; 156#else 157 /* then do an EOF */ 158 terminal_writec(el, c); 159 return CC_EOF; 160#endif 161 } else { 162#ifdef KSHVI 163 el->el_line.cursor--; 164#else 165 return CC_ERROR; 166#endif 167 } 168 } else { 169 if (el->el_line.cursor != el->el_line.buffer) 170 el->el_line.cursor--; 171 else 172 return CC_ERROR; 173 } 174 } 175 c_delafter(el, el->el_state.argument); /* delete after dot */ 176 if (el->el_line.cursor >= el->el_line.lastchar && 177 el->el_line.cursor > el->el_line.buffer) 178 /* bounds check */ 179 el->el_line.cursor = el->el_line.lastchar - 1; 180 return CC_REFRESH; 181} 182 183 184/* ed_kill_line(): 185 * Cut to the end of line 186 * [^K] [^K] 187 */ 188protected el_action_t 189/*ARGSUSED*/ 190ed_kill_line(EditLine *el, wint_t c __attribute__((__unused__))) 191{ 192 wchar_t *kp, *cp; 193 194 cp = el->el_line.cursor; 195 kp = el->el_chared.c_kill.buf; 196 while (cp < el->el_line.lastchar) 197 *kp++ = *cp++; /* copy it */ 198 el->el_chared.c_kill.last = kp; 199 /* zap! -- delete to end */ 200 el->el_line.lastchar = el->el_line.cursor; 201 return CC_REFRESH; 202} 203 204 205/* ed_move_to_end(): 206 * Move cursor to the end of line 207 * [^E] [^E] 208 */ 209protected el_action_t 210/*ARGSUSED*/ 211ed_move_to_end(EditLine *el, wint_t c __attribute__((__unused__))) 212{ 213 214 el->el_line.cursor = el->el_line.lastchar; 215 if (el->el_map.type == MAP_VI) { 216 if (el->el_chared.c_vcmd.action != NOP) { 217 cv_delfini(el); 218 return CC_REFRESH; 219 } 220#ifdef VI_MOVE 221 el->el_line.cursor--; 222#endif 223 } 224 return CC_CURSOR; 225} 226 227 228/* ed_move_to_beg(): 229 * Move cursor to the beginning of line 230 * [^A] [^A] 231 */ 232protected el_action_t 233/*ARGSUSED*/ 234ed_move_to_beg(EditLine *el, wint_t c __attribute__((__unused__))) 235{ 236 237 el->el_line.cursor = el->el_line.buffer; 238 239 if (el->el_map.type == MAP_VI) { 240 /* We want FIRST non space character */ 241 while (iswspace(*el->el_line.cursor)) 242 el->el_line.cursor++; 243 if (el->el_chared.c_vcmd.action != NOP) { 244 cv_delfini(el); 245 return CC_REFRESH; 246 } 247 } 248 return CC_CURSOR; 249} 250 251 252/* ed_transpose_chars(): 253 * Exchange the character to the left of the cursor with the one under it 254 * [^T] [^T] 255 */ 256protected el_action_t 257ed_transpose_chars(EditLine *el, wint_t c) 258{ 259 260 if (el->el_line.cursor < el->el_line.lastchar) { 261 if (el->el_line.lastchar <= &el->el_line.buffer[1]) 262 return CC_ERROR; 263 else 264 el->el_line.cursor++; 265 } 266 if (el->el_line.cursor > &el->el_line.buffer[1]) { 267 /* must have at least two chars entered */ 268 c = el->el_line.cursor[-2]; 269 el->el_line.cursor[-2] = el->el_line.cursor[-1]; 270 el->el_line.cursor[-1] = c; 271 return CC_REFRESH; 272 } else 273 return CC_ERROR; 274} 275 276 277/* ed_next_char(): 278 * Move to the right one character 279 * [^F] [^F] 280 */ 281protected el_action_t 282/*ARGSUSED*/ 283ed_next_char(EditLine *el, wint_t c __attribute__((__unused__))) 284{ 285 wchar_t *lim = el->el_line.lastchar; 286 287 if (el->el_line.cursor >= lim || 288 (el->el_line.cursor == lim - 1 && 289 el->el_map.type == MAP_VI && 290 el->el_chared.c_vcmd.action == NOP)) 291 return CC_ERROR; 292 293 el->el_line.cursor += el->el_state.argument; 294 if (el->el_line.cursor > lim) 295 el->el_line.cursor = lim; 296 297 if (el->el_map.type == MAP_VI) 298 if (el->el_chared.c_vcmd.action != NOP) { 299 cv_delfini(el); 300 return CC_REFRESH; 301 } 302 return CC_CURSOR; 303} 304 305 306/* ed_prev_word(): 307 * Move to the beginning of the current word 308 * [M-b] [b] 309 */ 310protected el_action_t 311/*ARGSUSED*/ 312ed_prev_word(EditLine *el, wint_t c __attribute__((__unused__))) 313{ 314 315 if (el->el_line.cursor == el->el_line.buffer) 316 return CC_ERROR; 317 318 el->el_line.cursor = c__prev_word(el->el_line.cursor, 319 el->el_line.buffer, 320 el->el_state.argument, 321 ce__isword); 322 323 if (el->el_map.type == MAP_VI) 324 if (el->el_chared.c_vcmd.action != NOP) { 325 cv_delfini(el); 326 return CC_REFRESH; 327 } 328 return CC_CURSOR; 329} 330 331 332/* ed_prev_char(): 333 * Move to the left one character 334 * [^B] [^B] 335 */ 336protected el_action_t 337/*ARGSUSED*/ 338ed_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) 339{ 340 341 if (el->el_line.cursor > el->el_line.buffer) { 342 el->el_line.cursor -= el->el_state.argument; 343 if (el->el_line.cursor < el->el_line.buffer) 344 el->el_line.cursor = el->el_line.buffer; 345 346 if (el->el_map.type == MAP_VI) 347 if (el->el_chared.c_vcmd.action != NOP) { 348 cv_delfini(el); 349 return CC_REFRESH; 350 } 351 return CC_CURSOR; 352 } else 353 return CC_ERROR; 354} 355 356 357/* ed_quoted_insert(): 358 * Add the next character typed verbatim 359 * [^V] [^V] 360 */ 361protected el_action_t 362ed_quoted_insert(EditLine *el, wint_t c) 363{ 364 int num; 365 366 tty_quotemode(el); 367 num = el_wgetc(el, &c); 368 tty_noquotemode(el); 369 if (num == 1) 370 return ed_insert(el, c); 371 else 372 return ed_end_of_file(el, 0); 373} 374 375 376/* ed_digit(): 377 * Adds to argument or enters a digit 378 */ 379protected el_action_t 380ed_digit(EditLine *el, wint_t c) 381{ 382 383 if (!iswdigit(c)) 384 return CC_ERROR; 385 386 if (el->el_state.doingarg) { 387 /* if doing an arg, add this in... */ 388 if (el->el_state.lastcmd == EM_UNIVERSAL_ARGUMENT) 389 el->el_state.argument = c - '0'; 390 else { 391 if (el->el_state.argument > 1000000) 392 return CC_ERROR; 393 el->el_state.argument = 394 (el->el_state.argument * 10) + (c - '0'); 395 } 396 return CC_ARGHACK; 397 } 398 399 return ed_insert(el, c); 400} 401 402 403/* ed_argument_digit(): 404 * Digit that starts argument 405 * For ESC-n 406 */ 407protected el_action_t 408ed_argument_digit(EditLine *el, wint_t c) 409{ 410 411 if (!iswdigit(c)) 412 return CC_ERROR; 413 414 if (el->el_state.doingarg) { 415 if (el->el_state.argument > 1000000) 416 return CC_ERROR; 417 el->el_state.argument = (el->el_state.argument * 10) + 418 (c - '0'); 419 } else { /* else starting an argument */ 420 el->el_state.argument = c - '0'; 421 el->el_state.doingarg = 1; 422 } 423 return CC_ARGHACK; 424} 425 426 427/* ed_unassigned(): 428 * Indicates unbound character 429 * Bound to keys that are not assigned 430 */ 431protected el_action_t 432/*ARGSUSED*/ 433ed_unassigned(EditLine *el, wint_t c __attribute__((__unused__))) 434{ 435 436 return CC_ERROR; 437} 438 439 440/** 441 ** TTY key handling. 442 **/ 443 444/* ed_tty_sigint(): 445 * Tty interrupt character 446 * [^C] 447 */ 448protected el_action_t 449/*ARGSUSED*/ 450ed_tty_sigint(EditLine *el __attribute__((__unused__)), 451 wint_t c __attribute__((__unused__))) 452{ 453 454 return CC_NORM; 455} 456 457 458/* ed_tty_dsusp(): 459 * Tty delayed suspend character 460 * [^Y] 461 */ 462protected el_action_t 463/*ARGSUSED*/ 464ed_tty_dsusp(EditLine *el __attribute__((__unused__)), 465 wint_t c __attribute__((__unused__))) 466{ 467 468 return CC_NORM; 469} 470 471 472/* ed_tty_flush_output(): 473 * Tty flush output characters 474 * [^O] 475 */ 476protected el_action_t 477/*ARGSUSED*/ 478ed_tty_flush_output(EditLine *el __attribute__((__unused__)), 479 wint_t c __attribute__((__unused__))) 480{ 481 482 return CC_NORM; 483} 484 485 486/* ed_tty_sigquit(): 487 * Tty quit character 488 * [^\] 489 */ 490protected el_action_t 491/*ARGSUSED*/ 492ed_tty_sigquit(EditLine *el __attribute__((__unused__)), 493 wint_t c __attribute__((__unused__))) 494{ 495 496 return CC_NORM; 497} 498 499 500/* ed_tty_sigtstp(): 501 * Tty suspend character 502 * [^Z] 503 */ 504protected el_action_t 505/*ARGSUSED*/ 506ed_tty_sigtstp(EditLine *el __attribute__((__unused__)), 507 wint_t c __attribute__((__unused__))) 508{ 509 510 return CC_NORM; 511} 512 513 514/* ed_tty_stop_output(): 515 * Tty disallow output characters 516 * [^S] 517 */ 518protected el_action_t 519/*ARGSUSED*/ 520ed_tty_stop_output(EditLine *el __attribute__((__unused__)), 521 wint_t c __attribute__((__unused__))) 522{ 523 524 return CC_NORM; 525} 526 527 528/* ed_tty_start_output(): 529 * Tty allow output characters 530 * [^Q] 531 */ 532protected el_action_t 533/*ARGSUSED*/ 534ed_tty_start_output(EditLine *el __attribute__((__unused__)), 535 wint_t c __attribute__((__unused__))) 536{ 537 538 return CC_NORM; 539} 540 541 542/* ed_newline(): 543 * Execute command 544 * [^J] 545 */ 546protected el_action_t 547/*ARGSUSED*/ 548ed_newline(EditLine *el, wint_t c __attribute__((__unused__))) 549{ 550 551 re_goto_bottom(el); 552 *el->el_line.lastchar++ = '\n'; 553 *el->el_line.lastchar = '\0'; 554 return CC_NEWLINE; 555} 556 557 558/* ed_delete_prev_char(): 559 * Delete the character to the left of the cursor 560 * [^?] 561 */ 562protected el_action_t 563/*ARGSUSED*/ 564ed_delete_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) 565{ 566 567 if (el->el_line.cursor <= el->el_line.buffer) 568 return CC_ERROR; 569 570 c_delbefore(el, el->el_state.argument); 571 el->el_line.cursor -= el->el_state.argument; 572 if (el->el_line.cursor < el->el_line.buffer) 573 el->el_line.cursor = el->el_line.buffer; 574 return CC_REFRESH; 575} 576 577 578/* ed_clear_screen(): 579 * Clear screen leaving current line at the top 580 * [^L] 581 */ 582protected el_action_t 583/*ARGSUSED*/ 584ed_clear_screen(EditLine *el, wint_t c __attribute__((__unused__))) 585{ 586 587 terminal_clear_screen(el); /* clear the whole real screen */ 588 re_clear_display(el); /* reset everything */ 589 return CC_REFRESH; 590} 591 592 593/* ed_redisplay(): 594 * Redisplay everything 595 * ^R 596 */ 597protected el_action_t 598/*ARGSUSED*/ 599ed_redisplay(EditLine *el __attribute__((__unused__)), 600 wint_t c __attribute__((__unused__))) 601{ 602 603 return CC_REDISPLAY; 604} 605 606 607/* ed_start_over(): 608 * Erase current line and start from scratch 609 * [^G] 610 */ 611protected el_action_t 612/*ARGSUSED*/ 613ed_start_over(EditLine *el, wint_t c __attribute__((__unused__))) 614{ 615 616 ch_reset(el, 0); 617 return CC_REFRESH; 618} 619 620 621/* ed_sequence_lead_in(): 622 * First character in a bound sequence 623 * Placeholder for external keys 624 */ 625protected el_action_t 626/*ARGSUSED*/ 627ed_sequence_lead_in(EditLine *el __attribute__((__unused__)), 628 wint_t c __attribute__((__unused__))) 629{ 630 631 return CC_NORM; 632} 633 634 635/* ed_prev_history(): 636 * Move to the previous history line 637 * [^P] [k] 638 */ 639protected el_action_t 640/*ARGSUSED*/ 641ed_prev_history(EditLine *el, wint_t c __attribute__((__unused__))) 642{ 643 char beep = 0; 644 int sv_event = el->el_history.eventno; 645 646 el->el_chared.c_undo.len = -1; 647 *el->el_line.lastchar = '\0'; /* just in case */ 648 649 if (el->el_history.eventno == 0) { /* save the current buffer 650 * away */ 651 (void) wcsncpy(el->el_history.buf, el->el_line.buffer, 652 EL_BUFSIZ); 653 el->el_history.last = el->el_history.buf + 654 (el->el_line.lastchar - el->el_line.buffer); 655 } 656 el->el_history.eventno += el->el_state.argument; 657 658 if (hist_get(el) == CC_ERROR) { 659 if (el->el_map.type == MAP_VI) { 660 el->el_history.eventno = sv_event; 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 wchar_t *hp; 708 int h; 709 int 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) wcsncpy(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 ((wcsncmp(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 = 1; 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 wchar_t *hp; 776 int h; 777 int 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 ((wcsncmp(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 wchar_t *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 wchar_t *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 wchar_t tmpbuf[EL_BUFSIZ]; 907 int tmplen; 908 909 tmplen = c_gets(el, tmpbuf, L"\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