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