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