1*ea4fdcd7Schristos /* $NetBSD: common.c,v 1.50 2024/06/30 16:29:42 christos Exp $ */
22543e3e6Slukem
36dc2f1dbScgd /*-
46dc2f1dbScgd * Copyright (c) 1992, 1993
56dc2f1dbScgd * The Regents of the University of California. All rights reserved.
66dc2f1dbScgd *
76dc2f1dbScgd * This code is derived from software contributed to Berkeley by
86dc2f1dbScgd * Christos Zoulas of Cornell University.
96dc2f1dbScgd *
106dc2f1dbScgd * Redistribution and use in source and binary forms, with or without
116dc2f1dbScgd * modification, are permitted provided that the following conditions
126dc2f1dbScgd * are met:
136dc2f1dbScgd * 1. Redistributions of source code must retain the above copyright
146dc2f1dbScgd * notice, this list of conditions and the following disclaimer.
156dc2f1dbScgd * 2. Redistributions in binary form must reproduce the above copyright
166dc2f1dbScgd * notice, this list of conditions and the following disclaimer in the
176dc2f1dbScgd * documentation and/or other materials provided with the distribution.
18eb7c1594Sagc * 3. Neither the name of the University nor the names of its contributors
196dc2f1dbScgd * may be used to endorse or promote products derived from this software
206dc2f1dbScgd * without specific prior written permission.
216dc2f1dbScgd *
226dc2f1dbScgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
236dc2f1dbScgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
246dc2f1dbScgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
256dc2f1dbScgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
266dc2f1dbScgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
276dc2f1dbScgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
286dc2f1dbScgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
296dc2f1dbScgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
306dc2f1dbScgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
316dc2f1dbScgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
326dc2f1dbScgd * SUCH DAMAGE.
336dc2f1dbScgd */
346dc2f1dbScgd
350e0ac6b7Schristos #include "config.h"
366dc2f1dbScgd #if !defined(lint) && !defined(SCCSID)
372543e3e6Slukem #if 0
386dc2f1dbScgd static char sccsid[] = "@(#)common.c 8.1 (Berkeley) 6/4/93";
392543e3e6Slukem #else
40*ea4fdcd7Schristos __RCSID("$NetBSD: common.c,v 1.50 2024/06/30 16:29:42 christos Exp $");
412543e3e6Slukem #endif
426dc2f1dbScgd #endif /* not lint && not SCCSID */
436dc2f1dbScgd
446dc2f1dbScgd /*
456dc2f1dbScgd * common.c: Common Editor functions
466dc2f1dbScgd */
47e84df91eSchristos #include <ctype.h>
48e84df91eSchristos #include <string.h>
49e84df91eSchristos
506dc2f1dbScgd #include "el.h"
51747f6811Schristos #include "common.h"
524fc1f47dSchristos #include "fcns.h"
53747f6811Schristos #include "parse.h"
54747f6811Schristos #include "vi.h"
556dc2f1dbScgd
566dc2f1dbScgd /* ed_end_of_file():
576dc2f1dbScgd * Indicate end of file
586dc2f1dbScgd * [^D]
596dc2f1dbScgd */
60a2d6b270Schristos libedit_private el_action_t
616dc2f1dbScgd /*ARGSUSED*/
ed_end_of_file(EditLine * el,wint_t c)62f54e4f97Schristos ed_end_of_file(EditLine *el, wint_t c __attribute__((__unused__)))
636dc2f1dbScgd {
64d30d584aSlukem
656dc2f1dbScgd re_goto_bottom(el);
666dc2f1dbScgd *el->el_line.lastchar = '\0';
67b71bed95Schristos return CC_EOF;
686dc2f1dbScgd }
696dc2f1dbScgd
706dc2f1dbScgd
716dc2f1dbScgd /* ed_insert():
726dc2f1dbScgd * Add character to the line
736dc2f1dbScgd * Insert a character [bound to all insert keys]
746dc2f1dbScgd */
75a2d6b270Schristos libedit_private el_action_t
ed_insert(EditLine * el,wint_t c)76f54e4f97Schristos ed_insert(EditLine *el, wint_t c)
776dc2f1dbScgd {
7839f224afSchristos int count = el->el_state.argument;
796dc2f1dbScgd
806dc2f1dbScgd if (c == '\0')
81b71bed95Schristos return CC_ERROR;
826dc2f1dbScgd
836dc2f1dbScgd if (el->el_line.lastchar + el->el_state.argument >=
8400ff7cacSjdolecek el->el_line.limit) {
8500ff7cacSjdolecek /* end of buffer space, try to allocate more */
8639f224afSchristos if (!ch_enlargebufs(el, (size_t) count))
8700ff7cacSjdolecek return CC_ERROR; /* error allocating more */
8800ff7cacSjdolecek }
896dc2f1dbScgd
9039f224afSchristos if (count == 1) {
91a17c7fe4Schristos if (el->el_state.inputmode == MODE_INSERT
92a17c7fe4Schristos || el->el_line.cursor >= el->el_line.lastchar)
936dc2f1dbScgd c_insert(el, 1);
946dc2f1dbScgd
950594af80Schristos *el->el_line.cursor++ = c;
966dc2f1dbScgd re_fastaddc(el); /* fast refresh for one char. */
97d30d584aSlukem } else {
98a17c7fe4Schristos if (el->el_state.inputmode != MODE_REPLACE_1)
996dc2f1dbScgd c_insert(el, el->el_state.argument);
1006dc2f1dbScgd
10139f224afSchristos while (count-- && el->el_line.cursor < el->el_line.lastchar)
1020594af80Schristos *el->el_line.cursor++ = c;
1036dc2f1dbScgd re_refresh(el);
1046dc2f1dbScgd }
1056dc2f1dbScgd
1066dc2f1dbScgd if (el->el_state.inputmode == MODE_REPLACE_1)
107a17c7fe4Schristos return vi_command_mode(el, 0);
1086dc2f1dbScgd
109b71bed95Schristos return CC_NORM;
1106dc2f1dbScgd }
1116dc2f1dbScgd
1126dc2f1dbScgd
1136dc2f1dbScgd /* ed_delete_prev_word():
1146dc2f1dbScgd * Delete from beginning of current word to cursor
1156dc2f1dbScgd * [M-^?] [^W]
1166dc2f1dbScgd */
117a2d6b270Schristos libedit_private el_action_t
1186dc2f1dbScgd /*ARGSUSED*/
ed_delete_prev_word(EditLine * el,wint_t c)119f54e4f97Schristos ed_delete_prev_word(EditLine *el, wint_t c __attribute__((__unused__)))
1206dc2f1dbScgd {
1210594af80Schristos wchar_t *cp, *p, *kp;
1226dc2f1dbScgd
1236dc2f1dbScgd if (el->el_line.cursor == el->el_line.buffer)
124b71bed95Schristos return CC_ERROR;
1256dc2f1dbScgd
1266dc2f1dbScgd cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
1276dc2f1dbScgd el->el_state.argument, ce__isword);
1286dc2f1dbScgd
1296dc2f1dbScgd for (p = cp, kp = el->el_chared.c_kill.buf; p < el->el_line.cursor; p++)
1306dc2f1dbScgd *kp++ = *p;
1316dc2f1dbScgd el->el_chared.c_kill.last = kp;
1326dc2f1dbScgd
1335c894153Schristos c_delbefore(el, (int)(el->el_line.cursor - cp));/* delete before dot */
1346dc2f1dbScgd el->el_line.cursor = cp;
1356dc2f1dbScgd if (el->el_line.cursor < el->el_line.buffer)
1366dc2f1dbScgd el->el_line.cursor = el->el_line.buffer; /* bounds check */
137b71bed95Schristos return CC_REFRESH;
1386dc2f1dbScgd }
1396dc2f1dbScgd
1406dc2f1dbScgd
1416dc2f1dbScgd /* ed_delete_next_char():
1426dc2f1dbScgd * Delete character under cursor
1436dc2f1dbScgd * [^D] [x]
1446dc2f1dbScgd */
145a2d6b270Schristos libedit_private el_action_t
1466dc2f1dbScgd /*ARGSUSED*/
ed_delete_next_char(EditLine * el,wint_t c)147f54e4f97Schristos ed_delete_next_char(EditLine *el, wint_t c __attribute__((__unused__)))
1486dc2f1dbScgd {
1497ecb1ef2Schristos #ifdef DEBUG_EDIT
1506dc2f1dbScgd #define EL el->el_line
151d784c575Schristos (void) fprintf(el->el_errfile,
152fcf85103Schristos "\nD(b: %p(%ls) c: %p(%ls) last: %p(%ls) limit: %p(%ls)\n",
15384c5ecc4Schristos EL.buffer, EL.buffer, EL.cursor, EL.cursor, EL.lastchar,
15484c5ecc4Schristos EL.lastchar, EL.limit, EL.limit);
1556dc2f1dbScgd #endif
156d30d584aSlukem if (el->el_line.cursor == el->el_line.lastchar) {
157d30d584aSlukem /* if I'm at the end */
1586dc2f1dbScgd if (el->el_map.type == MAP_VI) {
1596dc2f1dbScgd if (el->el_line.cursor == el->el_line.buffer) {
1606dc2f1dbScgd /* if I'm also at the beginning */
1616dc2f1dbScgd #ifdef KSHVI
162b71bed95Schristos return CC_ERROR;
1636dc2f1dbScgd #else
1642ecb0fb7Schristos /* then do an EOF */
16598c7cbebSchristos terminal_writec(el, c);
166b71bed95Schristos return CC_EOF;
1676dc2f1dbScgd #endif
168d30d584aSlukem } else {
1696dc2f1dbScgd #ifdef KSHVI
1706dc2f1dbScgd el->el_line.cursor--;
1716dc2f1dbScgd #else
172b71bed95Schristos return CC_ERROR;
1736dc2f1dbScgd #endif
1746dc2f1dbScgd }
175d067817eSchristos } else
176b71bed95Schristos return CC_ERROR;
1776dc2f1dbScgd }
1786dc2f1dbScgd c_delafter(el, el->el_state.argument); /* delete after dot */
179d067817eSchristos if (el->el_map.type == MAP_VI &&
180d067817eSchristos el->el_line.cursor >= el->el_line.lastchar &&
181d30d584aSlukem el->el_line.cursor > el->el_line.buffer)
182d30d584aSlukem /* bounds check */
183d30d584aSlukem el->el_line.cursor = el->el_line.lastchar - 1;
184b71bed95Schristos return CC_REFRESH;
1856dc2f1dbScgd }
1866dc2f1dbScgd
1876dc2f1dbScgd
1886dc2f1dbScgd /* ed_kill_line():
1896dc2f1dbScgd * Cut to the end of line
1906dc2f1dbScgd * [^K] [^K]
1916dc2f1dbScgd */
192a2d6b270Schristos libedit_private el_action_t
1936dc2f1dbScgd /*ARGSUSED*/
ed_kill_line(EditLine * el,wint_t c)194f54e4f97Schristos ed_kill_line(EditLine *el, wint_t c __attribute__((__unused__)))
1956dc2f1dbScgd {
1960594af80Schristos wchar_t *kp, *cp;
1976dc2f1dbScgd
1986dc2f1dbScgd cp = el->el_line.cursor;
1996dc2f1dbScgd kp = el->el_chared.c_kill.buf;
2006dc2f1dbScgd while (cp < el->el_line.lastchar)
2016dc2f1dbScgd *kp++ = *cp++; /* copy it */
2026dc2f1dbScgd el->el_chared.c_kill.last = kp;
203d30d584aSlukem /* zap! -- delete to end */
204d30d584aSlukem el->el_line.lastchar = el->el_line.cursor;
205b71bed95Schristos return CC_REFRESH;
2066dc2f1dbScgd }
2076dc2f1dbScgd
2086dc2f1dbScgd
2096dc2f1dbScgd /* ed_move_to_end():
2106dc2f1dbScgd * Move cursor to the end of line
2116dc2f1dbScgd * [^E] [^E]
2126dc2f1dbScgd */
213a2d6b270Schristos libedit_private el_action_t
2146dc2f1dbScgd /*ARGSUSED*/
ed_move_to_end(EditLine * el,wint_t c)215f54e4f97Schristos ed_move_to_end(EditLine *el, wint_t c __attribute__((__unused__)))
2166dc2f1dbScgd {
217d30d584aSlukem
2186dc2f1dbScgd el->el_line.cursor = el->el_line.lastchar;
2196dc2f1dbScgd if (el->el_map.type == MAP_VI) {
22039f224afSchristos if (el->el_chared.c_vcmd.action != NOP) {
2216dc2f1dbScgd cv_delfini(el);
222b71bed95Schristos return CC_REFRESH;
2236dc2f1dbScgd }
224e56ab650Saymeric #ifdef VI_MOVE
225*ea4fdcd7Schristos if (el->el_line.cursor > el->el_line.buffer)
226e56ab650Saymeric el->el_line.cursor--;
227e56ab650Saymeric #endif
2286dc2f1dbScgd }
229b71bed95Schristos return CC_CURSOR;
2306dc2f1dbScgd }
2316dc2f1dbScgd
2326dc2f1dbScgd
2336dc2f1dbScgd /* ed_move_to_beg():
2346dc2f1dbScgd * Move cursor to the beginning of line
2356dc2f1dbScgd * [^A] [^A]
2366dc2f1dbScgd */
237a2d6b270Schristos libedit_private el_action_t
2386dc2f1dbScgd /*ARGSUSED*/
ed_move_to_beg(EditLine * el,wint_t c)239f54e4f97Schristos ed_move_to_beg(EditLine *el, wint_t c __attribute__((__unused__)))
2406dc2f1dbScgd {
241d30d584aSlukem
2426dc2f1dbScgd el->el_line.cursor = el->el_line.buffer;
2436dc2f1dbScgd
2446dc2f1dbScgd if (el->el_map.type == MAP_VI) {
2456dc2f1dbScgd /* We want FIRST non space character */
246fcf85103Schristos while (iswspace(*el->el_line.cursor))
2476dc2f1dbScgd el->el_line.cursor++;
24839f224afSchristos if (el->el_chared.c_vcmd.action != NOP) {
2496dc2f1dbScgd cv_delfini(el);
250b71bed95Schristos return CC_REFRESH;
2516dc2f1dbScgd }
2526dc2f1dbScgd }
253b71bed95Schristos return CC_CURSOR;
2546dc2f1dbScgd }
2556dc2f1dbScgd
2566dc2f1dbScgd
2576dc2f1dbScgd /* ed_transpose_chars():
2586dc2f1dbScgd * Exchange the character to the left of the cursor with the one under it
2596dc2f1dbScgd * [^T] [^T]
2606dc2f1dbScgd */
261a2d6b270Schristos libedit_private el_action_t
ed_transpose_chars(EditLine * el,wint_t c)262f54e4f97Schristos ed_transpose_chars(EditLine *el, wint_t c)
2636dc2f1dbScgd {
264d30d584aSlukem
2656dc2f1dbScgd if (el->el_line.cursor < el->el_line.lastchar) {
2666dc2f1dbScgd if (el->el_line.lastchar <= &el->el_line.buffer[1])
267b71bed95Schristos return CC_ERROR;
2686dc2f1dbScgd else
2696dc2f1dbScgd el->el_line.cursor++;
2706dc2f1dbScgd }
2716dc2f1dbScgd if (el->el_line.cursor > &el->el_line.buffer[1]) {
2726dc2f1dbScgd /* must have at least two chars entered */
2736dc2f1dbScgd c = el->el_line.cursor[-2];
2746dc2f1dbScgd el->el_line.cursor[-2] = el->el_line.cursor[-1];
2750594af80Schristos el->el_line.cursor[-1] = c;
276b71bed95Schristos return CC_REFRESH;
277d30d584aSlukem } else
278b71bed95Schristos return CC_ERROR;
2796dc2f1dbScgd }
2806dc2f1dbScgd
2816dc2f1dbScgd
2826dc2f1dbScgd /* ed_next_char():
2836dc2f1dbScgd * Move to the right one character
2846dc2f1dbScgd * [^F] [^F]
2856dc2f1dbScgd */
286a2d6b270Schristos libedit_private el_action_t
2876dc2f1dbScgd /*ARGSUSED*/
ed_next_char(EditLine * el,wint_t c)288f54e4f97Schristos ed_next_char(EditLine *el, wint_t c __attribute__((__unused__)))
2896dc2f1dbScgd {
2900594af80Schristos wchar_t *lim = el->el_line.lastchar;
291d30d584aSlukem
29239f224afSchristos if (el->el_line.cursor >= lim ||
29339f224afSchristos (el->el_line.cursor == lim - 1 &&
29439f224afSchristos el->el_map.type == MAP_VI &&
29539f224afSchristos el->el_chared.c_vcmd.action == NOP))
296b71bed95Schristos return CC_ERROR;
2976dc2f1dbScgd
2986dc2f1dbScgd el->el_line.cursor += el->el_state.argument;
29939f224afSchristos if (el->el_line.cursor > lim)
30039f224afSchristos el->el_line.cursor = lim;
3016dc2f1dbScgd
3026dc2f1dbScgd if (el->el_map.type == MAP_VI)
30339f224afSchristos if (el->el_chared.c_vcmd.action != NOP) {
3046dc2f1dbScgd cv_delfini(el);
305b71bed95Schristos return CC_REFRESH;
3066dc2f1dbScgd }
307b71bed95Schristos return CC_CURSOR;
3086dc2f1dbScgd }
3096dc2f1dbScgd
3106dc2f1dbScgd
3116dc2f1dbScgd /* ed_prev_word():
3126dc2f1dbScgd * Move to the beginning of the current word
3136dc2f1dbScgd * [M-b] [b]
3146dc2f1dbScgd */
315a2d6b270Schristos libedit_private el_action_t
3166dc2f1dbScgd /*ARGSUSED*/
ed_prev_word(EditLine * el,wint_t c)317f54e4f97Schristos ed_prev_word(EditLine *el, wint_t c __attribute__((__unused__)))
3186dc2f1dbScgd {
3196dc2f1dbScgd
320d30d584aSlukem if (el->el_line.cursor == el->el_line.buffer)
321b71bed95Schristos return CC_ERROR;
322d30d584aSlukem
323d30d584aSlukem el->el_line.cursor = c__prev_word(el->el_line.cursor,
324d30d584aSlukem el->el_line.buffer,
3256dc2f1dbScgd el->el_state.argument,
3266dc2f1dbScgd ce__isword);
3276dc2f1dbScgd
3286dc2f1dbScgd if (el->el_map.type == MAP_VI)
32939f224afSchristos if (el->el_chared.c_vcmd.action != NOP) {
3306dc2f1dbScgd cv_delfini(el);
331b71bed95Schristos return CC_REFRESH;
3326dc2f1dbScgd }
333b71bed95Schristos return CC_CURSOR;
3346dc2f1dbScgd }
3356dc2f1dbScgd
3366dc2f1dbScgd
3376dc2f1dbScgd /* ed_prev_char():
3386dc2f1dbScgd * Move to the left one character
3396dc2f1dbScgd * [^B] [^B]
3406dc2f1dbScgd */
341a2d6b270Schristos libedit_private el_action_t
3426dc2f1dbScgd /*ARGSUSED*/
ed_prev_char(EditLine * el,wint_t c)343f54e4f97Schristos ed_prev_char(EditLine *el, wint_t c __attribute__((__unused__)))
3446dc2f1dbScgd {
345d30d584aSlukem
3466dc2f1dbScgd if (el->el_line.cursor > el->el_line.buffer) {
3476dc2f1dbScgd el->el_line.cursor -= el->el_state.argument;
3486dc2f1dbScgd if (el->el_line.cursor < el->el_line.buffer)
3496dc2f1dbScgd el->el_line.cursor = el->el_line.buffer;
3506dc2f1dbScgd
3516dc2f1dbScgd if (el->el_map.type == MAP_VI)
35239f224afSchristos if (el->el_chared.c_vcmd.action != NOP) {
3536dc2f1dbScgd cv_delfini(el);
354b71bed95Schristos return CC_REFRESH;
3556dc2f1dbScgd }
356b71bed95Schristos return CC_CURSOR;
357d30d584aSlukem } else
358b71bed95Schristos return CC_ERROR;
3596dc2f1dbScgd }
3606dc2f1dbScgd
3616dc2f1dbScgd
3626dc2f1dbScgd /* ed_quoted_insert():
3636dc2f1dbScgd * Add the next character typed verbatim
3646dc2f1dbScgd * [^V] [^V]
3656dc2f1dbScgd */
366a2d6b270Schristos libedit_private el_action_t
3677767204cSchristos /*ARGSUSED*/
ed_quoted_insert(EditLine * el,wint_t c)3687767204cSchristos ed_quoted_insert(EditLine *el, wint_t c __attribute__((__unused__)))
3696dc2f1dbScgd {
3706dc2f1dbScgd int num;
3717767204cSchristos wchar_t ch;
3726dc2f1dbScgd
3736dc2f1dbScgd tty_quotemode(el);
3747767204cSchristos num = el_wgetc(el, &ch);
3756dc2f1dbScgd tty_noquotemode(el);
3766dc2f1dbScgd if (num == 1)
3777767204cSchristos return ed_insert(el, ch);
3786dc2f1dbScgd else
379b71bed95Schristos return ed_end_of_file(el, 0);
3806dc2f1dbScgd }
3816dc2f1dbScgd
3826dc2f1dbScgd
3836dc2f1dbScgd /* ed_digit():
3846dc2f1dbScgd * Adds to argument or enters a digit
3856dc2f1dbScgd */
386a2d6b270Schristos libedit_private el_action_t
ed_digit(EditLine * el,wint_t c)387f54e4f97Schristos ed_digit(EditLine *el, wint_t c)
3886dc2f1dbScgd {
389d30d584aSlukem
390fcf85103Schristos if (!iswdigit(c))
391b71bed95Schristos return CC_ERROR;
3926dc2f1dbScgd
3936dc2f1dbScgd if (el->el_state.doingarg) {
3946dc2f1dbScgd /* if doing an arg, add this in... */
3956dc2f1dbScgd if (el->el_state.lastcmd == EM_UNIVERSAL_ARGUMENT)
3966dc2f1dbScgd el->el_state.argument = c - '0';
3976dc2f1dbScgd else {
3986dc2f1dbScgd if (el->el_state.argument > 1000000)
399b71bed95Schristos return CC_ERROR;
4006dc2f1dbScgd el->el_state.argument =
4016dc2f1dbScgd (el->el_state.argument * 10) + (c - '0');
4026dc2f1dbScgd }
403b71bed95Schristos return CC_ARGHACK;
40400ff7cacSjdolecek }
4056dc2f1dbScgd
406a17c7fe4Schristos return ed_insert(el, c);
4076dc2f1dbScgd }
4086dc2f1dbScgd
4096dc2f1dbScgd
4106dc2f1dbScgd /* ed_argument_digit():
4116dc2f1dbScgd * Digit that starts argument
4126dc2f1dbScgd * For ESC-n
4136dc2f1dbScgd */
414a2d6b270Schristos libedit_private el_action_t
ed_argument_digit(EditLine * el,wint_t c)415f54e4f97Schristos ed_argument_digit(EditLine *el, wint_t c)
4166dc2f1dbScgd {
417d30d584aSlukem
418fcf85103Schristos if (!iswdigit(c))
419b71bed95Schristos return CC_ERROR;
4206dc2f1dbScgd
4216dc2f1dbScgd if (el->el_state.doingarg) {
4226dc2f1dbScgd if (el->el_state.argument > 1000000)
423b71bed95Schristos return CC_ERROR;
424d30d584aSlukem el->el_state.argument = (el->el_state.argument * 10) +
425d30d584aSlukem (c - '0');
426d30d584aSlukem } else { /* else starting an argument */
4276dc2f1dbScgd el->el_state.argument = c - '0';
4286dc2f1dbScgd el->el_state.doingarg = 1;
4296dc2f1dbScgd }
430b71bed95Schristos return CC_ARGHACK;
4316dc2f1dbScgd }
4326dc2f1dbScgd
4336dc2f1dbScgd
4346dc2f1dbScgd /* ed_unassigned():
4356dc2f1dbScgd * Indicates unbound character
4366dc2f1dbScgd * Bound to keys that are not assigned
4376dc2f1dbScgd */
438a2d6b270Schristos libedit_private el_action_t
4396dc2f1dbScgd /*ARGSUSED*/
ed_unassigned(EditLine * el,wint_t c)4401237974aSchristos ed_unassigned(EditLine *el __attribute__((__unused__)),
441f54e4f97Schristos wint_t c __attribute__((__unused__)))
4426dc2f1dbScgd {
443d30d584aSlukem
444b71bed95Schristos return CC_ERROR;
4456dc2f1dbScgd }
4466dc2f1dbScgd
4476dc2f1dbScgd
448a2eaeedbSchristos /* ed_ignore():
449a2eaeedbSchristos * Input characters that have no effect
450a2eaeedbSchristos * [^C ^O ^Q ^S ^Z ^\ ^]] [^C ^O ^Q ^S ^\]
4516dc2f1dbScgd */
452a2d6b270Schristos libedit_private el_action_t
4536dc2f1dbScgd /*ARGSUSED*/
ed_ignore(EditLine * el,wint_t c)454a2eaeedbSchristos ed_ignore(EditLine *el __attribute__((__unused__)),
455f54e4f97Schristos wint_t c __attribute__((__unused__)))
4566dc2f1dbScgd {
457d30d584aSlukem
458b71bed95Schristos return CC_NORM;
4596dc2f1dbScgd }
4606dc2f1dbScgd
4616dc2f1dbScgd
4626dc2f1dbScgd /* ed_newline():
4636dc2f1dbScgd * Execute command
4646dc2f1dbScgd * [^J]
4656dc2f1dbScgd */
466a2d6b270Schristos libedit_private el_action_t
4676dc2f1dbScgd /*ARGSUSED*/
ed_newline(EditLine * el,wint_t c)468f54e4f97Schristos ed_newline(EditLine *el, wint_t c __attribute__((__unused__)))
4696dc2f1dbScgd {
470d30d584aSlukem
4716dc2f1dbScgd re_goto_bottom(el);
4726dc2f1dbScgd *el->el_line.lastchar++ = '\n';
4736dc2f1dbScgd *el->el_line.lastchar = '\0';
474b71bed95Schristos return CC_NEWLINE;
4756dc2f1dbScgd }
4766dc2f1dbScgd
4776dc2f1dbScgd
4786dc2f1dbScgd /* ed_delete_prev_char():
4796dc2f1dbScgd * Delete the character to the left of the cursor
4806dc2f1dbScgd * [^?]
4816dc2f1dbScgd */
482a2d6b270Schristos libedit_private el_action_t
4836dc2f1dbScgd /*ARGSUSED*/
ed_delete_prev_char(EditLine * el,wint_t c)484f54e4f97Schristos ed_delete_prev_char(EditLine *el, wint_t c __attribute__((__unused__)))
4856dc2f1dbScgd {
486d30d584aSlukem
4876dc2f1dbScgd if (el->el_line.cursor <= el->el_line.buffer)
488b71bed95Schristos return CC_ERROR;
4896dc2f1dbScgd
4906dc2f1dbScgd c_delbefore(el, el->el_state.argument);
4916dc2f1dbScgd el->el_line.cursor -= el->el_state.argument;
4926dc2f1dbScgd if (el->el_line.cursor < el->el_line.buffer)
4936dc2f1dbScgd el->el_line.cursor = el->el_line.buffer;
494b71bed95Schristos return CC_REFRESH;
4956dc2f1dbScgd }
4966dc2f1dbScgd
4976dc2f1dbScgd
4986dc2f1dbScgd /* ed_clear_screen():
4996dc2f1dbScgd * Clear screen leaving current line at the top
5006dc2f1dbScgd * [^L]
5016dc2f1dbScgd */
502a2d6b270Schristos libedit_private el_action_t
5036dc2f1dbScgd /*ARGSUSED*/
ed_clear_screen(EditLine * el,wint_t c)504f54e4f97Schristos ed_clear_screen(EditLine *el, wint_t c __attribute__((__unused__)))
5056dc2f1dbScgd {
506d30d584aSlukem
50798c7cbebSchristos terminal_clear_screen(el); /* clear the whole real screen */
5086dc2f1dbScgd re_clear_display(el); /* reset everything */
509b71bed95Schristos return CC_REFRESH;
5106dc2f1dbScgd }
5116dc2f1dbScgd
5126dc2f1dbScgd
5136dc2f1dbScgd /* ed_redisplay():
5146dc2f1dbScgd * Redisplay everything
5156dc2f1dbScgd * ^R
5166dc2f1dbScgd */
517a2d6b270Schristos libedit_private el_action_t
5186dc2f1dbScgd /*ARGSUSED*/
ed_redisplay(EditLine * el,wint_t c)519839ca00bSchristos ed_redisplay(EditLine *el __attribute__((__unused__)),
520f54e4f97Schristos wint_t c __attribute__((__unused__)))
5216dc2f1dbScgd {
522d30d584aSlukem
523b71bed95Schristos return CC_REDISPLAY;
5246dc2f1dbScgd }
5256dc2f1dbScgd
5266dc2f1dbScgd
5276dc2f1dbScgd /* ed_start_over():
5286dc2f1dbScgd * Erase current line and start from scratch
5296dc2f1dbScgd * [^G]
5306dc2f1dbScgd */
531a2d6b270Schristos libedit_private el_action_t
5326dc2f1dbScgd /*ARGSUSED*/
ed_start_over(EditLine * el,wint_t c)533f54e4f97Schristos ed_start_over(EditLine *el, wint_t c __attribute__((__unused__)))
5346dc2f1dbScgd {
535d30d584aSlukem
536bb64d9f1Schristos ch_reset(el);
537b71bed95Schristos return CC_REFRESH;
5386dc2f1dbScgd }
5396dc2f1dbScgd
5406dc2f1dbScgd
5416dc2f1dbScgd /* ed_sequence_lead_in():
5426dc2f1dbScgd * First character in a bound sequence
5436dc2f1dbScgd * Placeholder for external keys
5446dc2f1dbScgd */
545a2d6b270Schristos libedit_private el_action_t
5466dc2f1dbScgd /*ARGSUSED*/
ed_sequence_lead_in(EditLine * el,wint_t c)547839ca00bSchristos ed_sequence_lead_in(EditLine *el __attribute__((__unused__)),
548f54e4f97Schristos wint_t c __attribute__((__unused__)))
5496dc2f1dbScgd {
550d30d584aSlukem
551b71bed95Schristos return CC_NORM;
5526dc2f1dbScgd }
5536dc2f1dbScgd
5546dc2f1dbScgd
5556dc2f1dbScgd /* ed_prev_history():
5566dc2f1dbScgd * Move to the previous history line
5576dc2f1dbScgd * [^P] [k]
5586dc2f1dbScgd */
559a2d6b270Schristos libedit_private el_action_t
5606dc2f1dbScgd /*ARGSUSED*/
ed_prev_history(EditLine * el,wint_t c)561f54e4f97Schristos ed_prev_history(EditLine *el, wint_t c __attribute__((__unused__)))
5626dc2f1dbScgd {
5636dc2f1dbScgd char beep = 0;
56439f224afSchristos int sv_event = el->el_history.eventno;
5656dc2f1dbScgd
566a17c7fe4Schristos el->el_chared.c_undo.len = -1;
5676dc2f1dbScgd *el->el_line.lastchar = '\0'; /* just in case */
5686dc2f1dbScgd
569d30d584aSlukem if (el->el_history.eventno == 0) { /* save the current buffer
570d30d584aSlukem * away */
5710aefc7f9Schristos (void) wcsncpy(el->el_history.buf, el->el_line.buffer,
572d30d584aSlukem EL_BUFSIZ);
5736dc2f1dbScgd el->el_history.last = el->el_history.buf +
5746dc2f1dbScgd (el->el_line.lastchar - el->el_line.buffer);
5756dc2f1dbScgd }
5766dc2f1dbScgd el->el_history.eventno += el->el_state.argument;
5776dc2f1dbScgd
5786dc2f1dbScgd if (hist_get(el) == CC_ERROR) {
57939f224afSchristos if (el->el_map.type == MAP_VI) {
58039f224afSchristos el->el_history.eventno = sv_event;
58139f224afSchristos }
5826dc2f1dbScgd beep = 1;
5836dc2f1dbScgd /* el->el_history.eventno was fixed by first call */
5846dc2f1dbScgd (void) hist_get(el);
5856dc2f1dbScgd }
5866dc2f1dbScgd if (beep)
58739f224afSchristos return CC_REFRESH_BEEP;
58839f224afSchristos return CC_REFRESH;
5896dc2f1dbScgd }
5906dc2f1dbScgd
5916dc2f1dbScgd
5926dc2f1dbScgd /* ed_next_history():
5936dc2f1dbScgd * Move to the next history line
5946dc2f1dbScgd * [^N] [j]
5956dc2f1dbScgd */
596a2d6b270Schristos libedit_private el_action_t
5976dc2f1dbScgd /*ARGSUSED*/
ed_next_history(EditLine * el,wint_t c)598f54e4f97Schristos ed_next_history(EditLine *el, wint_t c __attribute__((__unused__)))
5996dc2f1dbScgd {
60039f224afSchristos el_action_t beep = CC_REFRESH, rval;
601d30d584aSlukem
602a17c7fe4Schristos el->el_chared.c_undo.len = -1;
6036dc2f1dbScgd *el->el_line.lastchar = '\0'; /* just in case */
6046dc2f1dbScgd
6056dc2f1dbScgd el->el_history.eventno -= el->el_state.argument;
6066dc2f1dbScgd
6076dc2f1dbScgd if (el->el_history.eventno < 0) {
6086dc2f1dbScgd el->el_history.eventno = 0;
60939f224afSchristos beep = CC_REFRESH_BEEP;
6106dc2f1dbScgd }
61139f224afSchristos rval = hist_get(el);
61239f224afSchristos if (rval == CC_REFRESH)
61339f224afSchristos return beep;
61439f224afSchristos return rval;
61539f224afSchristos
6166dc2f1dbScgd }
6176dc2f1dbScgd
6186dc2f1dbScgd
6196dc2f1dbScgd /* ed_search_prev_history():
6206dc2f1dbScgd * Search previous in history for a line matching the current
6216dc2f1dbScgd * next search history [M-P] [K]
6226dc2f1dbScgd */
623a2d6b270Schristos libedit_private el_action_t
6246dc2f1dbScgd /*ARGSUSED*/
ed_search_prev_history(EditLine * el,wint_t c)625f54e4f97Schristos ed_search_prev_history(EditLine *el, wint_t c __attribute__((__unused__)))
6266dc2f1dbScgd {
6270594af80Schristos const wchar_t *hp;
6286dc2f1dbScgd int h;
62923f3e707Schristos int found = 0;
6306dc2f1dbScgd
6316dc2f1dbScgd el->el_chared.c_vcmd.action = NOP;
632a17c7fe4Schristos el->el_chared.c_undo.len = -1;
6336dc2f1dbScgd *el->el_line.lastchar = '\0'; /* just in case */
6346dc2f1dbScgd if (el->el_history.eventno < 0) {
6356dc2f1dbScgd #ifdef DEBUG_EDIT
636d30d584aSlukem (void) fprintf(el->el_errfile,
637d30d584aSlukem "e_prev_search_hist(): eventno < 0;\n");
6386dc2f1dbScgd #endif
6396dc2f1dbScgd el->el_history.eventno = 0;
640b71bed95Schristos return CC_ERROR;
6416dc2f1dbScgd }
6426dc2f1dbScgd if (el->el_history.eventno == 0) {
6430aefc7f9Schristos (void) wcsncpy(el->el_history.buf, el->el_line.buffer,
644d30d584aSlukem EL_BUFSIZ);
6456dc2f1dbScgd el->el_history.last = el->el_history.buf +
6466dc2f1dbScgd (el->el_line.lastchar - el->el_line.buffer);
6476dc2f1dbScgd }
6486dc2f1dbScgd if (el->el_history.ref == NULL)
649b71bed95Schristos return CC_ERROR;
6506dc2f1dbScgd
6516dc2f1dbScgd hp = HIST_FIRST(el);
6526dc2f1dbScgd if (hp == NULL)
653b71bed95Schristos return CC_ERROR;
6546dc2f1dbScgd
6556dc2f1dbScgd c_setpat(el); /* Set search pattern !! */
6566dc2f1dbScgd
6576dc2f1dbScgd for (h = 1; h <= el->el_history.eventno; h++)
6586dc2f1dbScgd hp = HIST_NEXT(el);
6596dc2f1dbScgd
6606dc2f1dbScgd while (hp != NULL) {
6616dc2f1dbScgd #ifdef SDEBUG
6621148c426Sryo (void) fprintf(el->el_errfile, "Comparing with \"%ls\"\n", hp);
6636dc2f1dbScgd #endif
6640aefc7f9Schristos if ((wcsncmp(hp, el->el_line.buffer, (size_t)
665a6d4afbaSchristos (el->el_line.lastchar - el->el_line.buffer)) ||
6666dc2f1dbScgd hp[el->el_line.lastchar - el->el_line.buffer]) &&
6676dc2f1dbScgd c_hmatch(el, hp)) {
66823f3e707Schristos found = 1;
6696dc2f1dbScgd break;
6706dc2f1dbScgd }
6716dc2f1dbScgd h++;
6726dc2f1dbScgd hp = HIST_NEXT(el);
6736dc2f1dbScgd }
6746dc2f1dbScgd
6756dc2f1dbScgd if (!found) {
6766dc2f1dbScgd #ifdef SDEBUG
6776dc2f1dbScgd (void) fprintf(el->el_errfile, "not found\n");
6786dc2f1dbScgd #endif
679b71bed95Schristos return CC_ERROR;
6806dc2f1dbScgd }
6816dc2f1dbScgd el->el_history.eventno = h;
6826dc2f1dbScgd
683b71bed95Schristos return hist_get(el);
6846dc2f1dbScgd }
6856dc2f1dbScgd
6866dc2f1dbScgd
6876dc2f1dbScgd /* ed_search_next_history():
6886dc2f1dbScgd * Search next in history for a line matching the current
6896dc2f1dbScgd * [M-N] [J]
6906dc2f1dbScgd */
691a2d6b270Schristos libedit_private el_action_t
6926dc2f1dbScgd /*ARGSUSED*/
ed_search_next_history(EditLine * el,wint_t c)693f54e4f97Schristos ed_search_next_history(EditLine *el, wint_t c __attribute__((__unused__)))
6946dc2f1dbScgd {
6950594af80Schristos const wchar_t *hp;
6966dc2f1dbScgd int h;
69723f3e707Schristos int found = 0;
6986dc2f1dbScgd
6996dc2f1dbScgd el->el_chared.c_vcmd.action = NOP;
700a17c7fe4Schristos el->el_chared.c_undo.len = -1;
7016dc2f1dbScgd *el->el_line.lastchar = '\0'; /* just in case */
7026dc2f1dbScgd
7036dc2f1dbScgd if (el->el_history.eventno == 0)
704b71bed95Schristos return CC_ERROR;
7056dc2f1dbScgd
7066dc2f1dbScgd if (el->el_history.ref == NULL)
707b71bed95Schristos return CC_ERROR;
7086dc2f1dbScgd
7096dc2f1dbScgd hp = HIST_FIRST(el);
7106dc2f1dbScgd if (hp == NULL)
711b71bed95Schristos return CC_ERROR;
7126dc2f1dbScgd
7136dc2f1dbScgd c_setpat(el); /* Set search pattern !! */
7146dc2f1dbScgd
7156dc2f1dbScgd for (h = 1; h < el->el_history.eventno && hp; h++) {
7166dc2f1dbScgd #ifdef SDEBUG
7171148c426Sryo (void) fprintf(el->el_errfile, "Comparing with \"%ls\"\n", hp);
7186dc2f1dbScgd #endif
7190aefc7f9Schristos if ((wcsncmp(hp, el->el_line.buffer, (size_t)
720a6d4afbaSchristos (el->el_line.lastchar - el->el_line.buffer)) ||
7216dc2f1dbScgd hp[el->el_line.lastchar - el->el_line.buffer]) &&
7226dc2f1dbScgd c_hmatch(el, hp))
7236dc2f1dbScgd found = h;
7246dc2f1dbScgd hp = HIST_NEXT(el);
7256dc2f1dbScgd }
7266dc2f1dbScgd
7276dc2f1dbScgd if (!found) { /* is it the current history number? */
7286dc2f1dbScgd if (!c_hmatch(el, el->el_history.buf)) {
7296dc2f1dbScgd #ifdef SDEBUG
7306dc2f1dbScgd (void) fprintf(el->el_errfile, "not found\n");
7316dc2f1dbScgd #endif
732b71bed95Schristos return CC_ERROR;
7336dc2f1dbScgd }
7346dc2f1dbScgd }
7356dc2f1dbScgd el->el_history.eventno = found;
7366dc2f1dbScgd
737b71bed95Schristos return hist_get(el);
7386dc2f1dbScgd }
7396dc2f1dbScgd
7406dc2f1dbScgd
7416dc2f1dbScgd /* ed_prev_line():
7426dc2f1dbScgd * Move up one line
7436dc2f1dbScgd * Could be [k] [^p]
7446dc2f1dbScgd */
745a2d6b270Schristos libedit_private el_action_t
7466dc2f1dbScgd /*ARGSUSED*/
ed_prev_line(EditLine * el,wint_t c)747f54e4f97Schristos ed_prev_line(EditLine *el, wint_t c __attribute__((__unused__)))
7486dc2f1dbScgd {
7490594af80Schristos wchar_t *ptr;
7506dc2f1dbScgd int nchars = c_hpos(el);
7516dc2f1dbScgd
7526dc2f1dbScgd /*
7536dc2f1dbScgd * Move to the line requested
7546dc2f1dbScgd */
7556dc2f1dbScgd if (*(ptr = el->el_line.cursor) == '\n')
7566dc2f1dbScgd ptr--;
7576dc2f1dbScgd
7586dc2f1dbScgd for (; ptr >= el->el_line.buffer; ptr--)
7596dc2f1dbScgd if (*ptr == '\n' && --el->el_state.argument <= 0)
7606dc2f1dbScgd break;
7616dc2f1dbScgd
7626dc2f1dbScgd if (el->el_state.argument > 0)
763b71bed95Schristos return CC_ERROR;
7646dc2f1dbScgd
7656dc2f1dbScgd /*
7666dc2f1dbScgd * Move to the beginning of the line
7676dc2f1dbScgd */
7686dc2f1dbScgd for (ptr--; ptr >= el->el_line.buffer && *ptr != '\n'; ptr--)
7696dc2f1dbScgd continue;
7706dc2f1dbScgd
7716dc2f1dbScgd /*
7726dc2f1dbScgd * Move to the character requested
7736dc2f1dbScgd */
7746dc2f1dbScgd for (ptr++;
7756dc2f1dbScgd nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
7766dc2f1dbScgd ptr++)
7776dc2f1dbScgd continue;
7786dc2f1dbScgd
7796dc2f1dbScgd el->el_line.cursor = ptr;
780b71bed95Schristos return CC_CURSOR;
7816dc2f1dbScgd }
7826dc2f1dbScgd
7836dc2f1dbScgd
7846dc2f1dbScgd /* ed_next_line():
7856dc2f1dbScgd * Move down one line
7866dc2f1dbScgd * Could be [j] [^n]
7876dc2f1dbScgd */
788a2d6b270Schristos libedit_private el_action_t
7896dc2f1dbScgd /*ARGSUSED*/
ed_next_line(EditLine * el,wint_t c)790f54e4f97Schristos ed_next_line(EditLine *el, wint_t c __attribute__((__unused__)))
7916dc2f1dbScgd {
7920594af80Schristos wchar_t *ptr;
7936dc2f1dbScgd int nchars = c_hpos(el);
7946dc2f1dbScgd
7956dc2f1dbScgd /*
7966dc2f1dbScgd * Move to the line requested
7976dc2f1dbScgd */
7986dc2f1dbScgd for (ptr = el->el_line.cursor; ptr < el->el_line.lastchar; ptr++)
7996dc2f1dbScgd if (*ptr == '\n' && --el->el_state.argument <= 0)
8006dc2f1dbScgd break;
8016dc2f1dbScgd
8026dc2f1dbScgd if (el->el_state.argument > 0)
803b71bed95Schristos return CC_ERROR;
8046dc2f1dbScgd
8056dc2f1dbScgd /*
8066dc2f1dbScgd * Move to the character requested
8076dc2f1dbScgd */
8086dc2f1dbScgd for (ptr++;
8096dc2f1dbScgd nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
8106dc2f1dbScgd ptr++)
8116dc2f1dbScgd continue;
8126dc2f1dbScgd
8136dc2f1dbScgd el->el_line.cursor = ptr;
814b71bed95Schristos return CC_CURSOR;
8156dc2f1dbScgd }
8166dc2f1dbScgd
8176dc2f1dbScgd
8186dc2f1dbScgd /* ed_command():
8196dc2f1dbScgd * Editline extended command
8206dc2f1dbScgd * [M-X] [:]
8216dc2f1dbScgd */
822a2d6b270Schristos libedit_private el_action_t
8236dc2f1dbScgd /*ARGSUSED*/
ed_command(EditLine * el,wint_t c)824f54e4f97Schristos ed_command(EditLine *el, wint_t c __attribute__((__unused__)))
8256dc2f1dbScgd {
8260594af80Schristos wchar_t tmpbuf[EL_BUFSIZ];
8276dc2f1dbScgd int tmplen;
8286dc2f1dbScgd
8290aefc7f9Schristos tmplen = c_gets(el, tmpbuf, L"\n: ");
83098c7cbebSchristos terminal__putc(el, '\n');
8316dc2f1dbScgd
8324a97685cSchristos if (tmplen < 0 || (tmpbuf[tmplen] = 0, parse_line(el, tmpbuf)) == -1)
83398c7cbebSchristos terminal_beep(el);
8346dc2f1dbScgd
8354a97685cSchristos el->el_map.current = el->el_map.key;
8364a97685cSchristos re_clear_display(el);
8374a97685cSchristos return CC_REFRESH;
8386dc2f1dbScgd }
839