wlan - Rip out all wlan locks part 1/2
[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. 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  * @(#)common.c 8.1 (Berkeley) 6/4/93
33  * $NetBSD: common.c,v 1.19 2006/03/06 21:11:56 christos Exp $
34  * $DragonFly: src/lib/libedit/common.c,v 1.6 2007/05/05 00:27:39 pavalos Exp $
35  */
36
37 #include "config.h"
38
39 /*
40  * common.c: Common Editor functions
41  */
42 #include "el.h"
43
44 /* ed_end_of_file():
45  *      Indicate end of file
46  *      [^D]
47  */
48 protected el_action_t
49 /*ARGSUSED*/
50 ed_end_of_file(EditLine *el, int c __attribute__((__unused__)))
51 {
52
53         re_goto_bottom(el);
54         *el->el_line.lastchar = '\0';
55         return (CC_EOF);
56 }
57
58
59 /* ed_insert():
60  *      Add character to the line
61  *      Insert a character [bound to all insert keys]
62  */
63 protected el_action_t
64 ed_insert(EditLine *el, int c)
65 {
66         int count = el->el_state.argument;
67
68         if (c == '\0')
69                 return (CC_ERROR);
70
71         if (el->el_line.lastchar + el->el_state.argument >=
72             el->el_line.limit) {
73                 /* end of buffer space, try to allocate more */
74                 if (!ch_enlargebufs(el, (size_t) count))
75                         return CC_ERROR;        /* error allocating more */
76         }
77
78         if (count == 1) {
79                 if (el->el_state.inputmode == MODE_INSERT
80                     || el->el_line.cursor >= el->el_line.lastchar)
81                         c_insert(el, 1);
82
83                 *el->el_line.cursor++ = c;
84                 re_fastaddc(el);                /* fast refresh for one char. */
85         } else {
86                 if (el->el_state.inputmode != MODE_REPLACE_1)
87                         c_insert(el, el->el_state.argument);
88
89                 while (count-- && el->el_line.cursor < el->el_line.lastchar)
90                         *el->el_line.cursor++ = c;
91                 re_refresh(el);
92         }
93
94         if (el->el_state.inputmode == MODE_REPLACE_1)
95                 return vi_command_mode(el, 0);
96
97         return (CC_NORM);
98 }
99
100
101 /* ed_delete_prev_word():
102  *      Delete from beginning of current word to cursor
103  *      [M-^?] [^W]
104  */
105 protected el_action_t
106 /*ARGSUSED*/
107 ed_delete_prev_word(EditLine *el, int c __attribute__((__unused__)))
108 {
109         char *cp, *p, *kp;
110
111         if (el->el_line.cursor == el->el_line.buffer)
112                 return (CC_ERROR);
113
114         cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
115             el->el_state.argument, ce__isword);
116
117         for (p = cp, kp = el->el_chared.c_kill.buf; p < el->el_line.cursor; p++)
118                 *kp++ = *p;
119         el->el_chared.c_kill.last = kp;
120
121         c_delbefore(el, el->el_line.cursor - cp);       /* delete before dot */
122         el->el_line.cursor = cp;
123         if (el->el_line.cursor < el->el_line.buffer)
124                 el->el_line.cursor = el->el_line.buffer; /* bounds check */
125         return (CC_REFRESH);
126 }
127
128
129 /* ed_delete_next_char():
130  *      Delete character under cursor
131  *      [^D] [x]
132  */
133 protected el_action_t
134 /*ARGSUSED*/
135 ed_delete_next_char(EditLine *el, int c)
136 {
137 #ifdef notdef                   /* XXX */
138 #define EL      el->el_line
139         (void) fprintf(el->el_errlfile,
140             "\nD(b: %x(%s)  c: %x(%s) last: %x(%s) limit: %x(%s)\n",
141             EL.buffer, EL.buffer, EL.cursor, EL.cursor, EL.lastchar,
142             EL.lastchar, EL.limit, EL.limit);
143 #endif
144         if (el->el_line.cursor == el->el_line.lastchar) {
145                         /* if I'm at the end */
146                 if (el->el_map.type == MAP_VI) {
147                         if (el->el_line.cursor == el->el_line.buffer) {
148                                 /* if I'm also at the beginning */
149 #ifdef KSHVI
150                                 return (CC_ERROR);
151 #else
152                                 /* then do an EOF */
153                                 term_writechar(el, c);
154                                 return (CC_EOF);
155 #endif
156                         } else {
157 #ifdef KSHVI
158                                 el->el_line.cursor--;
159 #else
160                                 return (CC_ERROR);
161 #endif
162                         }
163                 } else {
164                         if (el->el_line.cursor != el->el_line.buffer)
165                                 el->el_line.cursor--;
166                         else
167                                 return (CC_ERROR);
168                 }
169         }
170         c_delafter(el, el->el_state.argument);  /* delete after dot */
171         if (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 __attribute__((__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 __attribute__((__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 __attribute__((__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 __attribute__((__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 __attribute__((__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 __attribute__((__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(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(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 __attribute__((__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 __attribute__((__unused__)), 
448               int c __attribute__((__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 __attribute__((__unused__)), 
462              int c __attribute__((__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 __attribute__((__unused__)), 
476                     int c __attribute__((__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 __attribute__((__unused__)), 
490                int c __attribute__((__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 __attribute__((__unused__)), 
504                int c __attribute__((__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 __attribute__((__unused__)), 
518                    int c __attribute__((__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 __attribute__((__unused__)), 
532                     int c __attribute__((__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 __attribute__((__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 __attribute__((__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 __attribute__((__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 __attribute__((__unused__)), 
597              int c __attribute__((__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 __attribute__((__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 __attribute__((__unused__)), 
625                     int c __attribute__((__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 __attribute__((__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 __attribute__((__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 __attribute__((__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 __attribute__((__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 __attribute__((__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 __attribute__((__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 __attribute__((__unused__)))
903 {
904         char tmpbuf[EL_BUFSIZ];
905         int tmplen;
906
907         tmplen = c_gets(el, tmpbuf, "\n: ");
908         term__putc('\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 }