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