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