Home | History | Annotate | Line # | Download | only in libedit
common.c revision 1.13
      1 /*	$NetBSD: common.c,v 1.13 2002/11/15 14:32:33 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.13 2002/11/15 14:32:33 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)
     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)
    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)
    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)
    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)
    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)
    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)
    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)
    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)
    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)
    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, int c)
    458 {
    459 
    460 	return (CC_NORM);
    461 }
    462 
    463 
    464 /* ed_tty_dsusp():
    465  *	Tty delayed suspend character
    466  *	[^Y]
    467  */
    468 protected el_action_t
    469 /*ARGSUSED*/
    470 ed_tty_dsusp(EditLine *el, int c)
    471 {
    472 
    473 	return (CC_NORM);
    474 }
    475 
    476 
    477 /* ed_tty_flush_output():
    478  *	Tty flush output characters
    479  *	[^O]
    480  */
    481 protected el_action_t
    482 /*ARGSUSED*/
    483 ed_tty_flush_output(EditLine *el, int c)
    484 {
    485 
    486 	return (CC_NORM);
    487 }
    488 
    489 
    490 /* ed_tty_sigquit():
    491  *	Tty quit character
    492  *	[^\]
    493  */
    494 protected el_action_t
    495 /*ARGSUSED*/
    496 ed_tty_sigquit(EditLine *el, int c)
    497 {
    498 
    499 	return (CC_NORM);
    500 }
    501 
    502 
    503 /* ed_tty_sigtstp():
    504  *	Tty suspend character
    505  *	[^Z]
    506  */
    507 protected el_action_t
    508 /*ARGSUSED*/
    509 ed_tty_sigtstp(EditLine *el, int c)
    510 {
    511 
    512 	return (CC_NORM);
    513 }
    514 
    515 
    516 /* ed_tty_stop_output():
    517  *	Tty disallow output characters
    518  *	[^S]
    519  */
    520 protected el_action_t
    521 /*ARGSUSED*/
    522 ed_tty_stop_output(EditLine *el, int c)
    523 {
    524 
    525 	return (CC_NORM);
    526 }
    527 
    528 
    529 /* ed_tty_start_output():
    530  *	Tty allow output characters
    531  *	[^Q]
    532  */
    533 protected el_action_t
    534 /*ARGSUSED*/
    535 ed_tty_start_output(EditLine *el, int c)
    536 {
    537 
    538 	return (CC_NORM);
    539 }
    540 
    541 
    542 /* ed_newline():
    543  *	Execute command
    544  *	[^J]
    545  */
    546 protected el_action_t
    547 /*ARGSUSED*/
    548 ed_newline(EditLine *el, int c)
    549 {
    550 
    551 	re_goto_bottom(el);
    552 	*el->el_line.lastchar++ = '\n';
    553 	*el->el_line.lastchar = '\0';
    554 	return (CC_NEWLINE);
    555 }
    556 
    557 
    558 /* ed_delete_prev_char():
    559  *	Delete the character to the left of the cursor
    560  *	[^?]
    561  */
    562 protected el_action_t
    563 /*ARGSUSED*/
    564 ed_delete_prev_char(EditLine *el, int c)
    565 {
    566 
    567 	if (el->el_line.cursor <= el->el_line.buffer)
    568 		return (CC_ERROR);
    569 
    570 	c_delbefore(el, el->el_state.argument);
    571 	el->el_line.cursor -= el->el_state.argument;
    572 	if (el->el_line.cursor < el->el_line.buffer)
    573 		el->el_line.cursor = el->el_line.buffer;
    574 	return (CC_REFRESH);
    575 }
    576 
    577 
    578 /* ed_clear_screen():
    579  *	Clear screen leaving current line at the top
    580  *	[^L]
    581  */
    582 protected el_action_t
    583 /*ARGSUSED*/
    584 ed_clear_screen(EditLine *el, int c)
    585 {
    586 
    587 	term_clear_screen(el);	/* clear the whole real screen */
    588 	re_clear_display(el);	/* reset everything */
    589 	return (CC_REFRESH);
    590 }
    591 
    592 
    593 /* ed_redisplay():
    594  *	Redisplay everything
    595  *	^R
    596  */
    597 protected el_action_t
    598 /*ARGSUSED*/
    599 ed_redisplay(EditLine *el, int c)
    600 {
    601 
    602 	return (CC_REDISPLAY);
    603 }
    604 
    605 
    606 /* ed_start_over():
    607  *	Erase current line and start from scratch
    608  *	[^G]
    609  */
    610 protected el_action_t
    611 /*ARGSUSED*/
    612 ed_start_over(EditLine *el, int c)
    613 {
    614 
    615 	ch_reset(el);
    616 	return (CC_REFRESH);
    617 }
    618 
    619 
    620 /* ed_sequence_lead_in():
    621  *	First character in a bound sequence
    622  *	Placeholder for external keys
    623  */
    624 protected el_action_t
    625 /*ARGSUSED*/
    626 ed_sequence_lead_in(EditLine *el, int c)
    627 {
    628 
    629 	return (CC_NORM);
    630 }
    631 
    632 
    633 /* ed_prev_history():
    634  *	Move to the previous history line
    635  *	[^P] [k]
    636  */
    637 protected el_action_t
    638 /*ARGSUSED*/
    639 ed_prev_history(EditLine *el, int c)
    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  */
    675 protected el_action_t
    676 /*ARGSUSED*/
    677 ed_next_history(EditLine *el, int c)
    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  */
    702 protected el_action_t
    703 /*ARGSUSED*/
    704 ed_search_prev_history(EditLine *el, int c)
    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  */
    770 protected el_action_t
    771 /*ARGSUSED*/
    772 ed_search_next_history(EditLine *el, int c)
    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  */
    824 protected el_action_t
    825 /*ARGSUSED*/
    826 ed_prev_line(EditLine *el, int c)
    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  */
    867 protected el_action_t
    868 /*ARGSUSED*/
    869 ed_next_line(EditLine *el, int c)
    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  */
    901 protected el_action_t
    902 /*ARGSUSED*/
    903 ed_command(EditLine *el, int c)
    904 {
    905 	char tmpbuf[EL_BUFSIZ];
    906 	int tmplen;
    907 
    908 	el->el_line.buffer[0] = '\0';
    909 	el->el_line.lastchar = el->el_line.buffer;
    910 	el->el_line.cursor = el->el_line.buffer;
    911 
    912 	c_insert(el, 3);	/* prompt + ": " */
    913 	*el->el_line.cursor++ = '\n';
    914 	*el->el_line.cursor++ = ':';
    915 	*el->el_line.cursor++ = ' ';
    916 	re_refresh(el);
    917 
    918 	tmplen = c_gets(el, tmpbuf);
    919 	tmpbuf[tmplen] = '\0';
    920 
    921 	el->el_line.buffer[0] = '\0';
    922 	el->el_line.lastchar = el->el_line.buffer;
    923 	el->el_line.cursor = el->el_line.buffer;
    924 
    925 	if (parse_line(el, tmpbuf) == -1)
    926 		return (CC_ERROR);
    927 	else
    928 		return (CC_REFRESH);
    929 }
    930