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