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