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
40 * common.c: Common Editor functions
46 * Indicate end of file
56 *el->el_line.lastchar = '\0';
62 * Add character to the line
63 * Insert a character [bound to all insert keys]
75 if (el->el_line.lastchar + el->el_state.argument >=
77 return CC_ERROR; /* end of buffer space */
79 if (el->el_state.argument == 1) {
80 if (el->el_state.inputmode != MODE_INSERT) {
81 el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
83 el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] = '\0';
89 *el->el_line.cursor++ = c;
90 el->el_state.doingarg = 0; /* just in case */
91 re_fastaddc(el); /* fast refresh for one char. */
94 if (el->el_state.inputmode != MODE_INSERT) {
96 for(i = 0;i < el->el_state.argument; i++)
97 el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
98 el->el_line.cursor[i];
100 el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] = '\0';
101 c_delafter(el, el->el_state.argument);
104 c_insert(el, el->el_state.argument);
106 while (el->el_state.argument--)
107 *el->el_line.cursor++ = c;
111 if (el->el_state.inputmode == MODE_REPLACE_1 || el->el_state.inputmode == MODE_REPLACE)
112 el->el_chared.c_undo.action=CHANGE;
114 if (el->el_state.inputmode == MODE_REPLACE_1)
115 return vi_command_mode(el, 0);
121 /* ed_delete_prev_word():
122 * Delete from beginning of current word to cursor
125 protected el_action_t
127 ed_delete_prev_word(el, c)
133 if (el->el_line.cursor == el->el_line.buffer)
136 cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
137 el->el_state.argument, ce__isword);
139 for (p = cp, kp = el->el_chared.c_kill.buf; p < el->el_line.cursor; p++)
141 el->el_chared.c_kill.last = kp;
143 c_delbefore(el, el->el_line.cursor - cp); /* delete before dot */
144 el->el_line.cursor = cp;
145 if (el->el_line.cursor < el->el_line.buffer)
146 el->el_line.cursor = el->el_line.buffer; /* bounds check */
151 /* ed_delete_next_char():
152 * Delete character under cursor
155 protected el_action_t
157 ed_delete_next_char(el, c)
161 #ifdef notdef /* XXX */
162 #define EL el->el_line
163 fprintf(stderr, "\nD(b: %x(%s) c: %x(%s) last: %x(%s) limit: %x(%s)\n",
164 EL.buffer, EL.buffer, EL.cursor, EL.cursor, EL.lastchar, EL.lastchar, EL.limit, EL.limit);
166 if (el->el_line.cursor == el->el_line.lastchar) {/* 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 */
173 term_overwrite(el, STReof, 4);/* then do a EOF */
180 el->el_line.cursor--;
187 if (el->el_line.cursor != el->el_line.buffer)
188 el->el_line.cursor--;
193 c_delafter(el, el->el_state.argument); /* delete after dot */
194 if (el->el_line.cursor >= el->el_line.lastchar && el->el_line.cursor > el->el_line.buffer)
195 el->el_line.cursor = el->el_line.lastchar - 1; /* bounds check */
201 * Cut to the end of line
204 protected el_action_t
212 cp = el->el_line.cursor;
213 kp = el->el_chared.c_kill.buf;
214 while (cp < el->el_line.lastchar)
215 *kp++ = *cp++; /* copy it */
216 el->el_chared.c_kill.last = kp;
217 el->el_line.lastchar = el->el_line.cursor; /* zap! -- delete to end */
223 * Move cursor to the end of line
226 protected el_action_t
228 ed_move_to_end(el, c)
232 el->el_line.cursor = el->el_line.lastchar;
233 if (el->el_map.type == MAP_VI) {
235 el->el_line.cursor--;
237 if (el->el_chared.c_vcmd.action & DELETE) {
247 * Move cursor to the beginning of line
250 protected el_action_t
252 ed_move_to_beg(el, c)
256 el->el_line.cursor = el->el_line.buffer;
258 if (el->el_map.type == MAP_VI) {
259 /* We want FIRST non space character */
260 while (isspace((unsigned char) *el->el_line.cursor))
261 el->el_line.cursor++;
262 if (el->el_chared.c_vcmd.action & DELETE) {
272 /* ed_transpose_chars():
273 * Exchange the character to the left of the cursor with the one under it
276 protected el_action_t
277 ed_transpose_chars(el, c)
281 if (el->el_line.cursor < el->el_line.lastchar) {
282 if (el->el_line.lastchar <= &el->el_line.buffer[1])
285 el->el_line.cursor++;
287 if (el->el_line.cursor > &el->el_line.buffer[1]) {
288 /* must have at least two chars entered */
289 c = el->el_line.cursor[-2];
290 el->el_line.cursor[-2] = el->el_line.cursor[-1];
291 el->el_line.cursor[-1] = c;
300 * Move to the right one character
303 protected el_action_t
309 if (el->el_line.cursor >= el->el_line.lastchar)
312 el->el_line.cursor += el->el_state.argument;
313 if (el->el_line.cursor > el->el_line.lastchar)
314 el->el_line.cursor = el->el_line.lastchar;
316 if (el->el_map.type == MAP_VI)
317 if (el->el_chared.c_vcmd.action & DELETE) {
327 * Move to the beginning of the current word
330 protected el_action_t
336 if (el->el_line.cursor == el->el_line.buffer)
339 el->el_line.cursor = c__prev_word(el->el_line.cursor, el->el_line.buffer,
340 el->el_state.argument,
343 if (el->el_map.type == MAP_VI)
344 if (el->el_chared.c_vcmd.action & DELETE) {
354 * Move to the left one character
357 protected el_action_t
363 if (el->el_line.cursor > el->el_line.buffer) {
364 el->el_line.cursor -= el->el_state.argument;
365 if (el->el_line.cursor < el->el_line.buffer)
366 el->el_line.cursor = el->el_line.buffer;
368 if (el->el_map.type == MAP_VI)
369 if (el->el_chared.c_vcmd.action & DELETE) {
381 /* ed_quoted_insert():
382 * Add the next character typed verbatim
385 protected el_action_t
386 ed_quoted_insert(el, c)
394 num = el_getc(el, &tc);
395 c = (unsigned char) tc;
398 return ed_insert(el, c);
400 return ed_end_of_file(el, 0);
405 * Adds to argument or enters a digit
407 protected el_action_t
412 if (!isdigit((unsigned char) c))
415 if (el->el_state.doingarg) {
416 /* if doing an arg, add this in... */
417 if (el->el_state.lastcmd == EM_UNIVERSAL_ARGUMENT)
418 el->el_state.argument = c - '0';
420 if (el->el_state.argument > 1000000)
422 el->el_state.argument =
423 (el->el_state.argument * 10) + (c - '0');
428 if (el->el_line.lastchar + 1 >= el->el_line.limit)
431 if (el->el_state.inputmode != MODE_INSERT) {
432 el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
434 el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] = '\0';
438 *el->el_line.cursor++ = c;
439 el->el_state.doingarg = 0;
446 /* ed_argument_digit():
447 * Digit that starts argument
450 protected el_action_t
451 ed_argument_digit(el, c)
455 if (!isdigit((unsigned char) c))
458 if (el->el_state.doingarg) {
459 if (el->el_state.argument > 1000000)
461 el->el_state.argument = (el->el_state.argument * 10) + (c - '0');
463 else { /* else starting an argument */
464 el->el_state.argument = c - '0';
465 el->el_state.doingarg = 1;
472 * Indicates unbound character
473 * Bound to keys that are not assigned
475 protected el_action_t
492 * Tty interrupt character
495 protected el_action_t
506 * Tty delayed suspend character
509 protected el_action_t
519 /* ed_tty_flush_output():
520 * Tty flush output characters
523 protected el_action_t
525 ed_tty_flush_output(el, c)
537 protected el_action_t
539 ed_tty_sigquit(el, c)
548 * Tty suspend character
551 protected el_action_t
553 ed_tty_sigtstp(el, c)
561 /* ed_tty_stop_output():
562 * Tty disallow output characters
565 protected el_action_t
567 ed_tty_stop_output(el, c)
575 /* ed_tty_start_output():
576 * Tty allow output characters
579 protected el_action_t
581 ed_tty_start_output(el, c)
593 protected el_action_t
600 *el->el_line.lastchar++ = '\n';
601 *el->el_line.lastchar = '\0';
602 if (el->el_map.type == MAP_VI)
603 el->el_chared.c_vcmd.ins = el->el_line.buffer;
608 /* ed_delete_prev_char():
609 * Delete the character to the left of the cursor
612 protected el_action_t
614 ed_delete_prev_char(el, c)
618 if (el->el_line.cursor <= el->el_line.buffer)
621 c_delbefore(el, el->el_state.argument);
622 el->el_line.cursor -= el->el_state.argument;
623 if (el->el_line.cursor < el->el_line.buffer)
624 el->el_line.cursor = el->el_line.buffer;
629 /* ed_clear_screen():
630 * Clear screen leaving current line at the top
633 protected el_action_t
635 ed_clear_screen(el, c)
639 term_clear_screen(el); /* clear the whole real screen */
640 re_clear_display(el); /* reset everything */
646 * Redisplay everything
649 protected el_action_t
660 * Erase current line and start from scratch
663 protected el_action_t
674 /* ed_sequence_lead_in():
675 * First character in a bound sequence
676 * Placeholder for external keys
678 protected el_action_t
680 ed_sequence_lead_in(el, c)
688 /* ed_prev_history():
689 * Move to the previous history line
692 protected el_action_t
694 ed_prev_history(el, c)
700 el->el_chared.c_undo.action = NOP;
701 *el->el_line.lastchar = '\0'; /* just in case */
703 if (el->el_history.eventno == 0) { /* save the current buffer away */
704 (void) strncpy(el->el_history.buf, el->el_line.buffer, EL_BUFSIZ);
705 el->el_history.last = el->el_history.buf +
706 (el->el_line.lastchar - el->el_line.buffer);
709 el->el_history.eventno += el->el_state.argument;
711 if (hist_get(el) == CC_ERROR) {
713 /* el->el_history.eventno was fixed by first call */
721 return CC_NORM; /* was CC_UP_HIST */
725 /* ed_next_history():
726 * Move to the next history line
729 protected el_action_t
731 ed_next_history(el, c)
735 el->el_chared.c_undo.action = NOP;
736 *el->el_line.lastchar = '\0'; /* just in case */
738 el->el_history.eventno -= el->el_state.argument;
740 if (el->el_history.eventno < 0) {
741 el->el_history.eventno = 0;
742 return CC_ERROR; /* make it beep */
749 /* ed_search_prev_history():
750 * Search previous in history for a line matching the current
751 * next search history [M-P] [K]
753 protected el_action_t
755 ed_search_prev_history(el, c)
763 el->el_chared.c_vcmd.action = NOP;
764 el->el_chared.c_undo.action = NOP;
765 *el->el_line.lastchar = '\0'; /* just in case */
766 if (el->el_history.eventno < 0) {
768 (void) fprintf(el->el_errfile, "e_prev_search_hist(): eventno < 0;\n");
770 el->el_history.eventno = 0;
774 if (el->el_history.eventno == 0) {
775 (void) strncpy(el->el_history.buf, el->el_line.buffer, EL_BUFSIZ);
776 el->el_history.last = el->el_history.buf +
777 (el->el_line.lastchar - el->el_line.buffer);
781 if (el->el_history.ref == NULL)
788 c_setpat(el); /* Set search pattern !! */
790 for (h = 1; h <= el->el_history.eventno; h++)
795 (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
797 if ((strncmp(hp, el->el_line.buffer,
798 el->el_line.lastchar - el->el_line.buffer) ||
799 hp[el->el_line.lastchar-el->el_line.buffer]) &&
810 (void) fprintf(el->el_errfile, "not found\n");
815 el->el_history.eventno = h;
821 /* ed_search_next_history():
822 * Search next in history for a line matching the current
825 protected el_action_t
827 ed_search_next_history(el, c)
835 el->el_chared.c_vcmd.action = NOP;
836 el->el_chared.c_undo.action = NOP;
837 *el->el_line.lastchar = '\0'; /* just in case */
839 if (el->el_history.eventno == 0)
842 if (el->el_history.ref == NULL)
849 c_setpat(el); /* Set search pattern !! */
851 for (h = 1; h < el->el_history.eventno && hp; h++) {
853 (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
855 if ((strncmp(hp, el->el_line.buffer,
856 el->el_line.lastchar - el->el_line.buffer) ||
857 hp[el->el_line.lastchar-el->el_line.buffer]) &&
863 if (!found) { /* is it the current history number? */
864 if (!c_hmatch(el, el->el_history.buf)) {
866 (void) fprintf(el->el_errfile, "not found\n");
872 el->el_history.eventno = found;
882 protected el_action_t
889 int nchars = c_hpos(el);
892 * Move to the line requested
894 if (*(ptr = el->el_line.cursor) == '\n')
897 for (; ptr >= el->el_line.buffer; ptr--)
898 if (*ptr == '\n' && --el->el_state.argument <= 0)
901 if (el->el_state.argument > 0)
905 * Move to the beginning of the line
907 for (ptr--; ptr >= el->el_line.buffer && *ptr != '\n'; ptr--)
911 * Move to the character requested
914 nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
918 el->el_line.cursor = ptr;
927 protected el_action_t
934 int nchars = c_hpos(el);
937 * Move to the line requested
939 for (ptr = el->el_line.cursor; ptr < el->el_line.lastchar; ptr++)
940 if (*ptr == '\n' && --el->el_state.argument <= 0)
943 if (el->el_state.argument > 0)
947 * Move to the character requested
950 nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
954 el->el_line.cursor = ptr;
960 * Editline extended command
963 protected el_action_t
969 char tmpbuf[EL_BUFSIZ];
972 el->el_line.buffer[0] = '\0';
973 el->el_line.lastchar = el->el_line.buffer;
974 el->el_line.cursor = el->el_line.buffer;
976 c_insert(el, 3); /* prompt + ": " */
977 *el->el_line.cursor++ = '\n';
978 *el->el_line.cursor++ = ':';
979 *el->el_line.cursor++ = ' ';
982 tmplen = c_gets(el, tmpbuf);
983 tmpbuf[tmplen] = '\0';
985 el->el_line.buffer[0] = '\0';
986 el->el_line.lastchar = el->el_line.buffer;
987 el->el_line.cursor = el->el_line.buffer;
989 if (parse_line(el, tmpbuf) == -1)