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