Home | History | Annotate | Line # | Download | only in libedit
common.c revision 1.15
      1 /*	$NetBSD: common.c,v 1.15 2003/06/19 15:55:05 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. 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 "config.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.15 2003/06/19 15:55:05 christos Exp $");
     45 #endif
     46 #endif /* not lint && not SCCSID */
     47 
     48 /*
     49  * common.c: Common Editor functions
     50  */
     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(EditLine *el, int c __attribute__((__unused__)))
     60 {
     61 
     62 	re_goto_bottom(el);
     63 	*el->el_line.lastchar = '\0';
     64 	return (CC_EOF);
     65 }
     66 
     67 
     68 /* ed_insert():
     69  *	Add character to the line
     70  *	Insert a character [bound to all insert keys]
     71  */
     72 protected el_action_t
     73 ed_insert(EditLine *el, int c)
     74 {
     75 	int count = el->el_state.argument;
     76 
     77 	if (c == '\0')
     78 		return (CC_ERROR);
     79 
     80 	if (el->el_line.lastchar + el->el_state.argument >=
     81 	    el->el_line.limit) {
     82 		/* end of buffer space, try to allocate more */
     83 		if (!ch_enlargebufs(el, (size_t) count))
     84 			return CC_ERROR;	/* error allocating more */
     85 	}
     86 
     87 	if (count == 1) {
     88 		if (el->el_state.inputmode == MODE_INSERT
     89 		    || el->el_line.cursor >= el->el_line.lastchar)
     90 			c_insert(el, 1);
     91 
     92 		*el->el_line.cursor++ = c;
     93 		re_fastaddc(el);		/* fast refresh for one char. */
     94 	} else {
     95 		if (el->el_state.inputmode != MODE_REPLACE_1)
     96 			c_insert(el, el->el_state.argument);
     97 
     98 		while (count-- && el->el_line.cursor < el->el_line.lastchar)
     99 			*el->el_line.cursor++ = c;
    100 		re_refresh(el);
    101 	}
    102 
    103 	if (el->el_state.inputmode == MODE_REPLACE_1)
    104 		return vi_command_mode(el, 0);
    105 
    106 	return (CC_NORM);
    107 }
    108 
    109 
    110 /* ed_delete_prev_word():
    111  *	Delete from beginning of current word to cursor
    112  *	[M-^?] [^W]
    113  */
    114 protected el_action_t
    115 /*ARGSUSED*/
    116 ed_delete_prev_word(EditLine *el, int c __attribute__((__unused__)))
    117 {
    118 	char *cp, *p, *kp;
    119 
    120 	if (el->el_line.cursor == el->el_line.buffer)
    121 		return (CC_ERROR);
    122 
    123 	cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
    124 	    el->el_state.argument, ce__isword);
    125 
    126 	for (p = cp, kp = el->el_chared.c_kill.buf; p < el->el_line.cursor; p++)
    127 		*kp++ = *p;
    128 	el->el_chared.c_kill.last = kp;
    129 
    130 	c_delbefore(el, el->el_line.cursor - cp);	/* delete before dot */
    131 	el->el_line.cursor = cp;
    132 	if (el->el_line.cursor < el->el_line.buffer)
    133 		el->el_line.cursor = el->el_line.buffer; /* bounds check */
    134 	return (CC_REFRESH);
    135 }
    136 
    137 
    138 /* ed_delete_next_char():
    139  *	Delete character under cursor
    140  *	[^D] [x]
    141  */
    142 protected el_action_t
    143 /*ARGSUSED*/
    144 ed_delete_next_char(EditLine *el, int c __attribute__((__unused__)))
    145 {
    146 #ifdef notdef			/* XXX */
    147 #define	EL	el->el_line
    148 	(void) fprintf(el->el_errlfile,
    149 	    "\nD(b: %x(%s)  c: %x(%s) last: %x(%s) limit: %x(%s)\n",
    150 	    EL.buffer, EL.buffer, EL.cursor, EL.cursor, EL.lastchar,
    151 	    EL.lastchar, EL.limit, EL.limit);
    152 #endif
    153 	if (el->el_line.cursor == el->el_line.lastchar) {
    154 			/* if I'm at the end */
    155 		if (el->el_map.type == MAP_VI) {
    156 			if (el->el_line.cursor == el->el_line.buffer) {
    157 				/* if I'm also at the beginning */
    158 #ifdef KSHVI
    159 				return (CC_ERROR);
    160 #else
    161 				term_overwrite(el, STReof, 4);
    162 					/* then do a EOF */
    163 				term__flush();
    164 				return (CC_EOF);
    165 #endif
    166 			} else {
    167 #ifdef KSHVI
    168 				el->el_line.cursor--;
    169 #else
    170 				return (CC_ERROR);
    171 #endif
    172 			}
    173 		} else {
    174 			if (el->el_line.cursor != el->el_line.buffer)
    175 				el->el_line.cursor--;
    176 			else
    177 				return (CC_ERROR);
    178 		}
    179 	}
    180 	c_delafter(el, el->el_state.argument);	/* delete after dot */
    181 	if (el->el_line.cursor >= el->el_line.lastchar &&
    182 	    el->el_line.cursor > el->el_line.buffer)
    183 			/* bounds check */
    184 		el->el_line.cursor = el->el_line.lastchar - 1;
    185 	return (CC_REFRESH);
    186 }
    187 
    188 
    189 /* ed_kill_line():
    190  *	Cut to the end of line
    191  *	[^K] [^K]
    192  */
    193 protected el_action_t
    194 /*ARGSUSED*/
    195 ed_kill_line(EditLine *el, int c __attribute__((__unused__)))
    196 {
    197 	char *kp, *cp;
    198 
    199 	cp = el->el_line.cursor;
    200 	kp = el->el_chared.c_kill.buf;
    201 	while (cp < el->el_line.lastchar)
    202 		*kp++ = *cp++;	/* copy it */
    203 	el->el_chared.c_kill.last = kp;
    204 			/* zap! -- delete to end */
    205 	el->el_line.lastchar = el->el_line.cursor;
    206 	return (CC_REFRESH);
    207 }
    208 
    209 
    210 /* ed_move_to_end():
    211  *	Move cursor to the end of line
    212  *	[^E] [^E]
    213  */
    214 protected el_action_t
    215 /*ARGSUSED*/
    216 ed_move_to_end(EditLine *el, int c __attribute__((__unused__)))
    217 {
    218 
    219 	el->el_line.cursor = el->el_line.lastchar;
    220 	if (el->el_map.type == MAP_VI) {
    221 #ifdef VI_MOVE
    222 		el->el_line.cursor--;
    223 #endif
    224 		if (el->el_chared.c_vcmd.action != NOP) {
    225 			cv_delfini(el);
    226 			return (CC_REFRESH);
    227 		}
    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 protected el_action_t
    238 /*ARGSUSED*/
    239 ed_move_to_beg(EditLine *el, int 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 (isspace((unsigned char) *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 protected el_action_t
    262 ed_transpose_chars(EditLine *el, int 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 protected el_action_t
    287 /*ARGSUSED*/
    288 ed_next_char(EditLine *el, int c __attribute__((__unused__)))
    289 {
    290 	char *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 protected el_action_t
    316 /*ARGSUSED*/
    317 ed_prev_word(EditLine *el, int 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 protected el_action_t
    342 /*ARGSUSED*/
    343 ed_prev_char(EditLine *el, int 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 protected el_action_t
    367 ed_quoted_insert(EditLine *el, int c)
    368 {
    369 	int num;
    370 	char tc;
    371 
    372 	tty_quotemode(el);
    373 	num = el_getc(el, &tc);
    374 	c = (unsigned char) tc;
    375 	tty_noquotemode(el);
    376 	if (num == 1)
    377 		return (ed_insert(el, c));
    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 protected el_action_t
    387 ed_digit(EditLine *el, int c)
    388 {
    389 
    390 	if (!isdigit(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 protected el_action_t
    415 ed_argument_digit(EditLine *el, int c)
    416 {
    417 
    418 	if (!isdigit(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 protected el_action_t
    439 /*ARGSUSED*/
    440 ed_unassigned(EditLine *el, int c __attribute__((__unused__)))
    441 {
    442 
    443 	return (CC_ERROR);
    444 }
    445 
    446 
    447 /**
    448  ** TTY key handling.
    449  **/
    450 
    451 /* ed_tty_sigint():
    452  *	Tty interrupt character
    453  *	[^C]
    454  */
    455 protected el_action_t
    456 /*ARGSUSED*/
    457 ed_tty_sigint(EditLine *el __attribute__((__unused__)),
    458 	      int c __attribute__((__unused__)))
    459 {
    460 
    461 	return (CC_NORM);
    462 }
    463 
    464 
    465 /* ed_tty_dsusp():
    466  *	Tty delayed suspend character
    467  *	[^Y]
    468  */
    469 protected el_action_t
    470 /*ARGSUSED*/
    471 ed_tty_dsusp(EditLine *el __attribute__((__unused__)),
    472 	     int c __attribute__((__unused__)))
    473 {
    474 
    475 	return (CC_NORM);
    476 }
    477 
    478 
    479 /* ed_tty_flush_output():
    480  *	Tty flush output characters
    481  *	[^O]
    482  */
    483 protected el_action_t
    484 /*ARGSUSED*/
    485 ed_tty_flush_output(EditLine *el __attribute__((__unused__)),
    486 		    int c __attribute__((__unused__)))
    487 {
    488 
    489 	return (CC_NORM);
    490 }
    491 
    492 
    493 /* ed_tty_sigquit():
    494  *	Tty quit character
    495  *	[^\]
    496  */
    497 protected el_action_t
    498 /*ARGSUSED*/
    499 ed_tty_sigquit(EditLine *el __attribute__((__unused__)),
    500 	       int c __attribute__((__unused__)))
    501 {
    502 
    503 	return (CC_NORM);
    504 }
    505 
    506 
    507 /* ed_tty_sigtstp():
    508  *	Tty suspend character
    509  *	[^Z]
    510  */
    511 protected el_action_t
    512 /*ARGSUSED*/
    513 ed_tty_sigtstp(EditLine *el __attribute__((__unused__)),
    514 	       int c __attribute__((__unused__)))
    515 {
    516 
    517 	return (CC_NORM);
    518 }
    519 
    520 
    521 /* ed_tty_stop_output():
    522  *	Tty disallow output characters
    523  *	[^S]
    524  */
    525 protected el_action_t
    526 /*ARGSUSED*/
    527 ed_tty_stop_output(EditLine *el __attribute__((__unused__)),
    528 		   int c __attribute__((__unused__)))
    529 {
    530 
    531 	return (CC_NORM);
    532 }
    533 
    534 
    535 /* ed_tty_start_output():
    536  *	Tty allow output characters
    537  *	[^Q]
    538  */
    539 protected el_action_t
    540 /*ARGSUSED*/
    541 ed_tty_start_output(EditLine *el __attribute__((__unused__)),
    542 		    int c __attribute__((__unused__)))
    543 {
    544 
    545 	return (CC_NORM);
    546 }
    547 
    548 
    549 /* ed_newline():
    550  *	Execute command
    551  *	[^J]
    552  */
    553 protected el_action_t
    554 /*ARGSUSED*/
    555 ed_newline(EditLine *el, int c __attribute__((__unused__)))
    556 {
    557 
    558 	re_goto_bottom(el);
    559 	*el->el_line.lastchar++ = '\n';
    560 	*el->el_line.lastchar = '\0';
    561 	return (CC_NEWLINE);
    562 }
    563 
    564 
    565 /* ed_delete_prev_char():
    566  *	Delete the character to the left of the cursor
    567  *	[^?]
    568  */
    569 protected el_action_t
    570 /*ARGSUSED*/
    571 ed_delete_prev_char(EditLine *el, int c __attribute__((__unused__)))
    572 {
    573 
    574 	if (el->el_line.cursor <= el->el_line.buffer)
    575 		return (CC_ERROR);
    576 
    577 	c_delbefore(el, el->el_state.argument);
    578 	el->el_line.cursor -= el->el_state.argument;
    579 	if (el->el_line.cursor < el->el_line.buffer)
    580 		el->el_line.cursor = el->el_line.buffer;
    581 	return (CC_REFRESH);
    582 }
    583 
    584 
    585 /* ed_clear_screen():
    586  *	Clear screen leaving current line at the top
    587  *	[^L]
    588  */
    589 protected el_action_t
    590 /*ARGSUSED*/
    591 ed_clear_screen(EditLine *el, int c __attribute__((__unused__)))
    592 {
    593 
    594 	term_clear_screen(el);	/* clear the whole real screen */
    595 	re_clear_display(el);	/* reset everything */
    596 	return (CC_REFRESH);
    597 }
    598 
    599 
    600 /* ed_redisplay():
    601  *	Redisplay everything
    602  *	^R
    603  */
    604 protected el_action_t
    605 /*ARGSUSED*/
    606 ed_redisplay(EditLine *el __attribute__((__unused__)),
    607 	     int c __attribute__((__unused__)))
    608 {
    609 
    610 	return (CC_REDISPLAY);
    611 }
    612 
    613 
    614 /* ed_start_over():
    615  *	Erase current line and start from scratch
    616  *	[^G]
    617  */
    618 protected el_action_t
    619 /*ARGSUSED*/
    620 ed_start_over(EditLine *el, int c __attribute__((__unused__)))
    621 {
    622 
    623 	ch_reset(el);
    624 	return (CC_REFRESH);
    625 }
    626 
    627 
    628 /* ed_sequence_lead_in():
    629  *	First character in a bound sequence
    630  *	Placeholder for external keys
    631  */
    632 protected el_action_t
    633 /*ARGSUSED*/
    634 ed_sequence_lead_in(EditLine *el __attribute__((__unused__)),
    635 		    int c __attribute__((__unused__)))
    636 {
    637 
    638 	return (CC_NORM);
    639 }
    640 
    641 
    642 /* ed_prev_history():
    643  *	Move to the previous history line
    644  *	[^P] [k]
    645  */
    646 protected el_action_t
    647 /*ARGSUSED*/
    648 ed_prev_history(EditLine *el, int c __attribute__((__unused__)))
    649 {
    650 	char beep = 0;
    651 	int sv_event = el->el_history.eventno;
    652 
    653 	el->el_chared.c_undo.len = -1;
    654 	*el->el_line.lastchar = '\0';		/* just in case */
    655 
    656 	if (el->el_history.eventno == 0) {	/* save the current buffer
    657 						 * away */
    658 		(void) strncpy(el->el_history.buf, el->el_line.buffer,
    659 		    EL_BUFSIZ);
    660 		el->el_history.last = el->el_history.buf +
    661 		    (el->el_line.lastchar - el->el_line.buffer);
    662 	}
    663 	el->el_history.eventno += el->el_state.argument;
    664 
    665 	if (hist_get(el) == CC_ERROR) {
    666 		if (el->el_map.type == MAP_VI) {
    667 			el->el_history.eventno = sv_event;
    668 			return CC_ERROR;
    669 		}
    670 		beep = 1;
    671 		/* el->el_history.eventno was fixed by first call */
    672 		(void) hist_get(el);
    673 	}
    674 	if (beep)
    675 		return CC_REFRESH_BEEP;
    676 	return CC_REFRESH;
    677 }
    678 
    679 
    680 /* ed_next_history():
    681  *	Move to the next history line
    682  *	[^N] [j]
    683  */
    684 protected el_action_t
    685 /*ARGSUSED*/
    686 ed_next_history(EditLine *el, int c __attribute__((__unused__)))
    687 {
    688 	el_action_t beep = CC_REFRESH, rval;
    689 
    690 	el->el_chared.c_undo.len = -1;
    691 	*el->el_line.lastchar = '\0';	/* just in case */
    692 
    693 	el->el_history.eventno -= el->el_state.argument;
    694 
    695 	if (el->el_history.eventno < 0) {
    696 		el->el_history.eventno = 0;
    697 		beep = CC_REFRESH_BEEP;
    698 	}
    699 	rval = hist_get(el);
    700 	if (rval == CC_REFRESH)
    701 		return beep;
    702 	return rval;
    703 
    704 }
    705 
    706 
    707 /* ed_search_prev_history():
    708  *	Search previous in history for a line matching the current
    709  *	next search history [M-P] [K]
    710  */
    711 protected el_action_t
    712 /*ARGSUSED*/
    713 ed_search_prev_history(EditLine *el, int c __attribute__((__unused__)))
    714 {
    715 	const char *hp;
    716 	int h;
    717 	bool_t found = 0;
    718 
    719 	el->el_chared.c_vcmd.action = NOP;
    720 	el->el_chared.c_undo.len = -1;
    721 	*el->el_line.lastchar = '\0';	/* just in case */
    722 	if (el->el_history.eventno < 0) {
    723 #ifdef DEBUG_EDIT
    724 		(void) fprintf(el->el_errfile,
    725 		    "e_prev_search_hist(): eventno < 0;\n");
    726 #endif
    727 		el->el_history.eventno = 0;
    728 		return (CC_ERROR);
    729 	}
    730 	if (el->el_history.eventno == 0) {
    731 		(void) strncpy(el->el_history.buf, el->el_line.buffer,
    732 		    EL_BUFSIZ);
    733 		el->el_history.last = el->el_history.buf +
    734 		    (el->el_line.lastchar - el->el_line.buffer);
    735 	}
    736 	if (el->el_history.ref == NULL)
    737 		return (CC_ERROR);
    738 
    739 	hp = HIST_FIRST(el);
    740 	if (hp == NULL)
    741 		return (CC_ERROR);
    742 
    743 	c_setpat(el);		/* Set search pattern !! */
    744 
    745 	for (h = 1; h <= el->el_history.eventno; h++)
    746 		hp = HIST_NEXT(el);
    747 
    748 	while (hp != NULL) {
    749 #ifdef SDEBUG
    750 		(void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
    751 #endif
    752 		if ((strncmp(hp, el->el_line.buffer, (size_t)
    753 			    (el->el_line.lastchar - el->el_line.buffer)) ||
    754 			hp[el->el_line.lastchar - el->el_line.buffer]) &&
    755 		    c_hmatch(el, hp)) {
    756 			found++;
    757 			break;
    758 		}
    759 		h++;
    760 		hp = HIST_NEXT(el);
    761 	}
    762 
    763 	if (!found) {
    764 #ifdef SDEBUG
    765 		(void) fprintf(el->el_errfile, "not found\n");
    766 #endif
    767 		return (CC_ERROR);
    768 	}
    769 	el->el_history.eventno = h;
    770 
    771 	return (hist_get(el));
    772 }
    773 
    774 
    775 /* ed_search_next_history():
    776  *	Search next in history for a line matching the current
    777  *	[M-N] [J]
    778  */
    779 protected el_action_t
    780 /*ARGSUSED*/
    781 ed_search_next_history(EditLine *el, int c __attribute__((__unused__)))
    782 {
    783 	const char *hp;
    784 	int h;
    785 	bool_t found = 0;
    786 
    787 	el->el_chared.c_vcmd.action = NOP;
    788 	el->el_chared.c_undo.len = -1;
    789 	*el->el_line.lastchar = '\0';	/* just in case */
    790 
    791 	if (el->el_history.eventno == 0)
    792 		return (CC_ERROR);
    793 
    794 	if (el->el_history.ref == NULL)
    795 		return (CC_ERROR);
    796 
    797 	hp = HIST_FIRST(el);
    798 	if (hp == NULL)
    799 		return (CC_ERROR);
    800 
    801 	c_setpat(el);		/* Set search pattern !! */
    802 
    803 	for (h = 1; h < el->el_history.eventno && hp; h++) {
    804 #ifdef SDEBUG
    805 		(void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
    806 #endif
    807 		if ((strncmp(hp, el->el_line.buffer, (size_t)
    808 			    (el->el_line.lastchar - el->el_line.buffer)) ||
    809 			hp[el->el_line.lastchar - el->el_line.buffer]) &&
    810 		    c_hmatch(el, hp))
    811 			found = h;
    812 		hp = HIST_NEXT(el);
    813 	}
    814 
    815 	if (!found) {		/* is it the current history number? */
    816 		if (!c_hmatch(el, el->el_history.buf)) {
    817 #ifdef SDEBUG
    818 			(void) fprintf(el->el_errfile, "not found\n");
    819 #endif
    820 			return (CC_ERROR);
    821 		}
    822 	}
    823 	el->el_history.eventno = found;
    824 
    825 	return (hist_get(el));
    826 }
    827 
    828 
    829 /* ed_prev_line():
    830  *	Move up one line
    831  *	Could be [k] [^p]
    832  */
    833 protected el_action_t
    834 /*ARGSUSED*/
    835 ed_prev_line(EditLine *el, int c __attribute__((__unused__)))
    836 {
    837 	char *ptr;
    838 	int nchars = c_hpos(el);
    839 
    840 	/*
    841          * Move to the line requested
    842          */
    843 	if (*(ptr = el->el_line.cursor) == '\n')
    844 		ptr--;
    845 
    846 	for (; ptr >= el->el_line.buffer; ptr--)
    847 		if (*ptr == '\n' && --el->el_state.argument <= 0)
    848 			break;
    849 
    850 	if (el->el_state.argument > 0)
    851 		return (CC_ERROR);
    852 
    853 	/*
    854          * Move to the beginning of the line
    855          */
    856 	for (ptr--; ptr >= el->el_line.buffer && *ptr != '\n'; ptr--)
    857 		continue;
    858 
    859 	/*
    860          * Move to the character requested
    861          */
    862 	for (ptr++;
    863 	    nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
    864 	    ptr++)
    865 		continue;
    866 
    867 	el->el_line.cursor = ptr;
    868 	return (CC_CURSOR);
    869 }
    870 
    871 
    872 /* ed_next_line():
    873  *	Move down one line
    874  *	Could be [j] [^n]
    875  */
    876 protected el_action_t
    877 /*ARGSUSED*/
    878 ed_next_line(EditLine *el, int c __attribute__((__unused__)))
    879 {
    880 	char *ptr;
    881 	int nchars = c_hpos(el);
    882 
    883 	/*
    884          * Move to the line requested
    885          */
    886 	for (ptr = el->el_line.cursor; ptr < el->el_line.lastchar; ptr++)
    887 		if (*ptr == '\n' && --el->el_state.argument <= 0)
    888 			break;
    889 
    890 	if (el->el_state.argument > 0)
    891 		return (CC_ERROR);
    892 
    893 	/*
    894          * Move to the character requested
    895          */
    896 	for (ptr++;
    897 	    nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
    898 	    ptr++)
    899 		continue;
    900 
    901 	el->el_line.cursor = ptr;
    902 	return (CC_CURSOR);
    903 }
    904 
    905 
    906 /* ed_command():
    907  *	Editline extended command
    908  *	[M-X] [:]
    909  */
    910 protected el_action_t
    911 /*ARGSUSED*/
    912 ed_command(EditLine *el, int c __attribute__((__unused__)))
    913 {
    914 	char tmpbuf[EL_BUFSIZ];
    915 	int tmplen;
    916 
    917 	tmplen = c_gets(el, tmpbuf, "\n: ");
    918 	term__putc('\n');
    919 
    920 	if (tmplen < 0 || (tmpbuf[tmplen] = 0, parse_line(el, tmpbuf)) == -1)
    921 		term_beep(el);
    922 
    923 	el->el_map.current = el->el_map.key;
    924 	re_clear_display(el);
    925 	return CC_REFRESH;
    926 }
    927