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