]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - lib/libedit/common.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.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                         return (CC_ERROR);
168         }
169         c_delafter(el, el->el_state.argument);  /* delete after dot */
170         if (el->el_map.type == MAP_VI &&
171             el->el_line.cursor >= el->el_line.lastchar &&
172             el->el_line.cursor > el->el_line.buffer)
173                         /* bounds check */
174                 el->el_line.cursor = el->el_line.lastchar - 1;
175         return (CC_REFRESH);
176 }
177
178
179 /* ed_kill_line():
180  *      Cut to the end of line
181  *      [^K] [^K]
182  */
183 protected el_action_t
184 /*ARGSUSED*/
185 ed_kill_line(EditLine *el, int c __unused)
186 {
187         char *kp, *cp;
188
189         cp = el->el_line.cursor;
190         kp = el->el_chared.c_kill.buf;
191         while (cp < el->el_line.lastchar)
192                 *kp++ = *cp++;  /* copy it */
193         el->el_chared.c_kill.last = kp;
194                         /* zap! -- delete to end */
195         el->el_line.lastchar = el->el_line.cursor;
196         return (CC_REFRESH);
197 }
198
199
200 /* ed_move_to_end():
201  *      Move cursor to the end of line
202  *      [^E] [^E]
203  */
204 protected el_action_t
205 /*ARGSUSED*/
206 ed_move_to_end(EditLine *el, int c __unused)
207 {
208
209         el->el_line.cursor = el->el_line.lastchar;
210         if (el->el_map.type == MAP_VI) {
211 #ifdef VI_MOVE
212                 el->el_line.cursor--;
213 #endif
214                 if (el->el_chared.c_vcmd.action != NOP) {
215                         cv_delfini(el);
216                         return (CC_REFRESH);
217                 }
218         }
219         return (CC_CURSOR);
220 }
221
222
223 /* ed_move_to_beg():
224  *      Move cursor to the beginning of line
225  *      [^A] [^A]
226  */
227 protected el_action_t
228 /*ARGSUSED*/
229 ed_move_to_beg(EditLine *el, int c __unused)
230 {
231
232         el->el_line.cursor = el->el_line.buffer;
233
234         if (el->el_map.type == MAP_VI) {
235                         /* We want FIRST non space character */
236                 while (isspace((unsigned char) *el->el_line.cursor))
237                         el->el_line.cursor++;
238                 if (el->el_chared.c_vcmd.action != NOP) {
239                         cv_delfini(el);
240                         return (CC_REFRESH);
241                 }
242         }
243         return (CC_CURSOR);
244 }
245
246
247 /* ed_transpose_chars():
248  *      Exchange the character to the left of the cursor with the one under it
249  *      [^T] [^T]
250  */
251 protected el_action_t
252 ed_transpose_chars(EditLine *el, int c)
253 {
254
255         if (el->el_line.cursor < el->el_line.lastchar) {
256                 if (el->el_line.lastchar <= &el->el_line.buffer[1])
257                         return (CC_ERROR);
258                 else
259                         el->el_line.cursor++;
260         }
261         if (el->el_line.cursor > &el->el_line.buffer[1]) {
262                 /* must have at least two chars entered */
263                 c = el->el_line.cursor[-2];
264                 el->el_line.cursor[-2] = el->el_line.cursor[-1];
265                 el->el_line.cursor[-1] = c;
266                 return (CC_REFRESH);
267         } else
268                 return (CC_ERROR);
269 }
270
271
272 /* ed_next_char():
273  *      Move to the right one character
274  *      [^F] [^F]
275  */
276 protected el_action_t
277 /*ARGSUSED*/
278 ed_next_char(EditLine *el, int c __unused)
279 {
280         char *lim = el->el_line.lastchar;
281
282         if (el->el_line.cursor >= lim ||
283             (el->el_line.cursor == lim - 1 &&
284             el->el_map.type == MAP_VI &&
285             el->el_chared.c_vcmd.action == NOP))
286                 return (CC_ERROR);
287
288         el->el_line.cursor += el->el_state.argument;
289         if (el->el_line.cursor > lim)
290                 el->el_line.cursor = lim;
291
292         if (el->el_map.type == MAP_VI)
293                 if (el->el_chared.c_vcmd.action != NOP) {
294                         cv_delfini(el);
295                         return (CC_REFRESH);
296                 }
297         return (CC_CURSOR);
298 }
299
300
301 /* ed_prev_word():
302  *      Move to the beginning of the current word
303  *      [M-b] [b]
304  */
305 protected el_action_t
306 /*ARGSUSED*/
307 ed_prev_word(EditLine *el, int c __unused)
308 {
309
310         if (el->el_line.cursor == el->el_line.buffer)
311                 return (CC_ERROR);
312
313         el->el_line.cursor = c__prev_word(el->el_line.cursor,
314             el->el_line.buffer,
315             el->el_state.argument,
316             ce__isword);
317
318         if (el->el_map.type == MAP_VI)
319                 if (el->el_chared.c_vcmd.action != NOP) {
320                         cv_delfini(el);
321                         return (CC_REFRESH);
322                 }
323         return (CC_CURSOR);
324 }
325
326
327 /* ed_prev_char():
328  *      Move to the left one character
329  *      [^B] [^B]
330  */
331 protected el_action_t
332 /*ARGSUSED*/
333 ed_prev_char(EditLine *el, int c __unused)
334 {
335
336         if (el->el_line.cursor > el->el_line.buffer) {
337                 el->el_line.cursor -= el->el_state.argument;
338                 if (el->el_line.cursor < el->el_line.buffer)
339                         el->el_line.cursor = el->el_line.buffer;
340
341                 if (el->el_map.type == MAP_VI)
342                         if (el->el_chared.c_vcmd.action != NOP) {
343                                 cv_delfini(el);
344                                 return (CC_REFRESH);
345                         }
346                 return (CC_CURSOR);
347         } else
348                 return (CC_ERROR);
349 }
350
351
352 /* ed_quoted_insert():
353  *      Add the next character typed verbatim
354  *      [^V] [^V]
355  */
356 protected el_action_t
357 ed_quoted_insert(EditLine *el, int c)
358 {
359         int num;
360         char tc;
361
362         tty_quotemode(el);
363         num = el_getc(el, &tc);
364         c = (unsigned char) tc;
365         tty_noquotemode(el);
366         if (num == 1)
367                 return (ed_insert(el, c));
368         else
369                 return (ed_end_of_file(el, 0));
370 }
371
372
373 /* ed_digit():
374  *      Adds to argument or enters a digit
375  */
376 protected el_action_t
377 ed_digit(EditLine *el, int c)
378 {
379
380         if (!isdigit((unsigned char) c))
381                 return (CC_ERROR);
382
383         if (el->el_state.doingarg) {
384                         /* if doing an arg, add this in... */
385                 if (el->el_state.lastcmd == EM_UNIVERSAL_ARGUMENT)
386                         el->el_state.argument = c - '0';
387                 else {
388                         if (el->el_state.argument > 1000000)
389                                 return (CC_ERROR);
390                         el->el_state.argument =
391                             (el->el_state.argument * 10) + (c - '0');
392                 }
393                 return (CC_ARGHACK);
394         }
395
396         return ed_insert(el, c);
397 }
398
399
400 /* ed_argument_digit():
401  *      Digit that starts argument
402  *      For ESC-n
403  */
404 protected el_action_t
405 ed_argument_digit(EditLine *el, int c)
406 {
407
408         if (!isdigit((unsigned char) c))
409                 return (CC_ERROR);
410
411         if (el->el_state.doingarg) {
412                 if (el->el_state.argument > 1000000)
413                         return (CC_ERROR);
414                 el->el_state.argument = (el->el_state.argument * 10) +
415                     (c - '0');
416         } else {                /* else starting an argument */
417                 el->el_state.argument = c - '0';
418                 el->el_state.doingarg = 1;
419         }
420         return (CC_ARGHACK);
421 }
422
423
424 /* ed_unassigned():
425  *      Indicates unbound character
426  *      Bound to keys that are not assigned
427  */
428 protected el_action_t
429 /*ARGSUSED*/
430 ed_unassigned(EditLine *el, int c __unused)
431 {
432
433         return (CC_ERROR);
434 }
435
436
437 /**
438  ** TTY key handling.
439  **/
440
441 /* ed_tty_sigint():
442  *      Tty interrupt character
443  *      [^C]
444  */
445 protected el_action_t
446 /*ARGSUSED*/
447 ed_tty_sigint(EditLine *el __unused, 
448               int c __unused)
449 {
450
451         return (CC_NORM);
452 }
453
454
455 /* ed_tty_dsusp():
456  *      Tty delayed suspend character
457  *      [^Y]
458  */
459 protected el_action_t
460 /*ARGSUSED*/
461 ed_tty_dsusp(EditLine *el __unused, 
462              int c __unused)
463 {
464
465         return (CC_NORM);
466 }
467
468
469 /* ed_tty_flush_output():
470  *      Tty flush output characters
471  *      [^O]
472  */
473 protected el_action_t
474 /*ARGSUSED*/
475 ed_tty_flush_output(EditLine *el __unused, 
476                     int c __unused)
477 {
478
479         return (CC_NORM);
480 }
481
482
483 /* ed_tty_sigquit():
484  *      Tty quit character
485  *      [^\]
486  */
487 protected el_action_t
488 /*ARGSUSED*/
489 ed_tty_sigquit(EditLine *el __unused, 
490                int c __unused)
491 {
492
493         return (CC_NORM);
494 }
495
496
497 /* ed_tty_sigtstp():
498  *      Tty suspend character
499  *      [^Z]
500  */
501 protected el_action_t
502 /*ARGSUSED*/
503 ed_tty_sigtstp(EditLine *el __unused, 
504                int c __unused)
505 {
506
507         return (CC_NORM);
508 }
509
510
511 /* ed_tty_stop_output():
512  *      Tty disallow output characters
513  *      [^S]
514  */
515 protected el_action_t
516 /*ARGSUSED*/
517 ed_tty_stop_output(EditLine *el __unused, 
518                    int c __unused)
519 {
520
521         return (CC_NORM);
522 }
523
524
525 /* ed_tty_start_output():
526  *      Tty allow output characters
527  *      [^Q]
528  */
529 protected el_action_t
530 /*ARGSUSED*/
531 ed_tty_start_output(EditLine *el __unused, 
532                     int c __unused)
533 {
534
535         return (CC_NORM);
536 }
537
538
539 /* ed_newline():
540  *      Execute command
541  *      [^J]
542  */
543 protected el_action_t
544 /*ARGSUSED*/
545 ed_newline(EditLine *el, int c __unused)
546 {
547
548         re_goto_bottom(el);
549         *el->el_line.lastchar++ = '\n';
550         *el->el_line.lastchar = '\0';
551         return (CC_NEWLINE);
552 }
553
554
555 /* ed_delete_prev_char():
556  *      Delete the character to the left of the cursor
557  *      [^?]
558  */
559 protected el_action_t
560 /*ARGSUSED*/
561 ed_delete_prev_char(EditLine *el, int c __unused)
562 {
563
564         if (el->el_line.cursor <= el->el_line.buffer)
565                 return (CC_ERROR);
566
567         c_delbefore(el, el->el_state.argument);
568         el->el_line.cursor -= el->el_state.argument;
569         if (el->el_line.cursor < el->el_line.buffer)
570                 el->el_line.cursor = el->el_line.buffer;
571         return (CC_REFRESH);
572 }
573
574
575 /* ed_clear_screen():
576  *      Clear screen leaving current line at the top
577  *      [^L]
578  */
579 protected el_action_t
580 /*ARGSUSED*/
581 ed_clear_screen(EditLine *el, int c __unused)
582 {
583
584         term_clear_screen(el);  /* clear the whole real screen */
585         re_clear_display(el);   /* reset everything */
586         return (CC_REFRESH);
587 }
588
589
590 /* ed_redisplay():
591  *      Redisplay everything
592  *      ^R
593  */
594 protected el_action_t
595 /*ARGSUSED*/
596 ed_redisplay(EditLine *el __unused, 
597              int c __unused)
598 {
599
600         return (CC_REDISPLAY);
601 }
602
603
604 /* ed_start_over():
605  *      Erase current line and start from scratch
606  *      [^G]
607  */
608 protected el_action_t
609 /*ARGSUSED*/
610 ed_start_over(EditLine *el, int c __unused)
611 {
612
613         ch_reset(el, 0);
614         return (CC_REFRESH);
615 }
616
617
618 /* ed_sequence_lead_in():
619  *      First character in a bound sequence
620  *      Placeholder for external keys
621  */
622 protected el_action_t
623 /*ARGSUSED*/
624 ed_sequence_lead_in(EditLine *el __unused, 
625                     int c __unused)
626 {
627
628         return (CC_NORM);
629 }
630
631
632 /* ed_prev_history():
633  *      Move to the previous history line
634  *      [^P] [k]
635  */
636 protected el_action_t
637 /*ARGSUSED*/
638 ed_prev_history(EditLine *el, int c __unused)
639 {
640         char beep = 0;
641         int sv_event = el->el_history.eventno;
642
643         el->el_chared.c_undo.len = -1;
644         *el->el_line.lastchar = '\0';           /* just in case */
645
646         if (el->el_history.eventno == 0) {      /* save the current buffer
647                                                  * away */
648                 (void) strncpy(el->el_history.buf, el->el_line.buffer,
649                     EL_BUFSIZ);
650                 el->el_history.last = el->el_history.buf +
651                     (el->el_line.lastchar - el->el_line.buffer);
652         }
653         el->el_history.eventno += el->el_state.argument;
654
655         if (hist_get(el) == CC_ERROR) {
656                 if (el->el_map.type == MAP_VI) {
657                         el->el_history.eventno = sv_event;
658                         return CC_ERROR;
659                 }
660                 beep = 1;
661                 /* el->el_history.eventno was fixed by first call */
662                 (void) hist_get(el);
663         }
664         if (beep)
665                 return CC_REFRESH_BEEP;
666         return CC_REFRESH;
667 }
668
669
670 /* ed_next_history():
671  *      Move to the next history line
672  *      [^N] [j]
673  */
674 protected el_action_t
675 /*ARGSUSED*/
676 ed_next_history(EditLine *el, int c __unused)
677 {
678         el_action_t beep = CC_REFRESH, rval;
679
680         el->el_chared.c_undo.len = -1;
681         *el->el_line.lastchar = '\0';   /* just in case */
682
683         el->el_history.eventno -= el->el_state.argument;
684
685         if (el->el_history.eventno < 0) {
686                 el->el_history.eventno = 0;
687                 beep = CC_REFRESH_BEEP;
688         }
689         rval = hist_get(el);
690         if (rval == CC_REFRESH)
691                 return beep;
692         return rval;
693
694 }
695
696
697 /* ed_search_prev_history():
698  *      Search previous in history for a line matching the current
699  *      next search history [M-P] [K]
700  */
701 protected el_action_t
702 /*ARGSUSED*/
703 ed_search_prev_history(EditLine *el, int c __unused)
704 {
705         const char *hp;
706         int h;
707         bool_t found = 0;
708
709         el->el_chared.c_vcmd.action = NOP;
710         el->el_chared.c_undo.len = -1;
711         *el->el_line.lastchar = '\0';   /* just in case */
712         if (el->el_history.eventno < 0) {
713 #ifdef DEBUG_EDIT
714                 (void) fprintf(el->el_errfile,
715                     "e_prev_search_hist(): eventno < 0;\n");
716 #endif
717                 el->el_history.eventno = 0;
718                 return (CC_ERROR);
719         }
720         if (el->el_history.eventno == 0) {
721                 (void) strncpy(el->el_history.buf, el->el_line.buffer,
722                     EL_BUFSIZ);
723                 el->el_history.last = el->el_history.buf +
724                     (el->el_line.lastchar - el->el_line.buffer);
725         }
726         if (el->el_history.ref == NULL)
727                 return (CC_ERROR);
728
729         hp = HIST_FIRST(el);
730         if (hp == NULL)
731                 return (CC_ERROR);
732
733         c_setpat(el);           /* Set search pattern !! */
734
735         for (h = 1; h <= el->el_history.eventno; h++)
736                 hp = HIST_NEXT(el);
737
738         while (hp != NULL) {
739 #ifdef SDEBUG
740                 (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
741 #endif
742                 if ((strncmp(hp, el->el_line.buffer, (size_t)
743                             (el->el_line.lastchar - el->el_line.buffer)) ||
744                         hp[el->el_line.lastchar - el->el_line.buffer]) &&
745                     c_hmatch(el, hp)) {
746                         found++;
747                         break;
748                 }
749                 h++;
750                 hp = HIST_NEXT(el);
751         }
752
753         if (!found) {
754 #ifdef SDEBUG
755                 (void) fprintf(el->el_errfile, "not found\n");
756 #endif
757                 return (CC_ERROR);
758         }
759         el->el_history.eventno = h;
760
761         return (hist_get(el));
762 }
763
764
765 /* ed_search_next_history():
766  *      Search next in history for a line matching the current
767  *      [M-N] [J]
768  */
769 protected el_action_t
770 /*ARGSUSED*/
771 ed_search_next_history(EditLine *el, int c __unused)
772 {
773         const char *hp;
774         int h;
775         bool_t found = 0;
776
777         el->el_chared.c_vcmd.action = NOP;
778         el->el_chared.c_undo.len = -1;
779         *el->el_line.lastchar = '\0';   /* just in case */
780
781         if (el->el_history.eventno == 0)
782                 return (CC_ERROR);
783
784         if (el->el_history.ref == NULL)
785                 return (CC_ERROR);
786
787         hp = HIST_FIRST(el);
788         if (hp == NULL)
789                 return (CC_ERROR);
790
791         c_setpat(el);           /* Set search pattern !! */
792
793         for (h = 1; h < el->el_history.eventno && hp; h++) {
794 #ifdef SDEBUG
795                 (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
796 #endif
797                 if ((strncmp(hp, el->el_line.buffer, (size_t)
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 = h;
802                 hp = HIST_NEXT(el);
803         }
804
805         if (!found) {           /* is it the current history number? */
806                 if (!c_hmatch(el, el->el_history.buf)) {
807 #ifdef SDEBUG
808                         (void) fprintf(el->el_errfile, "not found\n");
809 #endif
810                         return (CC_ERROR);
811                 }
812         }
813         el->el_history.eventno = found;
814
815         return (hist_get(el));
816 }
817
818
819 /* ed_prev_line():
820  *      Move up one line
821  *      Could be [k] [^p]
822  */
823 protected el_action_t
824 /*ARGSUSED*/
825 ed_prev_line(EditLine *el, int c __unused)
826 {
827         char *ptr;
828         int nchars = c_hpos(el);
829
830         /*
831          * Move to the line requested
832          */
833         if (*(ptr = el->el_line.cursor) == '\n')
834                 ptr--;
835
836         for (; ptr >= el->el_line.buffer; ptr--)
837                 if (*ptr == '\n' && --el->el_state.argument <= 0)
838                         break;
839
840         if (el->el_state.argument > 0)
841                 return (CC_ERROR);
842
843         /*
844          * Move to the beginning of the line
845          */
846         for (ptr--; ptr >= el->el_line.buffer && *ptr != '\n'; ptr--)
847                 continue;
848
849         /*
850          * Move to the character requested
851          */
852         for (ptr++;
853             nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
854             ptr++)
855                 continue;
856
857         el->el_line.cursor = ptr;
858         return (CC_CURSOR);
859 }
860
861
862 /* ed_next_line():
863  *      Move down one line
864  *      Could be [j] [^n]
865  */
866 protected el_action_t
867 /*ARGSUSED*/
868 ed_next_line(EditLine *el, int c __unused)
869 {
870         char *ptr;
871         int nchars = c_hpos(el);
872
873         /*
874          * Move to the line requested
875          */
876         for (ptr = el->el_line.cursor; ptr < el->el_line.lastchar; ptr++)
877                 if (*ptr == '\n' && --el->el_state.argument <= 0)
878                         break;
879
880         if (el->el_state.argument > 0)
881                 return (CC_ERROR);
882
883         /*
884          * Move to the character requested
885          */
886         for (ptr++;
887             nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
888             ptr++)
889                 continue;
890
891         el->el_line.cursor = ptr;
892         return (CC_CURSOR);
893 }
894
895
896 /* ed_command():
897  *      Editline extended command
898  *      [M-X] [:]
899  */
900 protected el_action_t
901 /*ARGSUSED*/
902 ed_command(EditLine *el, int c __unused)
903 {
904         char tmpbuf[EL_BUFSIZ];
905         int tmplen;
906
907         tmplen = c_gets(el, tmpbuf, "\n: ");
908         term__putc(el, '\n');
909
910         if (tmplen < 0 || (tmpbuf[tmplen] = 0, parse_line(el, tmpbuf)) == -1)
911                 term_beep(el);
912
913         el->el_map.current = el->el_map.key;
914         re_clear_display(el);
915         return CC_REFRESH;
916 }