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