1 /* $NetBSD: common.c,v 1.50 2024/06/30 16:29:42 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 38 static char sccsid[] = "@(#)common.c 8.1 (Berkeley) 6/4/93"; 39 #else 40 __RCSID("$NetBSD: common.c,v 1.50 2024/06/30 16:29:42 christos 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 if (el->el_line.cursor > el->el_line.buffer) 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 */ 237 libedit_private el_action_t 238 /*ARGSUSED*/ 239 ed_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 (iswspace(*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 */ 261 libedit_private el_action_t 262 ed_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] = 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 */ 286 libedit_private el_action_t 287 /*ARGSUSED*/ 288 ed_next_char(EditLine *el, wint_t c __attribute__((__unused__))) 289 { 290 wchar_t *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 */ 315 libedit_private el_action_t 316 /*ARGSUSED*/ 317 ed_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 */ 341 libedit_private el_action_t 342 /*ARGSUSED*/ 343 ed_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 */ 366 libedit_private el_action_t 367 /*ARGSUSED*/ 368 ed_quoted_insert(EditLine *el, wint_t c __attribute__((__unused__))) 369 { 370 int num; 371 wchar_t ch; 372 373 tty_quotemode(el); 374 num = el_wgetc(el, &ch); 375 tty_noquotemode(el); 376 if (num == 1) 377 return ed_insert(el, ch); 378 else 379 return ed_end_of_file(el, 0); 380 } 381 382 383 /* ed_digit(): 384 * Adds to argument or enters a digit 385 */ 386 libedit_private el_action_t 387 ed_digit(EditLine *el, wint_t c) 388 { 389 390 if (!iswdigit(c)) 391 return CC_ERROR; 392 393 if (el->el_state.doingarg) { 394 /* if doing an arg, add this in... */ 395 if (el->el_state.lastcmd == EM_UNIVERSAL_ARGUMENT) 396 el->el_state.argument = c - '0'; 397 else { 398 if (el->el_state.argument > 1000000) 399 return CC_ERROR; 400 el->el_state.argument = 401 (el->el_state.argument * 10) + (c - '0'); 402 } 403 return CC_ARGHACK; 404 } 405 406 return ed_insert(el, c); 407 } 408 409 410 /* ed_argument_digit(): 411 * Digit that starts argument 412 * For ESC-n 413 */ 414 libedit_private el_action_t 415 ed_argument_digit(EditLine *el, wint_t c) 416 { 417 418 if (!iswdigit(c)) 419 return CC_ERROR; 420 421 if (el->el_state.doingarg) { 422 if (el->el_state.argument > 1000000) 423 return CC_ERROR; 424 el->el_state.argument = (el->el_state.argument * 10) + 425 (c - '0'); 426 } else { /* else starting an argument */ 427 el->el_state.argument = c - '0'; 428 el->el_state.doingarg = 1; 429 } 430 return CC_ARGHACK; 431 } 432 433 434 /* ed_unassigned(): 435 * Indicates unbound character 436 * Bound to keys that are not assigned 437 */ 438 libedit_private el_action_t 439 /*ARGSUSED*/ 440 ed_unassigned(EditLine *el __attribute__((__unused__)), 441 wint_t c __attribute__((__unused__))) 442 { 443 444 return CC_ERROR; 445 } 446 447 448 /* ed_ignore(): 449 * Input characters that have no effect 450 * [^C ^O ^Q ^S ^Z ^\ ^]] [^C ^O ^Q ^S ^\] 451 */ 452 libedit_private el_action_t 453 /*ARGSUSED*/ 454 ed_ignore(EditLine *el __attribute__((__unused__)), 455 wint_t c __attribute__((__unused__))) 456 { 457 458 return CC_NORM; 459 } 460 461 462 /* ed_newline(): 463 * Execute command 464 * [^J] 465 */ 466 libedit_private el_action_t 467 /*ARGSUSED*/ 468 ed_newline(EditLine *el, wint_t c __attribute__((__unused__))) 469 { 470 471 re_goto_bottom(el); 472 *el->el_line.lastchar++ = '\n'; 473 *el->el_line.lastchar = '\0'; 474 return CC_NEWLINE; 475 } 476 477 478 /* ed_delete_prev_char(): 479 * Delete the character to the left of the cursor 480 * [^?] 481 */ 482 libedit_private el_action_t 483 /*ARGSUSED*/ 484 ed_delete_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) 485 { 486 487 if (el->el_line.cursor <= el->el_line.buffer) 488 return CC_ERROR; 489 490 c_delbefore(el, el->el_state.argument); 491 el->el_line.cursor -= el->el_state.argument; 492 if (el->el_line.cursor < el->el_line.buffer) 493 el->el_line.cursor = el->el_line.buffer; 494 return CC_REFRESH; 495 } 496 497 498 /* ed_clear_screen(): 499 * Clear screen leaving current line at the top 500 * [^L] 501 */ 502 libedit_private el_action_t 503 /*ARGSUSED*/ 504 ed_clear_screen(EditLine *el, wint_t c __attribute__((__unused__))) 505 { 506 507 terminal_clear_screen(el); /* clear the whole real screen */ 508 re_clear_display(el); /* reset everything */ 509 return CC_REFRESH; 510 } 511 512 513 /* ed_redisplay(): 514 * Redisplay everything 515 * ^R 516 */ 517 libedit_private el_action_t 518 /*ARGSUSED*/ 519 ed_redisplay(EditLine *el __attribute__((__unused__)), 520 wint_t c __attribute__((__unused__))) 521 { 522 523 return CC_REDISPLAY; 524 } 525 526 527 /* ed_start_over(): 528 * Erase current line and start from scratch 529 * [^G] 530 */ 531 libedit_private el_action_t 532 /*ARGSUSED*/ 533 ed_start_over(EditLine *el, wint_t c __attribute__((__unused__))) 534 { 535 536 ch_reset(el); 537 return CC_REFRESH; 538 } 539 540 541 /* ed_sequence_lead_in(): 542 * First character in a bound sequence 543 * Placeholder for external keys 544 */ 545 libedit_private el_action_t 546 /*ARGSUSED*/ 547 ed_sequence_lead_in(EditLine *el __attribute__((__unused__)), 548 wint_t c __attribute__((__unused__))) 549 { 550 551 return CC_NORM; 552 } 553 554 555 /* ed_prev_history(): 556 * Move to the previous history line 557 * [^P] [k] 558 */ 559 libedit_private el_action_t 560 /*ARGSUSED*/ 561 ed_prev_history(EditLine *el, wint_t c __attribute__((__unused__))) 562 { 563 char beep = 0; 564 int sv_event = el->el_history.eventno; 565 566 el->el_chared.c_undo.len = -1; 567 *el->el_line.lastchar = '\0'; /* just in case */ 568 569 if (el->el_history.eventno == 0) { /* save the current buffer 570 * away */ 571 (void) wcsncpy(el->el_history.buf, el->el_line.buffer, 572 EL_BUFSIZ); 573 el->el_history.last = el->el_history.buf + 574 (el->el_line.lastchar - el->el_line.buffer); 575 } 576 el->el_history.eventno += el->el_state.argument; 577 578 if (hist_get(el) == CC_ERROR) { 579 if (el->el_map.type == MAP_VI) { 580 el->el_history.eventno = sv_event; 581 } 582 beep = 1; 583 /* el->el_history.eventno was fixed by first call */ 584 (void) hist_get(el); 585 } 586 if (beep) 587 return CC_REFRESH_BEEP; 588 return CC_REFRESH; 589 } 590 591 592 /* ed_next_history(): 593 * Move to the next history line 594 * [^N] [j] 595 */ 596 libedit_private el_action_t 597 /*ARGSUSED*/ 598 ed_next_history(EditLine *el, wint_t c __attribute__((__unused__))) 599 { 600 el_action_t beep = CC_REFRESH, rval; 601 602 el->el_chared.c_undo.len = -1; 603 *el->el_line.lastchar = '\0'; /* just in case */ 604 605 el->el_history.eventno -= el->el_state.argument; 606 607 if (el->el_history.eventno < 0) { 608 el->el_history.eventno = 0; 609 beep = CC_REFRESH_BEEP; 610 } 611 rval = hist_get(el); 612 if (rval == CC_REFRESH) 613 return beep; 614 return rval; 615 616 } 617 618 619 /* ed_search_prev_history(): 620 * Search previous in history for a line matching the current 621 * next search history [M-P] [K] 622 */ 623 libedit_private el_action_t 624 /*ARGSUSED*/ 625 ed_search_prev_history(EditLine *el, wint_t c __attribute__((__unused__))) 626 { 627 const wchar_t *hp; 628 int h; 629 int found = 0; 630 631 el->el_chared.c_vcmd.action = NOP; 632 el->el_chared.c_undo.len = -1; 633 *el->el_line.lastchar = '\0'; /* just in case */ 634 if (el->el_history.eventno < 0) { 635 #ifdef DEBUG_EDIT 636 (void) fprintf(el->el_errfile, 637 "e_prev_search_hist(): eventno < 0;\n"); 638 #endif 639 el->el_history.eventno = 0; 640 return CC_ERROR; 641 } 642 if (el->el_history.eventno == 0) { 643 (void) wcsncpy(el->el_history.buf, el->el_line.buffer, 644 EL_BUFSIZ); 645 el->el_history.last = el->el_history.buf + 646 (el->el_line.lastchar - el->el_line.buffer); 647 } 648 if (el->el_history.ref == NULL) 649 return CC_ERROR; 650 651 hp = HIST_FIRST(el); 652 if (hp == NULL) 653 return CC_ERROR; 654 655 c_setpat(el); /* Set search pattern !! */ 656 657 for (h = 1; h <= el->el_history.eventno; h++) 658 hp = HIST_NEXT(el); 659 660 while (hp != NULL) { 661 #ifdef SDEBUG 662 (void) fprintf(el->el_errfile, "Comparing with \"%ls\"\n", hp); 663 #endif 664 if ((wcsncmp(hp, el->el_line.buffer, (size_t) 665 (el->el_line.lastchar - el->el_line.buffer)) || 666 hp[el->el_line.lastchar - el->el_line.buffer]) && 667 c_hmatch(el, hp)) { 668 found = 1; 669 break; 670 } 671 h++; 672 hp = HIST_NEXT(el); 673 } 674 675 if (!found) { 676 #ifdef SDEBUG 677 (void) fprintf(el->el_errfile, "not found\n"); 678 #endif 679 return CC_ERROR; 680 } 681 el->el_history.eventno = h; 682 683 return hist_get(el); 684 } 685 686 687 /* ed_search_next_history(): 688 * Search next in history for a line matching the current 689 * [M-N] [J] 690 */ 691 libedit_private el_action_t 692 /*ARGSUSED*/ 693 ed_search_next_history(EditLine *el, wint_t c __attribute__((__unused__))) 694 { 695 const wchar_t *hp; 696 int h; 697 int found = 0; 698 699 el->el_chared.c_vcmd.action = NOP; 700 el->el_chared.c_undo.len = -1; 701 *el->el_line.lastchar = '\0'; /* just in case */ 702 703 if (el->el_history.eventno == 0) 704 return CC_ERROR; 705 706 if (el->el_history.ref == NULL) 707 return CC_ERROR; 708 709 hp = HIST_FIRST(el); 710 if (hp == NULL) 711 return CC_ERROR; 712 713 c_setpat(el); /* Set search pattern !! */ 714 715 for (h = 1; h < el->el_history.eventno && hp; h++) { 716 #ifdef SDEBUG 717 (void) fprintf(el->el_errfile, "Comparing with \"%ls\"\n", hp); 718 #endif 719 if ((wcsncmp(hp, el->el_line.buffer, (size_t) 720 (el->el_line.lastchar - el->el_line.buffer)) || 721 hp[el->el_line.lastchar - el->el_line.buffer]) && 722 c_hmatch(el, hp)) 723 found = h; 724 hp = HIST_NEXT(el); 725 } 726 727 if (!found) { /* is it the current history number? */ 728 if (!c_hmatch(el, el->el_history.buf)) { 729 #ifdef SDEBUG 730 (void) fprintf(el->el_errfile, "not found\n"); 731 #endif 732 return CC_ERROR; 733 } 734 } 735 el->el_history.eventno = found; 736 737 return hist_get(el); 738 } 739 740 741 /* ed_prev_line(): 742 * Move up one line 743 * Could be [k] [^p] 744 */ 745 libedit_private el_action_t 746 /*ARGSUSED*/ 747 ed_prev_line(EditLine *el, wint_t c __attribute__((__unused__))) 748 { 749 wchar_t *ptr; 750 int nchars = c_hpos(el); 751 752 /* 753 * Move to the line requested 754 */ 755 if (*(ptr = el->el_line.cursor) == '\n') 756 ptr--; 757 758 for (; ptr >= el->el_line.buffer; ptr--) 759 if (*ptr == '\n' && --el->el_state.argument <= 0) 760 break; 761 762 if (el->el_state.argument > 0) 763 return CC_ERROR; 764 765 /* 766 * Move to the beginning of the line 767 */ 768 for (ptr--; ptr >= el->el_line.buffer && *ptr != '\n'; ptr--) 769 continue; 770 771 /* 772 * Move to the character requested 773 */ 774 for (ptr++; 775 nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n'; 776 ptr++) 777 continue; 778 779 el->el_line.cursor = ptr; 780 return CC_CURSOR; 781 } 782 783 784 /* ed_next_line(): 785 * Move down one line 786 * Could be [j] [^n] 787 */ 788 libedit_private el_action_t 789 /*ARGSUSED*/ 790 ed_next_line(EditLine *el, wint_t c __attribute__((__unused__))) 791 { 792 wchar_t *ptr; 793 int nchars = c_hpos(el); 794 795 /* 796 * Move to the line requested 797 */ 798 for (ptr = el->el_line.cursor; ptr < el->el_line.lastchar; ptr++) 799 if (*ptr == '\n' && --el->el_state.argument <= 0) 800 break; 801 802 if (el->el_state.argument > 0) 803 return CC_ERROR; 804 805 /* 806 * Move to the character requested 807 */ 808 for (ptr++; 809 nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n'; 810 ptr++) 811 continue; 812 813 el->el_line.cursor = ptr; 814 return CC_CURSOR; 815 } 816 817 818 /* ed_command(): 819 * Editline extended command 820 * [M-X] [:] 821 */ 822 libedit_private el_action_t 823 /*ARGSUSED*/ 824 ed_command(EditLine *el, wint_t c __attribute__((__unused__))) 825 { 826 wchar_t tmpbuf[EL_BUFSIZ]; 827 int tmplen; 828 829 tmplen = c_gets(el, tmpbuf, L"\n: "); 830 terminal__putc(el, '\n'); 831 832 if (tmplen < 0 || (tmpbuf[tmplen] = 0, parse_line(el, tmpbuf)) == -1) 833 terminal_beep(el); 834 835 el->el_map.current = el->el_map.key; 836 re_clear_display(el); 837 return CC_REFRESH; 838 } 839