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