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.3 2004/10/25 19:38:45 drhodus Exp $
41 * common.c: Common Editor functions
47 * Indicate end of file
57 *el->el_line.lastchar = '\0';
63 * Add character to the line
64 * Insert a character [bound to all insert keys]
76 if (el->el_line.lastchar + el->el_state.argument >=
78 return CC_ERROR; /* end of buffer space */
80 if (el->el_state.argument == 1) {
81 if (el->el_state.inputmode != MODE_INSERT) {
82 el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
84 el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] = '\0';
90 *el->el_line.cursor++ = c;
91 el->el_state.doingarg = 0; /* just in case */
92 re_fastaddc(el); /* fast refresh for one char. */
95 if (el->el_state.inputmode != MODE_INSERT) {
97 for(i = 0;i < el->el_state.argument; i++)
98 el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
99 el->el_line.cursor[i];
101 el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] = '\0';
102 c_delafter(el, el->el_state.argument);
105 c_insert(el, el->el_state.argument);
107 while (el->el_state.argument--)
108 *el->el_line.cursor++ = c;
112 if (el->el_state.inputmode == MODE_REPLACE_1 || el->el_state.inputmode == MODE_REPLACE)
113 el->el_chared.c_undo.action=CHANGE;
115 if (el->el_state.inputmode == MODE_REPLACE_1)
116 return vi_command_mode(el, 0);
122 /* ed_delete_prev_word():
123 * Delete from beginning of current word to cursor
126 protected el_action_t
128 ed_delete_prev_word(el, c)
134 if (el->el_line.cursor == el->el_line.buffer)
137 cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
138 el->el_state.argument, ce__isword);
140 for (p = cp, kp = el->el_chared.c_kill.buf; p < el->el_line.cursor; p++)
142 el->el_chared.c_kill.last = kp;
144 c_delbefore(el, el->el_line.cursor - cp); /* delete before dot */
145 el->el_line.cursor = cp;
146 if (el->el_line.cursor < el->el_line.buffer)
147 el->el_line.cursor = el->el_line.buffer; /* bounds check */
152 /* ed_delete_next_char():
153 * Delete character under cursor
156 protected el_action_t
158 ed_delete_next_char(el, c)
162 #ifdef notdef /* XXX */
163 #define EL el->el_line
164 fprintf(stderr, "\nD(b: %x(%s) c: %x(%s) last: %x(%s) limit: %x(%s)\n",
165 EL.buffer, EL.buffer, EL.cursor, EL.cursor, EL.lastchar, EL.lastchar, EL.limit, EL.limit);
167 if (el->el_line.cursor == el->el_line.lastchar) {/* if I'm at the end */
168 if (el->el_map.type == MAP_VI) {
169 if (el->el_line.cursor == el->el_line.buffer) {
170 /* if I'm also at the beginning */
174 term_overwrite(el, STReof, 4);/* then do a EOF */
181 el->el_line.cursor--;
188 if (el->el_line.cursor != el->el_line.buffer)
189 el->el_line.cursor--;
194 c_delafter(el, el->el_state.argument); /* delete after dot */
195 if (el->el_line.cursor >= el->el_line.lastchar && el->el_line.cursor > el->el_line.buffer)
196 el->el_line.cursor = el->el_line.lastchar - 1; /* bounds check */
202 * Cut to the end of line
205 protected el_action_t
213 cp = el->el_line.cursor;
214 kp = el->el_chared.c_kill.buf;
215 while (cp < el->el_line.lastchar)
216 *kp++ = *cp++; /* copy it */
217 el->el_chared.c_kill.last = kp;
218 el->el_line.lastchar = el->el_line.cursor; /* zap! -- delete to end */
224 * Move cursor to the end of line
227 protected el_action_t
229 ed_move_to_end(el, c)
233 el->el_line.cursor = el->el_line.lastchar;
234 if (el->el_map.type == MAP_VI) {
236 el->el_line.cursor--;
238 if (el->el_chared.c_vcmd.action & DELETE) {
248 * Move cursor to the beginning of line
251 protected el_action_t
253 ed_move_to_beg(el, c)
257 el->el_line.cursor = el->el_line.buffer;
259 if (el->el_map.type == MAP_VI) {
260 /* We want FIRST non space character */
261 while (isspace((unsigned char) *el->el_line.cursor))
262 el->el_line.cursor++;
263 if (el->el_chared.c_vcmd.action & DELETE) {
273 /* ed_transpose_chars():
274 * Exchange the character to the left of the cursor with the one under it
277 protected el_action_t
278 ed_transpose_chars(el, c)
282 if (el->el_line.cursor < el->el_line.lastchar) {
283 if (el->el_line.lastchar <= &el->el_line.buffer[1])
286 el->el_line.cursor++;
288 if (el->el_line.cursor > &el->el_line.buffer[1]) {
289 /* must have at least two chars entered */
290 c = el->el_line.cursor[-2];
291 el->el_line.cursor[-2] = el->el_line.cursor[-1];
292 el->el_line.cursor[-1] = c;
301 * Move to the right one character
304 protected el_action_t
310 if (el->el_line.cursor >= el->el_line.lastchar)
313 el->el_line.cursor += el->el_state.argument;
314 if (el->el_line.cursor > el->el_line.lastchar)
315 el->el_line.cursor = el->el_line.lastchar;
317 if (el->el_map.type == MAP_VI)
318 if (el->el_chared.c_vcmd.action & DELETE) {
328 * Move to the beginning of the current word
331 protected el_action_t
337 if (el->el_line.cursor == el->el_line.buffer)
340 el->el_line.cursor = c__prev_word(el->el_line.cursor, el->el_line.buffer,
341 el->el_state.argument,
344 if (el->el_map.type == MAP_VI)
345 if (el->el_chared.c_vcmd.action & DELETE) {
355 * Move to the left one character
358 protected el_action_t
364 if (el->el_line.cursor > el->el_line.buffer) {
365 el->el_line.cursor -= el->el_state.argument;
366 if (el->el_line.cursor < el->el_line.buffer)
367 el->el_line.cursor = el->el_line.buffer;
369 if (el->el_map.type == MAP_VI)
370 if (el->el_chared.c_vcmd.action & DELETE) {
382 /* ed_quoted_insert():
383 * Add the next character typed verbatim
386 protected el_action_t
387 ed_quoted_insert(el, c)
395 num = el_getc(el, &tc);
396 c = (unsigned char) tc;
399 return ed_insert(el, c);
401 return ed_end_of_file(el, 0);
406 * Adds to argument or enters a digit
408 protected el_action_t
413 if (!isdigit((unsigned char) c))
416 if (el->el_state.doingarg) {
417 /* if doing an arg, add this in... */
418 if (el->el_state.lastcmd == EM_UNIVERSAL_ARGUMENT)
419 el->el_state.argument = c - '0';
421 if (el->el_state.argument > 1000000)
423 el->el_state.argument =
424 (el->el_state.argument * 10) + (c - '0');
429 if (el->el_line.lastchar + 1 >= el->el_line.limit)
432 if (el->el_state.inputmode != MODE_INSERT) {
433 el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
435 el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] = '\0';
439 *el->el_line.cursor++ = c;
440 el->el_state.doingarg = 0;
447 /* ed_argument_digit():
448 * Digit that starts argument
451 protected el_action_t
452 ed_argument_digit(el, c)
456 if (!isdigit((unsigned char) c))
459 if (el->el_state.doingarg) {
460 if (el->el_state.argument > 1000000)
462 el->el_state.argument = (el->el_state.argument * 10) + (c - '0');
464 else { /* else starting an argument */
465 el->el_state.argument = c - '0';
466 el->el_state.doingarg = 1;
473 * Indicates unbound character
474 * Bound to keys that are not assigned
476 protected el_action_t
493 * Tty interrupt character
496 protected el_action_t
507 * Tty delayed suspend character
510 protected el_action_t
520 /* ed_tty_flush_output():
521 * Tty flush output characters
524 protected el_action_t
526 ed_tty_flush_output(el, c)
538 protected el_action_t
540 ed_tty_sigquit(el, c)
549 * Tty suspend character
552 protected el_action_t
554 ed_tty_sigtstp(el, c)
562 /* ed_tty_stop_output():
563 * Tty disallow output characters
566 protected el_action_t
568 ed_tty_stop_output(el, c)
576 /* ed_tty_start_output():
577 * Tty allow output characters
580 protected el_action_t
582 ed_tty_start_output(el, c)
594 protected el_action_t
601 *el->el_line.lastchar++ = '\n';
602 *el->el_line.lastchar = '\0';
603 if (el->el_map.type == MAP_VI)
604 el->el_chared.c_vcmd.ins = el->el_line.buffer;
609 /* ed_delete_prev_char():
610 * Delete the character to the left of the cursor
613 protected el_action_t
615 ed_delete_prev_char(el, c)
619 if (el->el_line.cursor <= el->el_line.buffer)
622 c_delbefore(el, el->el_state.argument);
623 el->el_line.cursor -= el->el_state.argument;
624 if (el->el_line.cursor < el->el_line.buffer)
625 el->el_line.cursor = el->el_line.buffer;
630 /* ed_clear_screen():
631 * Clear screen leaving current line at the top
634 protected el_action_t
636 ed_clear_screen(el, c)
640 term_clear_screen(el); /* clear the whole real screen */
641 re_clear_display(el); /* reset everything */
647 * Redisplay everything
650 protected el_action_t
661 * Erase current line and start from scratch
664 protected el_action_t
675 /* ed_sequence_lead_in():
676 * First character in a bound sequence
677 * Placeholder for external keys
679 protected el_action_t
681 ed_sequence_lead_in(el, c)
689 /* ed_prev_history():
690 * Move to the previous history line
693 protected el_action_t
695 ed_prev_history(el, c)
701 el->el_chared.c_undo.action = NOP;
702 *el->el_line.lastchar = '\0'; /* just in case */
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);
710 el->el_history.eventno += el->el_state.argument;
712 if (hist_get(el) == CC_ERROR) {
714 /* el->el_history.eventno was fixed by first call */
722 return CC_NORM; /* was CC_UP_HIST */
726 /* ed_next_history():
727 * Move to the next history line
730 protected el_action_t
732 ed_next_history(el, c)
736 el->el_chared.c_undo.action = NOP;
737 *el->el_line.lastchar = '\0'; /* just in case */
739 el->el_history.eventno -= el->el_state.argument;
741 if (el->el_history.eventno < 0) {
742 el->el_history.eventno = 0;
743 return CC_ERROR; /* make it beep */
750 /* ed_search_prev_history():
751 * Search previous in history for a line matching the current
752 * next search history [M-P] [K]
754 protected el_action_t
756 ed_search_prev_history(el, c)
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) {
769 (void) fprintf(el->el_errfile, "e_prev_search_hist(): eventno < 0;\n");
771 el->el_history.eventno = 0;
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);
782 if (el->el_history.ref == NULL)
789 c_setpat(el); /* Set search pattern !! */
791 for (h = 1; h <= el->el_history.eventno; h++)
796 (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
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]) &&
811 (void) fprintf(el->el_errfile, "not found\n");
816 el->el_history.eventno = h;
822 /* ed_search_next_history():
823 * Search next in history for a line matching the current
826 protected el_action_t
828 ed_search_next_history(el, c)
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 */
840 if (el->el_history.eventno == 0)
843 if (el->el_history.ref == NULL)
850 c_setpat(el); /* Set search pattern !! */
852 for (h = 1; h < el->el_history.eventno && hp; h++) {
854 (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
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]) &&
864 if (!found) { /* is it the current history number? */
865 if (!c_hmatch(el, el->el_history.buf)) {
867 (void) fprintf(el->el_errfile, "not found\n");
873 el->el_history.eventno = found;
883 protected el_action_t
890 int nchars = c_hpos(el);
893 * Move to the line requested
895 if (*(ptr = el->el_line.cursor) == '\n')
898 for (; ptr >= el->el_line.buffer; ptr--)
899 if (*ptr == '\n' && --el->el_state.argument <= 0)
902 if (el->el_state.argument > 0)
906 * Move to the beginning of the line
908 for (ptr--; ptr >= el->el_line.buffer && *ptr != '\n'; ptr--)
912 * Move to the character requested
915 nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
919 el->el_line.cursor = ptr;
928 protected el_action_t
935 int nchars = c_hpos(el);
938 * Move to the line requested
940 for (ptr = el->el_line.cursor; ptr < el->el_line.lastchar; ptr++)
941 if (*ptr == '\n' && --el->el_state.argument <= 0)
944 if (el->el_state.argument > 0)
948 * Move to the character requested
951 nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
955 el->el_line.cursor = ptr;
961 * Editline extended command
964 protected el_action_t
970 char tmpbuf[EL_BUFSIZ];
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;
977 c_insert(el, 3); /* prompt + ": " */
978 *el->el_line.cursor++ = '\n';
979 *el->el_line.cursor++ = ':';
980 *el->el_line.cursor++ = ' ';
983 tmplen = c_gets(el, tmpbuf);
984 tmpbuf[tmplen] = '\0';
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;
990 if (parse_line(el, tmpbuf) == -1)