common.c revision 167457
1/*- 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Christos Zoulas of Cornell University. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * $NetBSD: common.c,v 1.19 2006/03/06 21:11:56 christos Exp $ 33 */ 34 35#if !defined(lint) && !defined(SCCSID) 36static char sccsid[] = "@(#)common.c 8.1 (Berkeley) 6/4/93"; 37#endif /* not lint && not SCCSID */ 38#include <sys/cdefs.h> 39__FBSDID("$FreeBSD: head/lib/libedit/common.c 167457 2007-03-11 18:30:22Z stefanf $"); 40 41/* 42 * common.c: Common Editor functions 43 */ 44#include "sys.h" 45#include "el.h" 46 47/* ed_end_of_file(): 48 * Indicate end of file 49 * [^D] 50 */ 51protected el_action_t 52/*ARGSUSED*/ 53ed_end_of_file(EditLine *el, int c __unused) 54{ 55 56 re_goto_bottom(el); 57 *el->el_line.lastchar = '\0'; 58 return (CC_EOF); 59} 60 61 62/* ed_insert(): 63 * Add character to the line 64 * Insert a character [bound to all insert keys] 65 */ 66protected el_action_t 67ed_insert(EditLine *el, int c) 68{ 69 int count = el->el_state.argument; 70 71 if (c == '\0') 72 return (CC_ERROR); 73 74 if (el->el_line.lastchar + el->el_state.argument >= 75 el->el_line.limit) { 76 /* end of buffer space, try to allocate more */ 77 if (!ch_enlargebufs(el, (size_t) count)) 78 return CC_ERROR; /* error allocating more */ 79 } 80 81 if (count == 1) { 82 if (el->el_state.inputmode == MODE_INSERT 83 || el->el_line.cursor >= el->el_line.lastchar) 84 c_insert(el, 1); 85 86 *el->el_line.cursor++ = c; 87 re_fastaddc(el); /* fast refresh for one char. */ 88 } else { 89 if (el->el_state.inputmode != MODE_REPLACE_1) 90 c_insert(el, el->el_state.argument); 91 92 while (count-- && el->el_line.cursor < el->el_line.lastchar) 93 *el->el_line.cursor++ = c; 94 re_refresh(el); 95 } 96 97 if (el->el_state.inputmode == MODE_REPLACE_1) 98 return vi_command_mode(el, 0); 99 100 return (CC_NORM); 101} 102 103 104/* ed_delete_prev_word(): 105 * Delete from beginning of current word to cursor 106 * [M-^?] [^W] 107 */ 108protected el_action_t 109/*ARGSUSED*/ 110ed_delete_prev_word(EditLine *el, int c __unused) 111{ 112 char *cp, *p, *kp; 113 114 if (el->el_line.cursor == el->el_line.buffer) 115 return (CC_ERROR); 116 117 cp = c__prev_word(el->el_line.cursor, el->el_line.buffer, 118 el->el_state.argument, ce__isword); 119 120 for (p = cp, kp = el->el_chared.c_kill.buf; p < el->el_line.cursor; p++) 121 *kp++ = *p; 122 el->el_chared.c_kill.last = kp; 123 124 c_delbefore(el, el->el_line.cursor - cp); /* delete before dot */ 125 el->el_line.cursor = cp; 126 if (el->el_line.cursor < el->el_line.buffer) 127 el->el_line.cursor = el->el_line.buffer; /* bounds check */ 128 return (CC_REFRESH); 129} 130 131 132/* ed_delete_next_char(): 133 * Delete character under cursor 134 * [^D] [x] 135 */ 136protected el_action_t 137/*ARGSUSED*/ 138ed_delete_next_char(EditLine *el, int c) 139{ 140#ifdef notdef /* XXX */ 141#define EL el->el_line 142 (void) fprintf(el->el_errlfile, 143 "\nD(b: %x(%s) c: %x(%s) last: %x(%s) limit: %x(%s)\n", 144 EL.buffer, EL.buffer, EL.cursor, EL.cursor, EL.lastchar, 145 EL.lastchar, EL.limit, EL.limit); 146#endif 147 if (el->el_line.cursor == el->el_line.lastchar) { 148 /* if I'm at the end */ 149 if (el->el_map.type == MAP_VI) { 150 if (el->el_line.cursor == el->el_line.buffer) { 151 /* if I'm also at the beginning */ 152#ifdef KSHVI 153 return (CC_ERROR); 154#else 155 /* then do an EOF */ 156 term_writechar(el, c); 157 return (CC_EOF); 158#endif 159 } else { 160#ifdef KSHVI 161 el->el_line.cursor--; 162#else 163 return (CC_ERROR); 164#endif 165 } 166 } else { 167 if (el->el_line.cursor != el->el_line.buffer) 168 el->el_line.cursor--; 169 else 170 return (CC_ERROR); 171 } 172 } 173 c_delafter(el, el->el_state.argument); /* delete after dot */ 174 if (el->el_line.cursor >= el->el_line.lastchar && 175 el->el_line.cursor > el->el_line.buffer) 176 /* bounds check */ 177 el->el_line.cursor = el->el_line.lastchar - 1; 178 return (CC_REFRESH); 179} 180 181 182/* ed_kill_line(): 183 * Cut to the end of line 184 * [^K] [^K] 185 */ 186protected el_action_t 187/*ARGSUSED*/ 188ed_kill_line(EditLine *el, int c __unused) 189{ 190 char *kp, *cp; 191 192 cp = el->el_line.cursor; 193 kp = el->el_chared.c_kill.buf; 194 while (cp < el->el_line.lastchar) 195 *kp++ = *cp++; /* copy it */ 196 el->el_chared.c_kill.last = kp; 197 /* zap! -- delete to end */ 198 el->el_line.lastchar = el->el_line.cursor; 199 return (CC_REFRESH); 200} 201 202 203/* ed_move_to_end(): 204 * Move cursor to the end of line 205 * [^E] [^E] 206 */ 207protected el_action_t 208/*ARGSUSED*/ 209ed_move_to_end(EditLine *el, int c __unused) 210{ 211 212 el->el_line.cursor = el->el_line.lastchar; 213 if (el->el_map.type == MAP_VI) { 214#ifdef VI_MOVE 215 el->el_line.cursor--; 216#endif 217 if (el->el_chared.c_vcmd.action != NOP) { 218 cv_delfini(el); 219 return (CC_REFRESH); 220 } 221 } 222 return (CC_CURSOR); 223} 224 225 226/* ed_move_to_beg(): 227 * Move cursor to the beginning of line 228 * [^A] [^A] 229 */ 230protected el_action_t 231/*ARGSUSED*/ 232ed_move_to_beg(EditLine *el, int c __unused) 233{ 234 235 el->el_line.cursor = el->el_line.buffer; 236 237 if (el->el_map.type == MAP_VI) { 238 /* We want FIRST non space character */ 239 while (isspace((unsigned char) *el->el_line.cursor)) 240 el->el_line.cursor++; 241 if (el->el_chared.c_vcmd.action != NOP) { 242 cv_delfini(el); 243 return (CC_REFRESH); 244 } 245 } 246 return (CC_CURSOR); 247} 248 249 250/* ed_transpose_chars(): 251 * Exchange the character to the left of the cursor with the one under it 252 * [^T] [^T] 253 */ 254protected el_action_t 255ed_transpose_chars(EditLine *el, int c) 256{ 257 258 if (el->el_line.cursor < el->el_line.lastchar) { 259 if (el->el_line.lastchar <= &el->el_line.buffer[1]) 260 return (CC_ERROR); 261 else 262 el->el_line.cursor++; 263 } 264 if (el->el_line.cursor > &el->el_line.buffer[1]) { 265 /* must have at least two chars entered */ 266 c = el->el_line.cursor[-2]; 267 el->el_line.cursor[-2] = el->el_line.cursor[-1]; 268 el->el_line.cursor[-1] = c; 269 return (CC_REFRESH); 270 } else 271 return (CC_ERROR); 272} 273 274 275/* ed_next_char(): 276 * Move to the right one character 277 * [^F] [^F] 278 */ 279protected el_action_t 280/*ARGSUSED*/ 281ed_next_char(EditLine *el, int c __unused) 282{ 283 char *lim = el->el_line.lastchar; 284 285 if (el->el_line.cursor >= lim || 286 (el->el_line.cursor == lim - 1 && 287 el->el_map.type == MAP_VI && 288 el->el_chared.c_vcmd.action == NOP)) 289 return (CC_ERROR); 290 291 el->el_line.cursor += el->el_state.argument; 292 if (el->el_line.cursor > lim) 293 el->el_line.cursor = lim; 294 295 if (el->el_map.type == MAP_VI) 296 if (el->el_chared.c_vcmd.action != NOP) { 297 cv_delfini(el); 298 return (CC_REFRESH); 299 } 300 return (CC_CURSOR); 301} 302 303 304/* ed_prev_word(): 305 * Move to the beginning of the current word 306 * [M-b] [b] 307 */ 308protected el_action_t 309/*ARGSUSED*/ 310ed_prev_word(EditLine *el, int c __unused) 311{ 312 313 if (el->el_line.cursor == el->el_line.buffer) 314 return (CC_ERROR); 315 316 el->el_line.cursor = c__prev_word(el->el_line.cursor, 317 el->el_line.buffer, 318 el->el_state.argument, 319 ce__isword); 320 321 if (el->el_map.type == MAP_VI) 322 if (el->el_chared.c_vcmd.action != NOP) { 323 cv_delfini(el); 324 return (CC_REFRESH); 325 } 326 return (CC_CURSOR); 327} 328 329 330/* ed_prev_char(): 331 * Move to the left one character 332 * [^B] [^B] 333 */ 334protected el_action_t 335/*ARGSUSED*/ 336ed_prev_char(EditLine *el, int c __unused) 337{ 338 339 if (el->el_line.cursor > el->el_line.buffer) { 340 el->el_line.cursor -= el->el_state.argument; 341 if (el->el_line.cursor < el->el_line.buffer) 342 el->el_line.cursor = el->el_line.buffer; 343 344 if (el->el_map.type == MAP_VI) 345 if (el->el_chared.c_vcmd.action != NOP) { 346 cv_delfini(el); 347 return (CC_REFRESH); 348 } 349 return (CC_CURSOR); 350 } else 351 return (CC_ERROR); 352} 353 354 355/* ed_quoted_insert(): 356 * Add the next character typed verbatim 357 * [^V] [^V] 358 */ 359protected el_action_t 360ed_quoted_insert(EditLine *el, int c) 361{ 362 int num; 363 char tc; 364 365 tty_quotemode(el); 366 num = el_getc(el, &tc); 367 c = (unsigned char) tc; 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, int c) 381{ 382 383 if (!isdigit((unsigned char) 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, int c) 409{ 410 411 if (!isdigit((unsigned char) 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, int c __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 __unused, 451 int c __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 __unused, 465 int c __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 __unused, 479 int c __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 __unused, 493 int c __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 __unused, 507 int c __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 __unused, 521 int c __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 __unused, 535 int c __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, int c __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, int c __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, int c __unused) 585{ 586 587 term_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 __unused, 600 int c __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, int c __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 __unused, 628 int c __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, int c __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) strncpy(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 return CC_ERROR; 662 } 663 beep = 1; 664 /* el->el_history.eventno was fixed by first call */ 665 (void) hist_get(el); 666 } 667 if (beep) 668 return CC_REFRESH_BEEP; 669 return CC_REFRESH; 670} 671 672 673/* ed_next_history(): 674 * Move to the next history line 675 * [^N] [j] 676 */ 677protected el_action_t 678/*ARGSUSED*/ 679ed_next_history(EditLine *el, int c __unused) 680{ 681 el_action_t beep = CC_REFRESH, rval; 682 683 el->el_chared.c_undo.len = -1; 684 *el->el_line.lastchar = '\0'; /* just in case */ 685 686 el->el_history.eventno -= el->el_state.argument; 687 688 if (el->el_history.eventno < 0) { 689 el->el_history.eventno = 0; 690 beep = CC_REFRESH_BEEP; 691 } 692 rval = hist_get(el); 693 if (rval == CC_REFRESH) 694 return beep; 695 return rval; 696 697} 698 699 700/* ed_search_prev_history(): 701 * Search previous in history for a line matching the current 702 * next search history [M-P] [K] 703 */ 704protected el_action_t 705/*ARGSUSED*/ 706ed_search_prev_history(EditLine *el, int c __unused) 707{ 708 const char *hp; 709 int h; 710 bool_t found = 0; 711 712 el->el_chared.c_vcmd.action = NOP; 713 el->el_chared.c_undo.len = -1; 714 *el->el_line.lastchar = '\0'; /* just in case */ 715 if (el->el_history.eventno < 0) { 716#ifdef DEBUG_EDIT 717 (void) fprintf(el->el_errfile, 718 "e_prev_search_hist(): eventno < 0;\n"); 719#endif 720 el->el_history.eventno = 0; 721 return (CC_ERROR); 722 } 723 if (el->el_history.eventno == 0) { 724 (void) strncpy(el->el_history.buf, el->el_line.buffer, 725 EL_BUFSIZ); 726 el->el_history.last = el->el_history.buf + 727 (el->el_line.lastchar - el->el_line.buffer); 728 } 729 if (el->el_history.ref == NULL) 730 return (CC_ERROR); 731 732 hp = HIST_FIRST(el); 733 if (hp == NULL) 734 return (CC_ERROR); 735 736 c_setpat(el); /* Set search pattern !! */ 737 738 for (h = 1; h <= el->el_history.eventno; h++) 739 hp = HIST_NEXT(el); 740 741 while (hp != NULL) { 742#ifdef SDEBUG 743 (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp); 744#endif 745 if ((strncmp(hp, el->el_line.buffer, (size_t) 746 (el->el_line.lastchar - el->el_line.buffer)) || 747 hp[el->el_line.lastchar - el->el_line.buffer]) && 748 c_hmatch(el, hp)) { 749 found++; 750 break; 751 } 752 h++; 753 hp = HIST_NEXT(el); 754 } 755 756 if (!found) { 757#ifdef SDEBUG 758 (void) fprintf(el->el_errfile, "not found\n"); 759#endif 760 return (CC_ERROR); 761 } 762 el->el_history.eventno = h; 763 764 return (hist_get(el)); 765} 766 767 768/* ed_search_next_history(): 769 * Search next in history for a line matching the current 770 * [M-N] [J] 771 */ 772protected el_action_t 773/*ARGSUSED*/ 774ed_search_next_history(EditLine *el, int c __unused) 775{ 776 const char *hp; 777 int h; 778 bool_t found = 0; 779 780 el->el_chared.c_vcmd.action = NOP; 781 el->el_chared.c_undo.len = -1; 782 *el->el_line.lastchar = '\0'; /* just in case */ 783 784 if (el->el_history.eventno == 0) 785 return (CC_ERROR); 786 787 if (el->el_history.ref == NULL) 788 return (CC_ERROR); 789 790 hp = HIST_FIRST(el); 791 if (hp == NULL) 792 return (CC_ERROR); 793 794 c_setpat(el); /* Set search pattern !! */ 795 796 for (h = 1; h < el->el_history.eventno && hp; h++) { 797#ifdef SDEBUG 798 (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp); 799#endif 800 if ((strncmp(hp, el->el_line.buffer, (size_t) 801 (el->el_line.lastchar - el->el_line.buffer)) || 802 hp[el->el_line.lastchar - el->el_line.buffer]) && 803 c_hmatch(el, hp)) 804 found = h; 805 hp = HIST_NEXT(el); 806 } 807 808 if (!found) { /* is it the current history number? */ 809 if (!c_hmatch(el, el->el_history.buf)) { 810#ifdef SDEBUG 811 (void) fprintf(el->el_errfile, "not found\n"); 812#endif 813 return (CC_ERROR); 814 } 815 } 816 el->el_history.eventno = found; 817 818 return (hist_get(el)); 819} 820 821 822/* ed_prev_line(): 823 * Move up one line 824 * Could be [k] [^p] 825 */ 826protected el_action_t 827/*ARGSUSED*/ 828ed_prev_line(EditLine *el, int c __unused) 829{ 830 char *ptr; 831 int nchars = c_hpos(el); 832 833 /* 834 * Move to the line requested 835 */ 836 if (*(ptr = el->el_line.cursor) == '\n') 837 ptr--; 838 839 for (; ptr >= el->el_line.buffer; ptr--) 840 if (*ptr == '\n' && --el->el_state.argument <= 0) 841 break; 842 843 if (el->el_state.argument > 0) 844 return (CC_ERROR); 845 846 /* 847 * Move to the beginning of the line 848 */ 849 for (ptr--; ptr >= el->el_line.buffer && *ptr != '\n'; ptr--) 850 continue; 851 852 /* 853 * Move to the character requested 854 */ 855 for (ptr++; 856 nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n'; 857 ptr++) 858 continue; 859 860 el->el_line.cursor = ptr; 861 return (CC_CURSOR); 862} 863 864 865/* ed_next_line(): 866 * Move down one line 867 * Could be [j] [^n] 868 */ 869protected el_action_t 870/*ARGSUSED*/ 871ed_next_line(EditLine *el, int c __unused) 872{ 873 char *ptr; 874 int nchars = c_hpos(el); 875 876 /* 877 * Move to the line requested 878 */ 879 for (ptr = el->el_line.cursor; ptr < el->el_line.lastchar; ptr++) 880 if (*ptr == '\n' && --el->el_state.argument <= 0) 881 break; 882 883 if (el->el_state.argument > 0) 884 return (CC_ERROR); 885 886 /* 887 * Move to the character requested 888 */ 889 for (ptr++; 890 nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n'; 891 ptr++) 892 continue; 893 894 el->el_line.cursor = ptr; 895 return (CC_CURSOR); 896} 897 898 899/* ed_command(): 900 * Editline extended command 901 * [M-X] [:] 902 */ 903protected el_action_t 904/*ARGSUSED*/ 905ed_command(EditLine *el, int c __unused) 906{ 907 char tmpbuf[EL_BUFSIZ]; 908 int tmplen; 909 910 tmplen = c_gets(el, tmpbuf, "\n: "); 911 term__putc('\n'); 912 913 if (tmplen < 0 || (tmpbuf[tmplen] = 0, parse_line(el, tmpbuf)) == -1) 914 term_beep(el); 915 916 el->el_map.current = el->el_map.key; 917 re_clear_display(el); 918 return CC_REFRESH; 919} 920