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