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