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