2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Christos Zoulas of Cornell University.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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
36 * @(#)common.c 8.1 (Berkeley) 6/4/93
37 * $DragonFly: src/lib/libedit/common.c,v 1.4 2005/08/04 17:27:09 drhodus Exp $
41 * common.c: Common Editor functions
47 * Indicate end of file
52 ed_end_of_file(EditLine *el, int c)
55 *el->el_line.lastchar = '\0';
61 * Add character to the line
62 * Insert a character [bound to all insert keys]
65 ed_insert(EditLine *el, int c)
72 if (el->el_line.lastchar + el->el_state.argument >=
74 return CC_ERROR; /* end of buffer space */
76 if (el->el_state.argument == 1) {
77 if (el->el_state.inputmode != MODE_INSERT) {
78 el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
80 el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] = '\0';
86 *el->el_line.cursor++ = c;
87 el->el_state.doingarg = 0; /* just in case */
88 re_fastaddc(el); /* fast refresh for one char. */
91 if (el->el_state.inputmode != MODE_INSERT) {
93 for(i = 0;i < el->el_state.argument; i++)
94 el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
95 el->el_line.cursor[i];
97 el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] = '\0';
98 c_delafter(el, el->el_state.argument);
101 c_insert(el, el->el_state.argument);
103 while (el->el_state.argument--)
104 *el->el_line.cursor++ = c;
108 if (el->el_state.inputmode == MODE_REPLACE_1 || el->el_state.inputmode == MODE_REPLACE)
109 el->el_chared.c_undo.action=CHANGE;
111 if (el->el_state.inputmode == MODE_REPLACE_1)
112 return vi_command_mode(el, 0);
118 /* ed_delete_prev_word():
119 * Delete from beginning of current word to cursor
122 protected el_action_t
124 ed_delete_prev_word(EditLine *el, int c)
128 if (el->el_line.cursor == el->el_line.buffer)
131 cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
132 el->el_state.argument, ce__isword);
134 for (p = cp, kp = el->el_chared.c_kill.buf; p < el->el_line.cursor; p++)
136 el->el_chared.c_kill.last = kp;
138 c_delbefore(el, el->el_line.cursor - cp); /* delete before dot */
139 el->el_line.cursor = cp;
140 if (el->el_line.cursor < el->el_line.buffer)
141 el->el_line.cursor = el->el_line.buffer; /* bounds check */
146 /* ed_delete_next_char():
147 * Delete character under cursor
150 protected el_action_t
152 ed_delete_next_char(EditLine *el, int c)
154 #ifdef notdef /* XXX */
155 #define EL el->el_line
156 fprintf(stderr, "\nD(b: %x(%s) c: %x(%s) last: %x(%s) limit: %x(%s)\n",
157 EL.buffer, EL.buffer, EL.cursor, EL.cursor, EL.lastchar, EL.lastchar, EL.limit, EL.limit);
159 if (el->el_line.cursor == el->el_line.lastchar) {/* if I'm at the end */
160 if (el->el_map.type == MAP_VI) {
161 if (el->el_line.cursor == el->el_line.buffer) {
162 /* if I'm also at the beginning */
166 term_overwrite(el, STReof, 4);/* then do a EOF */
173 el->el_line.cursor--;
180 if (el->el_line.cursor != el->el_line.buffer)
181 el->el_line.cursor--;
186 c_delafter(el, el->el_state.argument); /* delete after dot */
187 if (el->el_line.cursor >= el->el_line.lastchar && el->el_line.cursor > el->el_line.buffer)
188 el->el_line.cursor = el->el_line.lastchar - 1; /* bounds check */
194 * Cut to the end of line
197 protected el_action_t
199 ed_kill_line(EditLine *el, int c)
203 cp = el->el_line.cursor;
204 kp = el->el_chared.c_kill.buf;
205 while (cp < el->el_line.lastchar)
206 *kp++ = *cp++; /* copy it */
207 el->el_chared.c_kill.last = kp;
208 el->el_line.lastchar = el->el_line.cursor; /* zap! -- delete to end */
214 * Move cursor to the end of line
217 protected el_action_t
219 ed_move_to_end(EditLine *el, int c)
221 el->el_line.cursor = el->el_line.lastchar;
222 if (el->el_map.type == MAP_VI) {
224 el->el_line.cursor--;
226 if (el->el_chared.c_vcmd.action & DELETE) {
236 * Move cursor to the beginning of line
239 protected el_action_t
241 ed_move_to_beg(EditLine *el, int c)
243 el->el_line.cursor = el->el_line.buffer;
245 if (el->el_map.type == MAP_VI) {
246 /* We want FIRST non space character */
247 while (isspace((unsigned char) *el->el_line.cursor))
248 el->el_line.cursor++;
249 if (el->el_chared.c_vcmd.action & DELETE) {
259 /* ed_transpose_chars():
260 * Exchange the character to the left of the cursor with the one under it
263 protected el_action_t
264 ed_transpose_chars(EditLine *el, int c)
266 if (el->el_line.cursor < el->el_line.lastchar) {
267 if (el->el_line.lastchar <= &el->el_line.buffer[1])
270 el->el_line.cursor++;
272 if (el->el_line.cursor > &el->el_line.buffer[1]) {
273 /* must have at least two chars entered */
274 c = el->el_line.cursor[-2];
275 el->el_line.cursor[-2] = el->el_line.cursor[-1];
276 el->el_line.cursor[-1] = c;
285 * Move to the right one character
288 protected el_action_t
290 ed_next_char(EditLine *el, int c)
292 if (el->el_line.cursor >= el->el_line.lastchar)
295 el->el_line.cursor += el->el_state.argument;
296 if (el->el_line.cursor > el->el_line.lastchar)
297 el->el_line.cursor = el->el_line.lastchar;
299 if (el->el_map.type == MAP_VI)
300 if (el->el_chared.c_vcmd.action & DELETE) {
310 * Move to the beginning of the current word
313 protected el_action_t
315 ed_prev_word(EditLine *el, int c)
317 if (el->el_line.cursor == el->el_line.buffer)
320 el->el_line.cursor = c__prev_word(el->el_line.cursor, el->el_line.buffer,
321 el->el_state.argument,
324 if (el->el_map.type == MAP_VI)
325 if (el->el_chared.c_vcmd.action & DELETE) {
335 * Move to the left one character
338 protected el_action_t
340 ed_prev_char(EditLine *el, int c)
342 if (el->el_line.cursor > el->el_line.buffer) {
343 el->el_line.cursor -= el->el_state.argument;
344 if (el->el_line.cursor < el->el_line.buffer)
345 el->el_line.cursor = el->el_line.buffer;
347 if (el->el_map.type == MAP_VI)
348 if (el->el_chared.c_vcmd.action & DELETE) {
360 /* ed_quoted_insert():
361 * Add the next character typed verbatim
364 protected el_action_t
365 ed_quoted_insert(EditLine *el, int c)
371 num = el_getc(el, &tc);
372 c = (unsigned char) tc;
375 return ed_insert(el, c);
377 return ed_end_of_file(el, 0);
382 * Adds to argument or enters a digit
384 protected el_action_t
385 ed_digit(EditLine *el, int c)
387 if (!isdigit((unsigned char) c))
390 if (el->el_state.doingarg) {
391 /* if doing an arg, add this in... */
392 if (el->el_state.lastcmd == EM_UNIVERSAL_ARGUMENT)
393 el->el_state.argument = c - '0';
395 if (el->el_state.argument > 1000000)
397 el->el_state.argument =
398 (el->el_state.argument * 10) + (c - '0');
403 if (el->el_line.lastchar + 1 >= el->el_line.limit)
406 if (el->el_state.inputmode != MODE_INSERT) {
407 el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
409 el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] = '\0';
413 *el->el_line.cursor++ = c;
414 el->el_state.doingarg = 0;
421 /* ed_argument_digit():
422 * Digit that starts argument
425 protected el_action_t
426 ed_argument_digit(EditLine *el, int c)
428 if (!isdigit((unsigned char) c))
431 if (el->el_state.doingarg) {
432 if (el->el_state.argument > 1000000)
434 el->el_state.argument = (el->el_state.argument * 10) + (c - '0');
436 else { /* else starting an argument */
437 el->el_state.argument = c - '0';
438 el->el_state.doingarg = 1;
445 * Indicates unbound character
446 * Bound to keys that are not assigned
448 protected el_action_t
450 ed_unassigned(EditLine *el, int c)
463 * Tty interrupt character
466 protected el_action_t
468 ed_tty_sigint(EditLine *el, int c)
475 * Tty delayed suspend character
478 protected el_action_t
480 ed_tty_dsusp(EditLine *el, int c)
486 /* ed_tty_flush_output():
487 * Tty flush output characters
490 protected el_action_t
492 ed_tty_flush_output(EditLine *el, int c)
502 protected el_action_t
504 ed_tty_sigquit(EditLine *el, int c)
511 * Tty suspend character
514 protected el_action_t
516 ed_tty_sigtstp(EditLine *el, int c)
522 /* ed_tty_stop_output():
523 * Tty disallow output characters
526 protected el_action_t
528 ed_tty_stop_output(EditLine *el, int c)
534 /* ed_tty_start_output():
535 * Tty allow output characters
538 protected el_action_t
540 ed_tty_start_output(EditLine *el, int c)
550 protected el_action_t
552 ed_newline(EditLine *el, int c)
555 *el->el_line.lastchar++ = '\n';
556 *el->el_line.lastchar = '\0';
557 if (el->el_map.type == MAP_VI)
558 el->el_chared.c_vcmd.ins = el->el_line.buffer;
563 /* ed_delete_prev_char():
564 * Delete the character to the left of the cursor
567 protected el_action_t
569 ed_delete_prev_char(EditLine *el, int c)
571 if (el->el_line.cursor <= el->el_line.buffer)
574 c_delbefore(el, el->el_state.argument);
575 el->el_line.cursor -= el->el_state.argument;
576 if (el->el_line.cursor < el->el_line.buffer)
577 el->el_line.cursor = el->el_line.buffer;
582 /* ed_clear_screen():
583 * Clear screen leaving current line at the top
586 protected el_action_t
588 ed_clear_screen(EditLine *el, int c)
590 term_clear_screen(el); /* clear the whole real screen */
591 re_clear_display(el); /* reset everything */
597 * Redisplay everything
600 protected el_action_t
602 ed_redisplay(EditLine *el, int c)
609 * Erase current line and start from scratch
612 protected el_action_t
614 ed_start_over(EditLine *el, int c)
621 /* ed_sequence_lead_in():
622 * First character in a bound sequence
623 * Placeholder for external keys
625 protected el_action_t
627 ed_sequence_lead_in(EditLine *el, int c)
633 /* ed_prev_history():
634 * Move to the previous history line
637 protected el_action_t
639 ed_prev_history(EditLine *el, int c)
643 el->el_chared.c_undo.action = NOP;
644 *el->el_line.lastchar = '\0'; /* just in case */
646 if (el->el_history.eventno == 0) { /* save the current buffer away */
647 (void) strncpy(el->el_history.buf, el->el_line.buffer, EL_BUFSIZ);
648 el->el_history.last = el->el_history.buf +
649 (el->el_line.lastchar - el->el_line.buffer);
652 el->el_history.eventno += el->el_state.argument;
654 if (hist_get(el) == CC_ERROR) {
656 /* el->el_history.eventno was fixed by first call */
664 return CC_NORM; /* was CC_UP_HIST */
668 /* ed_next_history():
669 * Move to the next history line
672 protected el_action_t
674 ed_next_history(EditLine *el, int c)
676 el->el_chared.c_undo.action = NOP;
677 *el->el_line.lastchar = '\0'; /* just in case */
679 el->el_history.eventno -= el->el_state.argument;
681 if (el->el_history.eventno < 0) {
682 el->el_history.eventno = 0;
683 return CC_ERROR; /* make it beep */
690 /* ed_search_prev_history():
691 * Search previous in history for a line matching the current
692 * next search history [M-P] [K]
694 protected el_action_t
696 ed_search_prev_history(EditLine *el, int c)
702 el->el_chared.c_vcmd.action = NOP;
703 el->el_chared.c_undo.action = NOP;
704 *el->el_line.lastchar = '\0'; /* just in case */
705 if (el->el_history.eventno < 0) {
707 (void) fprintf(el->el_errfile, "e_prev_search_hist(): eventno < 0;\n");
709 el->el_history.eventno = 0;
713 if (el->el_history.eventno == 0) {
714 (void) strncpy(el->el_history.buf, el->el_line.buffer, EL_BUFSIZ);
715 el->el_history.last = el->el_history.buf +
716 (el->el_line.lastchar - el->el_line.buffer);
720 if (el->el_history.ref == NULL)
727 c_setpat(el); /* Set search pattern !! */
729 for (h = 1; h <= el->el_history.eventno; h++)
734 (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
736 if ((strncmp(hp, el->el_line.buffer,
737 el->el_line.lastchar - el->el_line.buffer) ||
738 hp[el->el_line.lastchar-el->el_line.buffer]) &&
749 (void) fprintf(el->el_errfile, "not found\n");
754 el->el_history.eventno = h;
760 /* ed_search_next_history():
761 * Search next in history for a line matching the current
764 protected el_action_t
766 ed_search_next_history(EditLine *el, int c)
772 el->el_chared.c_vcmd.action = NOP;
773 el->el_chared.c_undo.action = NOP;
774 *el->el_line.lastchar = '\0'; /* just in case */
776 if (el->el_history.eventno == 0)
779 if (el->el_history.ref == NULL)
786 c_setpat(el); /* Set search pattern !! */
788 for (h = 1; h < el->el_history.eventno && hp; h++) {
790 (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
792 if ((strncmp(hp, el->el_line.buffer,
793 el->el_line.lastchar - el->el_line.buffer) ||
794 hp[el->el_line.lastchar-el->el_line.buffer]) &&
800 if (!found) { /* is it the current history number? */
801 if (!c_hmatch(el, el->el_history.buf)) {
803 (void) fprintf(el->el_errfile, "not found\n");
809 el->el_history.eventno = found;
819 protected el_action_t
821 ed_prev_line(EditLine *el, int c)
824 int nchars = c_hpos(el);
827 * Move to the line requested
829 if (*(ptr = el->el_line.cursor) == '\n')
832 for (; ptr >= el->el_line.buffer; ptr--)
833 if (*ptr == '\n' && --el->el_state.argument <= 0)
836 if (el->el_state.argument > 0)
840 * Move to the beginning of the line
842 for (ptr--; ptr >= el->el_line.buffer && *ptr != '\n'; ptr--)
846 * Move to the character requested
849 nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
853 el->el_line.cursor = ptr;
862 protected el_action_t
864 ed_next_line(EditLine *el, int c)
867 int nchars = c_hpos(el);
870 * Move to the line requested
872 for (ptr = el->el_line.cursor; ptr < el->el_line.lastchar; ptr++)
873 if (*ptr == '\n' && --el->el_state.argument <= 0)
876 if (el->el_state.argument > 0)
880 * Move to the character requested
883 nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
887 el->el_line.cursor = ptr;
893 * Editline extended command
896 protected el_action_t
898 ed_command(EditLine *el, int c)
900 char tmpbuf[EL_BUFSIZ];
903 el->el_line.buffer[0] = '\0';
904 el->el_line.lastchar = el->el_line.buffer;
905 el->el_line.cursor = el->el_line.buffer;
907 c_insert(el, 3); /* prompt + ": " */
908 *el->el_line.cursor++ = '\n';
909 *el->el_line.cursor++ = ':';
910 *el->el_line.cursor++ = ' ';
913 tmplen = c_gets(el, tmpbuf);
914 tmpbuf[tmplen] = '\0';
916 el->el_line.buffer[0] = '\0';
917 el->el_line.lastchar = el->el_line.buffer;
918 el->el_line.cursor = el->el_line.buffer;
920 if (parse_line(el, tmpbuf) == -1)