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