1*7c356e86SAndroid Build Coastguard Worker /* $OpenBSD: edit.c,v 1.41 2015/09/01 13:12:31 tedu Exp $ */
2*7c356e86SAndroid Build Coastguard Worker /* $OpenBSD: edit.h,v 1.9 2011/05/30 17:14:35 martynas Exp $ */
3*7c356e86SAndroid Build Coastguard Worker /* $OpenBSD: emacs.c,v 1.52 2015/09/10 22:48:58 nicm Exp $ */
4*7c356e86SAndroid Build Coastguard Worker /* $OpenBSD: vi.c,v 1.30 2015/09/10 22:48:58 nicm Exp $ */
5*7c356e86SAndroid Build Coastguard Worker
6*7c356e86SAndroid Build Coastguard Worker /*-
7*7c356e86SAndroid Build Coastguard Worker * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
8*7c356e86SAndroid Build Coastguard Worker * 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018,
9*7c356e86SAndroid Build Coastguard Worker * 2019, 2020
10*7c356e86SAndroid Build Coastguard Worker * mirabilos <[email protected]>
11*7c356e86SAndroid Build Coastguard Worker *
12*7c356e86SAndroid Build Coastguard Worker * Provided that these terms and disclaimer and all copyright notices
13*7c356e86SAndroid Build Coastguard Worker * are retained or reproduced in an accompanying document, permission
14*7c356e86SAndroid Build Coastguard Worker * is granted to deal in this work without restriction, including un-
15*7c356e86SAndroid Build Coastguard Worker * limited rights to use, publicly perform, distribute, sell, modify,
16*7c356e86SAndroid Build Coastguard Worker * merge, give away, or sublicence.
17*7c356e86SAndroid Build Coastguard Worker *
18*7c356e86SAndroid Build Coastguard Worker * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
19*7c356e86SAndroid Build Coastguard Worker * the utmost extent permitted by applicable law, neither express nor
20*7c356e86SAndroid Build Coastguard Worker * implied; without malicious intent or gross negligence. In no event
21*7c356e86SAndroid Build Coastguard Worker * may a licensor, author or contributor be held liable for indirect,
22*7c356e86SAndroid Build Coastguard Worker * direct, other damage, loss, or other issues arising in any way out
23*7c356e86SAndroid Build Coastguard Worker * of dealing in the work, even if advised of the possibility of such
24*7c356e86SAndroid Build Coastguard Worker * damage or existence of a defect, except proven that it results out
25*7c356e86SAndroid Build Coastguard Worker * of said person's immediate fault when using the work as intended.
26*7c356e86SAndroid Build Coastguard Worker */
27*7c356e86SAndroid Build Coastguard Worker
28*7c356e86SAndroid Build Coastguard Worker #include "sh.h"
29*7c356e86SAndroid Build Coastguard Worker
30*7c356e86SAndroid Build Coastguard Worker #ifndef MKSH_NO_CMDLINE_EDITING
31*7c356e86SAndroid Build Coastguard Worker
32*7c356e86SAndroid Build Coastguard Worker __RCSID("$MirOS: src/bin/mksh/edit.c,v 1.357 2020/10/31 05:02:17 tg Exp $");
33*7c356e86SAndroid Build Coastguard Worker
34*7c356e86SAndroid Build Coastguard Worker /*
35*7c356e86SAndroid Build Coastguard Worker * in later versions we might use libtermcap for this, but since external
36*7c356e86SAndroid Build Coastguard Worker * dependencies are problematic, this has not yet been decided on; another
37*7c356e86SAndroid Build Coastguard Worker * good string is KSH_ESC_STRING "c" except on hardware terminals like the
38*7c356e86SAndroid Build Coastguard Worker * DEC VT420 which do a full power cycle then...
39*7c356e86SAndroid Build Coastguard Worker */
40*7c356e86SAndroid Build Coastguard Worker #ifndef MKSH_CLS_STRING
41*7c356e86SAndroid Build Coastguard Worker #define MKSH_CLS_STRING KSH_ESC_STRING "[;H" KSH_ESC_STRING "[J"
42*7c356e86SAndroid Build Coastguard Worker #endif
43*7c356e86SAndroid Build Coastguard Worker
44*7c356e86SAndroid Build Coastguard Worker #if !defined(MKSH_SMALL) || !MKSH_S_NOVI
45*7c356e86SAndroid Build Coastguard Worker static const char ctrl_x_e[] = "fc -e \"${VISUAL:-${EDITOR:-vi}}\" --";
46*7c356e86SAndroid Build Coastguard Worker #endif
47*7c356e86SAndroid Build Coastguard Worker
48*7c356e86SAndroid Build Coastguard Worker /* tty driver characters we are interested in */
49*7c356e86SAndroid Build Coastguard Worker #define EDCHAR_DISABLED 0xFFFFU
50*7c356e86SAndroid Build Coastguard Worker #define EDCHAR_INITIAL 0xFFFEU
51*7c356e86SAndroid Build Coastguard Worker static struct {
52*7c356e86SAndroid Build Coastguard Worker unsigned short erase;
53*7c356e86SAndroid Build Coastguard Worker unsigned short kill;
54*7c356e86SAndroid Build Coastguard Worker unsigned short werase;
55*7c356e86SAndroid Build Coastguard Worker unsigned short intr;
56*7c356e86SAndroid Build Coastguard Worker unsigned short quit;
57*7c356e86SAndroid Build Coastguard Worker unsigned short eof;
58*7c356e86SAndroid Build Coastguard Worker } edchars;
59*7c356e86SAndroid Build Coastguard Worker
60*7c356e86SAndroid Build Coastguard Worker #define isched(x,e) ((unsigned short)(unsigned char)(x) == (e))
61*7c356e86SAndroid Build Coastguard Worker #define isedchar(x) (!((x) & ~0xFF))
62*7c356e86SAndroid Build Coastguard Worker #ifndef _POSIX_VDISABLE
63*7c356e86SAndroid Build Coastguard Worker #define toedchar(x) ((unsigned short)(unsigned char)(x))
64*7c356e86SAndroid Build Coastguard Worker #else
65*7c356e86SAndroid Build Coastguard Worker #define toedchar(x) (((_POSIX_VDISABLE != -1) && ((x) == _POSIX_VDISABLE)) ? \
66*7c356e86SAndroid Build Coastguard Worker ((unsigned short)EDCHAR_DISABLED) : \
67*7c356e86SAndroid Build Coastguard Worker ((unsigned short)(unsigned char)(x)))
68*7c356e86SAndroid Build Coastguard Worker #endif
69*7c356e86SAndroid Build Coastguard Worker
70*7c356e86SAndroid Build Coastguard Worker /* x_cf_glob() flags */
71*7c356e86SAndroid Build Coastguard Worker #define XCF_COMMAND BIT(0) /* Do command completion */
72*7c356e86SAndroid Build Coastguard Worker #define XCF_FILE BIT(1) /* Do file completion */
73*7c356e86SAndroid Build Coastguard Worker #define XCF_FULLPATH BIT(2) /* command completion: store full path */
74*7c356e86SAndroid Build Coastguard Worker #define XCF_COMMAND_FILE (XCF_COMMAND | XCF_FILE)
75*7c356e86SAndroid Build Coastguard Worker #define XCF_IS_COMMAND BIT(3) /* return flag: is command */
76*7c356e86SAndroid Build Coastguard Worker #define XCF_IS_NOSPACE BIT(4) /* return flag: do not append a space */
77*7c356e86SAndroid Build Coastguard Worker
78*7c356e86SAndroid Build Coastguard Worker static char editmode;
79*7c356e86SAndroid Build Coastguard Worker static int xx_cols; /* for Emacs mode */
80*7c356e86SAndroid Build Coastguard Worker static int modified; /* buffer has been "modified" */
81*7c356e86SAndroid Build Coastguard Worker static char *holdbufp; /* place to hold last edit buffer */
82*7c356e86SAndroid Build Coastguard Worker
83*7c356e86SAndroid Build Coastguard Worker /* 0=dumb 1=tmux (for now) */
84*7c356e86SAndroid Build Coastguard Worker static uint8_t x_term_mode;
85*7c356e86SAndroid Build Coastguard Worker
86*7c356e86SAndroid Build Coastguard Worker static void x_adjust(void);
87*7c356e86SAndroid Build Coastguard Worker static int x_getc(void);
88*7c356e86SAndroid Build Coastguard Worker static void x_putcf(int);
89*7c356e86SAndroid Build Coastguard Worker static void x_modified(void);
90*7c356e86SAndroid Build Coastguard Worker static void x_mode(bool);
91*7c356e86SAndroid Build Coastguard Worker static int x_do_comment(char *, ssize_t, ssize_t *);
92*7c356e86SAndroid Build Coastguard Worker static void x_print_expansions(int, char * const *, bool);
93*7c356e86SAndroid Build Coastguard Worker static int x_cf_glob(int *, const char *, int, int, int *, int *, char ***);
94*7c356e86SAndroid Build Coastguard Worker static size_t x_longest_prefix(int, char * const *);
95*7c356e86SAndroid Build Coastguard Worker static void x_glob_hlp_add_qchar(char *);
96*7c356e86SAndroid Build Coastguard Worker static char *x_glob_hlp_tilde_and_rem_qchar(char *, bool);
97*7c356e86SAndroid Build Coastguard Worker static size_t x_basename(const char *, const char *);
98*7c356e86SAndroid Build Coastguard Worker static void x_free_words(int, char **);
99*7c356e86SAndroid Build Coastguard Worker static int x_escape(const char *, size_t, int (*)(const char *, size_t));
100*7c356e86SAndroid Build Coastguard Worker static int x_emacs(char *);
101*7c356e86SAndroid Build Coastguard Worker static void x_init_prompt(bool);
102*7c356e86SAndroid Build Coastguard Worker #if !MKSH_S_NOVI
103*7c356e86SAndroid Build Coastguard Worker static int x_vi(char *);
104*7c356e86SAndroid Build Coastguard Worker #endif
105*7c356e86SAndroid Build Coastguard Worker static void x_intr(int, int) MKSH_A_NORETURN;
106*7c356e86SAndroid Build Coastguard Worker
107*7c356e86SAndroid Build Coastguard Worker #define x_flush() shf_flush(shl_out)
108*7c356e86SAndroid Build Coastguard Worker #if defined(MKSH_SMALL) && !defined(MKSH_SMALL_BUT_FAST)
109*7c356e86SAndroid Build Coastguard Worker #define x_putc(c) x_putcf(c)
110*7c356e86SAndroid Build Coastguard Worker #else
111*7c356e86SAndroid Build Coastguard Worker #define x_putc(c) shf_putc((c), shl_out)
112*7c356e86SAndroid Build Coastguard Worker #endif
113*7c356e86SAndroid Build Coastguard Worker
114*7c356e86SAndroid Build Coastguard Worker static int path_order_cmp(const void *, const void *);
115*7c356e86SAndroid Build Coastguard Worker static void glob_table(const char *, XPtrV *, struct table *);
116*7c356e86SAndroid Build Coastguard Worker static void glob_path(int, const char *, XPtrV *, const char *);
117*7c356e86SAndroid Build Coastguard Worker static int x_file_glob(int *, char *, char ***);
118*7c356e86SAndroid Build Coastguard Worker static int x_command_glob(int, char *, char ***);
119*7c356e86SAndroid Build Coastguard Worker static int x_locate_word(const char *, int, int, int *, bool *);
120*7c356e86SAndroid Build Coastguard Worker
121*7c356e86SAndroid Build Coastguard Worker static int x_e_getmbc(char *);
122*7c356e86SAndroid Build Coastguard Worker
123*7c356e86SAndroid Build Coastguard Worker /* +++ generic editing functions +++ */
124*7c356e86SAndroid Build Coastguard Worker
125*7c356e86SAndroid Build Coastguard Worker /*
126*7c356e86SAndroid Build Coastguard Worker * read an edited command line
127*7c356e86SAndroid Build Coastguard Worker */
128*7c356e86SAndroid Build Coastguard Worker int
x_read(char * buf)129*7c356e86SAndroid Build Coastguard Worker x_read(char *buf)
130*7c356e86SAndroid Build Coastguard Worker {
131*7c356e86SAndroid Build Coastguard Worker int i;
132*7c356e86SAndroid Build Coastguard Worker
133*7c356e86SAndroid Build Coastguard Worker x_mode(true);
134*7c356e86SAndroid Build Coastguard Worker modified = 1;
135*7c356e86SAndroid Build Coastguard Worker if (Flag(FEMACS) || Flag(FGMACS))
136*7c356e86SAndroid Build Coastguard Worker i = x_emacs(buf);
137*7c356e86SAndroid Build Coastguard Worker #if !MKSH_S_NOVI
138*7c356e86SAndroid Build Coastguard Worker else if (Flag(FVI))
139*7c356e86SAndroid Build Coastguard Worker i = x_vi(buf);
140*7c356e86SAndroid Build Coastguard Worker #endif
141*7c356e86SAndroid Build Coastguard Worker else
142*7c356e86SAndroid Build Coastguard Worker /* internal error */
143*7c356e86SAndroid Build Coastguard Worker i = -1;
144*7c356e86SAndroid Build Coastguard Worker editmode = 0;
145*7c356e86SAndroid Build Coastguard Worker x_mode(false);
146*7c356e86SAndroid Build Coastguard Worker return (i);
147*7c356e86SAndroid Build Coastguard Worker }
148*7c356e86SAndroid Build Coastguard Worker
149*7c356e86SAndroid Build Coastguard Worker /* tty I/O */
150*7c356e86SAndroid Build Coastguard Worker
151*7c356e86SAndroid Build Coastguard Worker static int
x_getc(void)152*7c356e86SAndroid Build Coastguard Worker x_getc(void)
153*7c356e86SAndroid Build Coastguard Worker {
154*7c356e86SAndroid Build Coastguard Worker #ifdef __OS2__
155*7c356e86SAndroid Build Coastguard Worker return (_read_kbd(0, 1, 0));
156*7c356e86SAndroid Build Coastguard Worker #else
157*7c356e86SAndroid Build Coastguard Worker char c;
158*7c356e86SAndroid Build Coastguard Worker ssize_t n;
159*7c356e86SAndroid Build Coastguard Worker
160*7c356e86SAndroid Build Coastguard Worker while ((n = blocking_read(0, &c, 1)) < 0 && errno == EINTR)
161*7c356e86SAndroid Build Coastguard Worker if (trap) {
162*7c356e86SAndroid Build Coastguard Worker x_mode(false);
163*7c356e86SAndroid Build Coastguard Worker runtraps(0);
164*7c356e86SAndroid Build Coastguard Worker #ifdef SIGWINCH
165*7c356e86SAndroid Build Coastguard Worker if (got_winch) {
166*7c356e86SAndroid Build Coastguard Worker change_winsz();
167*7c356e86SAndroid Build Coastguard Worker if (x_cols != xx_cols && editmode == 1) {
168*7c356e86SAndroid Build Coastguard Worker /* redraw line in Emacs mode */
169*7c356e86SAndroid Build Coastguard Worker xx_cols = x_cols;
170*7c356e86SAndroid Build Coastguard Worker x_init_prompt(false);
171*7c356e86SAndroid Build Coastguard Worker x_adjust();
172*7c356e86SAndroid Build Coastguard Worker }
173*7c356e86SAndroid Build Coastguard Worker }
174*7c356e86SAndroid Build Coastguard Worker #endif
175*7c356e86SAndroid Build Coastguard Worker x_mode(true);
176*7c356e86SAndroid Build Coastguard Worker }
177*7c356e86SAndroid Build Coastguard Worker return ((n == 1) ? (int)(unsigned char)c : -1);
178*7c356e86SAndroid Build Coastguard Worker #endif
179*7c356e86SAndroid Build Coastguard Worker }
180*7c356e86SAndroid Build Coastguard Worker
181*7c356e86SAndroid Build Coastguard Worker static void
x_putcf(int c)182*7c356e86SAndroid Build Coastguard Worker x_putcf(int c)
183*7c356e86SAndroid Build Coastguard Worker {
184*7c356e86SAndroid Build Coastguard Worker shf_putc_i(c, shl_out);
185*7c356e86SAndroid Build Coastguard Worker }
186*7c356e86SAndroid Build Coastguard Worker
187*7c356e86SAndroid Build Coastguard Worker /*********************************
188*7c356e86SAndroid Build Coastguard Worker * Misc common code for vi/emacs *
189*7c356e86SAndroid Build Coastguard Worker *********************************/
190*7c356e86SAndroid Build Coastguard Worker
191*7c356e86SAndroid Build Coastguard Worker /*-
192*7c356e86SAndroid Build Coastguard Worker * Handle the commenting/uncommenting of a line.
193*7c356e86SAndroid Build Coastguard Worker * Returns:
194*7c356e86SAndroid Build Coastguard Worker * 1 if a carriage return is indicated (comment added)
195*7c356e86SAndroid Build Coastguard Worker * 0 if no return (comment removed)
196*7c356e86SAndroid Build Coastguard Worker * -1 if there is an error (not enough room for comment chars)
197*7c356e86SAndroid Build Coastguard Worker * If successful, *lenp contains the new length. Note: cursor should be
198*7c356e86SAndroid Build Coastguard Worker * moved to the start of the line after (un)commenting.
199*7c356e86SAndroid Build Coastguard Worker */
200*7c356e86SAndroid Build Coastguard Worker static int
x_do_comment(char * buf,ssize_t bsize,ssize_t * lenp)201*7c356e86SAndroid Build Coastguard Worker x_do_comment(char *buf, ssize_t bsize, ssize_t *lenp)
202*7c356e86SAndroid Build Coastguard Worker {
203*7c356e86SAndroid Build Coastguard Worker ssize_t i, j, len = *lenp;
204*7c356e86SAndroid Build Coastguard Worker
205*7c356e86SAndroid Build Coastguard Worker if (len == 0)
206*7c356e86SAndroid Build Coastguard Worker /* somewhat arbitrary - it's what AT&T ksh does */
207*7c356e86SAndroid Build Coastguard Worker return (1);
208*7c356e86SAndroid Build Coastguard Worker
209*7c356e86SAndroid Build Coastguard Worker /* Already commented? */
210*7c356e86SAndroid Build Coastguard Worker if (buf[0] == '#') {
211*7c356e86SAndroid Build Coastguard Worker bool saw_nl = false;
212*7c356e86SAndroid Build Coastguard Worker
213*7c356e86SAndroid Build Coastguard Worker for (j = 0, i = 1; i < len; i++) {
214*7c356e86SAndroid Build Coastguard Worker if (!saw_nl || buf[i] != '#')
215*7c356e86SAndroid Build Coastguard Worker buf[j++] = buf[i];
216*7c356e86SAndroid Build Coastguard Worker saw_nl = buf[i] == '\n';
217*7c356e86SAndroid Build Coastguard Worker }
218*7c356e86SAndroid Build Coastguard Worker *lenp = j;
219*7c356e86SAndroid Build Coastguard Worker return (0);
220*7c356e86SAndroid Build Coastguard Worker } else {
221*7c356e86SAndroid Build Coastguard Worker int n = 1;
222*7c356e86SAndroid Build Coastguard Worker
223*7c356e86SAndroid Build Coastguard Worker /* See if there's room for the #s - 1 per \n */
224*7c356e86SAndroid Build Coastguard Worker for (i = 0; i < len; i++)
225*7c356e86SAndroid Build Coastguard Worker if (buf[i] == '\n')
226*7c356e86SAndroid Build Coastguard Worker n++;
227*7c356e86SAndroid Build Coastguard Worker if (len + n >= bsize)
228*7c356e86SAndroid Build Coastguard Worker return (-1);
229*7c356e86SAndroid Build Coastguard Worker /* Now add them... */
230*7c356e86SAndroid Build Coastguard Worker for (i = len, j = len + n; --i >= 0; ) {
231*7c356e86SAndroid Build Coastguard Worker if (buf[i] == '\n')
232*7c356e86SAndroid Build Coastguard Worker buf[--j] = '#';
233*7c356e86SAndroid Build Coastguard Worker buf[--j] = buf[i];
234*7c356e86SAndroid Build Coastguard Worker }
235*7c356e86SAndroid Build Coastguard Worker buf[0] = '#';
236*7c356e86SAndroid Build Coastguard Worker *lenp += n;
237*7c356e86SAndroid Build Coastguard Worker return (1);
238*7c356e86SAndroid Build Coastguard Worker }
239*7c356e86SAndroid Build Coastguard Worker }
240*7c356e86SAndroid Build Coastguard Worker
241*7c356e86SAndroid Build Coastguard Worker /****************************************************
242*7c356e86SAndroid Build Coastguard Worker * Common file/command completion code for vi/emacs *
243*7c356e86SAndroid Build Coastguard Worker ****************************************************/
244*7c356e86SAndroid Build Coastguard Worker
245*7c356e86SAndroid Build Coastguard Worker static void
x_print_expansions(int nwords,char * const * words,bool is_command)246*7c356e86SAndroid Build Coastguard Worker x_print_expansions(int nwords, char * const *words, bool is_command)
247*7c356e86SAndroid Build Coastguard Worker {
248*7c356e86SAndroid Build Coastguard Worker bool use_copy = false;
249*7c356e86SAndroid Build Coastguard Worker size_t prefix_len;
250*7c356e86SAndroid Build Coastguard Worker XPtrV l = { NULL, 0, 0 };
251*7c356e86SAndroid Build Coastguard Worker struct columnise_opts co;
252*7c356e86SAndroid Build Coastguard Worker
253*7c356e86SAndroid Build Coastguard Worker /*
254*7c356e86SAndroid Build Coastguard Worker * Check if all matches are in the same directory (in this
255*7c356e86SAndroid Build Coastguard Worker * case, we want to omit the directory name)
256*7c356e86SAndroid Build Coastguard Worker */
257*7c356e86SAndroid Build Coastguard Worker if (!is_command &&
258*7c356e86SAndroid Build Coastguard Worker (prefix_len = x_longest_prefix(nwords, words)) > 0) {
259*7c356e86SAndroid Build Coastguard Worker int i;
260*7c356e86SAndroid Build Coastguard Worker
261*7c356e86SAndroid Build Coastguard Worker /* Special case for 1 match (prefix is whole word) */
262*7c356e86SAndroid Build Coastguard Worker if (nwords == 1)
263*7c356e86SAndroid Build Coastguard Worker prefix_len = x_basename(words[0], NULL);
264*7c356e86SAndroid Build Coastguard Worker /* Any (non-trailing) slashes in non-common word suffixes? */
265*7c356e86SAndroid Build Coastguard Worker for (i = 0; i < nwords; i++)
266*7c356e86SAndroid Build Coastguard Worker if (x_basename(words[i] + prefix_len, NULL) >
267*7c356e86SAndroid Build Coastguard Worker prefix_len)
268*7c356e86SAndroid Build Coastguard Worker break;
269*7c356e86SAndroid Build Coastguard Worker /* All in same directory? */
270*7c356e86SAndroid Build Coastguard Worker if (i == nwords) {
271*7c356e86SAndroid Build Coastguard Worker while (prefix_len > 0 &&
272*7c356e86SAndroid Build Coastguard Worker !mksh_cdirsep(words[0][prefix_len - 1]))
273*7c356e86SAndroid Build Coastguard Worker prefix_len--;
274*7c356e86SAndroid Build Coastguard Worker use_copy = true;
275*7c356e86SAndroid Build Coastguard Worker XPinit(l, nwords + 1);
276*7c356e86SAndroid Build Coastguard Worker for (i = 0; i < nwords; i++)
277*7c356e86SAndroid Build Coastguard Worker XPput(l, words[i] + prefix_len);
278*7c356e86SAndroid Build Coastguard Worker XPput(l, NULL);
279*7c356e86SAndroid Build Coastguard Worker }
280*7c356e86SAndroid Build Coastguard Worker }
281*7c356e86SAndroid Build Coastguard Worker /*
282*7c356e86SAndroid Build Coastguard Worker * Enumerate expansions
283*7c356e86SAndroid Build Coastguard Worker */
284*7c356e86SAndroid Build Coastguard Worker x_putc('\r');
285*7c356e86SAndroid Build Coastguard Worker x_putc('\n');
286*7c356e86SAndroid Build Coastguard Worker co.shf = shl_out;
287*7c356e86SAndroid Build Coastguard Worker co.linesep = '\n';
288*7c356e86SAndroid Build Coastguard Worker co.do_last = true;
289*7c356e86SAndroid Build Coastguard Worker co.prefcol = false;
290*7c356e86SAndroid Build Coastguard Worker pr_list(&co, use_copy ? (char **)XPptrv(l) : words);
291*7c356e86SAndroid Build Coastguard Worker
292*7c356e86SAndroid Build Coastguard Worker if (use_copy)
293*7c356e86SAndroid Build Coastguard Worker /* not x_free_words() */
294*7c356e86SAndroid Build Coastguard Worker XPfree(l);
295*7c356e86SAndroid Build Coastguard Worker }
296*7c356e86SAndroid Build Coastguard Worker
297*7c356e86SAndroid Build Coastguard Worker /*
298*7c356e86SAndroid Build Coastguard Worker * Convert backslash-escaped string to QCHAR-escaped
299*7c356e86SAndroid Build Coastguard Worker * string useful for globbing; loses QCHAR unless it
300*7c356e86SAndroid Build Coastguard Worker * can squeeze in, eg. by previous loss of backslash
301*7c356e86SAndroid Build Coastguard Worker */
302*7c356e86SAndroid Build Coastguard Worker static void
x_glob_hlp_add_qchar(char * cp)303*7c356e86SAndroid Build Coastguard Worker x_glob_hlp_add_qchar(char *cp)
304*7c356e86SAndroid Build Coastguard Worker {
305*7c356e86SAndroid Build Coastguard Worker char ch, *dp = cp;
306*7c356e86SAndroid Build Coastguard Worker bool escaping = false;
307*7c356e86SAndroid Build Coastguard Worker
308*7c356e86SAndroid Build Coastguard Worker while ((ch = *cp++)) {
309*7c356e86SAndroid Build Coastguard Worker if (ch == '\\' && !escaping) {
310*7c356e86SAndroid Build Coastguard Worker escaping = true;
311*7c356e86SAndroid Build Coastguard Worker continue;
312*7c356e86SAndroid Build Coastguard Worker }
313*7c356e86SAndroid Build Coastguard Worker if (escaping || (ch == QCHAR && (cp - dp) > 1)) {
314*7c356e86SAndroid Build Coastguard Worker /*
315*7c356e86SAndroid Build Coastguard Worker * empirically made list of chars to escape
316*7c356e86SAndroid Build Coastguard Worker * for globbing as well as QCHAR itself
317*7c356e86SAndroid Build Coastguard Worker */
318*7c356e86SAndroid Build Coastguard Worker switch (ord(ch)) {
319*7c356e86SAndroid Build Coastguard Worker case QCHAR:
320*7c356e86SAndroid Build Coastguard Worker case ORD('$'):
321*7c356e86SAndroid Build Coastguard Worker case ORD('*'):
322*7c356e86SAndroid Build Coastguard Worker case ORD('?'):
323*7c356e86SAndroid Build Coastguard Worker case ORD('['):
324*7c356e86SAndroid Build Coastguard Worker case ORD('\\'):
325*7c356e86SAndroid Build Coastguard Worker case ORD('`'):
326*7c356e86SAndroid Build Coastguard Worker *dp++ = QCHAR;
327*7c356e86SAndroid Build Coastguard Worker break;
328*7c356e86SAndroid Build Coastguard Worker }
329*7c356e86SAndroid Build Coastguard Worker escaping = false;
330*7c356e86SAndroid Build Coastguard Worker }
331*7c356e86SAndroid Build Coastguard Worker *dp++ = ch;
332*7c356e86SAndroid Build Coastguard Worker }
333*7c356e86SAndroid Build Coastguard Worker *dp = '\0';
334*7c356e86SAndroid Build Coastguard Worker }
335*7c356e86SAndroid Build Coastguard Worker
336*7c356e86SAndroid Build Coastguard Worker /*
337*7c356e86SAndroid Build Coastguard Worker * Run tilde expansion on argument string, return the result
338*7c356e86SAndroid Build Coastguard Worker * after unescaping; if the flag is set, the original string
339*7c356e86SAndroid Build Coastguard Worker * is freed if changed and assumed backslash-escaped, if not
340*7c356e86SAndroid Build Coastguard Worker * it is assumed QCHAR-escaped
341*7c356e86SAndroid Build Coastguard Worker */
342*7c356e86SAndroid Build Coastguard Worker static char *
x_glob_hlp_tilde_and_rem_qchar(char * s,bool magic_flag)343*7c356e86SAndroid Build Coastguard Worker x_glob_hlp_tilde_and_rem_qchar(char *s, bool magic_flag)
344*7c356e86SAndroid Build Coastguard Worker {
345*7c356e86SAndroid Build Coastguard Worker char ch, *cp, *dp;
346*7c356e86SAndroid Build Coastguard Worker
347*7c356e86SAndroid Build Coastguard Worker /*
348*7c356e86SAndroid Build Coastguard Worker * On the string, check whether we have a tilde expansion,
349*7c356e86SAndroid Build Coastguard Worker * and if so, discern "~foo/bar" and "~/baz" from "~blah";
350*7c356e86SAndroid Build Coastguard Worker * if we have a directory part (the former), try to expand
351*7c356e86SAndroid Build Coastguard Worker */
352*7c356e86SAndroid Build Coastguard Worker if (*s == '~' && (cp = /* not sdirsep */ strchr(s, '/')) != NULL) {
353*7c356e86SAndroid Build Coastguard Worker /* ok, so split into "~foo"/"bar" or "~"/"baz" */
354*7c356e86SAndroid Build Coastguard Worker *cp++ = 0;
355*7c356e86SAndroid Build Coastguard Worker /* try to expand the tilde */
356*7c356e86SAndroid Build Coastguard Worker if (!(dp = do_tilde(s + 1))) {
357*7c356e86SAndroid Build Coastguard Worker /* nope, revert damage */
358*7c356e86SAndroid Build Coastguard Worker *--cp = '/';
359*7c356e86SAndroid Build Coastguard Worker } else {
360*7c356e86SAndroid Build Coastguard Worker /* ok, expand and replace */
361*7c356e86SAndroid Build Coastguard Worker strpathx(cp, dp, cp, 1);
362*7c356e86SAndroid Build Coastguard Worker if (magic_flag)
363*7c356e86SAndroid Build Coastguard Worker afree(s, ATEMP);
364*7c356e86SAndroid Build Coastguard Worker s = cp;
365*7c356e86SAndroid Build Coastguard Worker }
366*7c356e86SAndroid Build Coastguard Worker }
367*7c356e86SAndroid Build Coastguard Worker
368*7c356e86SAndroid Build Coastguard Worker /* ... convert it from backslash-escaped via QCHAR-escaped... */
369*7c356e86SAndroid Build Coastguard Worker if (magic_flag)
370*7c356e86SAndroid Build Coastguard Worker x_glob_hlp_add_qchar(s);
371*7c356e86SAndroid Build Coastguard Worker /* ... to unescaped, for comparison with the matches */
372*7c356e86SAndroid Build Coastguard Worker cp = dp = s;
373*7c356e86SAndroid Build Coastguard Worker
374*7c356e86SAndroid Build Coastguard Worker while ((ch = *cp++)) {
375*7c356e86SAndroid Build Coastguard Worker if (ch == QCHAR && !(ch = *cp++))
376*7c356e86SAndroid Build Coastguard Worker break;
377*7c356e86SAndroid Build Coastguard Worker *dp++ = ch;
378*7c356e86SAndroid Build Coastguard Worker }
379*7c356e86SAndroid Build Coastguard Worker *dp = '\0';
380*7c356e86SAndroid Build Coastguard Worker
381*7c356e86SAndroid Build Coastguard Worker return (s);
382*7c356e86SAndroid Build Coastguard Worker }
383*7c356e86SAndroid Build Coastguard Worker
384*7c356e86SAndroid Build Coastguard Worker /**
385*7c356e86SAndroid Build Coastguard Worker * Do file globbing:
386*7c356e86SAndroid Build Coastguard Worker * - does expansion, checks for no match, etc.
387*7c356e86SAndroid Build Coastguard Worker * - sets *wordsp to array of matching strings
388*7c356e86SAndroid Build Coastguard Worker * - returns number of matching strings
389*7c356e86SAndroid Build Coastguard Worker */
390*7c356e86SAndroid Build Coastguard Worker static int
x_file_glob(int * flagsp,char * toglob,char *** wordsp)391*7c356e86SAndroid Build Coastguard Worker x_file_glob(int *flagsp, char *toglob, char ***wordsp)
392*7c356e86SAndroid Build Coastguard Worker {
393*7c356e86SAndroid Build Coastguard Worker char **words, *cp;
394*7c356e86SAndroid Build Coastguard Worker int nwords;
395*7c356e86SAndroid Build Coastguard Worker XPtrV w;
396*7c356e86SAndroid Build Coastguard Worker struct source *s, *sold;
397*7c356e86SAndroid Build Coastguard Worker
398*7c356e86SAndroid Build Coastguard Worker /* remove all escaping backward slashes */
399*7c356e86SAndroid Build Coastguard Worker x_glob_hlp_add_qchar(toglob);
400*7c356e86SAndroid Build Coastguard Worker
401*7c356e86SAndroid Build Coastguard Worker /*
402*7c356e86SAndroid Build Coastguard Worker * Convert "foo*" (toglob) to an array of strings (words)
403*7c356e86SAndroid Build Coastguard Worker */
404*7c356e86SAndroid Build Coastguard Worker sold = source;
405*7c356e86SAndroid Build Coastguard Worker s = pushs(SWSTR, ATEMP);
406*7c356e86SAndroid Build Coastguard Worker s->start = s->str = toglob;
407*7c356e86SAndroid Build Coastguard Worker source = s;
408*7c356e86SAndroid Build Coastguard Worker if (yylex(ONEWORD | LQCHAR) != LWORD) {
409*7c356e86SAndroid Build Coastguard Worker source = sold;
410*7c356e86SAndroid Build Coastguard Worker internal_warningf(Tfg_badsubst);
411*7c356e86SAndroid Build Coastguard Worker return (0);
412*7c356e86SAndroid Build Coastguard Worker }
413*7c356e86SAndroid Build Coastguard Worker source = sold;
414*7c356e86SAndroid Build Coastguard Worker afree(s, ATEMP);
415*7c356e86SAndroid Build Coastguard Worker XPinit(w, 32);
416*7c356e86SAndroid Build Coastguard Worker cp = yylval.cp;
417*7c356e86SAndroid Build Coastguard Worker while (*cp == CHAR || *cp == QCHAR)
418*7c356e86SAndroid Build Coastguard Worker cp += 2;
419*7c356e86SAndroid Build Coastguard Worker nwords = DOGLOB | DOTILDE | DOMARKDIRS;
420*7c356e86SAndroid Build Coastguard Worker if (*cp != EOS) {
421*7c356e86SAndroid Build Coastguard Worker /* probably a $FOO expansion */
422*7c356e86SAndroid Build Coastguard Worker *flagsp |= XCF_IS_NOSPACE;
423*7c356e86SAndroid Build Coastguard Worker /* this always results in at most one match */
424*7c356e86SAndroid Build Coastguard Worker nwords = 0;
425*7c356e86SAndroid Build Coastguard Worker }
426*7c356e86SAndroid Build Coastguard Worker expand(yylval.cp, &w, nwords);
427*7c356e86SAndroid Build Coastguard Worker XPput(w, NULL);
428*7c356e86SAndroid Build Coastguard Worker words = (char **)XPclose(w);
429*7c356e86SAndroid Build Coastguard Worker
430*7c356e86SAndroid Build Coastguard Worker for (nwords = 0; words[nwords]; nwords++)
431*7c356e86SAndroid Build Coastguard Worker ;
432*7c356e86SAndroid Build Coastguard Worker if (nwords == 1) {
433*7c356e86SAndroid Build Coastguard Worker struct stat statb;
434*7c356e86SAndroid Build Coastguard Worker
435*7c356e86SAndroid Build Coastguard Worker /* Expand any tilde and drop all QCHAR for comparison */
436*7c356e86SAndroid Build Coastguard Worker toglob = x_glob_hlp_tilde_and_rem_qchar(toglob, false);
437*7c356e86SAndroid Build Coastguard Worker
438*7c356e86SAndroid Build Coastguard Worker /*
439*7c356e86SAndroid Build Coastguard Worker * Check if globbing failed (returned glob pattern),
440*7c356e86SAndroid Build Coastguard Worker * but be careful (e.g. toglob == "ab*" when the file
441*7c356e86SAndroid Build Coastguard Worker * "ab*" exists is not an error).
442*7c356e86SAndroid Build Coastguard Worker * Also, check for empty result - happens if we tried
443*7c356e86SAndroid Build Coastguard Worker * to glob something which evaluated to an empty
444*7c356e86SAndroid Build Coastguard Worker * string (e.g., "$FOO" when there is no FOO, etc).
445*7c356e86SAndroid Build Coastguard Worker */
446*7c356e86SAndroid Build Coastguard Worker if ((strcmp(words[0], toglob) == 0 &&
447*7c356e86SAndroid Build Coastguard Worker stat(words[0], &statb) < 0) ||
448*7c356e86SAndroid Build Coastguard Worker words[0][0] == '\0') {
449*7c356e86SAndroid Build Coastguard Worker x_free_words(nwords, words);
450*7c356e86SAndroid Build Coastguard Worker words = NULL;
451*7c356e86SAndroid Build Coastguard Worker nwords = 0;
452*7c356e86SAndroid Build Coastguard Worker }
453*7c356e86SAndroid Build Coastguard Worker }
454*7c356e86SAndroid Build Coastguard Worker
455*7c356e86SAndroid Build Coastguard Worker if ((*wordsp = nwords ? words : NULL) == NULL && words != NULL)
456*7c356e86SAndroid Build Coastguard Worker x_free_words(nwords, words);
457*7c356e86SAndroid Build Coastguard Worker
458*7c356e86SAndroid Build Coastguard Worker return (nwords);
459*7c356e86SAndroid Build Coastguard Worker }
460*7c356e86SAndroid Build Coastguard Worker
461*7c356e86SAndroid Build Coastguard Worker /* Data structure used in x_command_glob() */
462*7c356e86SAndroid Build Coastguard Worker struct path_order_info {
463*7c356e86SAndroid Build Coastguard Worker char *word;
464*7c356e86SAndroid Build Coastguard Worker size_t base;
465*7c356e86SAndroid Build Coastguard Worker size_t path_order;
466*7c356e86SAndroid Build Coastguard Worker };
467*7c356e86SAndroid Build Coastguard Worker
468*7c356e86SAndroid Build Coastguard Worker /* Compare routine used in x_command_glob() */
469*7c356e86SAndroid Build Coastguard Worker static int
path_order_cmp(const void * aa,const void * bb)470*7c356e86SAndroid Build Coastguard Worker path_order_cmp(const void *aa, const void *bb)
471*7c356e86SAndroid Build Coastguard Worker {
472*7c356e86SAndroid Build Coastguard Worker const struct path_order_info *a = (const struct path_order_info *)aa;
473*7c356e86SAndroid Build Coastguard Worker const struct path_order_info *b = (const struct path_order_info *)bb;
474*7c356e86SAndroid Build Coastguard Worker int t;
475*7c356e86SAndroid Build Coastguard Worker
476*7c356e86SAndroid Build Coastguard Worker if ((t = ascstrcmp(a->word + a->base, b->word + b->base)))
477*7c356e86SAndroid Build Coastguard Worker return (t);
478*7c356e86SAndroid Build Coastguard Worker if (a->path_order > b->path_order)
479*7c356e86SAndroid Build Coastguard Worker return (1);
480*7c356e86SAndroid Build Coastguard Worker if (a->path_order < b->path_order)
481*7c356e86SAndroid Build Coastguard Worker return (-1);
482*7c356e86SAndroid Build Coastguard Worker return (0);
483*7c356e86SAndroid Build Coastguard Worker }
484*7c356e86SAndroid Build Coastguard Worker
485*7c356e86SAndroid Build Coastguard Worker static int
x_command_glob(int flags,char * toglob,char *** wordsp)486*7c356e86SAndroid Build Coastguard Worker x_command_glob(int flags, char *toglob, char ***wordsp)
487*7c356e86SAndroid Build Coastguard Worker {
488*7c356e86SAndroid Build Coastguard Worker char *pat, *fpath;
489*7c356e86SAndroid Build Coastguard Worker size_t nwords;
490*7c356e86SAndroid Build Coastguard Worker XPtrV w;
491*7c356e86SAndroid Build Coastguard Worker struct block *l;
492*7c356e86SAndroid Build Coastguard Worker
493*7c356e86SAndroid Build Coastguard Worker /* Convert "foo*" (toglob) to a pattern for future use */
494*7c356e86SAndroid Build Coastguard Worker pat = evalstr(toglob, DOPAT | DOTILDE);
495*7c356e86SAndroid Build Coastguard Worker
496*7c356e86SAndroid Build Coastguard Worker XPinit(w, 32);
497*7c356e86SAndroid Build Coastguard Worker
498*7c356e86SAndroid Build Coastguard Worker glob_table(pat, &w, &keywords);
499*7c356e86SAndroid Build Coastguard Worker glob_table(pat, &w, &aliases);
500*7c356e86SAndroid Build Coastguard Worker glob_table(pat, &w, &builtins);
501*7c356e86SAndroid Build Coastguard Worker for (l = e->loc; l; l = l->next)
502*7c356e86SAndroid Build Coastguard Worker glob_table(pat, &w, &l->funs);
503*7c356e86SAndroid Build Coastguard Worker
504*7c356e86SAndroid Build Coastguard Worker glob_path(flags, pat, &w, path);
505*7c356e86SAndroid Build Coastguard Worker if ((fpath = str_val(global(TFPATH))) != null)
506*7c356e86SAndroid Build Coastguard Worker glob_path(flags, pat, &w, fpath);
507*7c356e86SAndroid Build Coastguard Worker
508*7c356e86SAndroid Build Coastguard Worker nwords = XPsize(w);
509*7c356e86SAndroid Build Coastguard Worker
510*7c356e86SAndroid Build Coastguard Worker if (!nwords) {
511*7c356e86SAndroid Build Coastguard Worker *wordsp = NULL;
512*7c356e86SAndroid Build Coastguard Worker XPfree(w);
513*7c356e86SAndroid Build Coastguard Worker return (0);
514*7c356e86SAndroid Build Coastguard Worker }
515*7c356e86SAndroid Build Coastguard Worker /* Sort entries */
516*7c356e86SAndroid Build Coastguard Worker if (flags & XCF_FULLPATH) {
517*7c356e86SAndroid Build Coastguard Worker /* Sort by basename, then path order */
518*7c356e86SAndroid Build Coastguard Worker struct path_order_info *info, *last_info = NULL;
519*7c356e86SAndroid Build Coastguard Worker char **words = (char **)XPptrv(w);
520*7c356e86SAndroid Build Coastguard Worker size_t i, path_order = 0;
521*7c356e86SAndroid Build Coastguard Worker
522*7c356e86SAndroid Build Coastguard Worker info = (struct path_order_info *)
523*7c356e86SAndroid Build Coastguard Worker alloc2(nwords, sizeof(struct path_order_info), ATEMP);
524*7c356e86SAndroid Build Coastguard Worker for (i = 0; i < nwords; i++) {
525*7c356e86SAndroid Build Coastguard Worker info[i].word = words[i];
526*7c356e86SAndroid Build Coastguard Worker info[i].base = x_basename(words[i], NULL);
527*7c356e86SAndroid Build Coastguard Worker if (!last_info || info[i].base != last_info->base ||
528*7c356e86SAndroid Build Coastguard Worker strncmp(words[i], last_info->word, info[i].base) != 0) {
529*7c356e86SAndroid Build Coastguard Worker last_info = &info[i];
530*7c356e86SAndroid Build Coastguard Worker path_order++;
531*7c356e86SAndroid Build Coastguard Worker }
532*7c356e86SAndroid Build Coastguard Worker info[i].path_order = path_order;
533*7c356e86SAndroid Build Coastguard Worker }
534*7c356e86SAndroid Build Coastguard Worker qsort(info, nwords, sizeof(struct path_order_info),
535*7c356e86SAndroid Build Coastguard Worker path_order_cmp);
536*7c356e86SAndroid Build Coastguard Worker for (i = 0; i < nwords; i++)
537*7c356e86SAndroid Build Coastguard Worker words[i] = info[i].word;
538*7c356e86SAndroid Build Coastguard Worker afree(info, ATEMP);
539*7c356e86SAndroid Build Coastguard Worker } else {
540*7c356e86SAndroid Build Coastguard Worker /* Sort and remove duplicate entries */
541*7c356e86SAndroid Build Coastguard Worker char **words = (char **)XPptrv(w);
542*7c356e86SAndroid Build Coastguard Worker size_t i, j;
543*7c356e86SAndroid Build Coastguard Worker
544*7c356e86SAndroid Build Coastguard Worker qsort(words, nwords, sizeof(void *), ascpstrcmp);
545*7c356e86SAndroid Build Coastguard Worker for (i = j = 0; i < nwords - 1; i++) {
546*7c356e86SAndroid Build Coastguard Worker if (strcmp(words[i], words[i + 1]))
547*7c356e86SAndroid Build Coastguard Worker words[j++] = words[i];
548*7c356e86SAndroid Build Coastguard Worker else
549*7c356e86SAndroid Build Coastguard Worker afree(words[i], ATEMP);
550*7c356e86SAndroid Build Coastguard Worker }
551*7c356e86SAndroid Build Coastguard Worker words[j++] = words[i];
552*7c356e86SAndroid Build Coastguard Worker w.len = nwords = j;
553*7c356e86SAndroid Build Coastguard Worker }
554*7c356e86SAndroid Build Coastguard Worker
555*7c356e86SAndroid Build Coastguard Worker XPput(w, NULL);
556*7c356e86SAndroid Build Coastguard Worker *wordsp = (char **)XPclose(w);
557*7c356e86SAndroid Build Coastguard Worker
558*7c356e86SAndroid Build Coastguard Worker return (nwords);
559*7c356e86SAndroid Build Coastguard Worker }
560*7c356e86SAndroid Build Coastguard Worker
561*7c356e86SAndroid Build Coastguard Worker #define IS_WORDC(c) (!ctype(c, C_EDNWC))
562*7c356e86SAndroid Build Coastguard Worker
563*7c356e86SAndroid Build Coastguard Worker static int
x_locate_word(const char * buf,int buflen,int pos,int * startp,bool * is_commandp)564*7c356e86SAndroid Build Coastguard Worker x_locate_word(const char *buf, int buflen, int pos, int *startp,
565*7c356e86SAndroid Build Coastguard Worker bool *is_commandp)
566*7c356e86SAndroid Build Coastguard Worker {
567*7c356e86SAndroid Build Coastguard Worker int start, end;
568*7c356e86SAndroid Build Coastguard Worker
569*7c356e86SAndroid Build Coastguard Worker /* Bad call? Probably should report error */
570*7c356e86SAndroid Build Coastguard Worker if (pos < 0 || pos > buflen) {
571*7c356e86SAndroid Build Coastguard Worker *startp = pos;
572*7c356e86SAndroid Build Coastguard Worker *is_commandp = false;
573*7c356e86SAndroid Build Coastguard Worker return (0);
574*7c356e86SAndroid Build Coastguard Worker }
575*7c356e86SAndroid Build Coastguard Worker /* The case where pos == buflen happens to take care of itself... */
576*7c356e86SAndroid Build Coastguard Worker
577*7c356e86SAndroid Build Coastguard Worker start = pos;
578*7c356e86SAndroid Build Coastguard Worker /*
579*7c356e86SAndroid Build Coastguard Worker * Keep going backwards to start of word (has effect of allowing
580*7c356e86SAndroid Build Coastguard Worker * one blank after the end of a word)
581*7c356e86SAndroid Build Coastguard Worker */
582*7c356e86SAndroid Build Coastguard Worker for (; (start > 0 && IS_WORDC(buf[start - 1])) ||
583*7c356e86SAndroid Build Coastguard Worker (start > 1 && buf[start - 2] == '\\'); start--)
584*7c356e86SAndroid Build Coastguard Worker ;
585*7c356e86SAndroid Build Coastguard Worker /* Go forwards to end of word */
586*7c356e86SAndroid Build Coastguard Worker for (end = start; end < buflen && IS_WORDC(buf[end]); end++) {
587*7c356e86SAndroid Build Coastguard Worker if (buf[end] == '\\' && (end + 1) < buflen)
588*7c356e86SAndroid Build Coastguard Worker end++;
589*7c356e86SAndroid Build Coastguard Worker }
590*7c356e86SAndroid Build Coastguard Worker
591*7c356e86SAndroid Build Coastguard Worker if (is_commandp) {
592*7c356e86SAndroid Build Coastguard Worker bool iscmd;
593*7c356e86SAndroid Build Coastguard Worker int p = start - 1;
594*7c356e86SAndroid Build Coastguard Worker
595*7c356e86SAndroid Build Coastguard Worker /* Figure out if this is a command */
596*7c356e86SAndroid Build Coastguard Worker while (p >= 0 && ctype(buf[p], C_SPACE))
597*7c356e86SAndroid Build Coastguard Worker p--;
598*7c356e86SAndroid Build Coastguard Worker iscmd = p < 0 || ctype(buf[p], C_EDCMD);
599*7c356e86SAndroid Build Coastguard Worker if (iscmd) {
600*7c356e86SAndroid Build Coastguard Worker /*
601*7c356e86SAndroid Build Coastguard Worker * If command has a /, path, etc. is not searched;
602*7c356e86SAndroid Build Coastguard Worker * only current directory is searched which is just
603*7c356e86SAndroid Build Coastguard Worker * like file globbing.
604*7c356e86SAndroid Build Coastguard Worker */
605*7c356e86SAndroid Build Coastguard Worker for (p = start; p < end; p++)
606*7c356e86SAndroid Build Coastguard Worker if (mksh_cdirsep(buf[p]))
607*7c356e86SAndroid Build Coastguard Worker break;
608*7c356e86SAndroid Build Coastguard Worker iscmd = p == end;
609*7c356e86SAndroid Build Coastguard Worker }
610*7c356e86SAndroid Build Coastguard Worker *is_commandp = iscmd;
611*7c356e86SAndroid Build Coastguard Worker }
612*7c356e86SAndroid Build Coastguard Worker *startp = start;
613*7c356e86SAndroid Build Coastguard Worker
614*7c356e86SAndroid Build Coastguard Worker return (end - start);
615*7c356e86SAndroid Build Coastguard Worker }
616*7c356e86SAndroid Build Coastguard Worker
617*7c356e86SAndroid Build Coastguard Worker static int
x_cf_glob(int * flagsp,const char * buf,int buflen,int pos,int * startp,int * endp,char *** wordsp)618*7c356e86SAndroid Build Coastguard Worker x_cf_glob(int *flagsp, const char *buf, int buflen, int pos, int *startp,
619*7c356e86SAndroid Build Coastguard Worker int *endp, char ***wordsp)
620*7c356e86SAndroid Build Coastguard Worker {
621*7c356e86SAndroid Build Coastguard Worker int len, nwords = 0;
622*7c356e86SAndroid Build Coastguard Worker char **words = NULL;
623*7c356e86SAndroid Build Coastguard Worker bool is_command;
624*7c356e86SAndroid Build Coastguard Worker
625*7c356e86SAndroid Build Coastguard Worker len = x_locate_word(buf, buflen, pos, startp, &is_command);
626*7c356e86SAndroid Build Coastguard Worker if (!((*flagsp) & XCF_COMMAND))
627*7c356e86SAndroid Build Coastguard Worker is_command = false;
628*7c356e86SAndroid Build Coastguard Worker /*
629*7c356e86SAndroid Build Coastguard Worker * Don't do command globing on zero length strings - it takes too
630*7c356e86SAndroid Build Coastguard Worker * long and isn't very useful. File globs are more likely to be
631*7c356e86SAndroid Build Coastguard Worker * useful, so allow these.
632*7c356e86SAndroid Build Coastguard Worker */
633*7c356e86SAndroid Build Coastguard Worker if (len == 0 && is_command)
634*7c356e86SAndroid Build Coastguard Worker return (0);
635*7c356e86SAndroid Build Coastguard Worker
636*7c356e86SAndroid Build Coastguard Worker if (len >= 0) {
637*7c356e86SAndroid Build Coastguard Worker char *toglob, *s;
638*7c356e86SAndroid Build Coastguard Worker
639*7c356e86SAndroid Build Coastguard Worker /*
640*7c356e86SAndroid Build Coastguard Worker * Given a string, copy it and possibly add a '*' to the end.
641*7c356e86SAndroid Build Coastguard Worker */
642*7c356e86SAndroid Build Coastguard Worker
643*7c356e86SAndroid Build Coastguard Worker strndupx(toglob, buf + *startp, len + /* the '*' */ 1, ATEMP);
644*7c356e86SAndroid Build Coastguard Worker toglob[len] = '\0';
645*7c356e86SAndroid Build Coastguard Worker
646*7c356e86SAndroid Build Coastguard Worker /*
647*7c356e86SAndroid Build Coastguard Worker * If the pathname contains a wildcard (an unquoted '*',
648*7c356e86SAndroid Build Coastguard Worker * '?', or '[') or an extglob, then it is globbed based
649*7c356e86SAndroid Build Coastguard Worker * on that value (i.e., without the appended '*'). Same
650*7c356e86SAndroid Build Coastguard Worker * for parameter substitutions (as in “cat $HOME/.ss↹”)
651*7c356e86SAndroid Build Coastguard Worker * without appending a trailing space (LP: #710539), as
652*7c356e86SAndroid Build Coastguard Worker * well as for “~foo” (but not “~foo/”).
653*7c356e86SAndroid Build Coastguard Worker */
654*7c356e86SAndroid Build Coastguard Worker for (s = toglob; *s; s++) {
655*7c356e86SAndroid Build Coastguard Worker if (*s == '\\' && s[1])
656*7c356e86SAndroid Build Coastguard Worker s++;
657*7c356e86SAndroid Build Coastguard Worker else if (ctype(*s, C_QUEST | C_DOLAR) ||
658*7c356e86SAndroid Build Coastguard Worker ord(*s) == ORD('*') || ord(*s) == ORD('[') ||
659*7c356e86SAndroid Build Coastguard Worker /* ?() *() +() @() !() but two already checked */
660*7c356e86SAndroid Build Coastguard Worker (ord(s[1]) == ORD('(' /*)*/) &&
661*7c356e86SAndroid Build Coastguard Worker (ord(*s) == ORD('+') || ord(*s) == ORD('@') ||
662*7c356e86SAndroid Build Coastguard Worker ord(*s) == ORD('!')))) {
663*7c356e86SAndroid Build Coastguard Worker /*
664*7c356e86SAndroid Build Coastguard Worker * just expand based on the extglob
665*7c356e86SAndroid Build Coastguard Worker * or parameter
666*7c356e86SAndroid Build Coastguard Worker */
667*7c356e86SAndroid Build Coastguard Worker goto dont_add_glob;
668*7c356e86SAndroid Build Coastguard Worker }
669*7c356e86SAndroid Build Coastguard Worker }
670*7c356e86SAndroid Build Coastguard Worker
671*7c356e86SAndroid Build Coastguard Worker if (*toglob == '~' && /* not vdirsep */ !vstrchr(toglob, '/')) {
672*7c356e86SAndroid Build Coastguard Worker /* neither for '~foo' (but '~foo/bar') */
673*7c356e86SAndroid Build Coastguard Worker *flagsp |= XCF_IS_NOSPACE;
674*7c356e86SAndroid Build Coastguard Worker goto dont_add_glob;
675*7c356e86SAndroid Build Coastguard Worker }
676*7c356e86SAndroid Build Coastguard Worker
677*7c356e86SAndroid Build Coastguard Worker /* append a glob */
678*7c356e86SAndroid Build Coastguard Worker toglob[len] = '*';
679*7c356e86SAndroid Build Coastguard Worker toglob[len + 1] = '\0';
680*7c356e86SAndroid Build Coastguard Worker dont_add_glob:
681*7c356e86SAndroid Build Coastguard Worker /*
682*7c356e86SAndroid Build Coastguard Worker * Expand (glob) it now.
683*7c356e86SAndroid Build Coastguard Worker */
684*7c356e86SAndroid Build Coastguard Worker
685*7c356e86SAndroid Build Coastguard Worker nwords = is_command ?
686*7c356e86SAndroid Build Coastguard Worker x_command_glob(*flagsp, toglob, &words) :
687*7c356e86SAndroid Build Coastguard Worker x_file_glob(flagsp, toglob, &words);
688*7c356e86SAndroid Build Coastguard Worker afree(toglob, ATEMP);
689*7c356e86SAndroid Build Coastguard Worker }
690*7c356e86SAndroid Build Coastguard Worker if (nwords == 0) {
691*7c356e86SAndroid Build Coastguard Worker *wordsp = NULL;
692*7c356e86SAndroid Build Coastguard Worker return (0);
693*7c356e86SAndroid Build Coastguard Worker }
694*7c356e86SAndroid Build Coastguard Worker if (is_command)
695*7c356e86SAndroid Build Coastguard Worker *flagsp |= XCF_IS_COMMAND;
696*7c356e86SAndroid Build Coastguard Worker *wordsp = words;
697*7c356e86SAndroid Build Coastguard Worker *endp = *startp + len;
698*7c356e86SAndroid Build Coastguard Worker
699*7c356e86SAndroid Build Coastguard Worker return (nwords);
700*7c356e86SAndroid Build Coastguard Worker }
701*7c356e86SAndroid Build Coastguard Worker
702*7c356e86SAndroid Build Coastguard Worker /*
703*7c356e86SAndroid Build Coastguard Worker * Find longest common prefix
704*7c356e86SAndroid Build Coastguard Worker */
705*7c356e86SAndroid Build Coastguard Worker static size_t
x_longest_prefix(int nwords,char * const * words)706*7c356e86SAndroid Build Coastguard Worker x_longest_prefix(int nwords, char * const * words)
707*7c356e86SAndroid Build Coastguard Worker {
708*7c356e86SAndroid Build Coastguard Worker int i;
709*7c356e86SAndroid Build Coastguard Worker size_t j, prefix_len;
710*7c356e86SAndroid Build Coastguard Worker char *p;
711*7c356e86SAndroid Build Coastguard Worker
712*7c356e86SAndroid Build Coastguard Worker if (nwords <= 0)
713*7c356e86SAndroid Build Coastguard Worker return (0);
714*7c356e86SAndroid Build Coastguard Worker
715*7c356e86SAndroid Build Coastguard Worker prefix_len = strlen(words[0]);
716*7c356e86SAndroid Build Coastguard Worker for (i = 1; i < nwords; i++)
717*7c356e86SAndroid Build Coastguard Worker for (j = 0, p = words[i]; j < prefix_len; j++)
718*7c356e86SAndroid Build Coastguard Worker if (p[j] != words[0][j]) {
719*7c356e86SAndroid Build Coastguard Worker prefix_len = j;
720*7c356e86SAndroid Build Coastguard Worker break;
721*7c356e86SAndroid Build Coastguard Worker }
722*7c356e86SAndroid Build Coastguard Worker /* false for nwords==1 as 0 = words[0][prefix_len] then */
723*7c356e86SAndroid Build Coastguard Worker if (UTFMODE && prefix_len && (rtt2asc(words[0][prefix_len]) & 0xC0) == 0x80)
724*7c356e86SAndroid Build Coastguard Worker while (prefix_len && (rtt2asc(words[0][prefix_len]) & 0xC0) != 0xC0)
725*7c356e86SAndroid Build Coastguard Worker --prefix_len;
726*7c356e86SAndroid Build Coastguard Worker return (prefix_len);
727*7c356e86SAndroid Build Coastguard Worker }
728*7c356e86SAndroid Build Coastguard Worker
729*7c356e86SAndroid Build Coastguard Worker static void
x_free_words(int nwords,char ** words)730*7c356e86SAndroid Build Coastguard Worker x_free_words(int nwords, char **words)
731*7c356e86SAndroid Build Coastguard Worker {
732*7c356e86SAndroid Build Coastguard Worker while (nwords)
733*7c356e86SAndroid Build Coastguard Worker afree(words[--nwords], ATEMP);
734*7c356e86SAndroid Build Coastguard Worker afree(words, ATEMP);
735*7c356e86SAndroid Build Coastguard Worker }
736*7c356e86SAndroid Build Coastguard Worker
737*7c356e86SAndroid Build Coastguard Worker /*-
738*7c356e86SAndroid Build Coastguard Worker * Return the offset of the basename of string s (which ends at se - need not
739*7c356e86SAndroid Build Coastguard Worker * be null terminated). Trailing slashes are ignored. If s is just a slash,
740*7c356e86SAndroid Build Coastguard Worker * then the offset is 0 (actually, length - 1).
741*7c356e86SAndroid Build Coastguard Worker * s Return
742*7c356e86SAndroid Build Coastguard Worker * /etc 1
743*7c356e86SAndroid Build Coastguard Worker * /etc/ 1
744*7c356e86SAndroid Build Coastguard Worker * /etc// 1
745*7c356e86SAndroid Build Coastguard Worker * /etc/fo 5
746*7c356e86SAndroid Build Coastguard Worker * foo 0
747*7c356e86SAndroid Build Coastguard Worker * /// 2
748*7c356e86SAndroid Build Coastguard Worker * 0
749*7c356e86SAndroid Build Coastguard Worker */
750*7c356e86SAndroid Build Coastguard Worker static size_t
x_basename(const char * s,const char * se)751*7c356e86SAndroid Build Coastguard Worker x_basename(const char *s, const char *se)
752*7c356e86SAndroid Build Coastguard Worker {
753*7c356e86SAndroid Build Coastguard Worker const char *p;
754*7c356e86SAndroid Build Coastguard Worker
755*7c356e86SAndroid Build Coastguard Worker if (se == NULL)
756*7c356e86SAndroid Build Coastguard Worker se = strnul(s);
757*7c356e86SAndroid Build Coastguard Worker if (s == se)
758*7c356e86SAndroid Build Coastguard Worker return (0);
759*7c356e86SAndroid Build Coastguard Worker
760*7c356e86SAndroid Build Coastguard Worker /* skip trailing directory separators */
761*7c356e86SAndroid Build Coastguard Worker p = se - 1;
762*7c356e86SAndroid Build Coastguard Worker while (p > s && mksh_cdirsep(*p))
763*7c356e86SAndroid Build Coastguard Worker --p;
764*7c356e86SAndroid Build Coastguard Worker /* drop last component */
765*7c356e86SAndroid Build Coastguard Worker while (p > s && !mksh_cdirsep(*p))
766*7c356e86SAndroid Build Coastguard Worker --p;
767*7c356e86SAndroid Build Coastguard Worker if (mksh_cdirsep(*p) && p + 1 < se)
768*7c356e86SAndroid Build Coastguard Worker ++p;
769*7c356e86SAndroid Build Coastguard Worker
770*7c356e86SAndroid Build Coastguard Worker return (p - s);
771*7c356e86SAndroid Build Coastguard Worker }
772*7c356e86SAndroid Build Coastguard Worker
773*7c356e86SAndroid Build Coastguard Worker /*
774*7c356e86SAndroid Build Coastguard Worker * Apply pattern matching to a table: all table entries that match a pattern
775*7c356e86SAndroid Build Coastguard Worker * are added to wp.
776*7c356e86SAndroid Build Coastguard Worker */
777*7c356e86SAndroid Build Coastguard Worker static void
glob_table(const char * pat,XPtrV * wp,struct table * tp)778*7c356e86SAndroid Build Coastguard Worker glob_table(const char *pat, XPtrV *wp, struct table *tp)
779*7c356e86SAndroid Build Coastguard Worker {
780*7c356e86SAndroid Build Coastguard Worker struct tstate ts;
781*7c356e86SAndroid Build Coastguard Worker struct tbl *te;
782*7c356e86SAndroid Build Coastguard Worker
783*7c356e86SAndroid Build Coastguard Worker ktwalk(&ts, tp);
784*7c356e86SAndroid Build Coastguard Worker while ((te = ktnext(&ts)))
785*7c356e86SAndroid Build Coastguard Worker if (gmatchx(te->name, pat, false)) {
786*7c356e86SAndroid Build Coastguard Worker char *cp;
787*7c356e86SAndroid Build Coastguard Worker
788*7c356e86SAndroid Build Coastguard Worker strdupx(cp, te->name, ATEMP);
789*7c356e86SAndroid Build Coastguard Worker XPput(*wp, cp);
790*7c356e86SAndroid Build Coastguard Worker }
791*7c356e86SAndroid Build Coastguard Worker }
792*7c356e86SAndroid Build Coastguard Worker
793*7c356e86SAndroid Build Coastguard Worker static void
glob_path(int flags,const char * pat,XPtrV * wp,const char * lpath)794*7c356e86SAndroid Build Coastguard Worker glob_path(int flags, const char *pat, XPtrV *wp, const char *lpath)
795*7c356e86SAndroid Build Coastguard Worker {
796*7c356e86SAndroid Build Coastguard Worker const char *sp = lpath, *p;
797*7c356e86SAndroid Build Coastguard Worker char *xp, **words;
798*7c356e86SAndroid Build Coastguard Worker size_t pathlen, patlen, oldsize, newsize, i, j;
799*7c356e86SAndroid Build Coastguard Worker XString xs;
800*7c356e86SAndroid Build Coastguard Worker
801*7c356e86SAndroid Build Coastguard Worker patlen = strlen(pat);
802*7c356e86SAndroid Build Coastguard Worker checkoktoadd(patlen, 129 + X_EXTRA);
803*7c356e86SAndroid Build Coastguard Worker ++patlen;
804*7c356e86SAndroid Build Coastguard Worker Xinit(xs, xp, patlen + 128, ATEMP);
805*7c356e86SAndroid Build Coastguard Worker while (sp) {
806*7c356e86SAndroid Build Coastguard Worker xp = Xstring(xs, xp);
807*7c356e86SAndroid Build Coastguard Worker if (!(p = cstrchr(sp, MKSH_PATHSEPC)))
808*7c356e86SAndroid Build Coastguard Worker p = strnul(sp);
809*7c356e86SAndroid Build Coastguard Worker pathlen = p - sp;
810*7c356e86SAndroid Build Coastguard Worker if (pathlen) {
811*7c356e86SAndroid Build Coastguard Worker /*
812*7c356e86SAndroid Build Coastguard Worker * Copy sp into xp, stuffing any MAGIC characters
813*7c356e86SAndroid Build Coastguard Worker * on the way
814*7c356e86SAndroid Build Coastguard Worker */
815*7c356e86SAndroid Build Coastguard Worker const char *s = sp;
816*7c356e86SAndroid Build Coastguard Worker
817*7c356e86SAndroid Build Coastguard Worker XcheckN(xs, xp, pathlen * 2);
818*7c356e86SAndroid Build Coastguard Worker while (s < p) {
819*7c356e86SAndroid Build Coastguard Worker if (ISMAGIC(*s))
820*7c356e86SAndroid Build Coastguard Worker *xp++ = MAGIC;
821*7c356e86SAndroid Build Coastguard Worker *xp++ = *s++;
822*7c356e86SAndroid Build Coastguard Worker }
823*7c356e86SAndroid Build Coastguard Worker *xp++ = '/';
824*7c356e86SAndroid Build Coastguard Worker pathlen++;
825*7c356e86SAndroid Build Coastguard Worker }
826*7c356e86SAndroid Build Coastguard Worker sp = p;
827*7c356e86SAndroid Build Coastguard Worker XcheckN(xs, xp, patlen);
828*7c356e86SAndroid Build Coastguard Worker memcpy(xp, pat, patlen);
829*7c356e86SAndroid Build Coastguard Worker
830*7c356e86SAndroid Build Coastguard Worker oldsize = XPsize(*wp);
831*7c356e86SAndroid Build Coastguard Worker /* mark dirs */
832*7c356e86SAndroid Build Coastguard Worker glob_str(Xstring(xs, xp), wp, true);
833*7c356e86SAndroid Build Coastguard Worker newsize = XPsize(*wp);
834*7c356e86SAndroid Build Coastguard Worker
835*7c356e86SAndroid Build Coastguard Worker /* Check that each match is executable... */
836*7c356e86SAndroid Build Coastguard Worker words = (char **)XPptrv(*wp);
837*7c356e86SAndroid Build Coastguard Worker for (i = j = oldsize; i < newsize; i++) {
838*7c356e86SAndroid Build Coastguard Worker if (ksh_access(words[i], X_OK) == 0) {
839*7c356e86SAndroid Build Coastguard Worker words[j] = words[i];
840*7c356e86SAndroid Build Coastguard Worker if (!(flags & XCF_FULLPATH))
841*7c356e86SAndroid Build Coastguard Worker memmove(words[j], words[j] + pathlen,
842*7c356e86SAndroid Build Coastguard Worker strlen(words[j] + pathlen) + 1);
843*7c356e86SAndroid Build Coastguard Worker j++;
844*7c356e86SAndroid Build Coastguard Worker } else
845*7c356e86SAndroid Build Coastguard Worker afree(words[i], ATEMP);
846*7c356e86SAndroid Build Coastguard Worker }
847*7c356e86SAndroid Build Coastguard Worker wp->len = j;
848*7c356e86SAndroid Build Coastguard Worker
849*7c356e86SAndroid Build Coastguard Worker if (!*sp++)
850*7c356e86SAndroid Build Coastguard Worker break;
851*7c356e86SAndroid Build Coastguard Worker }
852*7c356e86SAndroid Build Coastguard Worker Xfree(xs, xp);
853*7c356e86SAndroid Build Coastguard Worker }
854*7c356e86SAndroid Build Coastguard Worker
855*7c356e86SAndroid Build Coastguard Worker /*
856*7c356e86SAndroid Build Coastguard Worker * if argument string contains any special characters, they will
857*7c356e86SAndroid Build Coastguard Worker * be escaped and the result will be put into edit buffer by
858*7c356e86SAndroid Build Coastguard Worker * keybinding-specific function
859*7c356e86SAndroid Build Coastguard Worker */
860*7c356e86SAndroid Build Coastguard Worker static int
x_escape(const char * s,size_t len,int (* putbuf_func)(const char *,size_t))861*7c356e86SAndroid Build Coastguard Worker x_escape(const char *s, size_t len, int (*putbuf_func)(const char *, size_t))
862*7c356e86SAndroid Build Coastguard Worker {
863*7c356e86SAndroid Build Coastguard Worker size_t add = 0, wlen = len;
864*7c356e86SAndroid Build Coastguard Worker int rval = 0;
865*7c356e86SAndroid Build Coastguard Worker
866*7c356e86SAndroid Build Coastguard Worker while (wlen - add > 0)
867*7c356e86SAndroid Build Coastguard Worker if (ctype(s[add], C_IFS | C_EDQ)) {
868*7c356e86SAndroid Build Coastguard Worker if (putbuf_func(s, add) != 0) {
869*7c356e86SAndroid Build Coastguard Worker rval = -1;
870*7c356e86SAndroid Build Coastguard Worker break;
871*7c356e86SAndroid Build Coastguard Worker }
872*7c356e86SAndroid Build Coastguard Worker putbuf_func(s[add] == '\n' ? "'" : "\\", 1);
873*7c356e86SAndroid Build Coastguard Worker putbuf_func(&s[add], 1);
874*7c356e86SAndroid Build Coastguard Worker if (s[add] == '\n')
875*7c356e86SAndroid Build Coastguard Worker putbuf_func("'", 1);
876*7c356e86SAndroid Build Coastguard Worker
877*7c356e86SAndroid Build Coastguard Worker add++;
878*7c356e86SAndroid Build Coastguard Worker wlen -= add;
879*7c356e86SAndroid Build Coastguard Worker s += add;
880*7c356e86SAndroid Build Coastguard Worker add = 0;
881*7c356e86SAndroid Build Coastguard Worker } else
882*7c356e86SAndroid Build Coastguard Worker ++add;
883*7c356e86SAndroid Build Coastguard Worker if (wlen > 0 && rval == 0)
884*7c356e86SAndroid Build Coastguard Worker rval = putbuf_func(s, wlen);
885*7c356e86SAndroid Build Coastguard Worker
886*7c356e86SAndroid Build Coastguard Worker return (rval);
887*7c356e86SAndroid Build Coastguard Worker }
888*7c356e86SAndroid Build Coastguard Worker
889*7c356e86SAndroid Build Coastguard Worker
890*7c356e86SAndroid Build Coastguard Worker /* +++ emacs editing mode +++ */
891*7c356e86SAndroid Build Coastguard Worker
892*7c356e86SAndroid Build Coastguard Worker static Area aedit;
893*7c356e86SAndroid Build Coastguard Worker #define AEDIT &aedit /* area for kill ring and macro defns */
894*7c356e86SAndroid Build Coastguard Worker
895*7c356e86SAndroid Build Coastguard Worker /* values returned by keyboard functions */
896*7c356e86SAndroid Build Coastguard Worker #define KSTD 0
897*7c356e86SAndroid Build Coastguard Worker #define KEOL 1 /* ^M, ^J */
898*7c356e86SAndroid Build Coastguard Worker #define KINTR 2 /* ^G, ^C */
899*7c356e86SAndroid Build Coastguard Worker
900*7c356e86SAndroid Build Coastguard Worker struct x_ftab {
901*7c356e86SAndroid Build Coastguard Worker int (*xf_func)(int c);
902*7c356e86SAndroid Build Coastguard Worker const char *xf_name;
903*7c356e86SAndroid Build Coastguard Worker short xf_flags;
904*7c356e86SAndroid Build Coastguard Worker };
905*7c356e86SAndroid Build Coastguard Worker
906*7c356e86SAndroid Build Coastguard Worker struct x_defbindings {
907*7c356e86SAndroid Build Coastguard Worker unsigned char xdb_func; /* XFUNC_* */
908*7c356e86SAndroid Build Coastguard Worker unsigned char xdb_tab;
909*7c356e86SAndroid Build Coastguard Worker unsigned char xdb_char;
910*7c356e86SAndroid Build Coastguard Worker };
911*7c356e86SAndroid Build Coastguard Worker
912*7c356e86SAndroid Build Coastguard Worker #define XF_ARG 1 /* command takes number prefix */
913*7c356e86SAndroid Build Coastguard Worker #define XF_NOBIND 2 /* not allowed to bind to function */
914*7c356e86SAndroid Build Coastguard Worker #define XF_PREFIX 4 /* function sets prefix */
915*7c356e86SAndroid Build Coastguard Worker
916*7c356e86SAndroid Build Coastguard Worker #define X_NTABS 4 /* normal, meta1, meta2, pc */
917*7c356e86SAndroid Build Coastguard Worker #define X_TABSZ 256 /* size of keydef tables etc */
918*7c356e86SAndroid Build Coastguard Worker
919*7c356e86SAndroid Build Coastguard Worker /*-
920*7c356e86SAndroid Build Coastguard Worker * Arguments for do_complete()
921*7c356e86SAndroid Build Coastguard Worker * 0 = enumerate M-= complete as much as possible and then list
922*7c356e86SAndroid Build Coastguard Worker * 1 = complete M-Esc
923*7c356e86SAndroid Build Coastguard Worker * 2 = list M-?
924*7c356e86SAndroid Build Coastguard Worker */
925*7c356e86SAndroid Build Coastguard Worker typedef enum {
926*7c356e86SAndroid Build Coastguard Worker CT_LIST, /* list the possible completions */
927*7c356e86SAndroid Build Coastguard Worker CT_COMPLETE, /* complete to longest prefix */
928*7c356e86SAndroid Build Coastguard Worker CT_COMPLIST /* complete and then list (if non-exact) */
929*7c356e86SAndroid Build Coastguard Worker } Comp_type;
930*7c356e86SAndroid Build Coastguard Worker
931*7c356e86SAndroid Build Coastguard Worker /*
932*7c356e86SAndroid Build Coastguard Worker * The following are used for my horizontal scrolling stuff
933*7c356e86SAndroid Build Coastguard Worker */
934*7c356e86SAndroid Build Coastguard Worker static char *xbuf; /* beg input buffer */
935*7c356e86SAndroid Build Coastguard Worker static char *xend; /* end input buffer */
936*7c356e86SAndroid Build Coastguard Worker static char *xcp; /* current position */
937*7c356e86SAndroid Build Coastguard Worker static char *xep; /* current end */
938*7c356e86SAndroid Build Coastguard Worker static char *xbp; /* start of visible portion of input buffer */
939*7c356e86SAndroid Build Coastguard Worker static char *xlp; /* last char visible on screen */
940*7c356e86SAndroid Build Coastguard Worker static bool x_adj_ok;
941*7c356e86SAndroid Build Coastguard Worker /*
942*7c356e86SAndroid Build Coastguard Worker * we use x_adj_done so that functions can tell
943*7c356e86SAndroid Build Coastguard Worker * whether x_adjust() has been called while they are active.
944*7c356e86SAndroid Build Coastguard Worker */
945*7c356e86SAndroid Build Coastguard Worker static int x_adj_done; /* is incremented by x_adjust() */
946*7c356e86SAndroid Build Coastguard Worker
947*7c356e86SAndroid Build Coastguard Worker static int x_displen;
948*7c356e86SAndroid Build Coastguard Worker static int x_arg; /* general purpose arg */
949*7c356e86SAndroid Build Coastguard Worker static bool x_arg_defaulted; /* x_arg not explicitly set; defaulted to 1 */
950*7c356e86SAndroid Build Coastguard Worker
951*7c356e86SAndroid Build Coastguard Worker static bool xlp_valid; /* lastvis pointer was recalculated */
952*7c356e86SAndroid Build Coastguard Worker
953*7c356e86SAndroid Build Coastguard Worker static char **x_histp; /* history position */
954*7c356e86SAndroid Build Coastguard Worker static int x_nextcmd; /* for newline-and-next */
955*7c356e86SAndroid Build Coastguard Worker static char **x_histncp; /* saved x_histp for " */
956*7c356e86SAndroid Build Coastguard Worker static char **x_histmcp; /* saved x_histp for " */
957*7c356e86SAndroid Build Coastguard Worker static char *xmp; /* mark pointer */
958*7c356e86SAndroid Build Coastguard Worker static unsigned char x_last_command;
959*7c356e86SAndroid Build Coastguard Worker static unsigned char (*x_tab)[X_TABSZ]; /* key definition */
960*7c356e86SAndroid Build Coastguard Worker #ifndef MKSH_SMALL
961*7c356e86SAndroid Build Coastguard Worker static char *(*x_atab)[X_TABSZ]; /* macro definitions */
962*7c356e86SAndroid Build Coastguard Worker #endif
963*7c356e86SAndroid Build Coastguard Worker static unsigned char x_bound[(X_TABSZ * X_NTABS + 7) / 8];
964*7c356e86SAndroid Build Coastguard Worker #define KILLSIZE 20
965*7c356e86SAndroid Build Coastguard Worker static char *killstack[KILLSIZE];
966*7c356e86SAndroid Build Coastguard Worker static int killsp, killtp;
967*7c356e86SAndroid Build Coastguard Worker static int x_curprefix;
968*7c356e86SAndroid Build Coastguard Worker #ifndef MKSH_SMALL
969*7c356e86SAndroid Build Coastguard Worker static char *macroptr; /* bind key macro active? */
970*7c356e86SAndroid Build Coastguard Worker #endif
971*7c356e86SAndroid Build Coastguard Worker #if !MKSH_S_NOVI
972*7c356e86SAndroid Build Coastguard Worker static int winwidth; /* width of window */
973*7c356e86SAndroid Build Coastguard Worker static char *wbuf[2]; /* window buffers */
974*7c356e86SAndroid Build Coastguard Worker static int wbuf_len; /* length of window buffers (x_cols - 3) */
975*7c356e86SAndroid Build Coastguard Worker static int win; /* window buffer in use */
976*7c356e86SAndroid Build Coastguard Worker static char morec; /* more character at right of window */
977*7c356e86SAndroid Build Coastguard Worker static int holdlen; /* length of holdbuf */
978*7c356e86SAndroid Build Coastguard Worker #endif
979*7c356e86SAndroid Build Coastguard Worker static int pwidth; /* width of prompt */
980*7c356e86SAndroid Build Coastguard Worker static int prompt_trunc; /* how much of prompt to truncate or -1 */
981*7c356e86SAndroid Build Coastguard Worker static int x_col; /* current column on line */
982*7c356e86SAndroid Build Coastguard Worker
983*7c356e86SAndroid Build Coastguard Worker static int x_ins(const char *);
984*7c356e86SAndroid Build Coastguard Worker static void x_delete(size_t, bool);
985*7c356e86SAndroid Build Coastguard Worker static size_t x_bword(void);
986*7c356e86SAndroid Build Coastguard Worker static size_t x_fword(bool);
987*7c356e86SAndroid Build Coastguard Worker static void x_goto(char *);
988*7c356e86SAndroid Build Coastguard Worker static char *x_bs0(char *, char *) MKSH_A_PURE;
989*7c356e86SAndroid Build Coastguard Worker static void x_bs3(char **);
990*7c356e86SAndroid Build Coastguard Worker static int x_size2(char *, char **);
991*7c356e86SAndroid Build Coastguard Worker static void x_zots(char *);
992*7c356e86SAndroid Build Coastguard Worker static void x_zotc3(char **);
993*7c356e86SAndroid Build Coastguard Worker static void x_vi_zotc(int);
994*7c356e86SAndroid Build Coastguard Worker static void x_load_hist(char **);
995*7c356e86SAndroid Build Coastguard Worker static int x_search(const char *, int, int);
996*7c356e86SAndroid Build Coastguard Worker #ifndef MKSH_SMALL
997*7c356e86SAndroid Build Coastguard Worker static int x_search_dir(int);
998*7c356e86SAndroid Build Coastguard Worker #endif
999*7c356e86SAndroid Build Coastguard Worker static int x_match(const char *, const char *);
1000*7c356e86SAndroid Build Coastguard Worker static void x_redraw(int);
1001*7c356e86SAndroid Build Coastguard Worker static void x_push(size_t);
1002*7c356e86SAndroid Build Coastguard Worker static void x_bind_showone(int, int);
1003*7c356e86SAndroid Build Coastguard Worker static void x_e_ungetc(int);
1004*7c356e86SAndroid Build Coastguard Worker static int x_e_getc(void);
1005*7c356e86SAndroid Build Coastguard Worker static void x_e_putc2(int);
1006*7c356e86SAndroid Build Coastguard Worker static void x_e_putc3(const char **);
1007*7c356e86SAndroid Build Coastguard Worker static void x_e_puts(const char *);
1008*7c356e86SAndroid Build Coastguard Worker #ifndef MKSH_SMALL
1009*7c356e86SAndroid Build Coastguard Worker static int x_fold_case(int);
1010*7c356e86SAndroid Build Coastguard Worker #endif
1011*7c356e86SAndroid Build Coastguard Worker static char *x_lastcp(void);
1012*7c356e86SAndroid Build Coastguard Worker static void x_lastpos(void);
1013*7c356e86SAndroid Build Coastguard Worker static void do_complete(int, Comp_type);
1014*7c356e86SAndroid Build Coastguard Worker static size_t x_nb2nc(size_t) MKSH_A_PURE;
1015*7c356e86SAndroid Build Coastguard Worker
1016*7c356e86SAndroid Build Coastguard Worker static int unget_char = -1;
1017*7c356e86SAndroid Build Coastguard Worker
1018*7c356e86SAndroid Build Coastguard Worker static int x_do_ins(const char *, size_t);
1019*7c356e86SAndroid Build Coastguard Worker static void bind_if_not_bound(int, int, int);
1020*7c356e86SAndroid Build Coastguard Worker
1021*7c356e86SAndroid Build Coastguard Worker enum emacs_funcs {
1022*7c356e86SAndroid Build Coastguard Worker #define EMACSFN_ENUMS
1023*7c356e86SAndroid Build Coastguard Worker #include "emacsfn.h"
1024*7c356e86SAndroid Build Coastguard Worker XFUNC_MAX
1025*7c356e86SAndroid Build Coastguard Worker };
1026*7c356e86SAndroid Build Coastguard Worker
1027*7c356e86SAndroid Build Coastguard Worker #define EMACSFN_DEFNS
1028*7c356e86SAndroid Build Coastguard Worker #include "emacsfn.h"
1029*7c356e86SAndroid Build Coastguard Worker
1030*7c356e86SAndroid Build Coastguard Worker static const struct x_ftab x_ftab[] = {
1031*7c356e86SAndroid Build Coastguard Worker #define EMACSFN_ITEMS
1032*7c356e86SAndroid Build Coastguard Worker #include "emacsfn.h"
1033*7c356e86SAndroid Build Coastguard Worker };
1034*7c356e86SAndroid Build Coastguard Worker
1035*7c356e86SAndroid Build Coastguard Worker static struct x_defbindings const x_defbindings[] = {
1036*7c356e86SAndroid Build Coastguard Worker { XFUNC_del_back, 0, CTRL_QM },
1037*7c356e86SAndroid Build Coastguard Worker { XFUNC_del_bword, 1, CTRL_QM },
1038*7c356e86SAndroid Build Coastguard Worker { XFUNC_eot_del, 0, CTRL_D },
1039*7c356e86SAndroid Build Coastguard Worker { XFUNC_del_back, 0, CTRL_H },
1040*7c356e86SAndroid Build Coastguard Worker { XFUNC_del_bword, 1, CTRL_H },
1041*7c356e86SAndroid Build Coastguard Worker { XFUNC_del_bword, 1, 'h' },
1042*7c356e86SAndroid Build Coastguard Worker { XFUNC_mv_bword, 1, 'b' },
1043*7c356e86SAndroid Build Coastguard Worker { XFUNC_mv_fword, 1, 'f' },
1044*7c356e86SAndroid Build Coastguard Worker { XFUNC_del_fword, 1, 'd' },
1045*7c356e86SAndroid Build Coastguard Worker { XFUNC_mv_back, 0, CTRL_B },
1046*7c356e86SAndroid Build Coastguard Worker { XFUNC_mv_forw, 0, CTRL_F },
1047*7c356e86SAndroid Build Coastguard Worker { XFUNC_search_char_forw, 0, CTRL_BC },
1048*7c356e86SAndroid Build Coastguard Worker { XFUNC_search_char_back, 1, CTRL_BC },
1049*7c356e86SAndroid Build Coastguard Worker { XFUNC_newline, 0, CTRL_M },
1050*7c356e86SAndroid Build Coastguard Worker { XFUNC_newline, 0, CTRL_J },
1051*7c356e86SAndroid Build Coastguard Worker { XFUNC_end_of_text, 0, CTRL_US },
1052*7c356e86SAndroid Build Coastguard Worker { XFUNC_abort, 0, CTRL_G },
1053*7c356e86SAndroid Build Coastguard Worker { XFUNC_prev_com, 0, CTRL_P },
1054*7c356e86SAndroid Build Coastguard Worker { XFUNC_next_com, 0, CTRL_N },
1055*7c356e86SAndroid Build Coastguard Worker { XFUNC_nl_next_com, 0, CTRL_O },
1056*7c356e86SAndroid Build Coastguard Worker { XFUNC_search_hist, 0, CTRL_R },
1057*7c356e86SAndroid Build Coastguard Worker { XFUNC_beg_hist, 1, '<' },
1058*7c356e86SAndroid Build Coastguard Worker { XFUNC_end_hist, 1, '>' },
1059*7c356e86SAndroid Build Coastguard Worker { XFUNC_goto_hist, 1, 'g' },
1060*7c356e86SAndroid Build Coastguard Worker { XFUNC_mv_end, 0, CTRL_E },
1061*7c356e86SAndroid Build Coastguard Worker { XFUNC_mv_beg, 0, CTRL_A },
1062*7c356e86SAndroid Build Coastguard Worker { XFUNC_draw_line, 0, CTRL_L },
1063*7c356e86SAndroid Build Coastguard Worker { XFUNC_cls, 1, CTRL_L },
1064*7c356e86SAndroid Build Coastguard Worker { XFUNC_meta1, 0, CTRL_BO },
1065*7c356e86SAndroid Build Coastguard Worker { XFUNC_meta2, 0, CTRL_X },
1066*7c356e86SAndroid Build Coastguard Worker { XFUNC_kill, 0, CTRL_K },
1067*7c356e86SAndroid Build Coastguard Worker { XFUNC_yank, 0, CTRL_Y },
1068*7c356e86SAndroid Build Coastguard Worker { XFUNC_meta_yank, 1, 'y' },
1069*7c356e86SAndroid Build Coastguard Worker { XFUNC_literal, 0, CTRL_CA },
1070*7c356e86SAndroid Build Coastguard Worker { XFUNC_comment, 1, '#' },
1071*7c356e86SAndroid Build Coastguard Worker { XFUNC_transpose, 0, CTRL_T },
1072*7c356e86SAndroid Build Coastguard Worker { XFUNC_complete, 1, CTRL_BO },
1073*7c356e86SAndroid Build Coastguard Worker { XFUNC_comp_list, 0, CTRL_I },
1074*7c356e86SAndroid Build Coastguard Worker { XFUNC_comp_list, 1, '=' },
1075*7c356e86SAndroid Build Coastguard Worker { XFUNC_enumerate, 1, '?' },
1076*7c356e86SAndroid Build Coastguard Worker { XFUNC_expand, 1, '*' },
1077*7c356e86SAndroid Build Coastguard Worker { XFUNC_comp_file, 1, CTRL_X },
1078*7c356e86SAndroid Build Coastguard Worker { XFUNC_comp_comm, 2, CTRL_BO },
1079*7c356e86SAndroid Build Coastguard Worker { XFUNC_list_comm, 2, '?' },
1080*7c356e86SAndroid Build Coastguard Worker { XFUNC_list_file, 2, CTRL_Y },
1081*7c356e86SAndroid Build Coastguard Worker { XFUNC_set_mark, 1, ' ' },
1082*7c356e86SAndroid Build Coastguard Worker { XFUNC_kill_region, 0, CTRL_W },
1083*7c356e86SAndroid Build Coastguard Worker { XFUNC_xchg_point_mark, 2, CTRL_X },
1084*7c356e86SAndroid Build Coastguard Worker { XFUNC_literal, 0, CTRL_V },
1085*7c356e86SAndroid Build Coastguard Worker { XFUNC_version, 1, CTRL_V },
1086*7c356e86SAndroid Build Coastguard Worker { XFUNC_prev_histword, 1, '.' },
1087*7c356e86SAndroid Build Coastguard Worker { XFUNC_prev_histword, 1, '_' },
1088*7c356e86SAndroid Build Coastguard Worker { XFUNC_set_arg, 1, '0' },
1089*7c356e86SAndroid Build Coastguard Worker { XFUNC_set_arg, 1, '1' },
1090*7c356e86SAndroid Build Coastguard Worker { XFUNC_set_arg, 1, '2' },
1091*7c356e86SAndroid Build Coastguard Worker { XFUNC_set_arg, 1, '3' },
1092*7c356e86SAndroid Build Coastguard Worker { XFUNC_set_arg, 1, '4' },
1093*7c356e86SAndroid Build Coastguard Worker { XFUNC_set_arg, 1, '5' },
1094*7c356e86SAndroid Build Coastguard Worker { XFUNC_set_arg, 1, '6' },
1095*7c356e86SAndroid Build Coastguard Worker { XFUNC_set_arg, 1, '7' },
1096*7c356e86SAndroid Build Coastguard Worker { XFUNC_set_arg, 1, '8' },
1097*7c356e86SAndroid Build Coastguard Worker { XFUNC_set_arg, 1, '9' },
1098*7c356e86SAndroid Build Coastguard Worker #ifndef MKSH_SMALL
1099*7c356e86SAndroid Build Coastguard Worker { XFUNC_fold_upper, 1, 'U' },
1100*7c356e86SAndroid Build Coastguard Worker { XFUNC_fold_upper, 1, 'u' },
1101*7c356e86SAndroid Build Coastguard Worker { XFUNC_fold_lower, 1, 'L' },
1102*7c356e86SAndroid Build Coastguard Worker { XFUNC_fold_lower, 1, 'l' },
1103*7c356e86SAndroid Build Coastguard Worker { XFUNC_fold_capitalise, 1, 'C' },
1104*7c356e86SAndroid Build Coastguard Worker { XFUNC_fold_capitalise, 1, 'c' },
1105*7c356e86SAndroid Build Coastguard Worker #endif
1106*7c356e86SAndroid Build Coastguard Worker /*
1107*7c356e86SAndroid Build Coastguard Worker * These for ANSI arrow keys: arguablely shouldn't be here by
1108*7c356e86SAndroid Build Coastguard Worker * default, but its simpler/faster/smaller than using termcap
1109*7c356e86SAndroid Build Coastguard Worker * entries.
1110*7c356e86SAndroid Build Coastguard Worker */
1111*7c356e86SAndroid Build Coastguard Worker { XFUNC_meta2, 1, '[' },
1112*7c356e86SAndroid Build Coastguard Worker { XFUNC_meta2, 1, 'O' },
1113*7c356e86SAndroid Build Coastguard Worker { XFUNC_prev_com, 2, 'A' },
1114*7c356e86SAndroid Build Coastguard Worker { XFUNC_next_com, 2, 'B' },
1115*7c356e86SAndroid Build Coastguard Worker { XFUNC_mv_forw, 2, 'C' },
1116*7c356e86SAndroid Build Coastguard Worker { XFUNC_mv_back, 2, 'D' },
1117*7c356e86SAndroid Build Coastguard Worker #ifndef MKSH_SMALL
1118*7c356e86SAndroid Build Coastguard Worker { XFUNC_vt_hack, 2, '1' },
1119*7c356e86SAndroid Build Coastguard Worker { XFUNC_mv_beg | 0x80, 2, '7' },
1120*7c356e86SAndroid Build Coastguard Worker { XFUNC_mv_beg, 2, 'H' },
1121*7c356e86SAndroid Build Coastguard Worker { XFUNC_mv_end | 0x80, 2, '4' },
1122*7c356e86SAndroid Build Coastguard Worker { XFUNC_mv_end | 0x80, 2, '8' },
1123*7c356e86SAndroid Build Coastguard Worker { XFUNC_mv_end, 2, 'F' },
1124*7c356e86SAndroid Build Coastguard Worker { XFUNC_del_char | 0x80, 2, '3' },
1125*7c356e86SAndroid Build Coastguard Worker { XFUNC_del_char, 2, 'P' },
1126*7c356e86SAndroid Build Coastguard Worker { XFUNC_search_hist_up | 0x80, 2, '5' },
1127*7c356e86SAndroid Build Coastguard Worker { XFUNC_search_hist_dn | 0x80, 2, '6' },
1128*7c356e86SAndroid Build Coastguard Worker #endif
1129*7c356e86SAndroid Build Coastguard Worker /* PC scancodes */
1130*7c356e86SAndroid Build Coastguard Worker #if !defined(MKSH_SMALL) || defined(__OS2__)
1131*7c356e86SAndroid Build Coastguard Worker { XFUNC_meta3, 0, 0 },
1132*7c356e86SAndroid Build Coastguard Worker { XFUNC_mv_beg, 3, 71 },
1133*7c356e86SAndroid Build Coastguard Worker { XFUNC_prev_com, 3, 72 },
1134*7c356e86SAndroid Build Coastguard Worker #ifndef MKSH_SMALL
1135*7c356e86SAndroid Build Coastguard Worker { XFUNC_search_hist_up, 3, 73 },
1136*7c356e86SAndroid Build Coastguard Worker #endif
1137*7c356e86SAndroid Build Coastguard Worker { XFUNC_mv_back, 3, 75 },
1138*7c356e86SAndroid Build Coastguard Worker { XFUNC_mv_forw, 3, 77 },
1139*7c356e86SAndroid Build Coastguard Worker { XFUNC_mv_end, 3, 79 },
1140*7c356e86SAndroid Build Coastguard Worker { XFUNC_next_com, 3, 80 },
1141*7c356e86SAndroid Build Coastguard Worker #ifndef MKSH_SMALL
1142*7c356e86SAndroid Build Coastguard Worker { XFUNC_search_hist_dn, 3, 81 },
1143*7c356e86SAndroid Build Coastguard Worker #endif
1144*7c356e86SAndroid Build Coastguard Worker { XFUNC_del_char, 3, 83 },
1145*7c356e86SAndroid Build Coastguard Worker #endif
1146*7c356e86SAndroid Build Coastguard Worker #ifndef MKSH_SMALL
1147*7c356e86SAndroid Build Coastguard Worker /* more non-standard ones */
1148*7c356e86SAndroid Build Coastguard Worker { XFUNC_eval_region, 1, CTRL_E },
1149*7c356e86SAndroid Build Coastguard Worker { XFUNC_quote_region, 1, 'Q' },
1150*7c356e86SAndroid Build Coastguard Worker { XFUNC_edit_line, 2, 'e' }
1151*7c356e86SAndroid Build Coastguard Worker #endif
1152*7c356e86SAndroid Build Coastguard Worker };
1153*7c356e86SAndroid Build Coastguard Worker
1154*7c356e86SAndroid Build Coastguard Worker static size_t
x_nb2nc(size_t nb)1155*7c356e86SAndroid Build Coastguard Worker x_nb2nc(size_t nb)
1156*7c356e86SAndroid Build Coastguard Worker {
1157*7c356e86SAndroid Build Coastguard Worker char *cp;
1158*7c356e86SAndroid Build Coastguard Worker size_t nc = 0;
1159*7c356e86SAndroid Build Coastguard Worker
1160*7c356e86SAndroid Build Coastguard Worker for (cp = xcp; cp < (xcp + nb); ++nc)
1161*7c356e86SAndroid Build Coastguard Worker cp += utf_ptradj(cp);
1162*7c356e86SAndroid Build Coastguard Worker return (nc);
1163*7c356e86SAndroid Build Coastguard Worker }
1164*7c356e86SAndroid Build Coastguard Worker
1165*7c356e86SAndroid Build Coastguard Worker static void
x_modified(void)1166*7c356e86SAndroid Build Coastguard Worker x_modified(void)
1167*7c356e86SAndroid Build Coastguard Worker {
1168*7c356e86SAndroid Build Coastguard Worker if (!modified) {
1169*7c356e86SAndroid Build Coastguard Worker x_histmcp = x_histp;
1170*7c356e86SAndroid Build Coastguard Worker x_histp = histptr + 1;
1171*7c356e86SAndroid Build Coastguard Worker modified = 1;
1172*7c356e86SAndroid Build Coastguard Worker }
1173*7c356e86SAndroid Build Coastguard Worker }
1174*7c356e86SAndroid Build Coastguard Worker
1175*7c356e86SAndroid Build Coastguard Worker #ifdef MKSH_SMALL
1176*7c356e86SAndroid Build Coastguard Worker #define XFUNC_VALUE(f) (f)
1177*7c356e86SAndroid Build Coastguard Worker #else
1178*7c356e86SAndroid Build Coastguard Worker #define XFUNC_VALUE(f) (f & 0x7F)
1179*7c356e86SAndroid Build Coastguard Worker #endif
1180*7c356e86SAndroid Build Coastguard Worker
1181*7c356e86SAndroid Build Coastguard Worker static int
x_e_getmbc(char * sbuf)1182*7c356e86SAndroid Build Coastguard Worker x_e_getmbc(char *sbuf)
1183*7c356e86SAndroid Build Coastguard Worker {
1184*7c356e86SAndroid Build Coastguard Worker int c, pos = 0;
1185*7c356e86SAndroid Build Coastguard Worker unsigned char *buf = (unsigned char *)sbuf;
1186*7c356e86SAndroid Build Coastguard Worker
1187*7c356e86SAndroid Build Coastguard Worker memset(buf, 0, 4);
1188*7c356e86SAndroid Build Coastguard Worker buf[pos++] = c = x_e_getc();
1189*7c356e86SAndroid Build Coastguard Worker if (c == -1)
1190*7c356e86SAndroid Build Coastguard Worker return (-1);
1191*7c356e86SAndroid Build Coastguard Worker if (UTFMODE) {
1192*7c356e86SAndroid Build Coastguard Worker if ((rtt2asc(buf[0]) >= (unsigned char)0xC2) &&
1193*7c356e86SAndroid Build Coastguard Worker (rtt2asc(buf[0]) < (unsigned char)0xF0)) {
1194*7c356e86SAndroid Build Coastguard Worker c = x_e_getc();
1195*7c356e86SAndroid Build Coastguard Worker if (c == -1)
1196*7c356e86SAndroid Build Coastguard Worker return (-1);
1197*7c356e86SAndroid Build Coastguard Worker if ((rtt2asc(c) & 0xC0) != 0x80) {
1198*7c356e86SAndroid Build Coastguard Worker x_e_ungetc(c);
1199*7c356e86SAndroid Build Coastguard Worker return (1);
1200*7c356e86SAndroid Build Coastguard Worker }
1201*7c356e86SAndroid Build Coastguard Worker buf[pos++] = c;
1202*7c356e86SAndroid Build Coastguard Worker }
1203*7c356e86SAndroid Build Coastguard Worker if ((rtt2asc(buf[0]) >= (unsigned char)0xE0) &&
1204*7c356e86SAndroid Build Coastguard Worker (rtt2asc(buf[0]) < (unsigned char)0xF0)) {
1205*7c356e86SAndroid Build Coastguard Worker /* XXX x_e_ungetc is one-octet only */
1206*7c356e86SAndroid Build Coastguard Worker buf[pos++] = c = x_e_getc();
1207*7c356e86SAndroid Build Coastguard Worker if (c == -1)
1208*7c356e86SAndroid Build Coastguard Worker return (-1);
1209*7c356e86SAndroid Build Coastguard Worker }
1210*7c356e86SAndroid Build Coastguard Worker }
1211*7c356e86SAndroid Build Coastguard Worker return (pos);
1212*7c356e86SAndroid Build Coastguard Worker }
1213*7c356e86SAndroid Build Coastguard Worker
1214*7c356e86SAndroid Build Coastguard Worker /*
1215*7c356e86SAndroid Build Coastguard Worker * minimum required space to work with on a line - if the prompt
1216*7c356e86SAndroid Build Coastguard Worker * leaves less space than this on a line, the prompt is truncated
1217*7c356e86SAndroid Build Coastguard Worker */
1218*7c356e86SAndroid Build Coastguard Worker #define MIN_EDIT_SPACE 7
1219*7c356e86SAndroid Build Coastguard Worker
1220*7c356e86SAndroid Build Coastguard Worker static void
x_init_prompt(bool doprint)1221*7c356e86SAndroid Build Coastguard Worker x_init_prompt(bool doprint)
1222*7c356e86SAndroid Build Coastguard Worker {
1223*7c356e86SAndroid Build Coastguard Worker prompt_trunc = pprompt(prompt, doprint ? 0 : -1);
1224*7c356e86SAndroid Build Coastguard Worker pwidth = prompt_trunc % x_cols;
1225*7c356e86SAndroid Build Coastguard Worker prompt_trunc -= pwidth;
1226*7c356e86SAndroid Build Coastguard Worker if ((mksh_uari_t)pwidth > ((mksh_uari_t)x_cols - 3 - MIN_EDIT_SPACE)) {
1227*7c356e86SAndroid Build Coastguard Worker /* force newline after prompt */
1228*7c356e86SAndroid Build Coastguard Worker prompt_trunc = -1;
1229*7c356e86SAndroid Build Coastguard Worker pwidth = 0;
1230*7c356e86SAndroid Build Coastguard Worker if (doprint)
1231*7c356e86SAndroid Build Coastguard Worker x_e_putc2('\n');
1232*7c356e86SAndroid Build Coastguard Worker }
1233*7c356e86SAndroid Build Coastguard Worker }
1234*7c356e86SAndroid Build Coastguard Worker
1235*7c356e86SAndroid Build Coastguard Worker static int
x_emacs(char * buf)1236*7c356e86SAndroid Build Coastguard Worker x_emacs(char *buf)
1237*7c356e86SAndroid Build Coastguard Worker {
1238*7c356e86SAndroid Build Coastguard Worker int c, i;
1239*7c356e86SAndroid Build Coastguard Worker unsigned char f;
1240*7c356e86SAndroid Build Coastguard Worker
1241*7c356e86SAndroid Build Coastguard Worker xbp = xbuf = buf;
1242*7c356e86SAndroid Build Coastguard Worker xend = buf + LINE;
1243*7c356e86SAndroid Build Coastguard Worker xlp = xcp = xep = buf;
1244*7c356e86SAndroid Build Coastguard Worker *xcp = 0;
1245*7c356e86SAndroid Build Coastguard Worker xlp_valid = true;
1246*7c356e86SAndroid Build Coastguard Worker xmp = NULL;
1247*7c356e86SAndroid Build Coastguard Worker x_curprefix = 0;
1248*7c356e86SAndroid Build Coastguard Worker x_histmcp = x_histp = histptr + 1;
1249*7c356e86SAndroid Build Coastguard Worker x_last_command = XFUNC_error;
1250*7c356e86SAndroid Build Coastguard Worker
1251*7c356e86SAndroid Build Coastguard Worker x_init_prompt(true);
1252*7c356e86SAndroid Build Coastguard Worker x_displen = (xx_cols = x_cols) - 2 - (x_col = pwidth);
1253*7c356e86SAndroid Build Coastguard Worker x_adj_done = 0;
1254*7c356e86SAndroid Build Coastguard Worker x_adj_ok = true;
1255*7c356e86SAndroid Build Coastguard Worker
1256*7c356e86SAndroid Build Coastguard Worker x_histncp = NULL;
1257*7c356e86SAndroid Build Coastguard Worker if (x_nextcmd >= 0) {
1258*7c356e86SAndroid Build Coastguard Worker int off = source->line - x_nextcmd;
1259*7c356e86SAndroid Build Coastguard Worker if (histptr - history >= off) {
1260*7c356e86SAndroid Build Coastguard Worker x_load_hist(histptr - off);
1261*7c356e86SAndroid Build Coastguard Worker x_histncp = x_histp;
1262*7c356e86SAndroid Build Coastguard Worker }
1263*7c356e86SAndroid Build Coastguard Worker x_nextcmd = -1;
1264*7c356e86SAndroid Build Coastguard Worker }
1265*7c356e86SAndroid Build Coastguard Worker editmode = 1;
1266*7c356e86SAndroid Build Coastguard Worker while (/* CONSTCOND */ 1) {
1267*7c356e86SAndroid Build Coastguard Worker x_flush();
1268*7c356e86SAndroid Build Coastguard Worker if ((c = x_e_getc()) < 0)
1269*7c356e86SAndroid Build Coastguard Worker return (0);
1270*7c356e86SAndroid Build Coastguard Worker
1271*7c356e86SAndroid Build Coastguard Worker f = x_curprefix == -1 ? XFUNC_insert :
1272*7c356e86SAndroid Build Coastguard Worker x_tab[x_curprefix][c];
1273*7c356e86SAndroid Build Coastguard Worker #ifndef MKSH_SMALL
1274*7c356e86SAndroid Build Coastguard Worker if (f & 0x80) {
1275*7c356e86SAndroid Build Coastguard Worker f &= 0x7F;
1276*7c356e86SAndroid Build Coastguard Worker if ((i = x_e_getc()) != '~')
1277*7c356e86SAndroid Build Coastguard Worker x_e_ungetc(i);
1278*7c356e86SAndroid Build Coastguard Worker }
1279*7c356e86SAndroid Build Coastguard Worker
1280*7c356e86SAndroid Build Coastguard Worker /* avoid bind key macro recursion */
1281*7c356e86SAndroid Build Coastguard Worker if (macroptr && f == XFUNC_ins_string)
1282*7c356e86SAndroid Build Coastguard Worker f = XFUNC_insert;
1283*7c356e86SAndroid Build Coastguard Worker #endif
1284*7c356e86SAndroid Build Coastguard Worker
1285*7c356e86SAndroid Build Coastguard Worker if (!(x_ftab[f].xf_flags & XF_PREFIX) &&
1286*7c356e86SAndroid Build Coastguard Worker x_last_command != XFUNC_set_arg) {
1287*7c356e86SAndroid Build Coastguard Worker x_arg = 1;
1288*7c356e86SAndroid Build Coastguard Worker x_arg_defaulted = true;
1289*7c356e86SAndroid Build Coastguard Worker }
1290*7c356e86SAndroid Build Coastguard Worker i = c | (x_curprefix << 8);
1291*7c356e86SAndroid Build Coastguard Worker x_curprefix = 0;
1292*7c356e86SAndroid Build Coastguard Worker switch ((*x_ftab[f].xf_func)(i)) {
1293*7c356e86SAndroid Build Coastguard Worker case KSTD:
1294*7c356e86SAndroid Build Coastguard Worker if (!(x_ftab[f].xf_flags & XF_PREFIX))
1295*7c356e86SAndroid Build Coastguard Worker x_last_command = f;
1296*7c356e86SAndroid Build Coastguard Worker break;
1297*7c356e86SAndroid Build Coastguard Worker case KEOL:
1298*7c356e86SAndroid Build Coastguard Worker i = xep - xbuf;
1299*7c356e86SAndroid Build Coastguard Worker return (i);
1300*7c356e86SAndroid Build Coastguard Worker case KINTR:
1301*7c356e86SAndroid Build Coastguard Worker /* special case for interrupt */
1302*7c356e86SAndroid Build Coastguard Worker x_intr(SIGINT, c);
1303*7c356e86SAndroid Build Coastguard Worker }
1304*7c356e86SAndroid Build Coastguard Worker /* ad-hoc hack for fixing the cursor position */
1305*7c356e86SAndroid Build Coastguard Worker x_goto(xcp);
1306*7c356e86SAndroid Build Coastguard Worker }
1307*7c356e86SAndroid Build Coastguard Worker }
1308*7c356e86SAndroid Build Coastguard Worker
1309*7c356e86SAndroid Build Coastguard Worker static int
x_insert(int c)1310*7c356e86SAndroid Build Coastguard Worker x_insert(int c)
1311*7c356e86SAndroid Build Coastguard Worker {
1312*7c356e86SAndroid Build Coastguard Worker static int left, pos, save_arg;
1313*7c356e86SAndroid Build Coastguard Worker static char str[4];
1314*7c356e86SAndroid Build Coastguard Worker
1315*7c356e86SAndroid Build Coastguard Worker /*
1316*7c356e86SAndroid Build Coastguard Worker * Should allow tab and control chars.
1317*7c356e86SAndroid Build Coastguard Worker */
1318*7c356e86SAndroid Build Coastguard Worker if (c == 0) {
1319*7c356e86SAndroid Build Coastguard Worker invmbs:
1320*7c356e86SAndroid Build Coastguard Worker left = 0;
1321*7c356e86SAndroid Build Coastguard Worker x_e_putc2(KSH_BEL);
1322*7c356e86SAndroid Build Coastguard Worker return (KSTD);
1323*7c356e86SAndroid Build Coastguard Worker }
1324*7c356e86SAndroid Build Coastguard Worker if (UTFMODE) {
1325*7c356e86SAndroid Build Coastguard Worker if (((rtt2asc(c) & 0xC0) == 0x80) && left) {
1326*7c356e86SAndroid Build Coastguard Worker str[pos++] = c;
1327*7c356e86SAndroid Build Coastguard Worker if (!--left) {
1328*7c356e86SAndroid Build Coastguard Worker str[pos] = '\0';
1329*7c356e86SAndroid Build Coastguard Worker x_arg = save_arg;
1330*7c356e86SAndroid Build Coastguard Worker while (x_arg--)
1331*7c356e86SAndroid Build Coastguard Worker x_ins(str);
1332*7c356e86SAndroid Build Coastguard Worker }
1333*7c356e86SAndroid Build Coastguard Worker return (KSTD);
1334*7c356e86SAndroid Build Coastguard Worker }
1335*7c356e86SAndroid Build Coastguard Worker if (left) {
1336*7c356e86SAndroid Build Coastguard Worker if (x_curprefix == -1) {
1337*7c356e86SAndroid Build Coastguard Worker /* flush invalid multibyte */
1338*7c356e86SAndroid Build Coastguard Worker str[pos] = '\0';
1339*7c356e86SAndroid Build Coastguard Worker while (save_arg--)
1340*7c356e86SAndroid Build Coastguard Worker x_ins(str);
1341*7c356e86SAndroid Build Coastguard Worker }
1342*7c356e86SAndroid Build Coastguard Worker }
1343*7c356e86SAndroid Build Coastguard Worker if ((c >= 0xC2) && (c < 0xE0))
1344*7c356e86SAndroid Build Coastguard Worker left = 1;
1345*7c356e86SAndroid Build Coastguard Worker else if ((c >= 0xE0) && (c < 0xF0))
1346*7c356e86SAndroid Build Coastguard Worker left = 2;
1347*7c356e86SAndroid Build Coastguard Worker else if (c > 0x7F)
1348*7c356e86SAndroid Build Coastguard Worker goto invmbs;
1349*7c356e86SAndroid Build Coastguard Worker else
1350*7c356e86SAndroid Build Coastguard Worker left = 0;
1351*7c356e86SAndroid Build Coastguard Worker if (left) {
1352*7c356e86SAndroid Build Coastguard Worker save_arg = x_arg;
1353*7c356e86SAndroid Build Coastguard Worker pos = 1;
1354*7c356e86SAndroid Build Coastguard Worker str[0] = c;
1355*7c356e86SAndroid Build Coastguard Worker return (KSTD);
1356*7c356e86SAndroid Build Coastguard Worker }
1357*7c356e86SAndroid Build Coastguard Worker }
1358*7c356e86SAndroid Build Coastguard Worker left = 0;
1359*7c356e86SAndroid Build Coastguard Worker str[0] = c;
1360*7c356e86SAndroid Build Coastguard Worker str[1] = '\0';
1361*7c356e86SAndroid Build Coastguard Worker while (x_arg--)
1362*7c356e86SAndroid Build Coastguard Worker x_ins(str);
1363*7c356e86SAndroid Build Coastguard Worker return (KSTD);
1364*7c356e86SAndroid Build Coastguard Worker }
1365*7c356e86SAndroid Build Coastguard Worker
1366*7c356e86SAndroid Build Coastguard Worker #ifndef MKSH_SMALL
1367*7c356e86SAndroid Build Coastguard Worker static int
x_ins_string(int c)1368*7c356e86SAndroid Build Coastguard Worker x_ins_string(int c)
1369*7c356e86SAndroid Build Coastguard Worker {
1370*7c356e86SAndroid Build Coastguard Worker macroptr = x_atab[c >> 8][c & 255];
1371*7c356e86SAndroid Build Coastguard Worker /*
1372*7c356e86SAndroid Build Coastguard Worker * we no longer need to bother checking if macroptr is
1373*7c356e86SAndroid Build Coastguard Worker * not NULL but first char is NUL; x_e_getc() does it
1374*7c356e86SAndroid Build Coastguard Worker */
1375*7c356e86SAndroid Build Coastguard Worker return (KSTD);
1376*7c356e86SAndroid Build Coastguard Worker }
1377*7c356e86SAndroid Build Coastguard Worker #endif
1378*7c356e86SAndroid Build Coastguard Worker
1379*7c356e86SAndroid Build Coastguard Worker static int
x_do_ins(const char * cp,size_t len)1380*7c356e86SAndroid Build Coastguard Worker x_do_ins(const char *cp, size_t len)
1381*7c356e86SAndroid Build Coastguard Worker {
1382*7c356e86SAndroid Build Coastguard Worker if (xep + len >= xend) {
1383*7c356e86SAndroid Build Coastguard Worker x_e_putc2(KSH_BEL);
1384*7c356e86SAndroid Build Coastguard Worker return (-1);
1385*7c356e86SAndroid Build Coastguard Worker }
1386*7c356e86SAndroid Build Coastguard Worker memmove(xcp + len, xcp, xep - xcp + 1);
1387*7c356e86SAndroid Build Coastguard Worker memmove(xcp, cp, len);
1388*7c356e86SAndroid Build Coastguard Worker xcp += len;
1389*7c356e86SAndroid Build Coastguard Worker xep += len;
1390*7c356e86SAndroid Build Coastguard Worker x_modified();
1391*7c356e86SAndroid Build Coastguard Worker return (0);
1392*7c356e86SAndroid Build Coastguard Worker }
1393*7c356e86SAndroid Build Coastguard Worker
1394*7c356e86SAndroid Build Coastguard Worker static int
x_ins(const char * s)1395*7c356e86SAndroid Build Coastguard Worker x_ins(const char *s)
1396*7c356e86SAndroid Build Coastguard Worker {
1397*7c356e86SAndroid Build Coastguard Worker char *cp = xcp;
1398*7c356e86SAndroid Build Coastguard Worker int adj = x_adj_done;
1399*7c356e86SAndroid Build Coastguard Worker
1400*7c356e86SAndroid Build Coastguard Worker if (x_do_ins(s, strlen(s)) < 0)
1401*7c356e86SAndroid Build Coastguard Worker return (-1);
1402*7c356e86SAndroid Build Coastguard Worker /*
1403*7c356e86SAndroid Build Coastguard Worker * x_zots() may result in a call to x_adjust()
1404*7c356e86SAndroid Build Coastguard Worker * we want xcp to reflect the new position.
1405*7c356e86SAndroid Build Coastguard Worker */
1406*7c356e86SAndroid Build Coastguard Worker xlp_valid = false;
1407*7c356e86SAndroid Build Coastguard Worker x_lastcp();
1408*7c356e86SAndroid Build Coastguard Worker x_adj_ok = tobool(xcp >= xlp);
1409*7c356e86SAndroid Build Coastguard Worker x_zots(cp);
1410*7c356e86SAndroid Build Coastguard Worker if (adj == x_adj_done)
1411*7c356e86SAndroid Build Coastguard Worker /* x_adjust() has not been called */
1412*7c356e86SAndroid Build Coastguard Worker x_lastpos();
1413*7c356e86SAndroid Build Coastguard Worker x_adj_ok = true;
1414*7c356e86SAndroid Build Coastguard Worker return (0);
1415*7c356e86SAndroid Build Coastguard Worker }
1416*7c356e86SAndroid Build Coastguard Worker
1417*7c356e86SAndroid Build Coastguard Worker static int
x_del_back(int c MKSH_A_UNUSED)1418*7c356e86SAndroid Build Coastguard Worker x_del_back(int c MKSH_A_UNUSED)
1419*7c356e86SAndroid Build Coastguard Worker {
1420*7c356e86SAndroid Build Coastguard Worker ssize_t i = 0;
1421*7c356e86SAndroid Build Coastguard Worker
1422*7c356e86SAndroid Build Coastguard Worker if (xcp == xbuf) {
1423*7c356e86SAndroid Build Coastguard Worker x_e_putc2(KSH_BEL);
1424*7c356e86SAndroid Build Coastguard Worker return (KSTD);
1425*7c356e86SAndroid Build Coastguard Worker }
1426*7c356e86SAndroid Build Coastguard Worker do {
1427*7c356e86SAndroid Build Coastguard Worker x_goto(xcp - 1);
1428*7c356e86SAndroid Build Coastguard Worker } while ((++i < x_arg) && (xcp != xbuf));
1429*7c356e86SAndroid Build Coastguard Worker x_delete(i, false);
1430*7c356e86SAndroid Build Coastguard Worker return (KSTD);
1431*7c356e86SAndroid Build Coastguard Worker }
1432*7c356e86SAndroid Build Coastguard Worker
1433*7c356e86SAndroid Build Coastguard Worker static int
x_del_char(int c MKSH_A_UNUSED)1434*7c356e86SAndroid Build Coastguard Worker x_del_char(int c MKSH_A_UNUSED)
1435*7c356e86SAndroid Build Coastguard Worker {
1436*7c356e86SAndroid Build Coastguard Worker char *cp, *cp2;
1437*7c356e86SAndroid Build Coastguard Worker size_t i = 0;
1438*7c356e86SAndroid Build Coastguard Worker
1439*7c356e86SAndroid Build Coastguard Worker cp = xcp;
1440*7c356e86SAndroid Build Coastguard Worker while (i < (size_t)x_arg) {
1441*7c356e86SAndroid Build Coastguard Worker utf_ptradjx(cp, cp2);
1442*7c356e86SAndroid Build Coastguard Worker if (cp2 > xep)
1443*7c356e86SAndroid Build Coastguard Worker break;
1444*7c356e86SAndroid Build Coastguard Worker cp = cp2;
1445*7c356e86SAndroid Build Coastguard Worker i++;
1446*7c356e86SAndroid Build Coastguard Worker }
1447*7c356e86SAndroid Build Coastguard Worker
1448*7c356e86SAndroid Build Coastguard Worker if (!i) {
1449*7c356e86SAndroid Build Coastguard Worker x_e_putc2(KSH_BEL);
1450*7c356e86SAndroid Build Coastguard Worker return (KSTD);
1451*7c356e86SAndroid Build Coastguard Worker }
1452*7c356e86SAndroid Build Coastguard Worker x_delete(i, false);
1453*7c356e86SAndroid Build Coastguard Worker return (KSTD);
1454*7c356e86SAndroid Build Coastguard Worker }
1455*7c356e86SAndroid Build Coastguard Worker
1456*7c356e86SAndroid Build Coastguard Worker /* Delete nc chars to the right of the cursor (including cursor position) */
1457*7c356e86SAndroid Build Coastguard Worker static void
x_delete(size_t nc,bool push)1458*7c356e86SAndroid Build Coastguard Worker x_delete(size_t nc, bool push)
1459*7c356e86SAndroid Build Coastguard Worker {
1460*7c356e86SAndroid Build Coastguard Worker size_t i, nb, nw;
1461*7c356e86SAndroid Build Coastguard Worker char *cp;
1462*7c356e86SAndroid Build Coastguard Worker
1463*7c356e86SAndroid Build Coastguard Worker if (nc == 0)
1464*7c356e86SAndroid Build Coastguard Worker return;
1465*7c356e86SAndroid Build Coastguard Worker
1466*7c356e86SAndroid Build Coastguard Worker nw = 0;
1467*7c356e86SAndroid Build Coastguard Worker cp = xcp;
1468*7c356e86SAndroid Build Coastguard Worker for (i = 0; i < nc; ++i) {
1469*7c356e86SAndroid Build Coastguard Worker char *cp2;
1470*7c356e86SAndroid Build Coastguard Worker int j;
1471*7c356e86SAndroid Build Coastguard Worker
1472*7c356e86SAndroid Build Coastguard Worker j = x_size2(cp, &cp2);
1473*7c356e86SAndroid Build Coastguard Worker if (cp2 > xep)
1474*7c356e86SAndroid Build Coastguard Worker break;
1475*7c356e86SAndroid Build Coastguard Worker cp = cp2;
1476*7c356e86SAndroid Build Coastguard Worker nw += j;
1477*7c356e86SAndroid Build Coastguard Worker }
1478*7c356e86SAndroid Build Coastguard Worker nb = cp - xcp;
1479*7c356e86SAndroid Build Coastguard Worker /* nc = i; */
1480*7c356e86SAndroid Build Coastguard Worker
1481*7c356e86SAndroid Build Coastguard Worker if (xmp != NULL && xmp > xcp) {
1482*7c356e86SAndroid Build Coastguard Worker if (xcp + nb > xmp)
1483*7c356e86SAndroid Build Coastguard Worker xmp = xcp;
1484*7c356e86SAndroid Build Coastguard Worker else
1485*7c356e86SAndroid Build Coastguard Worker xmp -= nb;
1486*7c356e86SAndroid Build Coastguard Worker }
1487*7c356e86SAndroid Build Coastguard Worker /*
1488*7c356e86SAndroid Build Coastguard Worker * This lets us yank a word we have deleted.
1489*7c356e86SAndroid Build Coastguard Worker */
1490*7c356e86SAndroid Build Coastguard Worker if (push)
1491*7c356e86SAndroid Build Coastguard Worker x_push(nb);
1492*7c356e86SAndroid Build Coastguard Worker
1493*7c356e86SAndroid Build Coastguard Worker xep -= nb;
1494*7c356e86SAndroid Build Coastguard Worker /* Copies the NUL */
1495*7c356e86SAndroid Build Coastguard Worker memmove(xcp, xcp + nb, xep - xcp + 1);
1496*7c356e86SAndroid Build Coastguard Worker /* don't redraw */
1497*7c356e86SAndroid Build Coastguard Worker x_adj_ok = false;
1498*7c356e86SAndroid Build Coastguard Worker xlp_valid = false;
1499*7c356e86SAndroid Build Coastguard Worker x_zots(xcp);
1500*7c356e86SAndroid Build Coastguard Worker /*
1501*7c356e86SAndroid Build Coastguard Worker * if we are already filling the line,
1502*7c356e86SAndroid Build Coastguard Worker * there is no need to ' ', '\b'.
1503*7c356e86SAndroid Build Coastguard Worker * But if we must, make sure we do the minimum.
1504*7c356e86SAndroid Build Coastguard Worker */
1505*7c356e86SAndroid Build Coastguard Worker if ((i = xx_cols - 2 - x_col) > 0 || xep - xlp == 0) {
1506*7c356e86SAndroid Build Coastguard Worker nw = i = (nw < i) ? nw : i;
1507*7c356e86SAndroid Build Coastguard Worker while (i--)
1508*7c356e86SAndroid Build Coastguard Worker x_e_putc2(' ');
1509*7c356e86SAndroid Build Coastguard Worker if (x_col == xx_cols - 2) {
1510*7c356e86SAndroid Build Coastguard Worker x_e_putc2((xep > xlp) ? '>' : (xbp > xbuf) ? '<' : ' ');
1511*7c356e86SAndroid Build Coastguard Worker ++nw;
1512*7c356e86SAndroid Build Coastguard Worker }
1513*7c356e86SAndroid Build Coastguard Worker while (nw--)
1514*7c356e86SAndroid Build Coastguard Worker x_e_putc2('\b');
1515*7c356e86SAndroid Build Coastguard Worker }
1516*7c356e86SAndroid Build Coastguard Worker /*x_goto(xcp);*/
1517*7c356e86SAndroid Build Coastguard Worker x_adj_ok = true;
1518*7c356e86SAndroid Build Coastguard Worker xlp_valid = false;
1519*7c356e86SAndroid Build Coastguard Worker x_lastpos();
1520*7c356e86SAndroid Build Coastguard Worker x_modified();
1521*7c356e86SAndroid Build Coastguard Worker return;
1522*7c356e86SAndroid Build Coastguard Worker }
1523*7c356e86SAndroid Build Coastguard Worker
1524*7c356e86SAndroid Build Coastguard Worker static int
x_del_bword(int c MKSH_A_UNUSED)1525*7c356e86SAndroid Build Coastguard Worker x_del_bword(int c MKSH_A_UNUSED)
1526*7c356e86SAndroid Build Coastguard Worker {
1527*7c356e86SAndroid Build Coastguard Worker x_delete(x_bword(), true);
1528*7c356e86SAndroid Build Coastguard Worker return (KSTD);
1529*7c356e86SAndroid Build Coastguard Worker }
1530*7c356e86SAndroid Build Coastguard Worker
1531*7c356e86SAndroid Build Coastguard Worker static int
x_mv_bword(int c MKSH_A_UNUSED)1532*7c356e86SAndroid Build Coastguard Worker x_mv_bword(int c MKSH_A_UNUSED)
1533*7c356e86SAndroid Build Coastguard Worker {
1534*7c356e86SAndroid Build Coastguard Worker x_bword();
1535*7c356e86SAndroid Build Coastguard Worker return (KSTD);
1536*7c356e86SAndroid Build Coastguard Worker }
1537*7c356e86SAndroid Build Coastguard Worker
1538*7c356e86SAndroid Build Coastguard Worker static int
x_mv_fword(int c MKSH_A_UNUSED)1539*7c356e86SAndroid Build Coastguard Worker x_mv_fword(int c MKSH_A_UNUSED)
1540*7c356e86SAndroid Build Coastguard Worker {
1541*7c356e86SAndroid Build Coastguard Worker x_fword(true);
1542*7c356e86SAndroid Build Coastguard Worker return (KSTD);
1543*7c356e86SAndroid Build Coastguard Worker }
1544*7c356e86SAndroid Build Coastguard Worker
1545*7c356e86SAndroid Build Coastguard Worker static int
x_del_fword(int c MKSH_A_UNUSED)1546*7c356e86SAndroid Build Coastguard Worker x_del_fword(int c MKSH_A_UNUSED)
1547*7c356e86SAndroid Build Coastguard Worker {
1548*7c356e86SAndroid Build Coastguard Worker x_delete(x_fword(false), true);
1549*7c356e86SAndroid Build Coastguard Worker return (KSTD);
1550*7c356e86SAndroid Build Coastguard Worker }
1551*7c356e86SAndroid Build Coastguard Worker
1552*7c356e86SAndroid Build Coastguard Worker static size_t
x_bword(void)1553*7c356e86SAndroid Build Coastguard Worker x_bword(void)
1554*7c356e86SAndroid Build Coastguard Worker {
1555*7c356e86SAndroid Build Coastguard Worker size_t nb = 0;
1556*7c356e86SAndroid Build Coastguard Worker char *cp = xcp;
1557*7c356e86SAndroid Build Coastguard Worker
1558*7c356e86SAndroid Build Coastguard Worker if (cp == xbuf) {
1559*7c356e86SAndroid Build Coastguard Worker x_e_putc2(KSH_BEL);
1560*7c356e86SAndroid Build Coastguard Worker return (0);
1561*7c356e86SAndroid Build Coastguard Worker }
1562*7c356e86SAndroid Build Coastguard Worker while (x_arg--) {
1563*7c356e86SAndroid Build Coastguard Worker while (cp != xbuf && ctype(cp[-1], C_MFS)) {
1564*7c356e86SAndroid Build Coastguard Worker cp--;
1565*7c356e86SAndroid Build Coastguard Worker nb++;
1566*7c356e86SAndroid Build Coastguard Worker }
1567*7c356e86SAndroid Build Coastguard Worker while (cp != xbuf && !ctype(cp[-1], C_MFS)) {
1568*7c356e86SAndroid Build Coastguard Worker cp--;
1569*7c356e86SAndroid Build Coastguard Worker nb++;
1570*7c356e86SAndroid Build Coastguard Worker }
1571*7c356e86SAndroid Build Coastguard Worker }
1572*7c356e86SAndroid Build Coastguard Worker x_goto(cp);
1573*7c356e86SAndroid Build Coastguard Worker return (x_nb2nc(nb));
1574*7c356e86SAndroid Build Coastguard Worker }
1575*7c356e86SAndroid Build Coastguard Worker
1576*7c356e86SAndroid Build Coastguard Worker static size_t
x_fword(bool move)1577*7c356e86SAndroid Build Coastguard Worker x_fword(bool move)
1578*7c356e86SAndroid Build Coastguard Worker {
1579*7c356e86SAndroid Build Coastguard Worker size_t nc;
1580*7c356e86SAndroid Build Coastguard Worker char *cp = xcp;
1581*7c356e86SAndroid Build Coastguard Worker
1582*7c356e86SAndroid Build Coastguard Worker if (cp == xep) {
1583*7c356e86SAndroid Build Coastguard Worker x_e_putc2(KSH_BEL);
1584*7c356e86SAndroid Build Coastguard Worker return (0);
1585*7c356e86SAndroid Build Coastguard Worker }
1586*7c356e86SAndroid Build Coastguard Worker while (x_arg--) {
1587*7c356e86SAndroid Build Coastguard Worker while (cp != xep && ctype(*cp, C_MFS))
1588*7c356e86SAndroid Build Coastguard Worker cp++;
1589*7c356e86SAndroid Build Coastguard Worker while (cp != xep && !ctype(*cp, C_MFS))
1590*7c356e86SAndroid Build Coastguard Worker cp++;
1591*7c356e86SAndroid Build Coastguard Worker }
1592*7c356e86SAndroid Build Coastguard Worker nc = x_nb2nc(cp - xcp);
1593*7c356e86SAndroid Build Coastguard Worker if (move)
1594*7c356e86SAndroid Build Coastguard Worker x_goto(cp);
1595*7c356e86SAndroid Build Coastguard Worker return (nc);
1596*7c356e86SAndroid Build Coastguard Worker }
1597*7c356e86SAndroid Build Coastguard Worker
1598*7c356e86SAndroid Build Coastguard Worker static void
x_goto(char * cp)1599*7c356e86SAndroid Build Coastguard Worker x_goto(char *cp)
1600*7c356e86SAndroid Build Coastguard Worker {
1601*7c356e86SAndroid Build Coastguard Worker cp = cp >= xep ? xep : x_bs0(cp, xbuf);
1602*7c356e86SAndroid Build Coastguard Worker if (cp < xbp || cp >= utf_skipcols(xbp, x_displen, NULL)) {
1603*7c356e86SAndroid Build Coastguard Worker /* we are heading off screen */
1604*7c356e86SAndroid Build Coastguard Worker xcp = cp;
1605*7c356e86SAndroid Build Coastguard Worker x_adjust();
1606*7c356e86SAndroid Build Coastguard Worker } else if (cp < xcp) {
1607*7c356e86SAndroid Build Coastguard Worker /* move back */
1608*7c356e86SAndroid Build Coastguard Worker while (cp < xcp)
1609*7c356e86SAndroid Build Coastguard Worker x_bs3(&xcp);
1610*7c356e86SAndroid Build Coastguard Worker } else if (cp > xcp) {
1611*7c356e86SAndroid Build Coastguard Worker /* move forward */
1612*7c356e86SAndroid Build Coastguard Worker while (cp > xcp)
1613*7c356e86SAndroid Build Coastguard Worker x_zotc3(&xcp);
1614*7c356e86SAndroid Build Coastguard Worker }
1615*7c356e86SAndroid Build Coastguard Worker }
1616*7c356e86SAndroid Build Coastguard Worker
1617*7c356e86SAndroid Build Coastguard Worker static char *
x_bs0(char * cp,char * lower_bound)1618*7c356e86SAndroid Build Coastguard Worker x_bs0(char *cp, char *lower_bound)
1619*7c356e86SAndroid Build Coastguard Worker {
1620*7c356e86SAndroid Build Coastguard Worker if (UTFMODE)
1621*7c356e86SAndroid Build Coastguard Worker while ((!lower_bound || (cp > lower_bound)) &&
1622*7c356e86SAndroid Build Coastguard Worker ((rtt2asc(*cp) & 0xC0) == 0x80))
1623*7c356e86SAndroid Build Coastguard Worker --cp;
1624*7c356e86SAndroid Build Coastguard Worker return (cp);
1625*7c356e86SAndroid Build Coastguard Worker }
1626*7c356e86SAndroid Build Coastguard Worker
1627*7c356e86SAndroid Build Coastguard Worker static void
x_bs3(char ** p)1628*7c356e86SAndroid Build Coastguard Worker x_bs3(char **p)
1629*7c356e86SAndroid Build Coastguard Worker {
1630*7c356e86SAndroid Build Coastguard Worker int i;
1631*7c356e86SAndroid Build Coastguard Worker
1632*7c356e86SAndroid Build Coastguard Worker *p = x_bs0((*p) - 1, NULL);
1633*7c356e86SAndroid Build Coastguard Worker i = x_size2(*p, NULL);
1634*7c356e86SAndroid Build Coastguard Worker while (i--)
1635*7c356e86SAndroid Build Coastguard Worker x_e_putc2('\b');
1636*7c356e86SAndroid Build Coastguard Worker }
1637*7c356e86SAndroid Build Coastguard Worker
1638*7c356e86SAndroid Build Coastguard Worker static int
x_size2(char * cp,char ** dcp)1639*7c356e86SAndroid Build Coastguard Worker x_size2(char *cp, char **dcp)
1640*7c356e86SAndroid Build Coastguard Worker {
1641*7c356e86SAndroid Build Coastguard Worker uint8_t c = *(unsigned char *)cp;
1642*7c356e86SAndroid Build Coastguard Worker
1643*7c356e86SAndroid Build Coastguard Worker if (UTFMODE && (rtt2asc(c) > 0x7F))
1644*7c356e86SAndroid Build Coastguard Worker return (utf_widthadj(cp, (const char **)dcp));
1645*7c356e86SAndroid Build Coastguard Worker if (dcp)
1646*7c356e86SAndroid Build Coastguard Worker *dcp = cp + 1;
1647*7c356e86SAndroid Build Coastguard Worker if (c == '\t')
1648*7c356e86SAndroid Build Coastguard Worker /* Kludge, tabs are always four spaces. */
1649*7c356e86SAndroid Build Coastguard Worker return (4);
1650*7c356e86SAndroid Build Coastguard Worker if (ksh_isctrl(c))
1651*7c356e86SAndroid Build Coastguard Worker /* control unsigned char */
1652*7c356e86SAndroid Build Coastguard Worker return (2);
1653*7c356e86SAndroid Build Coastguard Worker return (1);
1654*7c356e86SAndroid Build Coastguard Worker }
1655*7c356e86SAndroid Build Coastguard Worker
1656*7c356e86SAndroid Build Coastguard Worker static void
x_zots(char * str)1657*7c356e86SAndroid Build Coastguard Worker x_zots(char *str)
1658*7c356e86SAndroid Build Coastguard Worker {
1659*7c356e86SAndroid Build Coastguard Worker int adj = x_adj_done;
1660*7c356e86SAndroid Build Coastguard Worker
1661*7c356e86SAndroid Build Coastguard Worker x_lastcp();
1662*7c356e86SAndroid Build Coastguard Worker while (*str && str < xlp && x_col < xx_cols && adj == x_adj_done)
1663*7c356e86SAndroid Build Coastguard Worker x_zotc3(&str);
1664*7c356e86SAndroid Build Coastguard Worker }
1665*7c356e86SAndroid Build Coastguard Worker
1666*7c356e86SAndroid Build Coastguard Worker static void
x_zotc3(char ** cp)1667*7c356e86SAndroid Build Coastguard Worker x_zotc3(char **cp)
1668*7c356e86SAndroid Build Coastguard Worker {
1669*7c356e86SAndroid Build Coastguard Worker unsigned char c = **(unsigned char **)cp;
1670*7c356e86SAndroid Build Coastguard Worker
1671*7c356e86SAndroid Build Coastguard Worker if (c == '\t') {
1672*7c356e86SAndroid Build Coastguard Worker /* Kludge, tabs are always four spaces. */
1673*7c356e86SAndroid Build Coastguard Worker x_e_puts(T4spaces);
1674*7c356e86SAndroid Build Coastguard Worker (*cp)++;
1675*7c356e86SAndroid Build Coastguard Worker } else if (ksh_isctrl(c)) {
1676*7c356e86SAndroid Build Coastguard Worker x_e_putc2('^');
1677*7c356e86SAndroid Build Coastguard Worker x_e_putc2(ksh_unctrl(c));
1678*7c356e86SAndroid Build Coastguard Worker (*cp)++;
1679*7c356e86SAndroid Build Coastguard Worker } else
1680*7c356e86SAndroid Build Coastguard Worker x_e_putc3((const char **)cp);
1681*7c356e86SAndroid Build Coastguard Worker }
1682*7c356e86SAndroid Build Coastguard Worker
1683*7c356e86SAndroid Build Coastguard Worker static int
x_mv_back(int c MKSH_A_UNUSED)1684*7c356e86SAndroid Build Coastguard Worker x_mv_back(int c MKSH_A_UNUSED)
1685*7c356e86SAndroid Build Coastguard Worker {
1686*7c356e86SAndroid Build Coastguard Worker if (xcp == xbuf) {
1687*7c356e86SAndroid Build Coastguard Worker x_e_putc2(KSH_BEL);
1688*7c356e86SAndroid Build Coastguard Worker return (KSTD);
1689*7c356e86SAndroid Build Coastguard Worker }
1690*7c356e86SAndroid Build Coastguard Worker while (x_arg--) {
1691*7c356e86SAndroid Build Coastguard Worker x_goto(xcp - 1);
1692*7c356e86SAndroid Build Coastguard Worker if (xcp == xbuf)
1693*7c356e86SAndroid Build Coastguard Worker break;
1694*7c356e86SAndroid Build Coastguard Worker }
1695*7c356e86SAndroid Build Coastguard Worker return (KSTD);
1696*7c356e86SAndroid Build Coastguard Worker }
1697*7c356e86SAndroid Build Coastguard Worker
1698*7c356e86SAndroid Build Coastguard Worker static int
x_mv_forw(int c MKSH_A_UNUSED)1699*7c356e86SAndroid Build Coastguard Worker x_mv_forw(int c MKSH_A_UNUSED)
1700*7c356e86SAndroid Build Coastguard Worker {
1701*7c356e86SAndroid Build Coastguard Worker char *cp = xcp, *cp2;
1702*7c356e86SAndroid Build Coastguard Worker
1703*7c356e86SAndroid Build Coastguard Worker if (xcp == xep) {
1704*7c356e86SAndroid Build Coastguard Worker x_e_putc2(KSH_BEL);
1705*7c356e86SAndroid Build Coastguard Worker return (KSTD);
1706*7c356e86SAndroid Build Coastguard Worker }
1707*7c356e86SAndroid Build Coastguard Worker while (x_arg--) {
1708*7c356e86SAndroid Build Coastguard Worker utf_ptradjx(cp, cp2);
1709*7c356e86SAndroid Build Coastguard Worker if (cp2 > xep)
1710*7c356e86SAndroid Build Coastguard Worker break;
1711*7c356e86SAndroid Build Coastguard Worker cp = cp2;
1712*7c356e86SAndroid Build Coastguard Worker }
1713*7c356e86SAndroid Build Coastguard Worker x_goto(cp);
1714*7c356e86SAndroid Build Coastguard Worker return (KSTD);
1715*7c356e86SAndroid Build Coastguard Worker }
1716*7c356e86SAndroid Build Coastguard Worker
1717*7c356e86SAndroid Build Coastguard Worker static int
x_search_char_forw(int c MKSH_A_UNUSED)1718*7c356e86SAndroid Build Coastguard Worker x_search_char_forw(int c MKSH_A_UNUSED)
1719*7c356e86SAndroid Build Coastguard Worker {
1720*7c356e86SAndroid Build Coastguard Worker char *cp = xcp;
1721*7c356e86SAndroid Build Coastguard Worker char tmp[4];
1722*7c356e86SAndroid Build Coastguard Worker
1723*7c356e86SAndroid Build Coastguard Worker *xep = '\0';
1724*7c356e86SAndroid Build Coastguard Worker if (x_e_getmbc(tmp) < 0) {
1725*7c356e86SAndroid Build Coastguard Worker x_e_putc2(KSH_BEL);
1726*7c356e86SAndroid Build Coastguard Worker return (KSTD);
1727*7c356e86SAndroid Build Coastguard Worker }
1728*7c356e86SAndroid Build Coastguard Worker while (x_arg--) {
1729*7c356e86SAndroid Build Coastguard Worker if ((cp = (cp == xep) ? NULL : strstr(cp + 1, tmp)) == NULL &&
1730*7c356e86SAndroid Build Coastguard Worker (cp = strstr(xbuf, tmp)) == NULL) {
1731*7c356e86SAndroid Build Coastguard Worker x_e_putc2(KSH_BEL);
1732*7c356e86SAndroid Build Coastguard Worker return (KSTD);
1733*7c356e86SAndroid Build Coastguard Worker }
1734*7c356e86SAndroid Build Coastguard Worker }
1735*7c356e86SAndroid Build Coastguard Worker x_goto(cp);
1736*7c356e86SAndroid Build Coastguard Worker return (KSTD);
1737*7c356e86SAndroid Build Coastguard Worker }
1738*7c356e86SAndroid Build Coastguard Worker
1739*7c356e86SAndroid Build Coastguard Worker static int
x_search_char_back(int c MKSH_A_UNUSED)1740*7c356e86SAndroid Build Coastguard Worker x_search_char_back(int c MKSH_A_UNUSED)
1741*7c356e86SAndroid Build Coastguard Worker {
1742*7c356e86SAndroid Build Coastguard Worker char *cp = xcp, *p, tmp[4];
1743*7c356e86SAndroid Build Coastguard Worker bool b;
1744*7c356e86SAndroid Build Coastguard Worker
1745*7c356e86SAndroid Build Coastguard Worker if (x_e_getmbc(tmp) < 0) {
1746*7c356e86SAndroid Build Coastguard Worker x_e_putc2(KSH_BEL);
1747*7c356e86SAndroid Build Coastguard Worker return (KSTD);
1748*7c356e86SAndroid Build Coastguard Worker }
1749*7c356e86SAndroid Build Coastguard Worker for (; x_arg--; cp = p)
1750*7c356e86SAndroid Build Coastguard Worker for (p = cp; ; ) {
1751*7c356e86SAndroid Build Coastguard Worker if (p-- == xbuf)
1752*7c356e86SAndroid Build Coastguard Worker p = xep;
1753*7c356e86SAndroid Build Coastguard Worker if (p == cp) {
1754*7c356e86SAndroid Build Coastguard Worker x_e_putc2(KSH_BEL);
1755*7c356e86SAndroid Build Coastguard Worker return (KSTD);
1756*7c356e86SAndroid Build Coastguard Worker }
1757*7c356e86SAndroid Build Coastguard Worker if ((tmp[1] && ((p+1) > xep)) ||
1758*7c356e86SAndroid Build Coastguard Worker (tmp[2] && ((p+2) > xep)))
1759*7c356e86SAndroid Build Coastguard Worker continue;
1760*7c356e86SAndroid Build Coastguard Worker b = true;
1761*7c356e86SAndroid Build Coastguard Worker if (*p != tmp[0])
1762*7c356e86SAndroid Build Coastguard Worker b = false;
1763*7c356e86SAndroid Build Coastguard Worker if (b && tmp[1] && p[1] != tmp[1])
1764*7c356e86SAndroid Build Coastguard Worker b = false;
1765*7c356e86SAndroid Build Coastguard Worker if (b && tmp[2] && p[2] != tmp[2])
1766*7c356e86SAndroid Build Coastguard Worker b = false;
1767*7c356e86SAndroid Build Coastguard Worker if (b)
1768*7c356e86SAndroid Build Coastguard Worker break;
1769*7c356e86SAndroid Build Coastguard Worker }
1770*7c356e86SAndroid Build Coastguard Worker x_goto(cp);
1771*7c356e86SAndroid Build Coastguard Worker return (KSTD);
1772*7c356e86SAndroid Build Coastguard Worker }
1773*7c356e86SAndroid Build Coastguard Worker
1774*7c356e86SAndroid Build Coastguard Worker static int
x_newline(int c MKSH_A_UNUSED)1775*7c356e86SAndroid Build Coastguard Worker x_newline(int c MKSH_A_UNUSED)
1776*7c356e86SAndroid Build Coastguard Worker {
1777*7c356e86SAndroid Build Coastguard Worker x_e_putc2('\r');
1778*7c356e86SAndroid Build Coastguard Worker x_e_putc2('\n');
1779*7c356e86SAndroid Build Coastguard Worker x_flush();
1780*7c356e86SAndroid Build Coastguard Worker *xep++ = '\n';
1781*7c356e86SAndroid Build Coastguard Worker return (KEOL);
1782*7c356e86SAndroid Build Coastguard Worker }
1783*7c356e86SAndroid Build Coastguard Worker
1784*7c356e86SAndroid Build Coastguard Worker static int
x_end_of_text(int c MKSH_A_UNUSED)1785*7c356e86SAndroid Build Coastguard Worker x_end_of_text(int c MKSH_A_UNUSED)
1786*7c356e86SAndroid Build Coastguard Worker {
1787*7c356e86SAndroid Build Coastguard Worker unsigned char tmp[1], *cp = tmp;
1788*7c356e86SAndroid Build Coastguard Worker
1789*7c356e86SAndroid Build Coastguard Worker *tmp = isedchar(edchars.eof) ? (unsigned char)edchars.eof :
1790*7c356e86SAndroid Build Coastguard Worker (unsigned char)CTRL_D;
1791*7c356e86SAndroid Build Coastguard Worker x_zotc3((char **)&cp);
1792*7c356e86SAndroid Build Coastguard Worker x_putc('\r');
1793*7c356e86SAndroid Build Coastguard Worker x_putc('\n');
1794*7c356e86SAndroid Build Coastguard Worker x_flush();
1795*7c356e86SAndroid Build Coastguard Worker return (KEOL);
1796*7c356e86SAndroid Build Coastguard Worker }
1797*7c356e86SAndroid Build Coastguard Worker
1798*7c356e86SAndroid Build Coastguard Worker static int
x_beg_hist(int c MKSH_A_UNUSED)1799*7c356e86SAndroid Build Coastguard Worker x_beg_hist(int c MKSH_A_UNUSED)
1800*7c356e86SAndroid Build Coastguard Worker {
1801*7c356e86SAndroid Build Coastguard Worker x_load_hist(history);
1802*7c356e86SAndroid Build Coastguard Worker return (KSTD);
1803*7c356e86SAndroid Build Coastguard Worker }
1804*7c356e86SAndroid Build Coastguard Worker
1805*7c356e86SAndroid Build Coastguard Worker static int
x_end_hist(int c MKSH_A_UNUSED)1806*7c356e86SAndroid Build Coastguard Worker x_end_hist(int c MKSH_A_UNUSED)
1807*7c356e86SAndroid Build Coastguard Worker {
1808*7c356e86SAndroid Build Coastguard Worker x_load_hist(histptr);
1809*7c356e86SAndroid Build Coastguard Worker return (KSTD);
1810*7c356e86SAndroid Build Coastguard Worker }
1811*7c356e86SAndroid Build Coastguard Worker
1812*7c356e86SAndroid Build Coastguard Worker static int
x_prev_com(int c MKSH_A_UNUSED)1813*7c356e86SAndroid Build Coastguard Worker x_prev_com(int c MKSH_A_UNUSED)
1814*7c356e86SAndroid Build Coastguard Worker {
1815*7c356e86SAndroid Build Coastguard Worker x_load_hist(x_histp - x_arg);
1816*7c356e86SAndroid Build Coastguard Worker return (KSTD);
1817*7c356e86SAndroid Build Coastguard Worker }
1818*7c356e86SAndroid Build Coastguard Worker
1819*7c356e86SAndroid Build Coastguard Worker static int
x_next_com(int c MKSH_A_UNUSED)1820*7c356e86SAndroid Build Coastguard Worker x_next_com(int c MKSH_A_UNUSED)
1821*7c356e86SAndroid Build Coastguard Worker {
1822*7c356e86SAndroid Build Coastguard Worker x_load_hist(x_histp + x_arg);
1823*7c356e86SAndroid Build Coastguard Worker return (KSTD);
1824*7c356e86SAndroid Build Coastguard Worker }
1825*7c356e86SAndroid Build Coastguard Worker
1826*7c356e86SAndroid Build Coastguard Worker /*
1827*7c356e86SAndroid Build Coastguard Worker * Goto a particular history number obtained from argument.
1828*7c356e86SAndroid Build Coastguard Worker * If no argument is given history 1 is probably not what you
1829*7c356e86SAndroid Build Coastguard Worker * want so we'll simply go to the oldest one.
1830*7c356e86SAndroid Build Coastguard Worker */
1831*7c356e86SAndroid Build Coastguard Worker static int
x_goto_hist(int c MKSH_A_UNUSED)1832*7c356e86SAndroid Build Coastguard Worker x_goto_hist(int c MKSH_A_UNUSED)
1833*7c356e86SAndroid Build Coastguard Worker {
1834*7c356e86SAndroid Build Coastguard Worker if (x_arg_defaulted)
1835*7c356e86SAndroid Build Coastguard Worker x_load_hist(history);
1836*7c356e86SAndroid Build Coastguard Worker else
1837*7c356e86SAndroid Build Coastguard Worker x_load_hist(histptr + x_arg - source->line);
1838*7c356e86SAndroid Build Coastguard Worker return (KSTD);
1839*7c356e86SAndroid Build Coastguard Worker }
1840*7c356e86SAndroid Build Coastguard Worker
1841*7c356e86SAndroid Build Coastguard Worker static void
x_load_hist(char ** hp)1842*7c356e86SAndroid Build Coastguard Worker x_load_hist(char **hp)
1843*7c356e86SAndroid Build Coastguard Worker {
1844*7c356e86SAndroid Build Coastguard Worker char *sp = NULL;
1845*7c356e86SAndroid Build Coastguard Worker
1846*7c356e86SAndroid Build Coastguard Worker if (hp == histptr + 1) {
1847*7c356e86SAndroid Build Coastguard Worker sp = holdbufp;
1848*7c356e86SAndroid Build Coastguard Worker modified = 0;
1849*7c356e86SAndroid Build Coastguard Worker } else if (hp < history || hp > histptr) {
1850*7c356e86SAndroid Build Coastguard Worker x_e_putc2(KSH_BEL);
1851*7c356e86SAndroid Build Coastguard Worker return;
1852*7c356e86SAndroid Build Coastguard Worker }
1853*7c356e86SAndroid Build Coastguard Worker if (sp == NULL)
1854*7c356e86SAndroid Build Coastguard Worker sp = *hp;
1855*7c356e86SAndroid Build Coastguard Worker x_histp = hp;
1856*7c356e86SAndroid Build Coastguard Worker if (modified)
1857*7c356e86SAndroid Build Coastguard Worker strlcpy(holdbufp, xbuf, LINE);
1858*7c356e86SAndroid Build Coastguard Worker strlcpy(xbuf, sp, xend - xbuf);
1859*7c356e86SAndroid Build Coastguard Worker xbp = xbuf;
1860*7c356e86SAndroid Build Coastguard Worker xep = xcp = strnul(xbuf);
1861*7c356e86SAndroid Build Coastguard Worker x_adjust();
1862*7c356e86SAndroid Build Coastguard Worker modified = 0;
1863*7c356e86SAndroid Build Coastguard Worker }
1864*7c356e86SAndroid Build Coastguard Worker
1865*7c356e86SAndroid Build Coastguard Worker static int
x_nl_next_com(int c MKSH_A_UNUSED)1866*7c356e86SAndroid Build Coastguard Worker x_nl_next_com(int c MKSH_A_UNUSED)
1867*7c356e86SAndroid Build Coastguard Worker {
1868*7c356e86SAndroid Build Coastguard Worker if (!modified)
1869*7c356e86SAndroid Build Coastguard Worker x_histmcp = x_histp;
1870*7c356e86SAndroid Build Coastguard Worker if (!x_histncp || (x_histmcp != x_histncp && x_histmcp != histptr + 1))
1871*7c356e86SAndroid Build Coastguard Worker /* fresh start of ^O */
1872*7c356e86SAndroid Build Coastguard Worker x_histncp = x_histmcp;
1873*7c356e86SAndroid Build Coastguard Worker x_nextcmd = source->line - (histptr - x_histncp) + 1;
1874*7c356e86SAndroid Build Coastguard Worker return (x_newline('\n'));
1875*7c356e86SAndroid Build Coastguard Worker }
1876*7c356e86SAndroid Build Coastguard Worker
1877*7c356e86SAndroid Build Coastguard Worker static int
x_eot_del(int c)1878*7c356e86SAndroid Build Coastguard Worker x_eot_del(int c)
1879*7c356e86SAndroid Build Coastguard Worker {
1880*7c356e86SAndroid Build Coastguard Worker if (xep == xbuf && x_arg_defaulted)
1881*7c356e86SAndroid Build Coastguard Worker return (x_end_of_text(c));
1882*7c356e86SAndroid Build Coastguard Worker else
1883*7c356e86SAndroid Build Coastguard Worker return (x_del_char(c));
1884*7c356e86SAndroid Build Coastguard Worker }
1885*7c356e86SAndroid Build Coastguard Worker
1886*7c356e86SAndroid Build Coastguard Worker /* reverse incremental history search */
1887*7c356e86SAndroid Build Coastguard Worker static int
x_search_hist(int c)1888*7c356e86SAndroid Build Coastguard Worker x_search_hist(int c)
1889*7c356e86SAndroid Build Coastguard Worker {
1890*7c356e86SAndroid Build Coastguard Worker int offset = -1; /* offset of match in xbuf, else -1 */
1891*7c356e86SAndroid Build Coastguard Worker char pat[80 + 1]; /* pattern buffer */
1892*7c356e86SAndroid Build Coastguard Worker char *p = pat;
1893*7c356e86SAndroid Build Coastguard Worker unsigned char f;
1894*7c356e86SAndroid Build Coastguard Worker
1895*7c356e86SAndroid Build Coastguard Worker *p = '\0';
1896*7c356e86SAndroid Build Coastguard Worker while (/* CONSTCOND */ 1) {
1897*7c356e86SAndroid Build Coastguard Worker if (offset < 0) {
1898*7c356e86SAndroid Build Coastguard Worker x_e_puts("\nI-search: ");
1899*7c356e86SAndroid Build Coastguard Worker x_e_puts(pat);
1900*7c356e86SAndroid Build Coastguard Worker }
1901*7c356e86SAndroid Build Coastguard Worker x_flush();
1902*7c356e86SAndroid Build Coastguard Worker if ((c = x_e_getc()) < 0)
1903*7c356e86SAndroid Build Coastguard Worker return (KSTD);
1904*7c356e86SAndroid Build Coastguard Worker f = x_tab[0][c];
1905*7c356e86SAndroid Build Coastguard Worker if (c == CTRL_BO) {
1906*7c356e86SAndroid Build Coastguard Worker if ((f & 0x7F) == XFUNC_meta1) {
1907*7c356e86SAndroid Build Coastguard Worker if ((c = x_e_getc()) < 0)
1908*7c356e86SAndroid Build Coastguard Worker return (KSTD);
1909*7c356e86SAndroid Build Coastguard Worker f = x_tab[1][c] & 0x7F;
1910*7c356e86SAndroid Build Coastguard Worker if (f == XFUNC_meta1 || f == XFUNC_meta2)
1911*7c356e86SAndroid Build Coastguard Worker x_meta1(CTRL_BO);
1912*7c356e86SAndroid Build Coastguard Worker x_e_ungetc(c);
1913*7c356e86SAndroid Build Coastguard Worker }
1914*7c356e86SAndroid Build Coastguard Worker break;
1915*7c356e86SAndroid Build Coastguard Worker }
1916*7c356e86SAndroid Build Coastguard Worker #ifndef MKSH_SMALL
1917*7c356e86SAndroid Build Coastguard Worker if (f & 0x80) {
1918*7c356e86SAndroid Build Coastguard Worker f &= 0x7F;
1919*7c356e86SAndroid Build Coastguard Worker if ((c = x_e_getc()) != '~')
1920*7c356e86SAndroid Build Coastguard Worker x_e_ungetc(c);
1921*7c356e86SAndroid Build Coastguard Worker }
1922*7c356e86SAndroid Build Coastguard Worker #endif
1923*7c356e86SAndroid Build Coastguard Worker if (f == XFUNC_search_hist)
1924*7c356e86SAndroid Build Coastguard Worker offset = x_search(pat, 0, offset);
1925*7c356e86SAndroid Build Coastguard Worker else if (f == XFUNC_del_back) {
1926*7c356e86SAndroid Build Coastguard Worker if (p == pat) {
1927*7c356e86SAndroid Build Coastguard Worker offset = -1;
1928*7c356e86SAndroid Build Coastguard Worker break;
1929*7c356e86SAndroid Build Coastguard Worker }
1930*7c356e86SAndroid Build Coastguard Worker if (p > pat) {
1931*7c356e86SAndroid Build Coastguard Worker p = x_bs0(p - 1, pat);
1932*7c356e86SAndroid Build Coastguard Worker *p = '\0';
1933*7c356e86SAndroid Build Coastguard Worker }
1934*7c356e86SAndroid Build Coastguard Worker if (p == pat)
1935*7c356e86SAndroid Build Coastguard Worker offset = -1;
1936*7c356e86SAndroid Build Coastguard Worker else
1937*7c356e86SAndroid Build Coastguard Worker offset = x_search(pat, 1, offset);
1938*7c356e86SAndroid Build Coastguard Worker continue;
1939*7c356e86SAndroid Build Coastguard Worker } else if (f == XFUNC_insert) {
1940*7c356e86SAndroid Build Coastguard Worker /* add char to pattern */
1941*7c356e86SAndroid Build Coastguard Worker /* overflow check... */
1942*7c356e86SAndroid Build Coastguard Worker if ((size_t)(p - pat) >= sizeof(pat) - 1) {
1943*7c356e86SAndroid Build Coastguard Worker x_e_putc2(KSH_BEL);
1944*7c356e86SAndroid Build Coastguard Worker continue;
1945*7c356e86SAndroid Build Coastguard Worker }
1946*7c356e86SAndroid Build Coastguard Worker *p++ = c, *p = '\0';
1947*7c356e86SAndroid Build Coastguard Worker if (offset >= 0) {
1948*7c356e86SAndroid Build Coastguard Worker /* already have partial match */
1949*7c356e86SAndroid Build Coastguard Worker offset = x_match(xbuf, pat);
1950*7c356e86SAndroid Build Coastguard Worker if (offset >= 0) {
1951*7c356e86SAndroid Build Coastguard Worker x_goto(xbuf + offset + (p - pat) -
1952*7c356e86SAndroid Build Coastguard Worker (*pat == '^' ? 1 : 0));
1953*7c356e86SAndroid Build Coastguard Worker continue;
1954*7c356e86SAndroid Build Coastguard Worker }
1955*7c356e86SAndroid Build Coastguard Worker }
1956*7c356e86SAndroid Build Coastguard Worker offset = x_search(pat, 0, offset);
1957*7c356e86SAndroid Build Coastguard Worker } else if (f == XFUNC_abort) {
1958*7c356e86SAndroid Build Coastguard Worker if (offset >= 0)
1959*7c356e86SAndroid Build Coastguard Worker x_load_hist(histptr + 1);
1960*7c356e86SAndroid Build Coastguard Worker break;
1961*7c356e86SAndroid Build Coastguard Worker } else {
1962*7c356e86SAndroid Build Coastguard Worker /* other command */
1963*7c356e86SAndroid Build Coastguard Worker x_e_ungetc(c);
1964*7c356e86SAndroid Build Coastguard Worker break;
1965*7c356e86SAndroid Build Coastguard Worker }
1966*7c356e86SAndroid Build Coastguard Worker }
1967*7c356e86SAndroid Build Coastguard Worker if (offset < 0)
1968*7c356e86SAndroid Build Coastguard Worker x_redraw('\n');
1969*7c356e86SAndroid Build Coastguard Worker return (KSTD);
1970*7c356e86SAndroid Build Coastguard Worker }
1971*7c356e86SAndroid Build Coastguard Worker
1972*7c356e86SAndroid Build Coastguard Worker /* search backward from current line */
1973*7c356e86SAndroid Build Coastguard Worker static int
x_search(const char * pat,int sameline,int offset)1974*7c356e86SAndroid Build Coastguard Worker x_search(const char *pat, int sameline, int offset)
1975*7c356e86SAndroid Build Coastguard Worker {
1976*7c356e86SAndroid Build Coastguard Worker char **hp;
1977*7c356e86SAndroid Build Coastguard Worker int i;
1978*7c356e86SAndroid Build Coastguard Worker size_t patlen = strlen(pat);
1979*7c356e86SAndroid Build Coastguard Worker
1980*7c356e86SAndroid Build Coastguard Worker if (*pat == '^')
1981*7c356e86SAndroid Build Coastguard Worker --patlen;
1982*7c356e86SAndroid Build Coastguard Worker for (hp = x_histp - (sameline ? 0 : 1); hp >= history; --hp) {
1983*7c356e86SAndroid Build Coastguard Worker i = x_match(*hp, pat);
1984*7c356e86SAndroid Build Coastguard Worker if (i >= 0) {
1985*7c356e86SAndroid Build Coastguard Worker if (offset < 0)
1986*7c356e86SAndroid Build Coastguard Worker x_e_putc2('\n');
1987*7c356e86SAndroid Build Coastguard Worker x_load_hist(hp);
1988*7c356e86SAndroid Build Coastguard Worker x_goto(xbuf + i + patlen);
1989*7c356e86SAndroid Build Coastguard Worker return (i);
1990*7c356e86SAndroid Build Coastguard Worker }
1991*7c356e86SAndroid Build Coastguard Worker }
1992*7c356e86SAndroid Build Coastguard Worker x_e_putc2(KSH_BEL);
1993*7c356e86SAndroid Build Coastguard Worker x_histp = histptr;
1994*7c356e86SAndroid Build Coastguard Worker return (-1);
1995*7c356e86SAndroid Build Coastguard Worker }
1996*7c356e86SAndroid Build Coastguard Worker
1997*7c356e86SAndroid Build Coastguard Worker #ifndef MKSH_SMALL
1998*7c356e86SAndroid Build Coastguard Worker /* anchored search up from current line */
1999*7c356e86SAndroid Build Coastguard Worker static int
x_search_hist_up(int c MKSH_A_UNUSED)2000*7c356e86SAndroid Build Coastguard Worker x_search_hist_up(int c MKSH_A_UNUSED)
2001*7c356e86SAndroid Build Coastguard Worker {
2002*7c356e86SAndroid Build Coastguard Worker return (x_search_dir(-1));
2003*7c356e86SAndroid Build Coastguard Worker }
2004*7c356e86SAndroid Build Coastguard Worker
2005*7c356e86SAndroid Build Coastguard Worker /* anchored search down from current line */
2006*7c356e86SAndroid Build Coastguard Worker static int
x_search_hist_dn(int c MKSH_A_UNUSED)2007*7c356e86SAndroid Build Coastguard Worker x_search_hist_dn(int c MKSH_A_UNUSED)
2008*7c356e86SAndroid Build Coastguard Worker {
2009*7c356e86SAndroid Build Coastguard Worker return (x_search_dir(1));
2010*7c356e86SAndroid Build Coastguard Worker }
2011*7c356e86SAndroid Build Coastguard Worker
2012*7c356e86SAndroid Build Coastguard Worker /* anchored search in the indicated direction */
2013*7c356e86SAndroid Build Coastguard Worker static int
x_search_dir(int search_dir)2014*7c356e86SAndroid Build Coastguard Worker x_search_dir(int search_dir /* should've been bool */)
2015*7c356e86SAndroid Build Coastguard Worker {
2016*7c356e86SAndroid Build Coastguard Worker char **hp = x_histp + search_dir;
2017*7c356e86SAndroid Build Coastguard Worker size_t curs = xcp - xbuf;
2018*7c356e86SAndroid Build Coastguard Worker
2019*7c356e86SAndroid Build Coastguard Worker while (histptr >= hp && hp >= history) {
2020*7c356e86SAndroid Build Coastguard Worker if (strncmp(xbuf, *hp, curs) == 0) {
2021*7c356e86SAndroid Build Coastguard Worker x_load_hist(hp);
2022*7c356e86SAndroid Build Coastguard Worker x_goto(xbuf + curs);
2023*7c356e86SAndroid Build Coastguard Worker break;
2024*7c356e86SAndroid Build Coastguard Worker }
2025*7c356e86SAndroid Build Coastguard Worker hp += search_dir;
2026*7c356e86SAndroid Build Coastguard Worker }
2027*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2028*7c356e86SAndroid Build Coastguard Worker }
2029*7c356e86SAndroid Build Coastguard Worker #endif
2030*7c356e86SAndroid Build Coastguard Worker
2031*7c356e86SAndroid Build Coastguard Worker /* return position of first match of pattern in string, else -1 */
2032*7c356e86SAndroid Build Coastguard Worker static int
x_match(const char * str,const char * pat)2033*7c356e86SAndroid Build Coastguard Worker x_match(const char *str, const char *pat)
2034*7c356e86SAndroid Build Coastguard Worker {
2035*7c356e86SAndroid Build Coastguard Worker if (*pat == '^') {
2036*7c356e86SAndroid Build Coastguard Worker return ((strncmp(str, pat + 1, strlen(pat + 1)) == 0) ? 0 : -1);
2037*7c356e86SAndroid Build Coastguard Worker } else {
2038*7c356e86SAndroid Build Coastguard Worker char *q = strstr(str, pat);
2039*7c356e86SAndroid Build Coastguard Worker return ((q == NULL) ? -1 : q - str);
2040*7c356e86SAndroid Build Coastguard Worker }
2041*7c356e86SAndroid Build Coastguard Worker }
2042*7c356e86SAndroid Build Coastguard Worker
2043*7c356e86SAndroid Build Coastguard Worker static int
x_del_line(int c MKSH_A_UNUSED)2044*7c356e86SAndroid Build Coastguard Worker x_del_line(int c MKSH_A_UNUSED)
2045*7c356e86SAndroid Build Coastguard Worker {
2046*7c356e86SAndroid Build Coastguard Worker *xep = 0;
2047*7c356e86SAndroid Build Coastguard Worker x_push(xep - (xcp = xbuf));
2048*7c356e86SAndroid Build Coastguard Worker xlp = xbp = xep = xbuf;
2049*7c356e86SAndroid Build Coastguard Worker xlp_valid = true;
2050*7c356e86SAndroid Build Coastguard Worker *xcp = 0;
2051*7c356e86SAndroid Build Coastguard Worker xmp = NULL;
2052*7c356e86SAndroid Build Coastguard Worker x_redraw('\r');
2053*7c356e86SAndroid Build Coastguard Worker x_modified();
2054*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2055*7c356e86SAndroid Build Coastguard Worker }
2056*7c356e86SAndroid Build Coastguard Worker
2057*7c356e86SAndroid Build Coastguard Worker static int
x_mv_end(int c MKSH_A_UNUSED)2058*7c356e86SAndroid Build Coastguard Worker x_mv_end(int c MKSH_A_UNUSED)
2059*7c356e86SAndroid Build Coastguard Worker {
2060*7c356e86SAndroid Build Coastguard Worker x_goto(xep);
2061*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2062*7c356e86SAndroid Build Coastguard Worker }
2063*7c356e86SAndroid Build Coastguard Worker
2064*7c356e86SAndroid Build Coastguard Worker static int
x_mv_beg(int c MKSH_A_UNUSED)2065*7c356e86SAndroid Build Coastguard Worker x_mv_beg(int c MKSH_A_UNUSED)
2066*7c356e86SAndroid Build Coastguard Worker {
2067*7c356e86SAndroid Build Coastguard Worker x_goto(xbuf);
2068*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2069*7c356e86SAndroid Build Coastguard Worker }
2070*7c356e86SAndroid Build Coastguard Worker
2071*7c356e86SAndroid Build Coastguard Worker static int
x_draw_line(int c MKSH_A_UNUSED)2072*7c356e86SAndroid Build Coastguard Worker x_draw_line(int c MKSH_A_UNUSED)
2073*7c356e86SAndroid Build Coastguard Worker {
2074*7c356e86SAndroid Build Coastguard Worker x_redraw('\n');
2075*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2076*7c356e86SAndroid Build Coastguard Worker }
2077*7c356e86SAndroid Build Coastguard Worker
2078*7c356e86SAndroid Build Coastguard Worker static int
x_cls(int c MKSH_A_UNUSED)2079*7c356e86SAndroid Build Coastguard Worker x_cls(int c MKSH_A_UNUSED)
2080*7c356e86SAndroid Build Coastguard Worker {
2081*7c356e86SAndroid Build Coastguard Worker shf_puts(MKSH_CLS_STRING, shl_out);
2082*7c356e86SAndroid Build Coastguard Worker x_redraw(0);
2083*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2084*7c356e86SAndroid Build Coastguard Worker }
2085*7c356e86SAndroid Build Coastguard Worker
2086*7c356e86SAndroid Build Coastguard Worker /*
2087*7c356e86SAndroid Build Coastguard Worker * clear line from x_col (current cursor position) to xx_cols - 2,
2088*7c356e86SAndroid Build Coastguard Worker * then output lastch, then go back to x_col; if lastch is space,
2089*7c356e86SAndroid Build Coastguard Worker * clear with termcap instead of spaces, or not if line_was_cleared;
2090*7c356e86SAndroid Build Coastguard Worker * lastch MUST be an ASCII character with wcwidth(lastch) == 1
2091*7c356e86SAndroid Build Coastguard Worker */
2092*7c356e86SAndroid Build Coastguard Worker static void
x_clrtoeol(int lastch,bool line_was_cleared)2093*7c356e86SAndroid Build Coastguard Worker x_clrtoeol(int lastch, bool line_was_cleared)
2094*7c356e86SAndroid Build Coastguard Worker {
2095*7c356e86SAndroid Build Coastguard Worker int col;
2096*7c356e86SAndroid Build Coastguard Worker
2097*7c356e86SAndroid Build Coastguard Worker if (lastch == ' ' && !line_was_cleared && x_term_mode == 1) {
2098*7c356e86SAndroid Build Coastguard Worker shf_puts(KSH_ESC_STRING "[K", shl_out);
2099*7c356e86SAndroid Build Coastguard Worker line_was_cleared = true;
2100*7c356e86SAndroid Build Coastguard Worker }
2101*7c356e86SAndroid Build Coastguard Worker if (lastch == ' ' && line_was_cleared)
2102*7c356e86SAndroid Build Coastguard Worker return;
2103*7c356e86SAndroid Build Coastguard Worker
2104*7c356e86SAndroid Build Coastguard Worker col = x_col;
2105*7c356e86SAndroid Build Coastguard Worker while (col < (xx_cols - 2)) {
2106*7c356e86SAndroid Build Coastguard Worker x_putc(' ');
2107*7c356e86SAndroid Build Coastguard Worker ++col;
2108*7c356e86SAndroid Build Coastguard Worker }
2109*7c356e86SAndroid Build Coastguard Worker x_putc(lastch);
2110*7c356e86SAndroid Build Coastguard Worker ++col;
2111*7c356e86SAndroid Build Coastguard Worker while (col > x_col) {
2112*7c356e86SAndroid Build Coastguard Worker x_putc('\b');
2113*7c356e86SAndroid Build Coastguard Worker --col;
2114*7c356e86SAndroid Build Coastguard Worker }
2115*7c356e86SAndroid Build Coastguard Worker }
2116*7c356e86SAndroid Build Coastguard Worker
2117*7c356e86SAndroid Build Coastguard Worker /* output the prompt, assuming a line has just been started */
2118*7c356e86SAndroid Build Coastguard Worker static void
x_pprompt(void)2119*7c356e86SAndroid Build Coastguard Worker x_pprompt(void)
2120*7c356e86SAndroid Build Coastguard Worker {
2121*7c356e86SAndroid Build Coastguard Worker if (prompt_trunc != -1)
2122*7c356e86SAndroid Build Coastguard Worker pprompt(prompt, prompt_trunc);
2123*7c356e86SAndroid Build Coastguard Worker x_col = pwidth;
2124*7c356e86SAndroid Build Coastguard Worker }
2125*7c356e86SAndroid Build Coastguard Worker
2126*7c356e86SAndroid Build Coastguard Worker /* output CR, then redraw the line, clearing to EOL if needed (cr ≠ 0, LF) */
2127*7c356e86SAndroid Build Coastguard Worker static void
x_redraw(int cr)2128*7c356e86SAndroid Build Coastguard Worker x_redraw(int cr)
2129*7c356e86SAndroid Build Coastguard Worker {
2130*7c356e86SAndroid Build Coastguard Worker int lch;
2131*7c356e86SAndroid Build Coastguard Worker
2132*7c356e86SAndroid Build Coastguard Worker x_adj_ok = false;
2133*7c356e86SAndroid Build Coastguard Worker /* clear the line */
2134*7c356e86SAndroid Build Coastguard Worker x_e_putc2(cr ? cr : '\r');
2135*7c356e86SAndroid Build Coastguard Worker x_flush();
2136*7c356e86SAndroid Build Coastguard Worker /* display the prompt */
2137*7c356e86SAndroid Build Coastguard Worker if (xbp == xbuf)
2138*7c356e86SAndroid Build Coastguard Worker x_pprompt();
2139*7c356e86SAndroid Build Coastguard Worker x_displen = xx_cols - 2 - x_col;
2140*7c356e86SAndroid Build Coastguard Worker /* display the line content */
2141*7c356e86SAndroid Build Coastguard Worker xlp_valid = false;
2142*7c356e86SAndroid Build Coastguard Worker x_zots(xbp);
2143*7c356e86SAndroid Build Coastguard Worker /* check whether there is more off-screen */
2144*7c356e86SAndroid Build Coastguard Worker lch = xep > xlp ? (xbp > xbuf ? '*' : '>') : (xbp > xbuf) ? '<' : ' ';
2145*7c356e86SAndroid Build Coastguard Worker /* clear the rest of the line */
2146*7c356e86SAndroid Build Coastguard Worker x_clrtoeol(lch, !cr || cr == '\n');
2147*7c356e86SAndroid Build Coastguard Worker /* go back to actual cursor position */
2148*7c356e86SAndroid Build Coastguard Worker x_lastpos();
2149*7c356e86SAndroid Build Coastguard Worker x_adj_ok = true;
2150*7c356e86SAndroid Build Coastguard Worker }
2151*7c356e86SAndroid Build Coastguard Worker
2152*7c356e86SAndroid Build Coastguard Worker static int
x_transpose(int c MKSH_A_UNUSED)2153*7c356e86SAndroid Build Coastguard Worker x_transpose(int c MKSH_A_UNUSED)
2154*7c356e86SAndroid Build Coastguard Worker {
2155*7c356e86SAndroid Build Coastguard Worker unsigned int tmpa, tmpb;
2156*7c356e86SAndroid Build Coastguard Worker
2157*7c356e86SAndroid Build Coastguard Worker /*-
2158*7c356e86SAndroid Build Coastguard Worker * What transpose is meant to do seems to be up for debate. This
2159*7c356e86SAndroid Build Coastguard Worker * is a general summary of the options; the text is abcd with the
2160*7c356e86SAndroid Build Coastguard Worker * upper case character or underscore indicating the cursor position:
2161*7c356e86SAndroid Build Coastguard Worker * Who Before After Before After
2162*7c356e86SAndroid Build Coastguard Worker * AT&T ksh in emacs mode: abCd abdC abcd_ (bell)
2163*7c356e86SAndroid Build Coastguard Worker * AT&T ksh in gmacs mode: abCd baCd abcd_ abdc_
2164*7c356e86SAndroid Build Coastguard Worker * gnu emacs: abCd acbD abcd_ abdc_
2165*7c356e86SAndroid Build Coastguard Worker * Pdksh currently goes with GNU behavior since I believe this is the
2166*7c356e86SAndroid Build Coastguard Worker * most common version of emacs, unless in gmacs mode, in which case
2167*7c356e86SAndroid Build Coastguard Worker * it does the AT&T ksh gmacs mode.
2168*7c356e86SAndroid Build Coastguard Worker * This should really be broken up into 3 functions so users can bind
2169*7c356e86SAndroid Build Coastguard Worker * to the one they want.
2170*7c356e86SAndroid Build Coastguard Worker */
2171*7c356e86SAndroid Build Coastguard Worker if (xcp == xbuf) {
2172*7c356e86SAndroid Build Coastguard Worker x_e_putc2(KSH_BEL);
2173*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2174*7c356e86SAndroid Build Coastguard Worker } else if (xcp == xep || Flag(FGMACS)) {
2175*7c356e86SAndroid Build Coastguard Worker if (xcp - xbuf == 1) {
2176*7c356e86SAndroid Build Coastguard Worker x_e_putc2(KSH_BEL);
2177*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2178*7c356e86SAndroid Build Coastguard Worker }
2179*7c356e86SAndroid Build Coastguard Worker /*
2180*7c356e86SAndroid Build Coastguard Worker * Gosling/Unipress emacs style: Swap two characters before
2181*7c356e86SAndroid Build Coastguard Worker * the cursor, do not change cursor position
2182*7c356e86SAndroid Build Coastguard Worker */
2183*7c356e86SAndroid Build Coastguard Worker x_bs3(&xcp);
2184*7c356e86SAndroid Build Coastguard Worker if (utf_mbtowc(&tmpa, xcp) == (size_t)-1) {
2185*7c356e86SAndroid Build Coastguard Worker x_e_putc2(KSH_BEL);
2186*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2187*7c356e86SAndroid Build Coastguard Worker }
2188*7c356e86SAndroid Build Coastguard Worker x_bs3(&xcp);
2189*7c356e86SAndroid Build Coastguard Worker if (utf_mbtowc(&tmpb, xcp) == (size_t)-1) {
2190*7c356e86SAndroid Build Coastguard Worker x_e_putc2(KSH_BEL);
2191*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2192*7c356e86SAndroid Build Coastguard Worker }
2193*7c356e86SAndroid Build Coastguard Worker utf_wctomb(xcp, tmpa);
2194*7c356e86SAndroid Build Coastguard Worker x_zotc3(&xcp);
2195*7c356e86SAndroid Build Coastguard Worker utf_wctomb(xcp, tmpb);
2196*7c356e86SAndroid Build Coastguard Worker x_zotc3(&xcp);
2197*7c356e86SAndroid Build Coastguard Worker } else {
2198*7c356e86SAndroid Build Coastguard Worker /*
2199*7c356e86SAndroid Build Coastguard Worker * GNU emacs style: Swap the characters before and under the
2200*7c356e86SAndroid Build Coastguard Worker * cursor, move cursor position along one.
2201*7c356e86SAndroid Build Coastguard Worker */
2202*7c356e86SAndroid Build Coastguard Worker if (utf_mbtowc(&tmpa, xcp) == (size_t)-1) {
2203*7c356e86SAndroid Build Coastguard Worker x_e_putc2(KSH_BEL);
2204*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2205*7c356e86SAndroid Build Coastguard Worker }
2206*7c356e86SAndroid Build Coastguard Worker x_bs3(&xcp);
2207*7c356e86SAndroid Build Coastguard Worker if (utf_mbtowc(&tmpb, xcp) == (size_t)-1) {
2208*7c356e86SAndroid Build Coastguard Worker x_e_putc2(KSH_BEL);
2209*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2210*7c356e86SAndroid Build Coastguard Worker }
2211*7c356e86SAndroid Build Coastguard Worker utf_wctomb(xcp, tmpa);
2212*7c356e86SAndroid Build Coastguard Worker x_zotc3(&xcp);
2213*7c356e86SAndroid Build Coastguard Worker utf_wctomb(xcp, tmpb);
2214*7c356e86SAndroid Build Coastguard Worker x_zotc3(&xcp);
2215*7c356e86SAndroid Build Coastguard Worker }
2216*7c356e86SAndroid Build Coastguard Worker x_modified();
2217*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2218*7c356e86SAndroid Build Coastguard Worker }
2219*7c356e86SAndroid Build Coastguard Worker
2220*7c356e86SAndroid Build Coastguard Worker static int
x_literal(int c MKSH_A_UNUSED)2221*7c356e86SAndroid Build Coastguard Worker x_literal(int c MKSH_A_UNUSED)
2222*7c356e86SAndroid Build Coastguard Worker {
2223*7c356e86SAndroid Build Coastguard Worker x_curprefix = -1;
2224*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2225*7c356e86SAndroid Build Coastguard Worker }
2226*7c356e86SAndroid Build Coastguard Worker
2227*7c356e86SAndroid Build Coastguard Worker static int
x_meta1(int c MKSH_A_UNUSED)2228*7c356e86SAndroid Build Coastguard Worker x_meta1(int c MKSH_A_UNUSED)
2229*7c356e86SAndroid Build Coastguard Worker {
2230*7c356e86SAndroid Build Coastguard Worker x_curprefix = 1;
2231*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2232*7c356e86SAndroid Build Coastguard Worker }
2233*7c356e86SAndroid Build Coastguard Worker
2234*7c356e86SAndroid Build Coastguard Worker static int
x_meta2(int c MKSH_A_UNUSED)2235*7c356e86SAndroid Build Coastguard Worker x_meta2(int c MKSH_A_UNUSED)
2236*7c356e86SAndroid Build Coastguard Worker {
2237*7c356e86SAndroid Build Coastguard Worker x_curprefix = 2;
2238*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2239*7c356e86SAndroid Build Coastguard Worker }
2240*7c356e86SAndroid Build Coastguard Worker
2241*7c356e86SAndroid Build Coastguard Worker static int
x_meta3(int c MKSH_A_UNUSED)2242*7c356e86SAndroid Build Coastguard Worker x_meta3(int c MKSH_A_UNUSED)
2243*7c356e86SAndroid Build Coastguard Worker {
2244*7c356e86SAndroid Build Coastguard Worker x_curprefix = 3;
2245*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2246*7c356e86SAndroid Build Coastguard Worker }
2247*7c356e86SAndroid Build Coastguard Worker
2248*7c356e86SAndroid Build Coastguard Worker static int
x_kill(int c MKSH_A_UNUSED)2249*7c356e86SAndroid Build Coastguard Worker x_kill(int c MKSH_A_UNUSED)
2250*7c356e86SAndroid Build Coastguard Worker {
2251*7c356e86SAndroid Build Coastguard Worker size_t col = xcp - xbuf;
2252*7c356e86SAndroid Build Coastguard Worker size_t lastcol = xep - xbuf;
2253*7c356e86SAndroid Build Coastguard Worker size_t ndel, narg;
2254*7c356e86SAndroid Build Coastguard Worker
2255*7c356e86SAndroid Build Coastguard Worker if (x_arg_defaulted || (narg = x_arg) > lastcol)
2256*7c356e86SAndroid Build Coastguard Worker narg = lastcol;
2257*7c356e86SAndroid Build Coastguard Worker if (narg < col) {
2258*7c356e86SAndroid Build Coastguard Worker x_goto(xbuf + narg);
2259*7c356e86SAndroid Build Coastguard Worker ndel = col - narg;
2260*7c356e86SAndroid Build Coastguard Worker } else
2261*7c356e86SAndroid Build Coastguard Worker ndel = narg - col;
2262*7c356e86SAndroid Build Coastguard Worker x_delete(x_nb2nc(ndel), true);
2263*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2264*7c356e86SAndroid Build Coastguard Worker }
2265*7c356e86SAndroid Build Coastguard Worker
2266*7c356e86SAndroid Build Coastguard Worker static void
x_push(size_t nchars)2267*7c356e86SAndroid Build Coastguard Worker x_push(size_t nchars)
2268*7c356e86SAndroid Build Coastguard Worker {
2269*7c356e86SAndroid Build Coastguard Worker afree(killstack[killsp], AEDIT);
2270*7c356e86SAndroid Build Coastguard Worker strndupx(killstack[killsp], xcp, nchars, AEDIT);
2271*7c356e86SAndroid Build Coastguard Worker killsp = (killsp + 1) % KILLSIZE;
2272*7c356e86SAndroid Build Coastguard Worker }
2273*7c356e86SAndroid Build Coastguard Worker
2274*7c356e86SAndroid Build Coastguard Worker static int
x_yank(int c MKSH_A_UNUSED)2275*7c356e86SAndroid Build Coastguard Worker x_yank(int c MKSH_A_UNUSED)
2276*7c356e86SAndroid Build Coastguard Worker {
2277*7c356e86SAndroid Build Coastguard Worker if (killsp == 0)
2278*7c356e86SAndroid Build Coastguard Worker killtp = KILLSIZE;
2279*7c356e86SAndroid Build Coastguard Worker else
2280*7c356e86SAndroid Build Coastguard Worker killtp = killsp;
2281*7c356e86SAndroid Build Coastguard Worker killtp--;
2282*7c356e86SAndroid Build Coastguard Worker if (killstack[killtp] == 0) {
2283*7c356e86SAndroid Build Coastguard Worker x_e_puts("\nnothing to yank");
2284*7c356e86SAndroid Build Coastguard Worker x_redraw('\n');
2285*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2286*7c356e86SAndroid Build Coastguard Worker }
2287*7c356e86SAndroid Build Coastguard Worker xmp = xcp;
2288*7c356e86SAndroid Build Coastguard Worker x_ins(killstack[killtp]);
2289*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2290*7c356e86SAndroid Build Coastguard Worker }
2291*7c356e86SAndroid Build Coastguard Worker
2292*7c356e86SAndroid Build Coastguard Worker static int
x_meta_yank(int c MKSH_A_UNUSED)2293*7c356e86SAndroid Build Coastguard Worker x_meta_yank(int c MKSH_A_UNUSED)
2294*7c356e86SAndroid Build Coastguard Worker {
2295*7c356e86SAndroid Build Coastguard Worker size_t len;
2296*7c356e86SAndroid Build Coastguard Worker
2297*7c356e86SAndroid Build Coastguard Worker if ((x_last_command != XFUNC_yank && x_last_command != XFUNC_meta_yank) ||
2298*7c356e86SAndroid Build Coastguard Worker killstack[killtp] == 0) {
2299*7c356e86SAndroid Build Coastguard Worker killtp = killsp;
2300*7c356e86SAndroid Build Coastguard Worker x_e_puts("\nyank something first");
2301*7c356e86SAndroid Build Coastguard Worker x_redraw('\n');
2302*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2303*7c356e86SAndroid Build Coastguard Worker }
2304*7c356e86SAndroid Build Coastguard Worker len = strlen(killstack[killtp]);
2305*7c356e86SAndroid Build Coastguard Worker x_goto(xcp - len);
2306*7c356e86SAndroid Build Coastguard Worker x_delete(x_nb2nc(len), false);
2307*7c356e86SAndroid Build Coastguard Worker do {
2308*7c356e86SAndroid Build Coastguard Worker if (killtp == 0)
2309*7c356e86SAndroid Build Coastguard Worker killtp = KILLSIZE - 1;
2310*7c356e86SAndroid Build Coastguard Worker else
2311*7c356e86SAndroid Build Coastguard Worker killtp--;
2312*7c356e86SAndroid Build Coastguard Worker } while (killstack[killtp] == 0);
2313*7c356e86SAndroid Build Coastguard Worker x_ins(killstack[killtp]);
2314*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2315*7c356e86SAndroid Build Coastguard Worker }
2316*7c356e86SAndroid Build Coastguard Worker
2317*7c356e86SAndroid Build Coastguard Worker /* fake receiving an interrupt */
2318*7c356e86SAndroid Build Coastguard Worker static void
x_intr(int signo,int c)2319*7c356e86SAndroid Build Coastguard Worker x_intr(int signo, int c)
2320*7c356e86SAndroid Build Coastguard Worker {
2321*7c356e86SAndroid Build Coastguard Worker x_vi_zotc(c);
2322*7c356e86SAndroid Build Coastguard Worker *xep = '\0';
2323*7c356e86SAndroid Build Coastguard Worker strip_nuls(xbuf, xep - xbuf);
2324*7c356e86SAndroid Build Coastguard Worker if (*xbuf)
2325*7c356e86SAndroid Build Coastguard Worker histsave(&source->line, xbuf, HIST_STORE, true);
2326*7c356e86SAndroid Build Coastguard Worker xlp = xep = xcp = xbp = xbuf;
2327*7c356e86SAndroid Build Coastguard Worker xlp_valid = true;
2328*7c356e86SAndroid Build Coastguard Worker *xcp = 0;
2329*7c356e86SAndroid Build Coastguard Worker x_modified();
2330*7c356e86SAndroid Build Coastguard Worker x_flush();
2331*7c356e86SAndroid Build Coastguard Worker trapsig(signo);
2332*7c356e86SAndroid Build Coastguard Worker x_mode(false);
2333*7c356e86SAndroid Build Coastguard Worker unwind(LSHELL);
2334*7c356e86SAndroid Build Coastguard Worker }
2335*7c356e86SAndroid Build Coastguard Worker
2336*7c356e86SAndroid Build Coastguard Worker static int
x_abort(int c MKSH_A_UNUSED)2337*7c356e86SAndroid Build Coastguard Worker x_abort(int c MKSH_A_UNUSED)
2338*7c356e86SAndroid Build Coastguard Worker {
2339*7c356e86SAndroid Build Coastguard Worker return (KINTR);
2340*7c356e86SAndroid Build Coastguard Worker }
2341*7c356e86SAndroid Build Coastguard Worker
2342*7c356e86SAndroid Build Coastguard Worker static int
x_error(int c MKSH_A_UNUSED)2343*7c356e86SAndroid Build Coastguard Worker x_error(int c MKSH_A_UNUSED)
2344*7c356e86SAndroid Build Coastguard Worker {
2345*7c356e86SAndroid Build Coastguard Worker x_e_putc2(KSH_BEL);
2346*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2347*7c356e86SAndroid Build Coastguard Worker }
2348*7c356e86SAndroid Build Coastguard Worker
2349*7c356e86SAndroid Build Coastguard Worker #ifndef MKSH_SMALL
2350*7c356e86SAndroid Build Coastguard Worker /* special VT100 style key sequence hack */
2351*7c356e86SAndroid Build Coastguard Worker static int
x_vt_hack(int c)2352*7c356e86SAndroid Build Coastguard Worker x_vt_hack(int c)
2353*7c356e86SAndroid Build Coastguard Worker {
2354*7c356e86SAndroid Build Coastguard Worker /* we only support PF2-'1' for now */
2355*7c356e86SAndroid Build Coastguard Worker if (c != (2 << 8 | '1'))
2356*7c356e86SAndroid Build Coastguard Worker return (x_error(c));
2357*7c356e86SAndroid Build Coastguard Worker
2358*7c356e86SAndroid Build Coastguard Worker /* what's the next character? */
2359*7c356e86SAndroid Build Coastguard Worker switch ((c = x_e_getc())) {
2360*7c356e86SAndroid Build Coastguard Worker case '~':
2361*7c356e86SAndroid Build Coastguard Worker x_arg = 1;
2362*7c356e86SAndroid Build Coastguard Worker x_arg_defaulted = true;
2363*7c356e86SAndroid Build Coastguard Worker return (x_mv_beg(0));
2364*7c356e86SAndroid Build Coastguard Worker case ';':
2365*7c356e86SAndroid Build Coastguard Worker /* "interesting" sequence detected */
2366*7c356e86SAndroid Build Coastguard Worker break;
2367*7c356e86SAndroid Build Coastguard Worker default:
2368*7c356e86SAndroid Build Coastguard Worker goto unwind_err;
2369*7c356e86SAndroid Build Coastguard Worker }
2370*7c356e86SAndroid Build Coastguard Worker
2371*7c356e86SAndroid Build Coastguard Worker /* XXX x_e_ungetc is one-octet only */
2372*7c356e86SAndroid Build Coastguard Worker if ((c = x_e_getc()) != '5' && c != '3')
2373*7c356e86SAndroid Build Coastguard Worker goto unwind_err;
2374*7c356e86SAndroid Build Coastguard Worker
2375*7c356e86SAndroid Build Coastguard Worker /*-
2376*7c356e86SAndroid Build Coastguard Worker * At this point, we have read the following octets so far:
2377*7c356e86SAndroid Build Coastguard Worker * - ESC+[ or ESC+O or Ctrl-X (Prefix 2)
2378*7c356e86SAndroid Build Coastguard Worker * - 1 (vt_hack)
2379*7c356e86SAndroid Build Coastguard Worker * - ;
2380*7c356e86SAndroid Build Coastguard Worker * - 5 (Ctrl key combiner) or 3 (Alt key combiner)
2381*7c356e86SAndroid Build Coastguard Worker * We can now accept one more octet designating the key.
2382*7c356e86SAndroid Build Coastguard Worker */
2383*7c356e86SAndroid Build Coastguard Worker
2384*7c356e86SAndroid Build Coastguard Worker switch ((c = x_e_getc())) {
2385*7c356e86SAndroid Build Coastguard Worker case 'C':
2386*7c356e86SAndroid Build Coastguard Worker return (x_mv_fword(c));
2387*7c356e86SAndroid Build Coastguard Worker case 'D':
2388*7c356e86SAndroid Build Coastguard Worker return (x_mv_bword(c));
2389*7c356e86SAndroid Build Coastguard Worker }
2390*7c356e86SAndroid Build Coastguard Worker
2391*7c356e86SAndroid Build Coastguard Worker unwind_err:
2392*7c356e86SAndroid Build Coastguard Worker x_e_ungetc(c);
2393*7c356e86SAndroid Build Coastguard Worker return (x_error(c));
2394*7c356e86SAndroid Build Coastguard Worker }
2395*7c356e86SAndroid Build Coastguard Worker #endif
2396*7c356e86SAndroid Build Coastguard Worker
2397*7c356e86SAndroid Build Coastguard Worker int
x_bind_check(void)2398*7c356e86SAndroid Build Coastguard Worker x_bind_check(void)
2399*7c356e86SAndroid Build Coastguard Worker {
2400*7c356e86SAndroid Build Coastguard Worker return (x_tab == NULL);
2401*7c356e86SAndroid Build Coastguard Worker }
2402*7c356e86SAndroid Build Coastguard Worker
2403*7c356e86SAndroid Build Coastguard Worker static XString x_bind_show_xs;
2404*7c356e86SAndroid Build Coastguard Worker static char *x_bind_show_xp;
2405*7c356e86SAndroid Build Coastguard Worker
2406*7c356e86SAndroid Build Coastguard Worker static void
x_bind_show_ch(unsigned char ch)2407*7c356e86SAndroid Build Coastguard Worker x_bind_show_ch(unsigned char ch)
2408*7c356e86SAndroid Build Coastguard Worker {
2409*7c356e86SAndroid Build Coastguard Worker Xcheck(x_bind_show_xs, x_bind_show_xp);
2410*7c356e86SAndroid Build Coastguard Worker switch (ch) {
2411*7c356e86SAndroid Build Coastguard Worker case ORD('^'):
2412*7c356e86SAndroid Build Coastguard Worker case ORD('\\'):
2413*7c356e86SAndroid Build Coastguard Worker case ORD('='):
2414*7c356e86SAndroid Build Coastguard Worker *x_bind_show_xp++ = '\\';
2415*7c356e86SAndroid Build Coastguard Worker *x_bind_show_xp++ = ch;
2416*7c356e86SAndroid Build Coastguard Worker break;
2417*7c356e86SAndroid Build Coastguard Worker default:
2418*7c356e86SAndroid Build Coastguard Worker if (ksh_isctrl(ch)) {
2419*7c356e86SAndroid Build Coastguard Worker *x_bind_show_xp++ = '^';
2420*7c356e86SAndroid Build Coastguard Worker *x_bind_show_xp++ = ksh_unctrl(ch);
2421*7c356e86SAndroid Build Coastguard Worker } else
2422*7c356e86SAndroid Build Coastguard Worker *x_bind_show_xp++ = ch;
2423*7c356e86SAndroid Build Coastguard Worker break;
2424*7c356e86SAndroid Build Coastguard Worker }
2425*7c356e86SAndroid Build Coastguard Worker }
2426*7c356e86SAndroid Build Coastguard Worker
2427*7c356e86SAndroid Build Coastguard Worker static void
x_bind_showone(int prefix,int key)2428*7c356e86SAndroid Build Coastguard Worker x_bind_showone(int prefix, int key)
2429*7c356e86SAndroid Build Coastguard Worker {
2430*7c356e86SAndroid Build Coastguard Worker unsigned char f = XFUNC_VALUE(x_tab[prefix][key]);
2431*7c356e86SAndroid Build Coastguard Worker
2432*7c356e86SAndroid Build Coastguard Worker if (!x_bind_show_xs.areap)
2433*7c356e86SAndroid Build Coastguard Worker XinitN(x_bind_show_xs, 16, AEDIT);
2434*7c356e86SAndroid Build Coastguard Worker
2435*7c356e86SAndroid Build Coastguard Worker x_bind_show_xp = Xstring(x_bind_show_xs, x_bind_show_xp);
2436*7c356e86SAndroid Build Coastguard Worker shf_puts("bind ", shl_stdout);
2437*7c356e86SAndroid Build Coastguard Worker #ifndef MKSH_SMALL
2438*7c356e86SAndroid Build Coastguard Worker if (f == XFUNC_ins_string)
2439*7c356e86SAndroid Build Coastguard Worker shf_puts("-m ", shl_stdout);
2440*7c356e86SAndroid Build Coastguard Worker #endif
2441*7c356e86SAndroid Build Coastguard Worker switch (prefix) {
2442*7c356e86SAndroid Build Coastguard Worker case 1:
2443*7c356e86SAndroid Build Coastguard Worker x_bind_show_ch(CTRL_BO);
2444*7c356e86SAndroid Build Coastguard Worker break;
2445*7c356e86SAndroid Build Coastguard Worker case 2:
2446*7c356e86SAndroid Build Coastguard Worker x_bind_show_ch(CTRL_X);
2447*7c356e86SAndroid Build Coastguard Worker break;
2448*7c356e86SAndroid Build Coastguard Worker case 3:
2449*7c356e86SAndroid Build Coastguard Worker x_bind_show_ch(0);
2450*7c356e86SAndroid Build Coastguard Worker break;
2451*7c356e86SAndroid Build Coastguard Worker }
2452*7c356e86SAndroid Build Coastguard Worker x_bind_show_ch(key);
2453*7c356e86SAndroid Build Coastguard Worker #ifndef MKSH_SMALL
2454*7c356e86SAndroid Build Coastguard Worker if (x_tab[prefix][key] & 0x80)
2455*7c356e86SAndroid Build Coastguard Worker *x_bind_show_xp++ = '~';
2456*7c356e86SAndroid Build Coastguard Worker #endif
2457*7c356e86SAndroid Build Coastguard Worker *x_bind_show_xp = '\0';
2458*7c356e86SAndroid Build Coastguard Worker x_bind_show_xp = Xstring(x_bind_show_xs, x_bind_show_xp);
2459*7c356e86SAndroid Build Coastguard Worker print_value_quoted(shl_stdout, x_bind_show_xp);
2460*7c356e86SAndroid Build Coastguard Worker shf_putc('=', shl_stdout);
2461*7c356e86SAndroid Build Coastguard Worker #ifndef MKSH_SMALL
2462*7c356e86SAndroid Build Coastguard Worker if (f == XFUNC_ins_string) {
2463*7c356e86SAndroid Build Coastguard Worker const unsigned char *cp = (const void *)x_atab[prefix][key];
2464*7c356e86SAndroid Build Coastguard Worker unsigned char c;
2465*7c356e86SAndroid Build Coastguard Worker
2466*7c356e86SAndroid Build Coastguard Worker while ((c = *cp++))
2467*7c356e86SAndroid Build Coastguard Worker x_bind_show_ch(c);
2468*7c356e86SAndroid Build Coastguard Worker *x_bind_show_xp = '\0';
2469*7c356e86SAndroid Build Coastguard Worker x_bind_show_xp = Xstring(x_bind_show_xs, x_bind_show_xp);
2470*7c356e86SAndroid Build Coastguard Worker print_value_quoted(shl_stdout, x_bind_show_xp);
2471*7c356e86SAndroid Build Coastguard Worker } else
2472*7c356e86SAndroid Build Coastguard Worker #endif
2473*7c356e86SAndroid Build Coastguard Worker shf_puts(x_ftab[f].xf_name, shl_stdout);
2474*7c356e86SAndroid Build Coastguard Worker shf_putc('\n', shl_stdout);
2475*7c356e86SAndroid Build Coastguard Worker }
2476*7c356e86SAndroid Build Coastguard Worker
2477*7c356e86SAndroid Build Coastguard Worker int
x_bind_list(void)2478*7c356e86SAndroid Build Coastguard Worker x_bind_list(void)
2479*7c356e86SAndroid Build Coastguard Worker {
2480*7c356e86SAndroid Build Coastguard Worker size_t f;
2481*7c356e86SAndroid Build Coastguard Worker
2482*7c356e86SAndroid Build Coastguard Worker for (f = 0; f < NELEM(x_ftab); f++)
2483*7c356e86SAndroid Build Coastguard Worker if (!(x_ftab[f].xf_flags & XF_NOBIND))
2484*7c356e86SAndroid Build Coastguard Worker shprintf(Tf_sN, x_ftab[f].xf_name);
2485*7c356e86SAndroid Build Coastguard Worker return (0);
2486*7c356e86SAndroid Build Coastguard Worker }
2487*7c356e86SAndroid Build Coastguard Worker
2488*7c356e86SAndroid Build Coastguard Worker int
x_bind_showall(void)2489*7c356e86SAndroid Build Coastguard Worker x_bind_showall(void)
2490*7c356e86SAndroid Build Coastguard Worker {
2491*7c356e86SAndroid Build Coastguard Worker int prefix, key;
2492*7c356e86SAndroid Build Coastguard Worker
2493*7c356e86SAndroid Build Coastguard Worker for (prefix = 0; prefix < X_NTABS; prefix++)
2494*7c356e86SAndroid Build Coastguard Worker for (key = 0; key < X_TABSZ; key++)
2495*7c356e86SAndroid Build Coastguard Worker switch (XFUNC_VALUE(x_tab[prefix][key])) {
2496*7c356e86SAndroid Build Coastguard Worker case XFUNC_error: /* unset */
2497*7c356e86SAndroid Build Coastguard Worker case XFUNC_insert: /* auto-insert */
2498*7c356e86SAndroid Build Coastguard Worker break;
2499*7c356e86SAndroid Build Coastguard Worker default:
2500*7c356e86SAndroid Build Coastguard Worker x_bind_showone(prefix, key);
2501*7c356e86SAndroid Build Coastguard Worker break;
2502*7c356e86SAndroid Build Coastguard Worker }
2503*7c356e86SAndroid Build Coastguard Worker return (0);
2504*7c356e86SAndroid Build Coastguard Worker }
2505*7c356e86SAndroid Build Coastguard Worker
2506*7c356e86SAndroid Build Coastguard Worker static unsigned int
x_bind_getc(const char ** ccpp)2507*7c356e86SAndroid Build Coastguard Worker x_bind_getc(const char **ccpp)
2508*7c356e86SAndroid Build Coastguard Worker {
2509*7c356e86SAndroid Build Coastguard Worker unsigned int ch, ec;
2510*7c356e86SAndroid Build Coastguard Worker
2511*7c356e86SAndroid Build Coastguard Worker if ((ch = ord(**ccpp)))
2512*7c356e86SAndroid Build Coastguard Worker ++(*ccpp);
2513*7c356e86SAndroid Build Coastguard Worker switch (ch) {
2514*7c356e86SAndroid Build Coastguard Worker case ORD('^'):
2515*7c356e86SAndroid Build Coastguard Worker ch = ksh_toctrl(**ccpp) | 0x100U;
2516*7c356e86SAndroid Build Coastguard Worker if (**ccpp)
2517*7c356e86SAndroid Build Coastguard Worker ++(*ccpp);
2518*7c356e86SAndroid Build Coastguard Worker break;
2519*7c356e86SAndroid Build Coastguard Worker case ORD('\\'):
2520*7c356e86SAndroid Build Coastguard Worker switch ((ec = ord(**ccpp))) {
2521*7c356e86SAndroid Build Coastguard Worker case ORD('^'):
2522*7c356e86SAndroid Build Coastguard Worker case ORD('\\'):
2523*7c356e86SAndroid Build Coastguard Worker case ORD('='):
2524*7c356e86SAndroid Build Coastguard Worker ch = ec | 0x100U;
2525*7c356e86SAndroid Build Coastguard Worker ++(*ccpp);
2526*7c356e86SAndroid Build Coastguard Worker break;
2527*7c356e86SAndroid Build Coastguard Worker }
2528*7c356e86SAndroid Build Coastguard Worker break;
2529*7c356e86SAndroid Build Coastguard Worker }
2530*7c356e86SAndroid Build Coastguard Worker return (ch);
2531*7c356e86SAndroid Build Coastguard Worker }
2532*7c356e86SAndroid Build Coastguard Worker
2533*7c356e86SAndroid Build Coastguard Worker int
x_bind(const char * s SMALLP (bool macro))2534*7c356e86SAndroid Build Coastguard Worker x_bind(const char *s SMALLP(bool macro))
2535*7c356e86SAndroid Build Coastguard Worker {
2536*7c356e86SAndroid Build Coastguard Worker const char *ccp = s;
2537*7c356e86SAndroid Build Coastguard Worker int prefix, key;
2538*7c356e86SAndroid Build Coastguard Worker unsigned int c;
2539*7c356e86SAndroid Build Coastguard Worker #ifndef MKSH_SMALL
2540*7c356e86SAndroid Build Coastguard Worker bool hastilde = false;
2541*7c356e86SAndroid Build Coastguard Worker char *ms = NULL;
2542*7c356e86SAndroid Build Coastguard Worker #endif
2543*7c356e86SAndroid Build Coastguard Worker
2544*7c356e86SAndroid Build Coastguard Worker prefix = 0;
2545*7c356e86SAndroid Build Coastguard Worker c = x_bind_getc(&ccp);
2546*7c356e86SAndroid Build Coastguard Worker if (!c || c == ORD('=')) {
2547*7c356e86SAndroid Build Coastguard Worker bi_errorf("no key to bind");
2548*7c356e86SAndroid Build Coastguard Worker return (1);
2549*7c356e86SAndroid Build Coastguard Worker }
2550*7c356e86SAndroid Build Coastguard Worker key = c & 0xFF;
2551*7c356e86SAndroid Build Coastguard Worker while ((c = x_bind_getc(&ccp)) != ORD('=')) {
2552*7c356e86SAndroid Build Coastguard Worker if (!c) {
2553*7c356e86SAndroid Build Coastguard Worker x_bind_showone(prefix, key);
2554*7c356e86SAndroid Build Coastguard Worker return (0);
2555*7c356e86SAndroid Build Coastguard Worker }
2556*7c356e86SAndroid Build Coastguard Worker switch (XFUNC_VALUE(x_tab[prefix][key])) {
2557*7c356e86SAndroid Build Coastguard Worker case XFUNC_meta1:
2558*7c356e86SAndroid Build Coastguard Worker prefix = 1;
2559*7c356e86SAndroid Build Coastguard Worker if (0)
2560*7c356e86SAndroid Build Coastguard Worker /* FALLTHROUGH */
2561*7c356e86SAndroid Build Coastguard Worker case XFUNC_meta2:
2562*7c356e86SAndroid Build Coastguard Worker prefix = 2;
2563*7c356e86SAndroid Build Coastguard Worker if (0)
2564*7c356e86SAndroid Build Coastguard Worker /* FALLTHROUGH */
2565*7c356e86SAndroid Build Coastguard Worker case XFUNC_meta3:
2566*7c356e86SAndroid Build Coastguard Worker prefix = 3;
2567*7c356e86SAndroid Build Coastguard Worker key = c & 0xFF;
2568*7c356e86SAndroid Build Coastguard Worker continue;
2569*7c356e86SAndroid Build Coastguard Worker }
2570*7c356e86SAndroid Build Coastguard Worker #ifndef MKSH_SMALL
2571*7c356e86SAndroid Build Coastguard Worker if (c == ORD('~')) {
2572*7c356e86SAndroid Build Coastguard Worker hastilde = true;
2573*7c356e86SAndroid Build Coastguard Worker continue;
2574*7c356e86SAndroid Build Coastguard Worker }
2575*7c356e86SAndroid Build Coastguard Worker #endif
2576*7c356e86SAndroid Build Coastguard Worker bi_errorf("too long key sequence: %s", s);
2577*7c356e86SAndroid Build Coastguard Worker return (-1);
2578*7c356e86SAndroid Build Coastguard Worker }
2579*7c356e86SAndroid Build Coastguard Worker
2580*7c356e86SAndroid Build Coastguard Worker #ifndef MKSH_SMALL
2581*7c356e86SAndroid Build Coastguard Worker if (macro) {
2582*7c356e86SAndroid Build Coastguard Worker char *cp;
2583*7c356e86SAndroid Build Coastguard Worker
2584*7c356e86SAndroid Build Coastguard Worker cp = ms = alloc(strlen(ccp) + 1, AEDIT);
2585*7c356e86SAndroid Build Coastguard Worker while ((c = x_bind_getc(&ccp)))
2586*7c356e86SAndroid Build Coastguard Worker *cp++ = c;
2587*7c356e86SAndroid Build Coastguard Worker *cp = '\0';
2588*7c356e86SAndroid Build Coastguard Worker c = XFUNC_ins_string;
2589*7c356e86SAndroid Build Coastguard Worker } else
2590*7c356e86SAndroid Build Coastguard Worker #endif
2591*7c356e86SAndroid Build Coastguard Worker if (!*ccp) {
2592*7c356e86SAndroid Build Coastguard Worker c = XFUNC_insert;
2593*7c356e86SAndroid Build Coastguard Worker } else {
2594*7c356e86SAndroid Build Coastguard Worker for (c = 0; c < NELEM(x_ftab); ++c)
2595*7c356e86SAndroid Build Coastguard Worker if (!strcmp(x_ftab[c].xf_name, ccp))
2596*7c356e86SAndroid Build Coastguard Worker break;
2597*7c356e86SAndroid Build Coastguard Worker if (c == NELEM(x_ftab) || x_ftab[c].xf_flags & XF_NOBIND) {
2598*7c356e86SAndroid Build Coastguard Worker bi_errorf("%s: no such editing command", ccp);
2599*7c356e86SAndroid Build Coastguard Worker return (1);
2600*7c356e86SAndroid Build Coastguard Worker }
2601*7c356e86SAndroid Build Coastguard Worker }
2602*7c356e86SAndroid Build Coastguard Worker
2603*7c356e86SAndroid Build Coastguard Worker #ifndef MKSH_SMALL
2604*7c356e86SAndroid Build Coastguard Worker if (XFUNC_VALUE(x_tab[prefix][key]) == XFUNC_ins_string)
2605*7c356e86SAndroid Build Coastguard Worker afree(x_atab[prefix][key], AEDIT);
2606*7c356e86SAndroid Build Coastguard Worker x_atab[prefix][key] = ms;
2607*7c356e86SAndroid Build Coastguard Worker if (hastilde)
2608*7c356e86SAndroid Build Coastguard Worker c |= 0x80U;
2609*7c356e86SAndroid Build Coastguard Worker #endif
2610*7c356e86SAndroid Build Coastguard Worker x_tab[prefix][key] = c;
2611*7c356e86SAndroid Build Coastguard Worker
2612*7c356e86SAndroid Build Coastguard Worker /* track what the user has bound, so x_mode(true) won't toast things */
2613*7c356e86SAndroid Build Coastguard Worker if (c == XFUNC_insert)
2614*7c356e86SAndroid Build Coastguard Worker x_bound[(prefix * X_TABSZ + key) / 8] &=
2615*7c356e86SAndroid Build Coastguard Worker ~(1 << ((prefix * X_TABSZ + key) % 8));
2616*7c356e86SAndroid Build Coastguard Worker else
2617*7c356e86SAndroid Build Coastguard Worker x_bound[(prefix * X_TABSZ + key) / 8] |=
2618*7c356e86SAndroid Build Coastguard Worker (1 << ((prefix * X_TABSZ + key) % 8));
2619*7c356e86SAndroid Build Coastguard Worker
2620*7c356e86SAndroid Build Coastguard Worker return (0);
2621*7c356e86SAndroid Build Coastguard Worker }
2622*7c356e86SAndroid Build Coastguard Worker
2623*7c356e86SAndroid Build Coastguard Worker static void
bind_if_not_bound(int p,int k,int func)2624*7c356e86SAndroid Build Coastguard Worker bind_if_not_bound(int p, int k, int func)
2625*7c356e86SAndroid Build Coastguard Worker {
2626*7c356e86SAndroid Build Coastguard Worker int t;
2627*7c356e86SAndroid Build Coastguard Worker
2628*7c356e86SAndroid Build Coastguard Worker /*
2629*7c356e86SAndroid Build Coastguard Worker * Has user already bound this key?
2630*7c356e86SAndroid Build Coastguard Worker * If so, do not override it.
2631*7c356e86SAndroid Build Coastguard Worker */
2632*7c356e86SAndroid Build Coastguard Worker t = p * X_TABSZ + k;
2633*7c356e86SAndroid Build Coastguard Worker if (x_bound[t >> 3] & (1 << (t & 7)))
2634*7c356e86SAndroid Build Coastguard Worker return;
2635*7c356e86SAndroid Build Coastguard Worker
2636*7c356e86SAndroid Build Coastguard Worker x_tab[p][k] = func;
2637*7c356e86SAndroid Build Coastguard Worker }
2638*7c356e86SAndroid Build Coastguard Worker
2639*7c356e86SAndroid Build Coastguard Worker static int
x_set_mark(int c MKSH_A_UNUSED)2640*7c356e86SAndroid Build Coastguard Worker x_set_mark(int c MKSH_A_UNUSED)
2641*7c356e86SAndroid Build Coastguard Worker {
2642*7c356e86SAndroid Build Coastguard Worker xmp = xcp;
2643*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2644*7c356e86SAndroid Build Coastguard Worker }
2645*7c356e86SAndroid Build Coastguard Worker
2646*7c356e86SAndroid Build Coastguard Worker static int
x_kill_region(int c MKSH_A_UNUSED)2647*7c356e86SAndroid Build Coastguard Worker x_kill_region(int c MKSH_A_UNUSED)
2648*7c356e86SAndroid Build Coastguard Worker {
2649*7c356e86SAndroid Build Coastguard Worker size_t rsize;
2650*7c356e86SAndroid Build Coastguard Worker char *xr;
2651*7c356e86SAndroid Build Coastguard Worker
2652*7c356e86SAndroid Build Coastguard Worker if (xmp == NULL) {
2653*7c356e86SAndroid Build Coastguard Worker x_e_putc2(KSH_BEL);
2654*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2655*7c356e86SAndroid Build Coastguard Worker }
2656*7c356e86SAndroid Build Coastguard Worker if (xmp > xcp) {
2657*7c356e86SAndroid Build Coastguard Worker rsize = xmp - xcp;
2658*7c356e86SAndroid Build Coastguard Worker xr = xcp;
2659*7c356e86SAndroid Build Coastguard Worker } else {
2660*7c356e86SAndroid Build Coastguard Worker rsize = xcp - xmp;
2661*7c356e86SAndroid Build Coastguard Worker xr = xmp;
2662*7c356e86SAndroid Build Coastguard Worker }
2663*7c356e86SAndroid Build Coastguard Worker x_goto(xr);
2664*7c356e86SAndroid Build Coastguard Worker x_delete(x_nb2nc(rsize), true);
2665*7c356e86SAndroid Build Coastguard Worker xmp = xr;
2666*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2667*7c356e86SAndroid Build Coastguard Worker }
2668*7c356e86SAndroid Build Coastguard Worker
2669*7c356e86SAndroid Build Coastguard Worker static int
x_xchg_point_mark(int c MKSH_A_UNUSED)2670*7c356e86SAndroid Build Coastguard Worker x_xchg_point_mark(int c MKSH_A_UNUSED)
2671*7c356e86SAndroid Build Coastguard Worker {
2672*7c356e86SAndroid Build Coastguard Worker char *tmp;
2673*7c356e86SAndroid Build Coastguard Worker
2674*7c356e86SAndroid Build Coastguard Worker if (xmp == NULL) {
2675*7c356e86SAndroid Build Coastguard Worker x_e_putc2(KSH_BEL);
2676*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2677*7c356e86SAndroid Build Coastguard Worker }
2678*7c356e86SAndroid Build Coastguard Worker tmp = xmp;
2679*7c356e86SAndroid Build Coastguard Worker xmp = xcp;
2680*7c356e86SAndroid Build Coastguard Worker x_goto(tmp);
2681*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2682*7c356e86SAndroid Build Coastguard Worker }
2683*7c356e86SAndroid Build Coastguard Worker
2684*7c356e86SAndroid Build Coastguard Worker static int
x_noop(int c MKSH_A_UNUSED)2685*7c356e86SAndroid Build Coastguard Worker x_noop(int c MKSH_A_UNUSED)
2686*7c356e86SAndroid Build Coastguard Worker {
2687*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2688*7c356e86SAndroid Build Coastguard Worker }
2689*7c356e86SAndroid Build Coastguard Worker
2690*7c356e86SAndroid Build Coastguard Worker /*
2691*7c356e86SAndroid Build Coastguard Worker * File/command name completion routines
2692*7c356e86SAndroid Build Coastguard Worker */
2693*7c356e86SAndroid Build Coastguard Worker static int
x_comp_comm(int c MKSH_A_UNUSED)2694*7c356e86SAndroid Build Coastguard Worker x_comp_comm(int c MKSH_A_UNUSED)
2695*7c356e86SAndroid Build Coastguard Worker {
2696*7c356e86SAndroid Build Coastguard Worker do_complete(XCF_COMMAND, CT_COMPLETE);
2697*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2698*7c356e86SAndroid Build Coastguard Worker }
2699*7c356e86SAndroid Build Coastguard Worker
2700*7c356e86SAndroid Build Coastguard Worker static int
x_list_comm(int c MKSH_A_UNUSED)2701*7c356e86SAndroid Build Coastguard Worker x_list_comm(int c MKSH_A_UNUSED)
2702*7c356e86SAndroid Build Coastguard Worker {
2703*7c356e86SAndroid Build Coastguard Worker do_complete(XCF_COMMAND, CT_LIST);
2704*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2705*7c356e86SAndroid Build Coastguard Worker }
2706*7c356e86SAndroid Build Coastguard Worker
2707*7c356e86SAndroid Build Coastguard Worker static int
x_complete(int c MKSH_A_UNUSED)2708*7c356e86SAndroid Build Coastguard Worker x_complete(int c MKSH_A_UNUSED)
2709*7c356e86SAndroid Build Coastguard Worker {
2710*7c356e86SAndroid Build Coastguard Worker do_complete(XCF_COMMAND_FILE, CT_COMPLETE);
2711*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2712*7c356e86SAndroid Build Coastguard Worker }
2713*7c356e86SAndroid Build Coastguard Worker
2714*7c356e86SAndroid Build Coastguard Worker static int
x_enumerate(int c MKSH_A_UNUSED)2715*7c356e86SAndroid Build Coastguard Worker x_enumerate(int c MKSH_A_UNUSED)
2716*7c356e86SAndroid Build Coastguard Worker {
2717*7c356e86SAndroid Build Coastguard Worker do_complete(XCF_COMMAND_FILE, CT_LIST);
2718*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2719*7c356e86SAndroid Build Coastguard Worker }
2720*7c356e86SAndroid Build Coastguard Worker
2721*7c356e86SAndroid Build Coastguard Worker static int
x_comp_file(int c MKSH_A_UNUSED)2722*7c356e86SAndroid Build Coastguard Worker x_comp_file(int c MKSH_A_UNUSED)
2723*7c356e86SAndroid Build Coastguard Worker {
2724*7c356e86SAndroid Build Coastguard Worker do_complete(XCF_FILE, CT_COMPLETE);
2725*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2726*7c356e86SAndroid Build Coastguard Worker }
2727*7c356e86SAndroid Build Coastguard Worker
2728*7c356e86SAndroid Build Coastguard Worker static int
x_list_file(int c MKSH_A_UNUSED)2729*7c356e86SAndroid Build Coastguard Worker x_list_file(int c MKSH_A_UNUSED)
2730*7c356e86SAndroid Build Coastguard Worker {
2731*7c356e86SAndroid Build Coastguard Worker do_complete(XCF_FILE, CT_LIST);
2732*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2733*7c356e86SAndroid Build Coastguard Worker }
2734*7c356e86SAndroid Build Coastguard Worker
2735*7c356e86SAndroid Build Coastguard Worker static int
x_comp_list(int c MKSH_A_UNUSED)2736*7c356e86SAndroid Build Coastguard Worker x_comp_list(int c MKSH_A_UNUSED)
2737*7c356e86SAndroid Build Coastguard Worker {
2738*7c356e86SAndroid Build Coastguard Worker do_complete(XCF_COMMAND_FILE, CT_COMPLIST);
2739*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2740*7c356e86SAndroid Build Coastguard Worker }
2741*7c356e86SAndroid Build Coastguard Worker
2742*7c356e86SAndroid Build Coastguard Worker static int
x_expand(int c MKSH_A_UNUSED)2743*7c356e86SAndroid Build Coastguard Worker x_expand(int c MKSH_A_UNUSED)
2744*7c356e86SAndroid Build Coastguard Worker {
2745*7c356e86SAndroid Build Coastguard Worker char **words;
2746*7c356e86SAndroid Build Coastguard Worker int start, end, nwords, i;
2747*7c356e86SAndroid Build Coastguard Worker
2748*7c356e86SAndroid Build Coastguard Worker i = XCF_FILE;
2749*7c356e86SAndroid Build Coastguard Worker nwords = x_cf_glob(&i, xbuf, xep - xbuf, xcp - xbuf,
2750*7c356e86SAndroid Build Coastguard Worker &start, &end, &words);
2751*7c356e86SAndroid Build Coastguard Worker
2752*7c356e86SAndroid Build Coastguard Worker if (nwords == 0) {
2753*7c356e86SAndroid Build Coastguard Worker x_e_putc2(KSH_BEL);
2754*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2755*7c356e86SAndroid Build Coastguard Worker }
2756*7c356e86SAndroid Build Coastguard Worker x_goto(xbuf + start);
2757*7c356e86SAndroid Build Coastguard Worker x_delete(x_nb2nc(end - start), false);
2758*7c356e86SAndroid Build Coastguard Worker
2759*7c356e86SAndroid Build Coastguard Worker i = 0;
2760*7c356e86SAndroid Build Coastguard Worker while (i < nwords) {
2761*7c356e86SAndroid Build Coastguard Worker if (x_escape(words[i], strlen(words[i]), x_do_ins) < 0 ||
2762*7c356e86SAndroid Build Coastguard Worker (++i < nwords && x_ins(T1space) < 0)) {
2763*7c356e86SAndroid Build Coastguard Worker x_e_putc2(KSH_BEL);
2764*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2765*7c356e86SAndroid Build Coastguard Worker }
2766*7c356e86SAndroid Build Coastguard Worker }
2767*7c356e86SAndroid Build Coastguard Worker x_adjust();
2768*7c356e86SAndroid Build Coastguard Worker
2769*7c356e86SAndroid Build Coastguard Worker return (KSTD);
2770*7c356e86SAndroid Build Coastguard Worker }
2771*7c356e86SAndroid Build Coastguard Worker
2772*7c356e86SAndroid Build Coastguard Worker static void
do_complete(int flags,Comp_type type)2773*7c356e86SAndroid Build Coastguard Worker do_complete(
2774*7c356e86SAndroid Build Coastguard Worker /* XCF_{COMMAND,FILE,COMMAND_FILE} */
2775*7c356e86SAndroid Build Coastguard Worker int flags,
2776*7c356e86SAndroid Build Coastguard Worker /* 0 for list, 1 for complete and 2 for complete-list */
2777*7c356e86SAndroid Build Coastguard Worker Comp_type type)
2778*7c356e86SAndroid Build Coastguard Worker {
2779*7c356e86SAndroid Build Coastguard Worker char **words;
2780*7c356e86SAndroid Build Coastguard Worker int start, end, nlen, olen, nwords;
2781*7c356e86SAndroid Build Coastguard Worker bool completed;
2782*7c356e86SAndroid Build Coastguard Worker
2783*7c356e86SAndroid Build Coastguard Worker nwords = x_cf_glob(&flags, xbuf, xep - xbuf, xcp - xbuf,
2784*7c356e86SAndroid Build Coastguard Worker &start, &end, &words);
2785*7c356e86SAndroid Build Coastguard Worker /* no match */
2786*7c356e86SAndroid Build Coastguard Worker if (nwords == 0) {
2787*7c356e86SAndroid Build Coastguard Worker x_e_putc2(KSH_BEL);
2788*7c356e86SAndroid Build Coastguard Worker return;
2789*7c356e86SAndroid Build Coastguard Worker }
2790*7c356e86SAndroid Build Coastguard Worker if (type == CT_LIST) {
2791*7c356e86SAndroid Build Coastguard Worker x_print_expansions(nwords, words,
2792*7c356e86SAndroid Build Coastguard Worker tobool(flags & XCF_IS_COMMAND));
2793*7c356e86SAndroid Build Coastguard Worker x_redraw(0);
2794*7c356e86SAndroid Build Coastguard Worker x_free_words(nwords, words);
2795*7c356e86SAndroid Build Coastguard Worker return;
2796*7c356e86SAndroid Build Coastguard Worker }
2797*7c356e86SAndroid Build Coastguard Worker olen = end - start;
2798*7c356e86SAndroid Build Coastguard Worker nlen = x_longest_prefix(nwords, words);
2799*7c356e86SAndroid Build Coastguard Worker if (nwords == 1) {
2800*7c356e86SAndroid Build Coastguard Worker /*
2801*7c356e86SAndroid Build Coastguard Worker * always complete single matches;
2802*7c356e86SAndroid Build Coastguard Worker * any expansion of parameter substitution
2803*7c356e86SAndroid Build Coastguard Worker * is always at most one result, too
2804*7c356e86SAndroid Build Coastguard Worker */
2805*7c356e86SAndroid Build Coastguard Worker completed = true;
2806*7c356e86SAndroid Build Coastguard Worker } else {
2807*7c356e86SAndroid Build Coastguard Worker char *unescaped;
2808*7c356e86SAndroid Build Coastguard Worker
2809*7c356e86SAndroid Build Coastguard Worker /* make a copy of the original string part */
2810*7c356e86SAndroid Build Coastguard Worker strndupx(unescaped, xbuf + start, olen, ATEMP);
2811*7c356e86SAndroid Build Coastguard Worker
2812*7c356e86SAndroid Build Coastguard Worker /* expand any tilde and unescape the string for comparison */
2813*7c356e86SAndroid Build Coastguard Worker unescaped = x_glob_hlp_tilde_and_rem_qchar(unescaped, true);
2814*7c356e86SAndroid Build Coastguard Worker
2815*7c356e86SAndroid Build Coastguard Worker /*
2816*7c356e86SAndroid Build Coastguard Worker * match iff entire original string is part of the
2817*7c356e86SAndroid Build Coastguard Worker * longest prefix, implying the latter is at least
2818*7c356e86SAndroid Build Coastguard Worker * the same size (after unescaping)
2819*7c356e86SAndroid Build Coastguard Worker */
2820*7c356e86SAndroid Build Coastguard Worker completed = !strncmp(words[0], unescaped, strlen(unescaped));
2821*7c356e86SAndroid Build Coastguard Worker
2822*7c356e86SAndroid Build Coastguard Worker afree(unescaped, ATEMP);
2823*7c356e86SAndroid Build Coastguard Worker }
2824*7c356e86SAndroid Build Coastguard Worker if (type == CT_COMPLIST && nwords > 1) {
2825*7c356e86SAndroid Build Coastguard Worker /*
2826*7c356e86SAndroid Build Coastguard Worker * print expansions, since we didn't get back
2827*7c356e86SAndroid Build Coastguard Worker * just a single match
2828*7c356e86SAndroid Build Coastguard Worker */
2829*7c356e86SAndroid Build Coastguard Worker x_print_expansions(nwords, words,
2830*7c356e86SAndroid Build Coastguard Worker tobool(flags & XCF_IS_COMMAND));
2831*7c356e86SAndroid Build Coastguard Worker }
2832*7c356e86SAndroid Build Coastguard Worker if (completed) {
2833*7c356e86SAndroid Build Coastguard Worker /* expand on the command line */
2834*7c356e86SAndroid Build Coastguard Worker xmp = NULL;
2835*7c356e86SAndroid Build Coastguard Worker xcp = xbuf + start;
2836*7c356e86SAndroid Build Coastguard Worker xep -= olen;
2837*7c356e86SAndroid Build Coastguard Worker memmove(xcp, xcp + olen, xep - xcp + 1);
2838*7c356e86SAndroid Build Coastguard Worker x_escape(words[0], nlen, x_do_ins);
2839*7c356e86SAndroid Build Coastguard Worker }
2840*7c356e86SAndroid Build Coastguard Worker x_adjust();
2841*7c356e86SAndroid Build Coastguard Worker /*
2842*7c356e86SAndroid Build Coastguard Worker * append a space if this is a single non-directory match
2843*7c356e86SAndroid Build Coastguard Worker * and not a parameter or homedir substitution
2844*7c356e86SAndroid Build Coastguard Worker */
2845*7c356e86SAndroid Build Coastguard Worker if (nwords == 1 && !mksh_cdirsep(words[0][nlen - 1]) &&
2846*7c356e86SAndroid Build Coastguard Worker !(flags & XCF_IS_NOSPACE)) {
2847*7c356e86SAndroid Build Coastguard Worker x_ins(T1space);
2848*7c356e86SAndroid Build Coastguard Worker }
2849*7c356e86SAndroid Build Coastguard Worker
2850*7c356e86SAndroid Build Coastguard Worker x_free_words(nwords, words);
2851*7c356e86SAndroid Build Coastguard Worker }
2852*7c356e86SAndroid Build Coastguard Worker
2853*7c356e86SAndroid Build Coastguard Worker /*-
2854*7c356e86SAndroid Build Coastguard Worker * NAME:
2855*7c356e86SAndroid Build Coastguard Worker * x_adjust - redraw the line adjusting starting point etc.
2856*7c356e86SAndroid Build Coastguard Worker *
2857*7c356e86SAndroid Build Coastguard Worker * DESCRIPTION:
2858*7c356e86SAndroid Build Coastguard Worker * This function is called when we have exceeded the bounds
2859*7c356e86SAndroid Build Coastguard Worker * of the edit window. It increments x_adj_done so that
2860*7c356e86SAndroid Build Coastguard Worker * functions like x_ins and x_delete know that we have been
2861*7c356e86SAndroid Build Coastguard Worker * called and can skip the x_bs() stuff which has already
2862*7c356e86SAndroid Build Coastguard Worker * been done by x_redraw.
2863*7c356e86SAndroid Build Coastguard Worker *
2864*7c356e86SAndroid Build Coastguard Worker * RETURN VALUE:
2865*7c356e86SAndroid Build Coastguard Worker * None
2866*7c356e86SAndroid Build Coastguard Worker */
2867*7c356e86SAndroid Build Coastguard Worker static void
x_adjust(void)2868*7c356e86SAndroid Build Coastguard Worker x_adjust(void)
2869*7c356e86SAndroid Build Coastguard Worker {
2870*7c356e86SAndroid Build Coastguard Worker int col_left, n;
2871*7c356e86SAndroid Build Coastguard Worker
2872*7c356e86SAndroid Build Coastguard Worker /* flag the fact that we were called */
2873*7c356e86SAndroid Build Coastguard Worker x_adj_done++;
2874*7c356e86SAndroid Build Coastguard Worker
2875*7c356e86SAndroid Build Coastguard Worker /*
2876*7c356e86SAndroid Build Coastguard Worker * calculate the amount of columns we need to "go back"
2877*7c356e86SAndroid Build Coastguard Worker * from xcp to set xbp to (but never < xbuf) to 2/3 of
2878*7c356e86SAndroid Build Coastguard Worker * the display width; take care of pwidth though
2879*7c356e86SAndroid Build Coastguard Worker */
2880*7c356e86SAndroid Build Coastguard Worker if ((col_left = xx_cols * 2 / 3) < MIN_EDIT_SPACE) {
2881*7c356e86SAndroid Build Coastguard Worker /*
2882*7c356e86SAndroid Build Coastguard Worker * cowardly refuse to do anything
2883*7c356e86SAndroid Build Coastguard Worker * if the available space is too small;
2884*7c356e86SAndroid Build Coastguard Worker * fall back to dumb pdksh code
2885*7c356e86SAndroid Build Coastguard Worker */
2886*7c356e86SAndroid Build Coastguard Worker if ((xbp = xcp - (x_displen / 2)) < xbuf)
2887*7c356e86SAndroid Build Coastguard Worker xbp = xbuf;
2888*7c356e86SAndroid Build Coastguard Worker /* elide UTF-8 fixup as penalty */
2889*7c356e86SAndroid Build Coastguard Worker goto x_adjust_out;
2890*7c356e86SAndroid Build Coastguard Worker }
2891*7c356e86SAndroid Build Coastguard Worker
2892*7c356e86SAndroid Build Coastguard Worker /* fix up xbp to just past a character end first */
2893*7c356e86SAndroid Build Coastguard Worker xbp = xcp >= xep ? xep : x_bs0(xcp, xbuf);
2894*7c356e86SAndroid Build Coastguard Worker /* walk backwards */
2895*7c356e86SAndroid Build Coastguard Worker while (xbp > xbuf && col_left > 0) {
2896*7c356e86SAndroid Build Coastguard Worker xbp = x_bs0(xbp - 1, xbuf);
2897*7c356e86SAndroid Build Coastguard Worker col_left -= (n = x_size2(xbp, NULL));
2898*7c356e86SAndroid Build Coastguard Worker }
2899*7c356e86SAndroid Build Coastguard Worker /* check if we hit the prompt */
2900*7c356e86SAndroid Build Coastguard Worker if (xbp == xbuf && xcp != xbuf && col_left >= 0 && col_left < pwidth) {
2901*7c356e86SAndroid Build Coastguard Worker /* so we did; force scrolling occurs */
2902*7c356e86SAndroid Build Coastguard Worker xbp += utf_ptradj(xbp);
2903*7c356e86SAndroid Build Coastguard Worker }
2904*7c356e86SAndroid Build Coastguard Worker
2905*7c356e86SAndroid Build Coastguard Worker x_adjust_out:
2906*7c356e86SAndroid Build Coastguard Worker xlp_valid = false;
2907*7c356e86SAndroid Build Coastguard Worker x_redraw('\r');
2908*7c356e86SAndroid Build Coastguard Worker x_flush();
2909*7c356e86SAndroid Build Coastguard Worker }
2910*7c356e86SAndroid Build Coastguard Worker
2911*7c356e86SAndroid Build Coastguard Worker static void
x_e_ungetc(int c)2912*7c356e86SAndroid Build Coastguard Worker x_e_ungetc(int c)
2913*7c356e86SAndroid Build Coastguard Worker {
2914*7c356e86SAndroid Build Coastguard Worker unget_char = c < 0 ? -1 : (c & 255);
2915*7c356e86SAndroid Build Coastguard Worker }
2916*7c356e86SAndroid Build Coastguard Worker
2917*7c356e86SAndroid Build Coastguard Worker static int
x_e_getc(void)2918*7c356e86SAndroid Build Coastguard Worker x_e_getc(void)
2919*7c356e86SAndroid Build Coastguard Worker {
2920*7c356e86SAndroid Build Coastguard Worker int c;
2921*7c356e86SAndroid Build Coastguard Worker
2922*7c356e86SAndroid Build Coastguard Worker if (unget_char >= 0) {
2923*7c356e86SAndroid Build Coastguard Worker c = unget_char;
2924*7c356e86SAndroid Build Coastguard Worker unget_char = -1;
2925*7c356e86SAndroid Build Coastguard Worker return (c);
2926*7c356e86SAndroid Build Coastguard Worker }
2927*7c356e86SAndroid Build Coastguard Worker
2928*7c356e86SAndroid Build Coastguard Worker #ifndef MKSH_SMALL
2929*7c356e86SAndroid Build Coastguard Worker if (macroptr) {
2930*7c356e86SAndroid Build Coastguard Worker if ((c = (unsigned char)*macroptr++))
2931*7c356e86SAndroid Build Coastguard Worker return (c);
2932*7c356e86SAndroid Build Coastguard Worker macroptr = NULL;
2933*7c356e86SAndroid Build Coastguard Worker }
2934*7c356e86SAndroid Build Coastguard Worker #endif
2935*7c356e86SAndroid Build Coastguard Worker
2936*7c356e86SAndroid Build Coastguard Worker return (x_getc());
2937*7c356e86SAndroid Build Coastguard Worker }
2938*7c356e86SAndroid Build Coastguard Worker
2939*7c356e86SAndroid Build Coastguard Worker static void
x_e_putc2(int c)2940*7c356e86SAndroid Build Coastguard Worker x_e_putc2(int c)
2941*7c356e86SAndroid Build Coastguard Worker {
2942*7c356e86SAndroid Build Coastguard Worker int width = 1;
2943*7c356e86SAndroid Build Coastguard Worker
2944*7c356e86SAndroid Build Coastguard Worker if (ctype(c, C_CR | C_LF))
2945*7c356e86SAndroid Build Coastguard Worker x_col = 0;
2946*7c356e86SAndroid Build Coastguard Worker if (x_col < xx_cols) {
2947*7c356e86SAndroid Build Coastguard Worker #ifndef MKSH_EBCDIC
2948*7c356e86SAndroid Build Coastguard Worker if (UTFMODE && (c > 0x7F)) {
2949*7c356e86SAndroid Build Coastguard Worker char utf_tmp[3];
2950*7c356e86SAndroid Build Coastguard Worker size_t x;
2951*7c356e86SAndroid Build Coastguard Worker
2952*7c356e86SAndroid Build Coastguard Worker if (c < 0xA0)
2953*7c356e86SAndroid Build Coastguard Worker c = 0xFFFD;
2954*7c356e86SAndroid Build Coastguard Worker x = utf_wctomb(utf_tmp, c);
2955*7c356e86SAndroid Build Coastguard Worker x_putc(utf_tmp[0]);
2956*7c356e86SAndroid Build Coastguard Worker if (x > 1)
2957*7c356e86SAndroid Build Coastguard Worker x_putc(utf_tmp[1]);
2958*7c356e86SAndroid Build Coastguard Worker if (x > 2)
2959*7c356e86SAndroid Build Coastguard Worker x_putc(utf_tmp[2]);
2960*7c356e86SAndroid Build Coastguard Worker width = utf_wcwidth(c);
2961*7c356e86SAndroid Build Coastguard Worker } else
2962*7c356e86SAndroid Build Coastguard Worker #endif
2963*7c356e86SAndroid Build Coastguard Worker x_putc(c);
2964*7c356e86SAndroid Build Coastguard Worker switch (c) {
2965*7c356e86SAndroid Build Coastguard Worker case KSH_BEL:
2966*7c356e86SAndroid Build Coastguard Worker break;
2967*7c356e86SAndroid Build Coastguard Worker case '\r':
2968*7c356e86SAndroid Build Coastguard Worker case '\n':
2969*7c356e86SAndroid Build Coastguard Worker break;
2970*7c356e86SAndroid Build Coastguard Worker case '\b':
2971*7c356e86SAndroid Build Coastguard Worker x_col--;
2972*7c356e86SAndroid Build Coastguard Worker break;
2973*7c356e86SAndroid Build Coastguard Worker default:
2974*7c356e86SAndroid Build Coastguard Worker x_col += width;
2975*7c356e86SAndroid Build Coastguard Worker break;
2976*7c356e86SAndroid Build Coastguard Worker }
2977*7c356e86SAndroid Build Coastguard Worker }
2978*7c356e86SAndroid Build Coastguard Worker if (x_adj_ok && (x_col < 0 || x_col >= (xx_cols - 2)))
2979*7c356e86SAndroid Build Coastguard Worker x_adjust();
2980*7c356e86SAndroid Build Coastguard Worker }
2981*7c356e86SAndroid Build Coastguard Worker
2982*7c356e86SAndroid Build Coastguard Worker static void
x_e_putc3(const char ** cp)2983*7c356e86SAndroid Build Coastguard Worker x_e_putc3(const char **cp)
2984*7c356e86SAndroid Build Coastguard Worker {
2985*7c356e86SAndroid Build Coastguard Worker int width = 1, c = **(const unsigned char **)cp;
2986*7c356e86SAndroid Build Coastguard Worker
2987*7c356e86SAndroid Build Coastguard Worker if (ctype(c, C_CR | C_LF))
2988*7c356e86SAndroid Build Coastguard Worker x_col = 0;
2989*7c356e86SAndroid Build Coastguard Worker if (x_col < xx_cols) {
2990*7c356e86SAndroid Build Coastguard Worker if (UTFMODE && (c > 0x7F)) {
2991*7c356e86SAndroid Build Coastguard Worker char *cp2;
2992*7c356e86SAndroid Build Coastguard Worker
2993*7c356e86SAndroid Build Coastguard Worker width = utf_widthadj(*cp, (const char **)&cp2);
2994*7c356e86SAndroid Build Coastguard Worker if (cp2 == *cp + 1) {
2995*7c356e86SAndroid Build Coastguard Worker (*cp)++;
2996*7c356e86SAndroid Build Coastguard Worker #ifdef MKSH_EBCDIC
2997*7c356e86SAndroid Build Coastguard Worker x_putc(asc2rtt(0xEF));
2998*7c356e86SAndroid Build Coastguard Worker x_putc(asc2rtt(0xBF));
2999*7c356e86SAndroid Build Coastguard Worker x_putc(asc2rtt(0xBD));
3000*7c356e86SAndroid Build Coastguard Worker #else
3001*7c356e86SAndroid Build Coastguard Worker shf_puts("\xEF\xBF\xBD", shl_out);
3002*7c356e86SAndroid Build Coastguard Worker #endif
3003*7c356e86SAndroid Build Coastguard Worker } else
3004*7c356e86SAndroid Build Coastguard Worker while (*cp < cp2)
3005*7c356e86SAndroid Build Coastguard Worker x_putcf(*(*cp)++);
3006*7c356e86SAndroid Build Coastguard Worker } else {
3007*7c356e86SAndroid Build Coastguard Worker (*cp)++;
3008*7c356e86SAndroid Build Coastguard Worker x_putc(c);
3009*7c356e86SAndroid Build Coastguard Worker }
3010*7c356e86SAndroid Build Coastguard Worker switch (c) {
3011*7c356e86SAndroid Build Coastguard Worker case KSH_BEL:
3012*7c356e86SAndroid Build Coastguard Worker break;
3013*7c356e86SAndroid Build Coastguard Worker case '\r':
3014*7c356e86SAndroid Build Coastguard Worker case '\n':
3015*7c356e86SAndroid Build Coastguard Worker break;
3016*7c356e86SAndroid Build Coastguard Worker case '\b':
3017*7c356e86SAndroid Build Coastguard Worker x_col--;
3018*7c356e86SAndroid Build Coastguard Worker break;
3019*7c356e86SAndroid Build Coastguard Worker default:
3020*7c356e86SAndroid Build Coastguard Worker x_col += width;
3021*7c356e86SAndroid Build Coastguard Worker break;
3022*7c356e86SAndroid Build Coastguard Worker }
3023*7c356e86SAndroid Build Coastguard Worker }
3024*7c356e86SAndroid Build Coastguard Worker if (x_adj_ok && (x_col < 0 || x_col >= (xx_cols - 2)))
3025*7c356e86SAndroid Build Coastguard Worker x_adjust();
3026*7c356e86SAndroid Build Coastguard Worker }
3027*7c356e86SAndroid Build Coastguard Worker
3028*7c356e86SAndroid Build Coastguard Worker static void
x_e_puts(const char * s)3029*7c356e86SAndroid Build Coastguard Worker x_e_puts(const char *s)
3030*7c356e86SAndroid Build Coastguard Worker {
3031*7c356e86SAndroid Build Coastguard Worker int adj = x_adj_done;
3032*7c356e86SAndroid Build Coastguard Worker
3033*7c356e86SAndroid Build Coastguard Worker while (*s && adj == x_adj_done)
3034*7c356e86SAndroid Build Coastguard Worker x_e_putc3(&s);
3035*7c356e86SAndroid Build Coastguard Worker }
3036*7c356e86SAndroid Build Coastguard Worker
3037*7c356e86SAndroid Build Coastguard Worker /*-
3038*7c356e86SAndroid Build Coastguard Worker * NAME:
3039*7c356e86SAndroid Build Coastguard Worker * x_set_arg - set an arg value for next function
3040*7c356e86SAndroid Build Coastguard Worker *
3041*7c356e86SAndroid Build Coastguard Worker * DESCRIPTION:
3042*7c356e86SAndroid Build Coastguard Worker * This is a simple implementation of M-[0-9].
3043*7c356e86SAndroid Build Coastguard Worker *
3044*7c356e86SAndroid Build Coastguard Worker * RETURN VALUE:
3045*7c356e86SAndroid Build Coastguard Worker * KSTD
3046*7c356e86SAndroid Build Coastguard Worker */
3047*7c356e86SAndroid Build Coastguard Worker static int
x_set_arg(int c)3048*7c356e86SAndroid Build Coastguard Worker x_set_arg(int c)
3049*7c356e86SAndroid Build Coastguard Worker {
3050*7c356e86SAndroid Build Coastguard Worker unsigned int n = 0;
3051*7c356e86SAndroid Build Coastguard Worker bool first = true;
3052*7c356e86SAndroid Build Coastguard Worker
3053*7c356e86SAndroid Build Coastguard Worker /* strip command prefix */
3054*7c356e86SAndroid Build Coastguard Worker c &= 255;
3055*7c356e86SAndroid Build Coastguard Worker while (c >= 0 && ctype(c, C_DIGIT)) {
3056*7c356e86SAndroid Build Coastguard Worker n = n * 10 + ksh_numdig(c);
3057*7c356e86SAndroid Build Coastguard Worker if (n > LINE)
3058*7c356e86SAndroid Build Coastguard Worker /* upper bound for repeat */
3059*7c356e86SAndroid Build Coastguard Worker goto x_set_arg_too_big;
3060*7c356e86SAndroid Build Coastguard Worker c = x_e_getc();
3061*7c356e86SAndroid Build Coastguard Worker first = false;
3062*7c356e86SAndroid Build Coastguard Worker }
3063*7c356e86SAndroid Build Coastguard Worker if (c < 0 || first) {
3064*7c356e86SAndroid Build Coastguard Worker x_set_arg_too_big:
3065*7c356e86SAndroid Build Coastguard Worker x_e_putc2(KSH_BEL);
3066*7c356e86SAndroid Build Coastguard Worker x_arg = 1;
3067*7c356e86SAndroid Build Coastguard Worker x_arg_defaulted = true;
3068*7c356e86SAndroid Build Coastguard Worker } else {
3069*7c356e86SAndroid Build Coastguard Worker x_e_ungetc(c);
3070*7c356e86SAndroid Build Coastguard Worker x_arg = n;
3071*7c356e86SAndroid Build Coastguard Worker x_arg_defaulted = false;
3072*7c356e86SAndroid Build Coastguard Worker }
3073*7c356e86SAndroid Build Coastguard Worker return (KSTD);
3074*7c356e86SAndroid Build Coastguard Worker }
3075*7c356e86SAndroid Build Coastguard Worker
3076*7c356e86SAndroid Build Coastguard Worker /* Comment or uncomment the current line. */
3077*7c356e86SAndroid Build Coastguard Worker static int
x_comment(int c MKSH_A_UNUSED)3078*7c356e86SAndroid Build Coastguard Worker x_comment(int c MKSH_A_UNUSED)
3079*7c356e86SAndroid Build Coastguard Worker {
3080*7c356e86SAndroid Build Coastguard Worker ssize_t len = xep - xbuf;
3081*7c356e86SAndroid Build Coastguard Worker int ret = x_do_comment(xbuf, xend - xbuf, &len);
3082*7c356e86SAndroid Build Coastguard Worker
3083*7c356e86SAndroid Build Coastguard Worker if (ret < 0)
3084*7c356e86SAndroid Build Coastguard Worker x_e_putc2(KSH_BEL);
3085*7c356e86SAndroid Build Coastguard Worker else {
3086*7c356e86SAndroid Build Coastguard Worker x_modified();
3087*7c356e86SAndroid Build Coastguard Worker xep = xbuf + len;
3088*7c356e86SAndroid Build Coastguard Worker *xep = '\0';
3089*7c356e86SAndroid Build Coastguard Worker xcp = xbp = xbuf;
3090*7c356e86SAndroid Build Coastguard Worker x_redraw('\r');
3091*7c356e86SAndroid Build Coastguard Worker if (ret > 0)
3092*7c356e86SAndroid Build Coastguard Worker return (x_newline('\n'));
3093*7c356e86SAndroid Build Coastguard Worker }
3094*7c356e86SAndroid Build Coastguard Worker return (KSTD);
3095*7c356e86SAndroid Build Coastguard Worker }
3096*7c356e86SAndroid Build Coastguard Worker
3097*7c356e86SAndroid Build Coastguard Worker static int
x_version(int c MKSH_A_UNUSED)3098*7c356e86SAndroid Build Coastguard Worker x_version(int c MKSH_A_UNUSED)
3099*7c356e86SAndroid Build Coastguard Worker {
3100*7c356e86SAndroid Build Coastguard Worker char *o_xbuf = xbuf, *o_xend = xend;
3101*7c356e86SAndroid Build Coastguard Worker char *o_xbp = xbp, *o_xep = xep, *o_xcp = xcp;
3102*7c356e86SAndroid Build Coastguard Worker char *v;
3103*7c356e86SAndroid Build Coastguard Worker
3104*7c356e86SAndroid Build Coastguard Worker strdupx(v, KSH_VERSION, ATEMP);
3105*7c356e86SAndroid Build Coastguard Worker
3106*7c356e86SAndroid Build Coastguard Worker xbuf = xbp = xcp = v;
3107*7c356e86SAndroid Build Coastguard Worker xend = xep = strnul(v);
3108*7c356e86SAndroid Build Coastguard Worker x_redraw('\r');
3109*7c356e86SAndroid Build Coastguard Worker x_flush();
3110*7c356e86SAndroid Build Coastguard Worker
3111*7c356e86SAndroid Build Coastguard Worker c = x_e_getc();
3112*7c356e86SAndroid Build Coastguard Worker xbuf = o_xbuf;
3113*7c356e86SAndroid Build Coastguard Worker xend = o_xend;
3114*7c356e86SAndroid Build Coastguard Worker xbp = o_xbp;
3115*7c356e86SAndroid Build Coastguard Worker xep = o_xep;
3116*7c356e86SAndroid Build Coastguard Worker xcp = o_xcp;
3117*7c356e86SAndroid Build Coastguard Worker x_redraw('\r');
3118*7c356e86SAndroid Build Coastguard Worker
3119*7c356e86SAndroid Build Coastguard Worker if (c < 0)
3120*7c356e86SAndroid Build Coastguard Worker return (KSTD);
3121*7c356e86SAndroid Build Coastguard Worker /* This is what AT&T ksh seems to do... Very bizarre */
3122*7c356e86SAndroid Build Coastguard Worker if (c != ' ')
3123*7c356e86SAndroid Build Coastguard Worker x_e_ungetc(c);
3124*7c356e86SAndroid Build Coastguard Worker
3125*7c356e86SAndroid Build Coastguard Worker afree(v, ATEMP);
3126*7c356e86SAndroid Build Coastguard Worker return (KSTD);
3127*7c356e86SAndroid Build Coastguard Worker }
3128*7c356e86SAndroid Build Coastguard Worker
3129*7c356e86SAndroid Build Coastguard Worker #ifndef MKSH_SMALL
3130*7c356e86SAndroid Build Coastguard Worker static int
x_edit_line(int c MKSH_A_UNUSED)3131*7c356e86SAndroid Build Coastguard Worker x_edit_line(int c MKSH_A_UNUSED)
3132*7c356e86SAndroid Build Coastguard Worker {
3133*7c356e86SAndroid Build Coastguard Worker if (x_arg_defaulted) {
3134*7c356e86SAndroid Build Coastguard Worker if (modified) {
3135*7c356e86SAndroid Build Coastguard Worker *xep = '\0';
3136*7c356e86SAndroid Build Coastguard Worker histsave(&source->line, xbuf, HIST_STORE, true);
3137*7c356e86SAndroid Build Coastguard Worker x_arg = 0;
3138*7c356e86SAndroid Build Coastguard Worker } else
3139*7c356e86SAndroid Build Coastguard Worker x_arg = source->line - (histptr - x_histp);
3140*7c356e86SAndroid Build Coastguard Worker }
3141*7c356e86SAndroid Build Coastguard Worker if (x_arg)
3142*7c356e86SAndroid Build Coastguard Worker shf_snprintf(xbuf, xend - xbuf, Tf_sd, ctrl_x_e, x_arg);
3143*7c356e86SAndroid Build Coastguard Worker else
3144*7c356e86SAndroid Build Coastguard Worker strlcpy(xbuf, ctrl_x_e, xend - xbuf);
3145*7c356e86SAndroid Build Coastguard Worker xep = strnul(xbuf);
3146*7c356e86SAndroid Build Coastguard Worker return (x_newline('\n'));
3147*7c356e86SAndroid Build Coastguard Worker }
3148*7c356e86SAndroid Build Coastguard Worker #endif
3149*7c356e86SAndroid Build Coastguard Worker
3150*7c356e86SAndroid Build Coastguard Worker /*-
3151*7c356e86SAndroid Build Coastguard Worker * NAME:
3152*7c356e86SAndroid Build Coastguard Worker * x_prev_histword - recover word from prev command
3153*7c356e86SAndroid Build Coastguard Worker *
3154*7c356e86SAndroid Build Coastguard Worker * DESCRIPTION:
3155*7c356e86SAndroid Build Coastguard Worker * This function recovers the last word from the previous
3156*7c356e86SAndroid Build Coastguard Worker * command and inserts it into the current edit line. If a
3157*7c356e86SAndroid Build Coastguard Worker * numeric arg is supplied then the n'th word from the
3158*7c356e86SAndroid Build Coastguard Worker * start of the previous command is used.
3159*7c356e86SAndroid Build Coastguard Worker * As a side effect, trashes the mark in order to achieve
3160*7c356e86SAndroid Build Coastguard Worker * being called in a repeatable fashion.
3161*7c356e86SAndroid Build Coastguard Worker *
3162*7c356e86SAndroid Build Coastguard Worker * Bound to M-.
3163*7c356e86SAndroid Build Coastguard Worker *
3164*7c356e86SAndroid Build Coastguard Worker * RETURN VALUE:
3165*7c356e86SAndroid Build Coastguard Worker * KSTD
3166*7c356e86SAndroid Build Coastguard Worker */
3167*7c356e86SAndroid Build Coastguard Worker static int
x_prev_histword(int c MKSH_A_UNUSED)3168*7c356e86SAndroid Build Coastguard Worker x_prev_histword(int c MKSH_A_UNUSED)
3169*7c356e86SAndroid Build Coastguard Worker {
3170*7c356e86SAndroid Build Coastguard Worker char *rcp, *cp;
3171*7c356e86SAndroid Build Coastguard Worker char **xhp;
3172*7c356e86SAndroid Build Coastguard Worker int m = 1;
3173*7c356e86SAndroid Build Coastguard Worker /* -1 = defaulted; 0+ = argument */
3174*7c356e86SAndroid Build Coastguard Worker static int last_arg = -1;
3175*7c356e86SAndroid Build Coastguard Worker
3176*7c356e86SAndroid Build Coastguard Worker if (x_last_command == XFUNC_prev_histword) {
3177*7c356e86SAndroid Build Coastguard Worker if (xmp && modified > 1)
3178*7c356e86SAndroid Build Coastguard Worker x_kill_region(0);
3179*7c356e86SAndroid Build Coastguard Worker if (modified)
3180*7c356e86SAndroid Build Coastguard Worker m = modified;
3181*7c356e86SAndroid Build Coastguard Worker } else
3182*7c356e86SAndroid Build Coastguard Worker last_arg = x_arg_defaulted ? -1 : x_arg;
3183*7c356e86SAndroid Build Coastguard Worker xhp = histptr - (m - 1);
3184*7c356e86SAndroid Build Coastguard Worker if ((xhp < history) || !(cp = *xhp)) {
3185*7c356e86SAndroid Build Coastguard Worker x_e_putc2(KSH_BEL);
3186*7c356e86SAndroid Build Coastguard Worker x_modified();
3187*7c356e86SAndroid Build Coastguard Worker return (KSTD);
3188*7c356e86SAndroid Build Coastguard Worker }
3189*7c356e86SAndroid Build Coastguard Worker x_set_mark(0);
3190*7c356e86SAndroid Build Coastguard Worker if ((x_arg = last_arg) == -1) {
3191*7c356e86SAndroid Build Coastguard Worker /* x_arg_defaulted */
3192*7c356e86SAndroid Build Coastguard Worker
3193*7c356e86SAndroid Build Coastguard Worker rcp = &cp[strlen(cp) - 1];
3194*7c356e86SAndroid Build Coastguard Worker /*
3195*7c356e86SAndroid Build Coastguard Worker * ignore white-space after the last word
3196*7c356e86SAndroid Build Coastguard Worker */
3197*7c356e86SAndroid Build Coastguard Worker while (rcp > cp && ctype(*rcp, C_CFS))
3198*7c356e86SAndroid Build Coastguard Worker rcp--;
3199*7c356e86SAndroid Build Coastguard Worker while (rcp > cp && !ctype(*rcp, C_CFS))
3200*7c356e86SAndroid Build Coastguard Worker rcp--;
3201*7c356e86SAndroid Build Coastguard Worker if (ctype(*rcp, C_CFS))
3202*7c356e86SAndroid Build Coastguard Worker rcp++;
3203*7c356e86SAndroid Build Coastguard Worker x_ins(rcp);
3204*7c356e86SAndroid Build Coastguard Worker } else {
3205*7c356e86SAndroid Build Coastguard Worker /* not x_arg_defaulted */
3206*7c356e86SAndroid Build Coastguard Worker char ch;
3207*7c356e86SAndroid Build Coastguard Worker
3208*7c356e86SAndroid Build Coastguard Worker rcp = cp;
3209*7c356e86SAndroid Build Coastguard Worker /*
3210*7c356e86SAndroid Build Coastguard Worker * ignore white-space at start of line
3211*7c356e86SAndroid Build Coastguard Worker */
3212*7c356e86SAndroid Build Coastguard Worker while (*rcp && ctype(*rcp, C_CFS))
3213*7c356e86SAndroid Build Coastguard Worker rcp++;
3214*7c356e86SAndroid Build Coastguard Worker while (x_arg-- > 0) {
3215*7c356e86SAndroid Build Coastguard Worker while (*rcp && !ctype(*rcp, C_CFS))
3216*7c356e86SAndroid Build Coastguard Worker rcp++;
3217*7c356e86SAndroid Build Coastguard Worker while (*rcp && ctype(*rcp, C_CFS))
3218*7c356e86SAndroid Build Coastguard Worker rcp++;
3219*7c356e86SAndroid Build Coastguard Worker }
3220*7c356e86SAndroid Build Coastguard Worker cp = rcp;
3221*7c356e86SAndroid Build Coastguard Worker while (*rcp && !ctype(*rcp, C_CFS))
3222*7c356e86SAndroid Build Coastguard Worker rcp++;
3223*7c356e86SAndroid Build Coastguard Worker ch = *rcp;
3224*7c356e86SAndroid Build Coastguard Worker *rcp = '\0';
3225*7c356e86SAndroid Build Coastguard Worker x_ins(cp);
3226*7c356e86SAndroid Build Coastguard Worker *rcp = ch;
3227*7c356e86SAndroid Build Coastguard Worker }
3228*7c356e86SAndroid Build Coastguard Worker if (!modified)
3229*7c356e86SAndroid Build Coastguard Worker x_histmcp = x_histp;
3230*7c356e86SAndroid Build Coastguard Worker modified = m + 1;
3231*7c356e86SAndroid Build Coastguard Worker return (KSTD);
3232*7c356e86SAndroid Build Coastguard Worker }
3233*7c356e86SAndroid Build Coastguard Worker
3234*7c356e86SAndroid Build Coastguard Worker #ifndef MKSH_SMALL
3235*7c356e86SAndroid Build Coastguard Worker /* Uppercase N(1) words */
3236*7c356e86SAndroid Build Coastguard Worker static int
x_fold_upper(int c MKSH_A_UNUSED)3237*7c356e86SAndroid Build Coastguard Worker x_fold_upper(int c MKSH_A_UNUSED)
3238*7c356e86SAndroid Build Coastguard Worker {
3239*7c356e86SAndroid Build Coastguard Worker return (x_fold_case('U'));
3240*7c356e86SAndroid Build Coastguard Worker }
3241*7c356e86SAndroid Build Coastguard Worker
3242*7c356e86SAndroid Build Coastguard Worker /* Lowercase N(1) words */
3243*7c356e86SAndroid Build Coastguard Worker static int
x_fold_lower(int c MKSH_A_UNUSED)3244*7c356e86SAndroid Build Coastguard Worker x_fold_lower(int c MKSH_A_UNUSED)
3245*7c356e86SAndroid Build Coastguard Worker {
3246*7c356e86SAndroid Build Coastguard Worker return (x_fold_case('L'));
3247*7c356e86SAndroid Build Coastguard Worker }
3248*7c356e86SAndroid Build Coastguard Worker
3249*7c356e86SAndroid Build Coastguard Worker /* Titlecase N(1) words */
3250*7c356e86SAndroid Build Coastguard Worker static int
x_fold_capitalise(int c MKSH_A_UNUSED)3251*7c356e86SAndroid Build Coastguard Worker x_fold_capitalise(int c MKSH_A_UNUSED)
3252*7c356e86SAndroid Build Coastguard Worker {
3253*7c356e86SAndroid Build Coastguard Worker return (x_fold_case('C'));
3254*7c356e86SAndroid Build Coastguard Worker }
3255*7c356e86SAndroid Build Coastguard Worker
3256*7c356e86SAndroid Build Coastguard Worker /*-
3257*7c356e86SAndroid Build Coastguard Worker * NAME:
3258*7c356e86SAndroid Build Coastguard Worker * x_fold_case - convert word to UPPER/lower/Capital case
3259*7c356e86SAndroid Build Coastguard Worker *
3260*7c356e86SAndroid Build Coastguard Worker * DESCRIPTION:
3261*7c356e86SAndroid Build Coastguard Worker * This function is used to implement M-U/M-u, M-L/M-l, M-C/M-c
3262*7c356e86SAndroid Build Coastguard Worker * to UPPER CASE, lower case or Capitalise Words.
3263*7c356e86SAndroid Build Coastguard Worker *
3264*7c356e86SAndroid Build Coastguard Worker * RETURN VALUE:
3265*7c356e86SAndroid Build Coastguard Worker * None
3266*7c356e86SAndroid Build Coastguard Worker */
3267*7c356e86SAndroid Build Coastguard Worker static int
x_fold_case(int c)3268*7c356e86SAndroid Build Coastguard Worker x_fold_case(int c)
3269*7c356e86SAndroid Build Coastguard Worker {
3270*7c356e86SAndroid Build Coastguard Worker char *cp = xcp;
3271*7c356e86SAndroid Build Coastguard Worker
3272*7c356e86SAndroid Build Coastguard Worker if (cp == xep) {
3273*7c356e86SAndroid Build Coastguard Worker x_e_putc2(KSH_BEL);
3274*7c356e86SAndroid Build Coastguard Worker return (KSTD);
3275*7c356e86SAndroid Build Coastguard Worker }
3276*7c356e86SAndroid Build Coastguard Worker while (x_arg--) {
3277*7c356e86SAndroid Build Coastguard Worker /*
3278*7c356e86SAndroid Build Coastguard Worker * first skip over any white-space
3279*7c356e86SAndroid Build Coastguard Worker */
3280*7c356e86SAndroid Build Coastguard Worker while (cp != xep && ctype(*cp, C_MFS))
3281*7c356e86SAndroid Build Coastguard Worker cp++;
3282*7c356e86SAndroid Build Coastguard Worker /*
3283*7c356e86SAndroid Build Coastguard Worker * do the first char on its own since it may be
3284*7c356e86SAndroid Build Coastguard Worker * a different action than for the rest.
3285*7c356e86SAndroid Build Coastguard Worker */
3286*7c356e86SAndroid Build Coastguard Worker if (cp != xep) {
3287*7c356e86SAndroid Build Coastguard Worker if (c == 'L')
3288*7c356e86SAndroid Build Coastguard Worker /* lowercase */
3289*7c356e86SAndroid Build Coastguard Worker *cp = ksh_tolower(*cp);
3290*7c356e86SAndroid Build Coastguard Worker else
3291*7c356e86SAndroid Build Coastguard Worker /* uppercase, capitalise */
3292*7c356e86SAndroid Build Coastguard Worker *cp = ksh_toupper(*cp);
3293*7c356e86SAndroid Build Coastguard Worker cp++;
3294*7c356e86SAndroid Build Coastguard Worker }
3295*7c356e86SAndroid Build Coastguard Worker /*
3296*7c356e86SAndroid Build Coastguard Worker * now for the rest of the word
3297*7c356e86SAndroid Build Coastguard Worker */
3298*7c356e86SAndroid Build Coastguard Worker while (cp != xep && !ctype(*cp, C_MFS)) {
3299*7c356e86SAndroid Build Coastguard Worker if (c == 'U')
3300*7c356e86SAndroid Build Coastguard Worker /* uppercase */
3301*7c356e86SAndroid Build Coastguard Worker *cp = ksh_toupper(*cp);
3302*7c356e86SAndroid Build Coastguard Worker else
3303*7c356e86SAndroid Build Coastguard Worker /* lowercase, capitalise */
3304*7c356e86SAndroid Build Coastguard Worker *cp = ksh_tolower(*cp);
3305*7c356e86SAndroid Build Coastguard Worker cp++;
3306*7c356e86SAndroid Build Coastguard Worker }
3307*7c356e86SAndroid Build Coastguard Worker }
3308*7c356e86SAndroid Build Coastguard Worker x_goto(cp);
3309*7c356e86SAndroid Build Coastguard Worker x_modified();
3310*7c356e86SAndroid Build Coastguard Worker return (KSTD);
3311*7c356e86SAndroid Build Coastguard Worker }
3312*7c356e86SAndroid Build Coastguard Worker #endif
3313*7c356e86SAndroid Build Coastguard Worker
3314*7c356e86SAndroid Build Coastguard Worker /*-
3315*7c356e86SAndroid Build Coastguard Worker * NAME:
3316*7c356e86SAndroid Build Coastguard Worker * x_lastcp - last visible char
3317*7c356e86SAndroid Build Coastguard Worker *
3318*7c356e86SAndroid Build Coastguard Worker * DESCRIPTION:
3319*7c356e86SAndroid Build Coastguard Worker * This function returns a pointer to that char in the
3320*7c356e86SAndroid Build Coastguard Worker * edit buffer that will be the last displayed on the
3321*7c356e86SAndroid Build Coastguard Worker * screen.
3322*7c356e86SAndroid Build Coastguard Worker */
3323*7c356e86SAndroid Build Coastguard Worker static char *
x_lastcp(void)3324*7c356e86SAndroid Build Coastguard Worker x_lastcp(void)
3325*7c356e86SAndroid Build Coastguard Worker {
3326*7c356e86SAndroid Build Coastguard Worker if (!xlp_valid) {
3327*7c356e86SAndroid Build Coastguard Worker int i = 0, j;
3328*7c356e86SAndroid Build Coastguard Worker char *xlp2;
3329*7c356e86SAndroid Build Coastguard Worker
3330*7c356e86SAndroid Build Coastguard Worker xlp = xbp;
3331*7c356e86SAndroid Build Coastguard Worker while (xlp < xep) {
3332*7c356e86SAndroid Build Coastguard Worker j = x_size2(xlp, &xlp2);
3333*7c356e86SAndroid Build Coastguard Worker if ((i + j) > x_displen)
3334*7c356e86SAndroid Build Coastguard Worker break;
3335*7c356e86SAndroid Build Coastguard Worker i += j;
3336*7c356e86SAndroid Build Coastguard Worker xlp = xlp2;
3337*7c356e86SAndroid Build Coastguard Worker }
3338*7c356e86SAndroid Build Coastguard Worker }
3339*7c356e86SAndroid Build Coastguard Worker xlp_valid = true;
3340*7c356e86SAndroid Build Coastguard Worker return (xlp);
3341*7c356e86SAndroid Build Coastguard Worker }
3342*7c356e86SAndroid Build Coastguard Worker
3343*7c356e86SAndroid Build Coastguard Worker /* correctly position the cursor on the screen from end of visible area */
3344*7c356e86SAndroid Build Coastguard Worker static void
x_lastpos(void)3345*7c356e86SAndroid Build Coastguard Worker x_lastpos(void)
3346*7c356e86SAndroid Build Coastguard Worker {
3347*7c356e86SAndroid Build Coastguard Worker char *cp = x_lastcp();
3348*7c356e86SAndroid Build Coastguard Worker
3349*7c356e86SAndroid Build Coastguard Worker while (cp > xcp)
3350*7c356e86SAndroid Build Coastguard Worker x_bs3(&cp);
3351*7c356e86SAndroid Build Coastguard Worker }
3352*7c356e86SAndroid Build Coastguard Worker
3353*7c356e86SAndroid Build Coastguard Worker static void
x_mode(bool onoff)3354*7c356e86SAndroid Build Coastguard Worker x_mode(bool onoff)
3355*7c356e86SAndroid Build Coastguard Worker {
3356*7c356e86SAndroid Build Coastguard Worker static bool x_cur_mode;
3357*7c356e86SAndroid Build Coastguard Worker
3358*7c356e86SAndroid Build Coastguard Worker if (x_cur_mode == onoff)
3359*7c356e86SAndroid Build Coastguard Worker return;
3360*7c356e86SAndroid Build Coastguard Worker x_cur_mode = onoff;
3361*7c356e86SAndroid Build Coastguard Worker
3362*7c356e86SAndroid Build Coastguard Worker if (onoff) {
3363*7c356e86SAndroid Build Coastguard Worker x_mkraw(tty_fd, NULL, false);
3364*7c356e86SAndroid Build Coastguard Worker
3365*7c356e86SAndroid Build Coastguard Worker edchars.erase = toedchar(tty_state.c_cc[VERASE]);
3366*7c356e86SAndroid Build Coastguard Worker edchars.kill = toedchar(tty_state.c_cc[VKILL]);
3367*7c356e86SAndroid Build Coastguard Worker edchars.intr = toedchar(tty_state.c_cc[VINTR]);
3368*7c356e86SAndroid Build Coastguard Worker edchars.quit = toedchar(tty_state.c_cc[VQUIT]);
3369*7c356e86SAndroid Build Coastguard Worker edchars.eof = toedchar(tty_state.c_cc[VEOF]);
3370*7c356e86SAndroid Build Coastguard Worker #ifdef VWERASE
3371*7c356e86SAndroid Build Coastguard Worker edchars.werase = toedchar(tty_state.c_cc[VWERASE]);
3372*7c356e86SAndroid Build Coastguard Worker #else
3373*7c356e86SAndroid Build Coastguard Worker edchars.werase = 0;
3374*7c356e86SAndroid Build Coastguard Worker #endif
3375*7c356e86SAndroid Build Coastguard Worker
3376*7c356e86SAndroid Build Coastguard Worker if (!edchars.erase)
3377*7c356e86SAndroid Build Coastguard Worker edchars.erase = CTRL_H;
3378*7c356e86SAndroid Build Coastguard Worker if (!edchars.kill)
3379*7c356e86SAndroid Build Coastguard Worker edchars.kill = CTRL_U;
3380*7c356e86SAndroid Build Coastguard Worker if (!edchars.intr)
3381*7c356e86SAndroid Build Coastguard Worker edchars.intr = CTRL_C;
3382*7c356e86SAndroid Build Coastguard Worker if (!edchars.quit)
3383*7c356e86SAndroid Build Coastguard Worker edchars.quit = CTRL_BK;
3384*7c356e86SAndroid Build Coastguard Worker if (!edchars.eof)
3385*7c356e86SAndroid Build Coastguard Worker edchars.eof = CTRL_D;
3386*7c356e86SAndroid Build Coastguard Worker if (!edchars.werase)
3387*7c356e86SAndroid Build Coastguard Worker edchars.werase = CTRL_W;
3388*7c356e86SAndroid Build Coastguard Worker
3389*7c356e86SAndroid Build Coastguard Worker if (isedchar(edchars.erase)) {
3390*7c356e86SAndroid Build Coastguard Worker bind_if_not_bound(0, edchars.erase, XFUNC_del_back);
3391*7c356e86SAndroid Build Coastguard Worker bind_if_not_bound(1, edchars.erase, XFUNC_del_bword);
3392*7c356e86SAndroid Build Coastguard Worker }
3393*7c356e86SAndroid Build Coastguard Worker if (isedchar(edchars.kill))
3394*7c356e86SAndroid Build Coastguard Worker bind_if_not_bound(0, edchars.kill, XFUNC_del_line);
3395*7c356e86SAndroid Build Coastguard Worker if (isedchar(edchars.werase))
3396*7c356e86SAndroid Build Coastguard Worker bind_if_not_bound(0, edchars.werase, XFUNC_del_bword);
3397*7c356e86SAndroid Build Coastguard Worker if (isedchar(edchars.intr))
3398*7c356e86SAndroid Build Coastguard Worker bind_if_not_bound(0, edchars.intr, XFUNC_abort);
3399*7c356e86SAndroid Build Coastguard Worker if (isedchar(edchars.quit))
3400*7c356e86SAndroid Build Coastguard Worker bind_if_not_bound(0, edchars.quit, XFUNC_noop);
3401*7c356e86SAndroid Build Coastguard Worker } else
3402*7c356e86SAndroid Build Coastguard Worker mksh_tcset(tty_fd, &tty_state);
3403*7c356e86SAndroid Build Coastguard Worker }
3404*7c356e86SAndroid Build Coastguard Worker
3405*7c356e86SAndroid Build Coastguard Worker #if !MKSH_S_NOVI
3406*7c356e86SAndroid Build Coastguard Worker /* +++ vi editing mode +++ */
3407*7c356e86SAndroid Build Coastguard Worker
3408*7c356e86SAndroid Build Coastguard Worker struct edstate {
3409*7c356e86SAndroid Build Coastguard Worker char *cbuf;
3410*7c356e86SAndroid Build Coastguard Worker ssize_t winleft;
3411*7c356e86SAndroid Build Coastguard Worker ssize_t cbufsize;
3412*7c356e86SAndroid Build Coastguard Worker ssize_t linelen;
3413*7c356e86SAndroid Build Coastguard Worker ssize_t cursor;
3414*7c356e86SAndroid Build Coastguard Worker };
3415*7c356e86SAndroid Build Coastguard Worker
3416*7c356e86SAndroid Build Coastguard Worker static int vi_hook(int);
3417*7c356e86SAndroid Build Coastguard Worker static int nextstate(int);
3418*7c356e86SAndroid Build Coastguard Worker static int vi_insert(int);
3419*7c356e86SAndroid Build Coastguard Worker static int vi_cmd(int, const char *);
3420*7c356e86SAndroid Build Coastguard Worker static int domove(int, const char *, int);
3421*7c356e86SAndroid Build Coastguard Worker static int domovebeg(void);
3422*7c356e86SAndroid Build Coastguard Worker static int redo_insert(int);
3423*7c356e86SAndroid Build Coastguard Worker static void yank_range(int, int);
3424*7c356e86SAndroid Build Coastguard Worker static int bracktype(int);
3425*7c356e86SAndroid Build Coastguard Worker static void save_cbuf(void);
3426*7c356e86SAndroid Build Coastguard Worker static void restore_cbuf(void);
3427*7c356e86SAndroid Build Coastguard Worker static int putbuf(const char *, ssize_t, bool);
3428*7c356e86SAndroid Build Coastguard Worker static void del_range(int, int);
3429*7c356e86SAndroid Build Coastguard Worker static int findch(int, int, bool, bool) MKSH_A_PURE;
3430*7c356e86SAndroid Build Coastguard Worker static int forwword(int);
3431*7c356e86SAndroid Build Coastguard Worker static int backword(int);
3432*7c356e86SAndroid Build Coastguard Worker static int endword(int);
3433*7c356e86SAndroid Build Coastguard Worker static int Forwword(int);
3434*7c356e86SAndroid Build Coastguard Worker static int Backword(int);
3435*7c356e86SAndroid Build Coastguard Worker static int Endword(int);
3436*7c356e86SAndroid Build Coastguard Worker static int grabhist(int, int);
3437*7c356e86SAndroid Build Coastguard Worker static int grabsearch(const char *, int, int, bool);
3438*7c356e86SAndroid Build Coastguard Worker static void redraw_line(bool);
3439*7c356e86SAndroid Build Coastguard Worker static void refresh(bool);
3440*7c356e86SAndroid Build Coastguard Worker static int outofwin(void);
3441*7c356e86SAndroid Build Coastguard Worker static void rewindow(void);
3442*7c356e86SAndroid Build Coastguard Worker static int newcol(unsigned char, int);
3443*7c356e86SAndroid Build Coastguard Worker static void display(char *, char *, bool);
3444*7c356e86SAndroid Build Coastguard Worker static void ed_mov_opt(int, char *);
3445*7c356e86SAndroid Build Coastguard Worker static int expand_word(int);
3446*7c356e86SAndroid Build Coastguard Worker static int complete_word(int, int);
3447*7c356e86SAndroid Build Coastguard Worker static int print_expansions(struct edstate *, int);
3448*7c356e86SAndroid Build Coastguard Worker static void vi_error(void);
3449*7c356e86SAndroid Build Coastguard Worker static void vi_macro_reset(void);
3450*7c356e86SAndroid Build Coastguard Worker static int x_vi_putbuf(const char *, size_t);
3451*7c356e86SAndroid Build Coastguard Worker #define char_len(c) (ksh_isctrl(c) ? 2 : 1)
3452*7c356e86SAndroid Build Coastguard Worker
3453*7c356e86SAndroid Build Coastguard Worker #define vC 0x01 /* a valid command that isn't a vM, vE, vU */
3454*7c356e86SAndroid Build Coastguard Worker #define vM 0x02 /* movement command (h, l, etc.) */
3455*7c356e86SAndroid Build Coastguard Worker #define vE 0x04 /* extended command (c, d, y) */
3456*7c356e86SAndroid Build Coastguard Worker #define vX 0x08 /* long command (@, f, F, t, T, etc.) */
3457*7c356e86SAndroid Build Coastguard Worker #define vU 0x10 /* an UN-undoable command (that isn't a vM) */
3458*7c356e86SAndroid Build Coastguard Worker #define vB 0x20 /* bad command (^@) */
3459*7c356e86SAndroid Build Coastguard Worker #define vZ 0x40 /* repeat count defaults to 0 (not 1) */
3460*7c356e86SAndroid Build Coastguard Worker #define vS 0x80 /* search (/, ?) */
3461*7c356e86SAndroid Build Coastguard Worker
3462*7c356e86SAndroid Build Coastguard Worker #define is_bad(c) (classify[rtt2asc(c) & 0x7F] & vB)
3463*7c356e86SAndroid Build Coastguard Worker #define is_cmd(c) (classify[rtt2asc(c) & 0x7F] & (vM | vE | vC | vU))
3464*7c356e86SAndroid Build Coastguard Worker #define is_move(c) (classify[rtt2asc(c) & 0x7F] & vM)
3465*7c356e86SAndroid Build Coastguard Worker #define is_extend(c) (classify[rtt2asc(c) & 0x7F] & vE)
3466*7c356e86SAndroid Build Coastguard Worker #define is_long(c) (classify[rtt2asc(c) & 0x7F] & vX)
3467*7c356e86SAndroid Build Coastguard Worker #define is_undoable(c) (!(classify[rtt2asc(c) & 0x7F] & vU))
3468*7c356e86SAndroid Build Coastguard Worker #define is_srch(c) (classify[rtt2asc(c) & 0x7F] & vS)
3469*7c356e86SAndroid Build Coastguard Worker #define is_zerocount(c) (classify[rtt2asc(c) & 0x7F] & vZ)
3470*7c356e86SAndroid Build Coastguard Worker
3471*7c356e86SAndroid Build Coastguard Worker static const unsigned char classify[128] = {
3472*7c356e86SAndroid Build Coastguard Worker /* 0 1 2 3 4 5 6 7 */
3473*7c356e86SAndroid Build Coastguard Worker /* 0 ^@ ^A ^B ^C ^D ^E ^F ^G */
3474*7c356e86SAndroid Build Coastguard Worker vB, 0, 0, 0, 0, vC|vU, vC|vZ, 0,
3475*7c356e86SAndroid Build Coastguard Worker /* 1 ^H ^I ^J ^K ^L ^M ^N ^O */
3476*7c356e86SAndroid Build Coastguard Worker vM, vC|vZ, 0, 0, vC|vU, 0, vC, 0,
3477*7c356e86SAndroid Build Coastguard Worker /* 2 ^P ^Q ^R ^S ^T ^U ^V ^W */
3478*7c356e86SAndroid Build Coastguard Worker vC, 0, vC|vU, 0, 0, 0, vC, 0,
3479*7c356e86SAndroid Build Coastguard Worker /* 3 ^X ^Y ^Z ^[ ^\ ^] ^^ ^_ */
3480*7c356e86SAndroid Build Coastguard Worker vC, 0, 0, vC|vZ, 0, 0, 0, 0,
3481*7c356e86SAndroid Build Coastguard Worker /* 4 <space> ! " # $ % & ' */
3482*7c356e86SAndroid Build Coastguard Worker vM, 0, 0, vC, vM, vM, 0, 0,
3483*7c356e86SAndroid Build Coastguard Worker /* 5 ( ) * + , - . / */
3484*7c356e86SAndroid Build Coastguard Worker 0, 0, vC, vC, vM, vC, 0, vC|vS,
3485*7c356e86SAndroid Build Coastguard Worker /* 6 0 1 2 3 4 5 6 7 */
3486*7c356e86SAndroid Build Coastguard Worker vM, 0, 0, 0, 0, 0, 0, 0,
3487*7c356e86SAndroid Build Coastguard Worker /* 7 8 9 : ; < = > ? */
3488*7c356e86SAndroid Build Coastguard Worker 0, 0, 0, vM, 0, vC, 0, vC|vS,
3489*7c356e86SAndroid Build Coastguard Worker /* 8 @ A B C D E F G */
3490*7c356e86SAndroid Build Coastguard Worker vC|vX, vC, vM, vC, vC, vM, vM|vX, vC|vU|vZ,
3491*7c356e86SAndroid Build Coastguard Worker /* 9 H I J K L M N O */
3492*7c356e86SAndroid Build Coastguard Worker 0, vC, 0, 0, 0, 0, vC|vU, vU,
3493*7c356e86SAndroid Build Coastguard Worker /* A P Q R S T U V W */
3494*7c356e86SAndroid Build Coastguard Worker vC, 0, vC, vC, vM|vX, vC, 0, vM,
3495*7c356e86SAndroid Build Coastguard Worker /* B X Y Z [ \ ] ^ _ */
3496*7c356e86SAndroid Build Coastguard Worker vC, vC|vU, 0, vU, vC|vZ, 0, vM, vC|vZ,
3497*7c356e86SAndroid Build Coastguard Worker /* C ` a b c d e f g */
3498*7c356e86SAndroid Build Coastguard Worker 0, vC, vM, vE, vE, vM, vM|vX, vC|vZ,
3499*7c356e86SAndroid Build Coastguard Worker /* D h i j k l m n o */
3500*7c356e86SAndroid Build Coastguard Worker vM, vC, vC|vU, vC|vU, vM, 0, vC|vU, 0,
3501*7c356e86SAndroid Build Coastguard Worker /* E p q r s t u v w */
3502*7c356e86SAndroid Build Coastguard Worker vC, 0, vX, vC, vM|vX, vC|vU, vC|vU|vZ, vM,
3503*7c356e86SAndroid Build Coastguard Worker /* F x y z { | } ~ ^? */
3504*7c356e86SAndroid Build Coastguard Worker vC, vE|vU, 0, 0, vM|vZ, 0, vC, 0
3505*7c356e86SAndroid Build Coastguard Worker };
3506*7c356e86SAndroid Build Coastguard Worker
3507*7c356e86SAndroid Build Coastguard Worker #define MAXVICMD 3
3508*7c356e86SAndroid Build Coastguard Worker #define SRCHLEN 40
3509*7c356e86SAndroid Build Coastguard Worker
3510*7c356e86SAndroid Build Coastguard Worker #define INSERT 1
3511*7c356e86SAndroid Build Coastguard Worker #define REPLACE 2
3512*7c356e86SAndroid Build Coastguard Worker
3513*7c356e86SAndroid Build Coastguard Worker #define VNORMAL 0 /* command, insert or replace mode */
3514*7c356e86SAndroid Build Coastguard Worker #define VARG1 1 /* digit prefix (first, eg, 5l) */
3515*7c356e86SAndroid Build Coastguard Worker #define VEXTCMD 2 /* cmd + movement (eg, cl) */
3516*7c356e86SAndroid Build Coastguard Worker #define VARG2 3 /* digit prefix (second, eg, 2c3l) */
3517*7c356e86SAndroid Build Coastguard Worker #define VXCH 4 /* f, F, t, T, @ */
3518*7c356e86SAndroid Build Coastguard Worker #define VFAIL 5 /* bad command */
3519*7c356e86SAndroid Build Coastguard Worker #define VCMD 6 /* single char command (eg, X) */
3520*7c356e86SAndroid Build Coastguard Worker #define VREDO 7 /* . */
3521*7c356e86SAndroid Build Coastguard Worker #define VLIT 8 /* ^V */
3522*7c356e86SAndroid Build Coastguard Worker #define VSEARCH 9 /* /, ? */
3523*7c356e86SAndroid Build Coastguard Worker #define VVERSION 10 /* <ESC> ^V */
3524*7c356e86SAndroid Build Coastguard Worker #define VPREFIX2 11 /* ^[[ and ^[O in insert mode */
3525*7c356e86SAndroid Build Coastguard Worker
3526*7c356e86SAndroid Build Coastguard Worker static struct edstate *save_edstate(struct edstate *old);
3527*7c356e86SAndroid Build Coastguard Worker static void restore_edstate(struct edstate *old, struct edstate *news);
3528*7c356e86SAndroid Build Coastguard Worker static void free_edstate(struct edstate *old);
3529*7c356e86SAndroid Build Coastguard Worker
3530*7c356e86SAndroid Build Coastguard Worker static struct edstate ebuf;
3531*7c356e86SAndroid Build Coastguard Worker static struct edstate undobuf;
3532*7c356e86SAndroid Build Coastguard Worker
3533*7c356e86SAndroid Build Coastguard Worker static struct edstate *vs; /* current Vi editing mode state */
3534*7c356e86SAndroid Build Coastguard Worker static struct edstate *undo;
3535*7c356e86SAndroid Build Coastguard Worker
3536*7c356e86SAndroid Build Coastguard Worker static char *ibuf; /* input buffer */
3537*7c356e86SAndroid Build Coastguard Worker static bool first_insert; /* set when starting in insert mode */
3538*7c356e86SAndroid Build Coastguard Worker static int saved_inslen; /* saved inslen for first insert */
3539*7c356e86SAndroid Build Coastguard Worker static int inslen; /* length of input buffer */
3540*7c356e86SAndroid Build Coastguard Worker static int srchlen; /* length of current search pattern */
3541*7c356e86SAndroid Build Coastguard Worker static char *ybuf; /* yank buffer */
3542*7c356e86SAndroid Build Coastguard Worker static int yanklen; /* length of yank buffer */
3543*7c356e86SAndroid Build Coastguard Worker static uint8_t fsavecmd = ORD(' '); /* last find command */
3544*7c356e86SAndroid Build Coastguard Worker static int fsavech; /* character to find */
3545*7c356e86SAndroid Build Coastguard Worker static char lastcmd[MAXVICMD]; /* last non-move command */
3546*7c356e86SAndroid Build Coastguard Worker static int lastac; /* argcnt for lastcmd */
3547*7c356e86SAndroid Build Coastguard Worker static uint8_t lastsearch = ORD(' '); /* last search command */
3548*7c356e86SAndroid Build Coastguard Worker static char srchpat[SRCHLEN]; /* last search pattern */
3549*7c356e86SAndroid Build Coastguard Worker static int insert; /* <>0 in insert mode */
3550*7c356e86SAndroid Build Coastguard Worker static int hnum; /* position in history */
3551*7c356e86SAndroid Build Coastguard Worker static int ohnum; /* history line copied (after mod) */
3552*7c356e86SAndroid Build Coastguard Worker static int hlast; /* 1 past last position in history */
3553*7c356e86SAndroid Build Coastguard Worker static int state;
3554*7c356e86SAndroid Build Coastguard Worker
3555*7c356e86SAndroid Build Coastguard Worker /*
3556*7c356e86SAndroid Build Coastguard Worker * Information for keeping track of macros that are being expanded.
3557*7c356e86SAndroid Build Coastguard Worker * The format of buf is the alias contents followed by a NUL byte followed
3558*7c356e86SAndroid Build Coastguard Worker * by the name (letter) of the alias. The end of the buffer is marked by
3559*7c356e86SAndroid Build Coastguard Worker * a double NUL. The name of the alias is stored so recursive macros can
3560*7c356e86SAndroid Build Coastguard Worker * be detected.
3561*7c356e86SAndroid Build Coastguard Worker */
3562*7c356e86SAndroid Build Coastguard Worker struct macro_state {
3563*7c356e86SAndroid Build Coastguard Worker unsigned char *p; /* current position in buf */
3564*7c356e86SAndroid Build Coastguard Worker unsigned char *buf; /* pointer to macro(s) being expanded */
3565*7c356e86SAndroid Build Coastguard Worker size_t len; /* how much data in buffer */
3566*7c356e86SAndroid Build Coastguard Worker };
3567*7c356e86SAndroid Build Coastguard Worker static struct macro_state macro;
3568*7c356e86SAndroid Build Coastguard Worker
3569*7c356e86SAndroid Build Coastguard Worker /* last input was expanded */
3570*7c356e86SAndroid Build Coastguard Worker static enum expand_mode {
3571*7c356e86SAndroid Build Coastguard Worker NONE = 0, EXPAND, COMPLETE, PRINT
3572*7c356e86SAndroid Build Coastguard Worker } expanded;
3573*7c356e86SAndroid Build Coastguard Worker
3574*7c356e86SAndroid Build Coastguard Worker static int
x_vi(char * buf)3575*7c356e86SAndroid Build Coastguard Worker x_vi(char *buf)
3576*7c356e86SAndroid Build Coastguard Worker {
3577*7c356e86SAndroid Build Coastguard Worker int c;
3578*7c356e86SAndroid Build Coastguard Worker
3579*7c356e86SAndroid Build Coastguard Worker state = VNORMAL;
3580*7c356e86SAndroid Build Coastguard Worker ohnum = hnum = hlast = histnum(-1) + 1;
3581*7c356e86SAndroid Build Coastguard Worker insert = INSERT;
3582*7c356e86SAndroid Build Coastguard Worker saved_inslen = inslen;
3583*7c356e86SAndroid Build Coastguard Worker first_insert = true;
3584*7c356e86SAndroid Build Coastguard Worker inslen = 0;
3585*7c356e86SAndroid Build Coastguard Worker vi_macro_reset();
3586*7c356e86SAndroid Build Coastguard Worker
3587*7c356e86SAndroid Build Coastguard Worker ebuf.cbuf = buf;
3588*7c356e86SAndroid Build Coastguard Worker if (undobuf.cbuf == NULL) {
3589*7c356e86SAndroid Build Coastguard Worker ibuf = alloc(LINE, AEDIT);
3590*7c356e86SAndroid Build Coastguard Worker ybuf = alloc(LINE, AEDIT);
3591*7c356e86SAndroid Build Coastguard Worker undobuf.cbuf = alloc(LINE, AEDIT);
3592*7c356e86SAndroid Build Coastguard Worker }
3593*7c356e86SAndroid Build Coastguard Worker undobuf.cbufsize = ebuf.cbufsize = LINE;
3594*7c356e86SAndroid Build Coastguard Worker undobuf.linelen = ebuf.linelen = 0;
3595*7c356e86SAndroid Build Coastguard Worker undobuf.cursor = ebuf.cursor = 0;
3596*7c356e86SAndroid Build Coastguard Worker undobuf.winleft = ebuf.winleft = 0;
3597*7c356e86SAndroid Build Coastguard Worker vs = &ebuf;
3598*7c356e86SAndroid Build Coastguard Worker undo = &undobuf;
3599*7c356e86SAndroid Build Coastguard Worker
3600*7c356e86SAndroid Build Coastguard Worker x_init_prompt(true);
3601*7c356e86SAndroid Build Coastguard Worker x_col = pwidth;
3602*7c356e86SAndroid Build Coastguard Worker
3603*7c356e86SAndroid Build Coastguard Worker if (wbuf_len != x_cols - 3 && ((wbuf_len = x_cols - 3))) {
3604*7c356e86SAndroid Build Coastguard Worker wbuf[0] = aresize(wbuf[0], wbuf_len, AEDIT);
3605*7c356e86SAndroid Build Coastguard Worker wbuf[1] = aresize(wbuf[1], wbuf_len, AEDIT);
3606*7c356e86SAndroid Build Coastguard Worker }
3607*7c356e86SAndroid Build Coastguard Worker if (wbuf_len) {
3608*7c356e86SAndroid Build Coastguard Worker memset(wbuf[0], ' ', wbuf_len);
3609*7c356e86SAndroid Build Coastguard Worker memset(wbuf[1], ' ', wbuf_len);
3610*7c356e86SAndroid Build Coastguard Worker }
3611*7c356e86SAndroid Build Coastguard Worker winwidth = x_cols - pwidth - 3;
3612*7c356e86SAndroid Build Coastguard Worker win = 0;
3613*7c356e86SAndroid Build Coastguard Worker morec = ' ';
3614*7c356e86SAndroid Build Coastguard Worker holdlen = 0;
3615*7c356e86SAndroid Build Coastguard Worker
3616*7c356e86SAndroid Build Coastguard Worker editmode = 2;
3617*7c356e86SAndroid Build Coastguard Worker x_flush();
3618*7c356e86SAndroid Build Coastguard Worker while (/* CONSTCOND */ 1) {
3619*7c356e86SAndroid Build Coastguard Worker if (macro.p) {
3620*7c356e86SAndroid Build Coastguard Worker c = (unsigned char)*macro.p++;
3621*7c356e86SAndroid Build Coastguard Worker /* end of current macro? */
3622*7c356e86SAndroid Build Coastguard Worker if (!c) {
3623*7c356e86SAndroid Build Coastguard Worker /* more macros left to finish? */
3624*7c356e86SAndroid Build Coastguard Worker if (*macro.p++)
3625*7c356e86SAndroid Build Coastguard Worker continue;
3626*7c356e86SAndroid Build Coastguard Worker /* must be the end of all the macros */
3627*7c356e86SAndroid Build Coastguard Worker vi_macro_reset();
3628*7c356e86SAndroid Build Coastguard Worker c = x_getc();
3629*7c356e86SAndroid Build Coastguard Worker }
3630*7c356e86SAndroid Build Coastguard Worker } else
3631*7c356e86SAndroid Build Coastguard Worker c = x_getc();
3632*7c356e86SAndroid Build Coastguard Worker
3633*7c356e86SAndroid Build Coastguard Worker if (c == -1)
3634*7c356e86SAndroid Build Coastguard Worker break;
3635*7c356e86SAndroid Build Coastguard Worker if (state != VLIT) {
3636*7c356e86SAndroid Build Coastguard Worker if (isched(c, edchars.intr) ||
3637*7c356e86SAndroid Build Coastguard Worker isched(c, edchars.quit)) {
3638*7c356e86SAndroid Build Coastguard Worker /* shove input buffer away */
3639*7c356e86SAndroid Build Coastguard Worker xbuf = ebuf.cbuf;
3640*7c356e86SAndroid Build Coastguard Worker xep = xbuf;
3641*7c356e86SAndroid Build Coastguard Worker if (ebuf.linelen > 0)
3642*7c356e86SAndroid Build Coastguard Worker xep += ebuf.linelen;
3643*7c356e86SAndroid Build Coastguard Worker /* pretend we got an interrupt */
3644*7c356e86SAndroid Build Coastguard Worker x_intr(isched(c, edchars.intr) ?
3645*7c356e86SAndroid Build Coastguard Worker SIGINT : SIGQUIT, c);
3646*7c356e86SAndroid Build Coastguard Worker } else if (isched(c, edchars.eof) &&
3647*7c356e86SAndroid Build Coastguard Worker state != VVERSION) {
3648*7c356e86SAndroid Build Coastguard Worker if (vs->linelen == 0) {
3649*7c356e86SAndroid Build Coastguard Worker x_vi_zotc(c);
3650*7c356e86SAndroid Build Coastguard Worker c = -1;
3651*7c356e86SAndroid Build Coastguard Worker break;
3652*7c356e86SAndroid Build Coastguard Worker }
3653*7c356e86SAndroid Build Coastguard Worker continue;
3654*7c356e86SAndroid Build Coastguard Worker }
3655*7c356e86SAndroid Build Coastguard Worker }
3656*7c356e86SAndroid Build Coastguard Worker if (vi_hook(c))
3657*7c356e86SAndroid Build Coastguard Worker break;
3658*7c356e86SAndroid Build Coastguard Worker x_flush();
3659*7c356e86SAndroid Build Coastguard Worker }
3660*7c356e86SAndroid Build Coastguard Worker
3661*7c356e86SAndroid Build Coastguard Worker x_putc('\r');
3662*7c356e86SAndroid Build Coastguard Worker x_putc('\n');
3663*7c356e86SAndroid Build Coastguard Worker x_flush();
3664*7c356e86SAndroid Build Coastguard Worker
3665*7c356e86SAndroid Build Coastguard Worker if (c == -1 || (ssize_t)LINE <= vs->linelen)
3666*7c356e86SAndroid Build Coastguard Worker return (-1);
3667*7c356e86SAndroid Build Coastguard Worker
3668*7c356e86SAndroid Build Coastguard Worker if (vs->cbuf != buf)
3669*7c356e86SAndroid Build Coastguard Worker memcpy(buf, vs->cbuf, vs->linelen);
3670*7c356e86SAndroid Build Coastguard Worker
3671*7c356e86SAndroid Build Coastguard Worker buf[vs->linelen++] = '\n';
3672*7c356e86SAndroid Build Coastguard Worker
3673*7c356e86SAndroid Build Coastguard Worker return (vs->linelen);
3674*7c356e86SAndroid Build Coastguard Worker }
3675*7c356e86SAndroid Build Coastguard Worker
3676*7c356e86SAndroid Build Coastguard Worker static int
vi_hook(int ch)3677*7c356e86SAndroid Build Coastguard Worker vi_hook(int ch)
3678*7c356e86SAndroid Build Coastguard Worker {
3679*7c356e86SAndroid Build Coastguard Worker static char curcmd[MAXVICMD], locpat[SRCHLEN];
3680*7c356e86SAndroid Build Coastguard Worker static int cmdlen, argc1, argc2;
3681*7c356e86SAndroid Build Coastguard Worker
3682*7c356e86SAndroid Build Coastguard Worker switch (state) {
3683*7c356e86SAndroid Build Coastguard Worker
3684*7c356e86SAndroid Build Coastguard Worker case VNORMAL:
3685*7c356e86SAndroid Build Coastguard Worker /* PC scancodes */
3686*7c356e86SAndroid Build Coastguard Worker if (!ch) {
3687*7c356e86SAndroid Build Coastguard Worker cmdlen = 0;
3688*7c356e86SAndroid Build Coastguard Worker switch (ch = x_getc()) {
3689*7c356e86SAndroid Build Coastguard Worker case 71: ch = ORD('0'); goto pseudo_vi_command;
3690*7c356e86SAndroid Build Coastguard Worker case 72: ch = ORD('k'); goto pseudo_vi_command;
3691*7c356e86SAndroid Build Coastguard Worker case 73: ch = ORD('A'); goto vi_xfunc_search;
3692*7c356e86SAndroid Build Coastguard Worker case 75: ch = ORD('h'); goto pseudo_vi_command;
3693*7c356e86SAndroid Build Coastguard Worker case 77: ch = ORD('l'); goto pseudo_vi_command;
3694*7c356e86SAndroid Build Coastguard Worker case 79: ch = ORD('$'); goto pseudo_vi_command;
3695*7c356e86SAndroid Build Coastguard Worker case 80: ch = ORD('j'); goto pseudo_vi_command;
3696*7c356e86SAndroid Build Coastguard Worker case 81: ch = ORD('B'); goto vi_xfunc_search;
3697*7c356e86SAndroid Build Coastguard Worker case 83: ch = ORD('x'); goto pseudo_vi_command;
3698*7c356e86SAndroid Build Coastguard Worker default: ch = 0; goto vi_insert_failed;
3699*7c356e86SAndroid Build Coastguard Worker }
3700*7c356e86SAndroid Build Coastguard Worker }
3701*7c356e86SAndroid Build Coastguard Worker if (insert != 0) {
3702*7c356e86SAndroid Build Coastguard Worker if (ch == CTRL_V) {
3703*7c356e86SAndroid Build Coastguard Worker state = VLIT;
3704*7c356e86SAndroid Build Coastguard Worker ch = ORD('^');
3705*7c356e86SAndroid Build Coastguard Worker }
3706*7c356e86SAndroid Build Coastguard Worker switch (vi_insert(ch)) {
3707*7c356e86SAndroid Build Coastguard Worker case -1:
3708*7c356e86SAndroid Build Coastguard Worker vi_insert_failed:
3709*7c356e86SAndroid Build Coastguard Worker vi_error();
3710*7c356e86SAndroid Build Coastguard Worker state = VNORMAL;
3711*7c356e86SAndroid Build Coastguard Worker break;
3712*7c356e86SAndroid Build Coastguard Worker case 0:
3713*7c356e86SAndroid Build Coastguard Worker if (state == VLIT) {
3714*7c356e86SAndroid Build Coastguard Worker vs->cursor--;
3715*7c356e86SAndroid Build Coastguard Worker refresh(false);
3716*7c356e86SAndroid Build Coastguard Worker } else
3717*7c356e86SAndroid Build Coastguard Worker refresh(insert != 0);
3718*7c356e86SAndroid Build Coastguard Worker break;
3719*7c356e86SAndroid Build Coastguard Worker case 1:
3720*7c356e86SAndroid Build Coastguard Worker return (1);
3721*7c356e86SAndroid Build Coastguard Worker }
3722*7c356e86SAndroid Build Coastguard Worker } else {
3723*7c356e86SAndroid Build Coastguard Worker if (ctype(ch, C_CR | C_LF))
3724*7c356e86SAndroid Build Coastguard Worker return (1);
3725*7c356e86SAndroid Build Coastguard Worker cmdlen = 0;
3726*7c356e86SAndroid Build Coastguard Worker argc1 = 0;
3727*7c356e86SAndroid Build Coastguard Worker if (ctype(ch, C_DIGIT) && ord(ch) != ORD('0')) {
3728*7c356e86SAndroid Build Coastguard Worker argc1 = ksh_numdig(ch);
3729*7c356e86SAndroid Build Coastguard Worker state = VARG1;
3730*7c356e86SAndroid Build Coastguard Worker } else {
3731*7c356e86SAndroid Build Coastguard Worker pseudo_vi_command:
3732*7c356e86SAndroid Build Coastguard Worker curcmd[cmdlen++] = ch;
3733*7c356e86SAndroid Build Coastguard Worker state = nextstate(ch);
3734*7c356e86SAndroid Build Coastguard Worker if (state == VSEARCH) {
3735*7c356e86SAndroid Build Coastguard Worker save_cbuf();
3736*7c356e86SAndroid Build Coastguard Worker vs->cursor = 0;
3737*7c356e86SAndroid Build Coastguard Worker vs->linelen = 0;
3738*7c356e86SAndroid Build Coastguard Worker if (putbuf(ord(ch) == ORD('/') ?
3739*7c356e86SAndroid Build Coastguard Worker "/" : "?", 1, false) != 0)
3740*7c356e86SAndroid Build Coastguard Worker return (-1);
3741*7c356e86SAndroid Build Coastguard Worker refresh(false);
3742*7c356e86SAndroid Build Coastguard Worker }
3743*7c356e86SAndroid Build Coastguard Worker if (state == VVERSION) {
3744*7c356e86SAndroid Build Coastguard Worker save_cbuf();
3745*7c356e86SAndroid Build Coastguard Worker vs->cursor = 0;
3746*7c356e86SAndroid Build Coastguard Worker vs->linelen = 0;
3747*7c356e86SAndroid Build Coastguard Worker putbuf(KSH_VERSION,
3748*7c356e86SAndroid Build Coastguard Worker strlen(KSH_VERSION), false);
3749*7c356e86SAndroid Build Coastguard Worker refresh(false);
3750*7c356e86SAndroid Build Coastguard Worker }
3751*7c356e86SAndroid Build Coastguard Worker }
3752*7c356e86SAndroid Build Coastguard Worker }
3753*7c356e86SAndroid Build Coastguard Worker break;
3754*7c356e86SAndroid Build Coastguard Worker
3755*7c356e86SAndroid Build Coastguard Worker case VLIT:
3756*7c356e86SAndroid Build Coastguard Worker if (is_bad(ch)) {
3757*7c356e86SAndroid Build Coastguard Worker del_range(vs->cursor, vs->cursor + 1);
3758*7c356e86SAndroid Build Coastguard Worker vi_error();
3759*7c356e86SAndroid Build Coastguard Worker } else
3760*7c356e86SAndroid Build Coastguard Worker vs->cbuf[vs->cursor++] = ch;
3761*7c356e86SAndroid Build Coastguard Worker refresh(true);
3762*7c356e86SAndroid Build Coastguard Worker state = VNORMAL;
3763*7c356e86SAndroid Build Coastguard Worker break;
3764*7c356e86SAndroid Build Coastguard Worker
3765*7c356e86SAndroid Build Coastguard Worker case VVERSION:
3766*7c356e86SAndroid Build Coastguard Worker restore_cbuf();
3767*7c356e86SAndroid Build Coastguard Worker state = VNORMAL;
3768*7c356e86SAndroid Build Coastguard Worker refresh(false);
3769*7c356e86SAndroid Build Coastguard Worker break;
3770*7c356e86SAndroid Build Coastguard Worker
3771*7c356e86SAndroid Build Coastguard Worker case VARG1:
3772*7c356e86SAndroid Build Coastguard Worker if (ctype(ch, C_DIGIT))
3773*7c356e86SAndroid Build Coastguard Worker argc1 = argc1 * 10 + ksh_numdig(ch);
3774*7c356e86SAndroid Build Coastguard Worker else {
3775*7c356e86SAndroid Build Coastguard Worker curcmd[cmdlen++] = ch;
3776*7c356e86SAndroid Build Coastguard Worker state = nextstate(ch);
3777*7c356e86SAndroid Build Coastguard Worker }
3778*7c356e86SAndroid Build Coastguard Worker break;
3779*7c356e86SAndroid Build Coastguard Worker
3780*7c356e86SAndroid Build Coastguard Worker case VEXTCMD:
3781*7c356e86SAndroid Build Coastguard Worker argc2 = 0;
3782*7c356e86SAndroid Build Coastguard Worker if (ctype(ch, C_DIGIT) && ord(ch) != ORD('0')) {
3783*7c356e86SAndroid Build Coastguard Worker argc2 = ksh_numdig(ch);
3784*7c356e86SAndroid Build Coastguard Worker state = VARG2;
3785*7c356e86SAndroid Build Coastguard Worker return (0);
3786*7c356e86SAndroid Build Coastguard Worker } else {
3787*7c356e86SAndroid Build Coastguard Worker curcmd[cmdlen++] = ch;
3788*7c356e86SAndroid Build Coastguard Worker if (ch == curcmd[0])
3789*7c356e86SAndroid Build Coastguard Worker state = VCMD;
3790*7c356e86SAndroid Build Coastguard Worker else if (is_move(ch))
3791*7c356e86SAndroid Build Coastguard Worker state = nextstate(ch);
3792*7c356e86SAndroid Build Coastguard Worker else
3793*7c356e86SAndroid Build Coastguard Worker state = VFAIL;
3794*7c356e86SAndroid Build Coastguard Worker }
3795*7c356e86SAndroid Build Coastguard Worker break;
3796*7c356e86SAndroid Build Coastguard Worker
3797*7c356e86SAndroid Build Coastguard Worker case VARG2:
3798*7c356e86SAndroid Build Coastguard Worker if (ctype(ch, C_DIGIT))
3799*7c356e86SAndroid Build Coastguard Worker argc2 = argc2 * 10 + ksh_numdig(ch);
3800*7c356e86SAndroid Build Coastguard Worker else {
3801*7c356e86SAndroid Build Coastguard Worker if (argc1 == 0)
3802*7c356e86SAndroid Build Coastguard Worker argc1 = argc2;
3803*7c356e86SAndroid Build Coastguard Worker else
3804*7c356e86SAndroid Build Coastguard Worker argc1 *= argc2;
3805*7c356e86SAndroid Build Coastguard Worker curcmd[cmdlen++] = ch;
3806*7c356e86SAndroid Build Coastguard Worker if (ch == curcmd[0])
3807*7c356e86SAndroid Build Coastguard Worker state = VCMD;
3808*7c356e86SAndroid Build Coastguard Worker else if (is_move(ch))
3809*7c356e86SAndroid Build Coastguard Worker state = nextstate(ch);
3810*7c356e86SAndroid Build Coastguard Worker else
3811*7c356e86SAndroid Build Coastguard Worker state = VFAIL;
3812*7c356e86SAndroid Build Coastguard Worker }
3813*7c356e86SAndroid Build Coastguard Worker break;
3814*7c356e86SAndroid Build Coastguard Worker
3815*7c356e86SAndroid Build Coastguard Worker case VXCH:
3816*7c356e86SAndroid Build Coastguard Worker if (ch == CTRL_BO)
3817*7c356e86SAndroid Build Coastguard Worker state = VNORMAL;
3818*7c356e86SAndroid Build Coastguard Worker else {
3819*7c356e86SAndroid Build Coastguard Worker curcmd[cmdlen++] = ch;
3820*7c356e86SAndroid Build Coastguard Worker state = VCMD;
3821*7c356e86SAndroid Build Coastguard Worker }
3822*7c356e86SAndroid Build Coastguard Worker break;
3823*7c356e86SAndroid Build Coastguard Worker
3824*7c356e86SAndroid Build Coastguard Worker case VSEARCH:
3825*7c356e86SAndroid Build Coastguard Worker if (ctype(ch, C_CR | C_LF) /* || ch == CTRL_BO */ ) {
3826*7c356e86SAndroid Build Coastguard Worker restore_cbuf();
3827*7c356e86SAndroid Build Coastguard Worker /* Repeat last search? */
3828*7c356e86SAndroid Build Coastguard Worker if (srchlen == 0) {
3829*7c356e86SAndroid Build Coastguard Worker if (!srchpat[0]) {
3830*7c356e86SAndroid Build Coastguard Worker vi_error();
3831*7c356e86SAndroid Build Coastguard Worker state = VNORMAL;
3832*7c356e86SAndroid Build Coastguard Worker refresh(false);
3833*7c356e86SAndroid Build Coastguard Worker return (0);
3834*7c356e86SAndroid Build Coastguard Worker }
3835*7c356e86SAndroid Build Coastguard Worker } else {
3836*7c356e86SAndroid Build Coastguard Worker locpat[srchlen] = '\0';
3837*7c356e86SAndroid Build Coastguard Worker memcpy(srchpat, locpat, srchlen + 1);
3838*7c356e86SAndroid Build Coastguard Worker }
3839*7c356e86SAndroid Build Coastguard Worker state = VCMD;
3840*7c356e86SAndroid Build Coastguard Worker } else if (isched(ch, edchars.erase) || ch == CTRL_H) {
3841*7c356e86SAndroid Build Coastguard Worker if (srchlen != 0) {
3842*7c356e86SAndroid Build Coastguard Worker srchlen--;
3843*7c356e86SAndroid Build Coastguard Worker vs->linelen -= char_len(locpat[srchlen]);
3844*7c356e86SAndroid Build Coastguard Worker vs->cursor = vs->linelen;
3845*7c356e86SAndroid Build Coastguard Worker refresh(false);
3846*7c356e86SAndroid Build Coastguard Worker return (0);
3847*7c356e86SAndroid Build Coastguard Worker }
3848*7c356e86SAndroid Build Coastguard Worker restore_cbuf();
3849*7c356e86SAndroid Build Coastguard Worker state = VNORMAL;
3850*7c356e86SAndroid Build Coastguard Worker refresh(false);
3851*7c356e86SAndroid Build Coastguard Worker } else if (isched(ch, edchars.kill)) {
3852*7c356e86SAndroid Build Coastguard Worker srchlen = 0;
3853*7c356e86SAndroid Build Coastguard Worker vs->linelen = 1;
3854*7c356e86SAndroid Build Coastguard Worker vs->cursor = 1;
3855*7c356e86SAndroid Build Coastguard Worker refresh(false);
3856*7c356e86SAndroid Build Coastguard Worker return (0);
3857*7c356e86SAndroid Build Coastguard Worker } else if (isched(ch, edchars.werase)) {
3858*7c356e86SAndroid Build Coastguard Worker unsigned int i, n;
3859*7c356e86SAndroid Build Coastguard Worker struct edstate new_es, *save_es;
3860*7c356e86SAndroid Build Coastguard Worker
3861*7c356e86SAndroid Build Coastguard Worker new_es.cursor = srchlen;
3862*7c356e86SAndroid Build Coastguard Worker new_es.cbuf = locpat;
3863*7c356e86SAndroid Build Coastguard Worker
3864*7c356e86SAndroid Build Coastguard Worker save_es = vs;
3865*7c356e86SAndroid Build Coastguard Worker vs = &new_es;
3866*7c356e86SAndroid Build Coastguard Worker n = backword(1);
3867*7c356e86SAndroid Build Coastguard Worker vs = save_es;
3868*7c356e86SAndroid Build Coastguard Worker
3869*7c356e86SAndroid Build Coastguard Worker i = (unsigned)srchlen;
3870*7c356e86SAndroid Build Coastguard Worker while (i-- > n)
3871*7c356e86SAndroid Build Coastguard Worker vs->linelen -= char_len(locpat[i]);
3872*7c356e86SAndroid Build Coastguard Worker srchlen = (int)n;
3873*7c356e86SAndroid Build Coastguard Worker vs->cursor = vs->linelen;
3874*7c356e86SAndroid Build Coastguard Worker refresh(false);
3875*7c356e86SAndroid Build Coastguard Worker return (0);
3876*7c356e86SAndroid Build Coastguard Worker } else {
3877*7c356e86SAndroid Build Coastguard Worker if (srchlen == SRCHLEN - 1)
3878*7c356e86SAndroid Build Coastguard Worker vi_error();
3879*7c356e86SAndroid Build Coastguard Worker else {
3880*7c356e86SAndroid Build Coastguard Worker locpat[srchlen++] = ch;
3881*7c356e86SAndroid Build Coastguard Worker if (ksh_isctrl(ch)) {
3882*7c356e86SAndroid Build Coastguard Worker if ((size_t)vs->linelen + 2 >
3883*7c356e86SAndroid Build Coastguard Worker (size_t)vs->cbufsize)
3884*7c356e86SAndroid Build Coastguard Worker vi_error();
3885*7c356e86SAndroid Build Coastguard Worker vs->cbuf[vs->linelen++] = '^';
3886*7c356e86SAndroid Build Coastguard Worker vs->cbuf[vs->linelen++] = ksh_unctrl(ch);
3887*7c356e86SAndroid Build Coastguard Worker } else {
3888*7c356e86SAndroid Build Coastguard Worker if (vs->linelen >= vs->cbufsize)
3889*7c356e86SAndroid Build Coastguard Worker vi_error();
3890*7c356e86SAndroid Build Coastguard Worker vs->cbuf[vs->linelen++] = ch;
3891*7c356e86SAndroid Build Coastguard Worker }
3892*7c356e86SAndroid Build Coastguard Worker vs->cursor = vs->linelen;
3893*7c356e86SAndroid Build Coastguard Worker refresh(false);
3894*7c356e86SAndroid Build Coastguard Worker }
3895*7c356e86SAndroid Build Coastguard Worker return (0);
3896*7c356e86SAndroid Build Coastguard Worker }
3897*7c356e86SAndroid Build Coastguard Worker break;
3898*7c356e86SAndroid Build Coastguard Worker
3899*7c356e86SAndroid Build Coastguard Worker case VPREFIX2:
3900*7c356e86SAndroid Build Coastguard Worker vi_xfunc_search:
3901*7c356e86SAndroid Build Coastguard Worker state = VFAIL;
3902*7c356e86SAndroid Build Coastguard Worker switch (ch) {
3903*7c356e86SAndroid Build Coastguard Worker case ORD('A'):
3904*7c356e86SAndroid Build Coastguard Worker case ORD('B'):
3905*7c356e86SAndroid Build Coastguard Worker /* the cursor may not be at the BOL */
3906*7c356e86SAndroid Build Coastguard Worker if (!vs->cursor)
3907*7c356e86SAndroid Build Coastguard Worker break;
3908*7c356e86SAndroid Build Coastguard Worker /* nor further in the line than we can search for */
3909*7c356e86SAndroid Build Coastguard Worker if ((size_t)vs->cursor >= sizeof(srchpat) - 1)
3910*7c356e86SAndroid Build Coastguard Worker vs->cursor = sizeof(srchpat) - 2;
3911*7c356e86SAndroid Build Coastguard Worker /* anchor the search pattern */
3912*7c356e86SAndroid Build Coastguard Worker srchpat[0] = '^';
3913*7c356e86SAndroid Build Coastguard Worker /* take current line up to the cursor */
3914*7c356e86SAndroid Build Coastguard Worker memcpy(srchpat + 1, vs->cbuf, vs->cursor);
3915*7c356e86SAndroid Build Coastguard Worker srchpat[vs->cursor + 1] = '\0';
3916*7c356e86SAndroid Build Coastguard Worker /* set a magic flag */
3917*7c356e86SAndroid Build Coastguard Worker argc1 = 2 + (int)vs->cursor;
3918*7c356e86SAndroid Build Coastguard Worker /* and emulate a history search */
3919*7c356e86SAndroid Build Coastguard Worker /* search backwards if PgUp, forwards for PgDn */
3920*7c356e86SAndroid Build Coastguard Worker lastsearch = ch == ORD('A') ? '/' : '?';
3921*7c356e86SAndroid Build Coastguard Worker *curcmd = 'n';
3922*7c356e86SAndroid Build Coastguard Worker goto pseudo_VCMD;
3923*7c356e86SAndroid Build Coastguard Worker }
3924*7c356e86SAndroid Build Coastguard Worker break;
3925*7c356e86SAndroid Build Coastguard Worker }
3926*7c356e86SAndroid Build Coastguard Worker
3927*7c356e86SAndroid Build Coastguard Worker switch (state) {
3928*7c356e86SAndroid Build Coastguard Worker case VCMD:
3929*7c356e86SAndroid Build Coastguard Worker pseudo_VCMD:
3930*7c356e86SAndroid Build Coastguard Worker state = VNORMAL;
3931*7c356e86SAndroid Build Coastguard Worker switch (vi_cmd(argc1, curcmd)) {
3932*7c356e86SAndroid Build Coastguard Worker case -1:
3933*7c356e86SAndroid Build Coastguard Worker vi_error();
3934*7c356e86SAndroid Build Coastguard Worker refresh(false);
3935*7c356e86SAndroid Build Coastguard Worker break;
3936*7c356e86SAndroid Build Coastguard Worker case 0:
3937*7c356e86SAndroid Build Coastguard Worker if (insert != 0)
3938*7c356e86SAndroid Build Coastguard Worker inslen = 0;
3939*7c356e86SAndroid Build Coastguard Worker refresh(insert != 0);
3940*7c356e86SAndroid Build Coastguard Worker break;
3941*7c356e86SAndroid Build Coastguard Worker case 1:
3942*7c356e86SAndroid Build Coastguard Worker refresh(false);
3943*7c356e86SAndroid Build Coastguard Worker return (1);
3944*7c356e86SAndroid Build Coastguard Worker case 2:
3945*7c356e86SAndroid Build Coastguard Worker /* back from a 'v' command - don't redraw the screen */
3946*7c356e86SAndroid Build Coastguard Worker return (1);
3947*7c356e86SAndroid Build Coastguard Worker }
3948*7c356e86SAndroid Build Coastguard Worker break;
3949*7c356e86SAndroid Build Coastguard Worker
3950*7c356e86SAndroid Build Coastguard Worker case VREDO:
3951*7c356e86SAndroid Build Coastguard Worker state = VNORMAL;
3952*7c356e86SAndroid Build Coastguard Worker if (argc1 != 0)
3953*7c356e86SAndroid Build Coastguard Worker lastac = argc1;
3954*7c356e86SAndroid Build Coastguard Worker switch (vi_cmd(lastac, lastcmd)) {
3955*7c356e86SAndroid Build Coastguard Worker case -1:
3956*7c356e86SAndroid Build Coastguard Worker vi_error();
3957*7c356e86SAndroid Build Coastguard Worker refresh(false);
3958*7c356e86SAndroid Build Coastguard Worker break;
3959*7c356e86SAndroid Build Coastguard Worker case 0:
3960*7c356e86SAndroid Build Coastguard Worker if (insert != 0) {
3961*7c356e86SAndroid Build Coastguard Worker if (lastcmd[0] == 's' ||
3962*7c356e86SAndroid Build Coastguard Worker ksh_eq(lastcmd[0], 'C', 'c')) {
3963*7c356e86SAndroid Build Coastguard Worker if (redo_insert(1) != 0)
3964*7c356e86SAndroid Build Coastguard Worker vi_error();
3965*7c356e86SAndroid Build Coastguard Worker } else {
3966*7c356e86SAndroid Build Coastguard Worker if (redo_insert(lastac) != 0)
3967*7c356e86SAndroid Build Coastguard Worker vi_error();
3968*7c356e86SAndroid Build Coastguard Worker }
3969*7c356e86SAndroid Build Coastguard Worker }
3970*7c356e86SAndroid Build Coastguard Worker refresh(false);
3971*7c356e86SAndroid Build Coastguard Worker break;
3972*7c356e86SAndroid Build Coastguard Worker case 1:
3973*7c356e86SAndroid Build Coastguard Worker refresh(false);
3974*7c356e86SAndroid Build Coastguard Worker return (1);
3975*7c356e86SAndroid Build Coastguard Worker case 2:
3976*7c356e86SAndroid Build Coastguard Worker /* back from a 'v' command - can't happen */
3977*7c356e86SAndroid Build Coastguard Worker break;
3978*7c356e86SAndroid Build Coastguard Worker }
3979*7c356e86SAndroid Build Coastguard Worker break;
3980*7c356e86SAndroid Build Coastguard Worker
3981*7c356e86SAndroid Build Coastguard Worker case VFAIL:
3982*7c356e86SAndroid Build Coastguard Worker state = VNORMAL;
3983*7c356e86SAndroid Build Coastguard Worker vi_error();
3984*7c356e86SAndroid Build Coastguard Worker break;
3985*7c356e86SAndroid Build Coastguard Worker }
3986*7c356e86SAndroid Build Coastguard Worker return (0);
3987*7c356e86SAndroid Build Coastguard Worker }
3988*7c356e86SAndroid Build Coastguard Worker
3989*7c356e86SAndroid Build Coastguard Worker static int
nextstate(int ch)3990*7c356e86SAndroid Build Coastguard Worker nextstate(int ch)
3991*7c356e86SAndroid Build Coastguard Worker {
3992*7c356e86SAndroid Build Coastguard Worker if (is_extend(ch))
3993*7c356e86SAndroid Build Coastguard Worker return (VEXTCMD);
3994*7c356e86SAndroid Build Coastguard Worker else if (is_srch(ch))
3995*7c356e86SAndroid Build Coastguard Worker return (VSEARCH);
3996*7c356e86SAndroid Build Coastguard Worker else if (is_long(ch))
3997*7c356e86SAndroid Build Coastguard Worker return (VXCH);
3998*7c356e86SAndroid Build Coastguard Worker else if (ch == '.')
3999*7c356e86SAndroid Build Coastguard Worker return (VREDO);
4000*7c356e86SAndroid Build Coastguard Worker else if (ch == CTRL_V)
4001*7c356e86SAndroid Build Coastguard Worker return (VVERSION);
4002*7c356e86SAndroid Build Coastguard Worker else if (is_cmd(ch))
4003*7c356e86SAndroid Build Coastguard Worker return (VCMD);
4004*7c356e86SAndroid Build Coastguard Worker else
4005*7c356e86SAndroid Build Coastguard Worker return (VFAIL);
4006*7c356e86SAndroid Build Coastguard Worker }
4007*7c356e86SAndroid Build Coastguard Worker
4008*7c356e86SAndroid Build Coastguard Worker static int
vi_insert(int ch)4009*7c356e86SAndroid Build Coastguard Worker vi_insert(int ch)
4010*7c356e86SAndroid Build Coastguard Worker {
4011*7c356e86SAndroid Build Coastguard Worker int tcursor;
4012*7c356e86SAndroid Build Coastguard Worker
4013*7c356e86SAndroid Build Coastguard Worker if (isched(ch, edchars.erase) || ch == CTRL_H) {
4014*7c356e86SAndroid Build Coastguard Worker if (insert == REPLACE) {
4015*7c356e86SAndroid Build Coastguard Worker if (vs->cursor == undo->cursor) {
4016*7c356e86SAndroid Build Coastguard Worker vi_error();
4017*7c356e86SAndroid Build Coastguard Worker return (0);
4018*7c356e86SAndroid Build Coastguard Worker }
4019*7c356e86SAndroid Build Coastguard Worker if (inslen > 0)
4020*7c356e86SAndroid Build Coastguard Worker inslen--;
4021*7c356e86SAndroid Build Coastguard Worker vs->cursor--;
4022*7c356e86SAndroid Build Coastguard Worker if (vs->cursor >= undo->linelen)
4023*7c356e86SAndroid Build Coastguard Worker vs->linelen--;
4024*7c356e86SAndroid Build Coastguard Worker else
4025*7c356e86SAndroid Build Coastguard Worker vs->cbuf[vs->cursor] = undo->cbuf[vs->cursor];
4026*7c356e86SAndroid Build Coastguard Worker } else {
4027*7c356e86SAndroid Build Coastguard Worker if (vs->cursor == 0)
4028*7c356e86SAndroid Build Coastguard Worker return (0);
4029*7c356e86SAndroid Build Coastguard Worker if (inslen > 0)
4030*7c356e86SAndroid Build Coastguard Worker inslen--;
4031*7c356e86SAndroid Build Coastguard Worker vs->cursor--;
4032*7c356e86SAndroid Build Coastguard Worker vs->linelen--;
4033*7c356e86SAndroid Build Coastguard Worker memmove(&vs->cbuf[vs->cursor], &vs->cbuf[vs->cursor + 1],
4034*7c356e86SAndroid Build Coastguard Worker vs->linelen - vs->cursor + 1);
4035*7c356e86SAndroid Build Coastguard Worker }
4036*7c356e86SAndroid Build Coastguard Worker expanded = NONE;
4037*7c356e86SAndroid Build Coastguard Worker return (0);
4038*7c356e86SAndroid Build Coastguard Worker }
4039*7c356e86SAndroid Build Coastguard Worker if (isched(ch, edchars.kill)) {
4040*7c356e86SAndroid Build Coastguard Worker if (vs->cursor != 0) {
4041*7c356e86SAndroid Build Coastguard Worker inslen = 0;
4042*7c356e86SAndroid Build Coastguard Worker memmove(vs->cbuf, &vs->cbuf[vs->cursor],
4043*7c356e86SAndroid Build Coastguard Worker vs->linelen - vs->cursor);
4044*7c356e86SAndroid Build Coastguard Worker vs->linelen -= vs->cursor;
4045*7c356e86SAndroid Build Coastguard Worker vs->cursor = 0;
4046*7c356e86SAndroid Build Coastguard Worker }
4047*7c356e86SAndroid Build Coastguard Worker expanded = NONE;
4048*7c356e86SAndroid Build Coastguard Worker return (0);
4049*7c356e86SAndroid Build Coastguard Worker }
4050*7c356e86SAndroid Build Coastguard Worker if (isched(ch, edchars.werase)) {
4051*7c356e86SAndroid Build Coastguard Worker if (vs->cursor != 0) {
4052*7c356e86SAndroid Build Coastguard Worker tcursor = backword(1);
4053*7c356e86SAndroid Build Coastguard Worker memmove(&vs->cbuf[tcursor], &vs->cbuf[vs->cursor],
4054*7c356e86SAndroid Build Coastguard Worker vs->linelen - vs->cursor);
4055*7c356e86SAndroid Build Coastguard Worker vs->linelen -= vs->cursor - tcursor;
4056*7c356e86SAndroid Build Coastguard Worker if (inslen < vs->cursor - tcursor)
4057*7c356e86SAndroid Build Coastguard Worker inslen = 0;
4058*7c356e86SAndroid Build Coastguard Worker else
4059*7c356e86SAndroid Build Coastguard Worker inslen -= vs->cursor - tcursor;
4060*7c356e86SAndroid Build Coastguard Worker vs->cursor = tcursor;
4061*7c356e86SAndroid Build Coastguard Worker }
4062*7c356e86SAndroid Build Coastguard Worker expanded = NONE;
4063*7c356e86SAndroid Build Coastguard Worker return (0);
4064*7c356e86SAndroid Build Coastguard Worker }
4065*7c356e86SAndroid Build Coastguard Worker /*
4066*7c356e86SAndroid Build Coastguard Worker * If any chars are entered before escape, trash the saved insert
4067*7c356e86SAndroid Build Coastguard Worker * buffer (if user inserts & deletes char, ibuf gets trashed and
4068*7c356e86SAndroid Build Coastguard Worker * we don't want to use it)
4069*7c356e86SAndroid Build Coastguard Worker */
4070*7c356e86SAndroid Build Coastguard Worker if (first_insert && ch != CTRL_BO)
4071*7c356e86SAndroid Build Coastguard Worker saved_inslen = 0;
4072*7c356e86SAndroid Build Coastguard Worker switch (ch) {
4073*7c356e86SAndroid Build Coastguard Worker case '\0':
4074*7c356e86SAndroid Build Coastguard Worker return (-1);
4075*7c356e86SAndroid Build Coastguard Worker
4076*7c356e86SAndroid Build Coastguard Worker case '\r':
4077*7c356e86SAndroid Build Coastguard Worker case '\n':
4078*7c356e86SAndroid Build Coastguard Worker return (1);
4079*7c356e86SAndroid Build Coastguard Worker
4080*7c356e86SAndroid Build Coastguard Worker case CTRL_BO:
4081*7c356e86SAndroid Build Coastguard Worker expanded = NONE;
4082*7c356e86SAndroid Build Coastguard Worker if (first_insert) {
4083*7c356e86SAndroid Build Coastguard Worker first_insert = false;
4084*7c356e86SAndroid Build Coastguard Worker if (inslen == 0) {
4085*7c356e86SAndroid Build Coastguard Worker inslen = saved_inslen;
4086*7c356e86SAndroid Build Coastguard Worker return (redo_insert(0));
4087*7c356e86SAndroid Build Coastguard Worker }
4088*7c356e86SAndroid Build Coastguard Worker lastcmd[0] = 'a';
4089*7c356e86SAndroid Build Coastguard Worker lastac = 1;
4090*7c356e86SAndroid Build Coastguard Worker }
4091*7c356e86SAndroid Build Coastguard Worker if (lastcmd[0] == 's' || ksh_eq(lastcmd[0], 'C', 'c'))
4092*7c356e86SAndroid Build Coastguard Worker return (redo_insert(0));
4093*7c356e86SAndroid Build Coastguard Worker else
4094*7c356e86SAndroid Build Coastguard Worker return (redo_insert(lastac - 1));
4095*7c356e86SAndroid Build Coastguard Worker
4096*7c356e86SAndroid Build Coastguard Worker /* { start nonstandard vi commands */
4097*7c356e86SAndroid Build Coastguard Worker case CTRL_X:
4098*7c356e86SAndroid Build Coastguard Worker expand_word(0);
4099*7c356e86SAndroid Build Coastguard Worker break;
4100*7c356e86SAndroid Build Coastguard Worker
4101*7c356e86SAndroid Build Coastguard Worker case CTRL_F:
4102*7c356e86SAndroid Build Coastguard Worker complete_word(0, 0);
4103*7c356e86SAndroid Build Coastguard Worker break;
4104*7c356e86SAndroid Build Coastguard Worker
4105*7c356e86SAndroid Build Coastguard Worker case CTRL_E:
4106*7c356e86SAndroid Build Coastguard Worker print_expansions(vs, 0);
4107*7c356e86SAndroid Build Coastguard Worker break;
4108*7c356e86SAndroid Build Coastguard Worker
4109*7c356e86SAndroid Build Coastguard Worker case CTRL_I:
4110*7c356e86SAndroid Build Coastguard Worker if (Flag(FVITABCOMPLETE)) {
4111*7c356e86SAndroid Build Coastguard Worker complete_word(0, 0);
4112*7c356e86SAndroid Build Coastguard Worker break;
4113*7c356e86SAndroid Build Coastguard Worker }
4114*7c356e86SAndroid Build Coastguard Worker /* FALLTHROUGH */
4115*7c356e86SAndroid Build Coastguard Worker /* end nonstandard vi commands } */
4116*7c356e86SAndroid Build Coastguard Worker
4117*7c356e86SAndroid Build Coastguard Worker default:
4118*7c356e86SAndroid Build Coastguard Worker if (vs->linelen >= vs->cbufsize - 1)
4119*7c356e86SAndroid Build Coastguard Worker return (-1);
4120*7c356e86SAndroid Build Coastguard Worker ibuf[inslen++] = ch;
4121*7c356e86SAndroid Build Coastguard Worker if (insert == INSERT) {
4122*7c356e86SAndroid Build Coastguard Worker memmove(&vs->cbuf[vs->cursor + 1], &vs->cbuf[vs->cursor],
4123*7c356e86SAndroid Build Coastguard Worker vs->linelen - vs->cursor);
4124*7c356e86SAndroid Build Coastguard Worker vs->linelen++;
4125*7c356e86SAndroid Build Coastguard Worker }
4126*7c356e86SAndroid Build Coastguard Worker vs->cbuf[vs->cursor++] = ch;
4127*7c356e86SAndroid Build Coastguard Worker if (insert == REPLACE && vs->cursor > vs->linelen)
4128*7c356e86SAndroid Build Coastguard Worker vs->linelen++;
4129*7c356e86SAndroid Build Coastguard Worker expanded = NONE;
4130*7c356e86SAndroid Build Coastguard Worker }
4131*7c356e86SAndroid Build Coastguard Worker return (0);
4132*7c356e86SAndroid Build Coastguard Worker }
4133*7c356e86SAndroid Build Coastguard Worker
4134*7c356e86SAndroid Build Coastguard Worker static int
vi_cmd(int argcnt,const char * cmd)4135*7c356e86SAndroid Build Coastguard Worker vi_cmd(int argcnt, const char *cmd)
4136*7c356e86SAndroid Build Coastguard Worker {
4137*7c356e86SAndroid Build Coastguard Worker int ncursor;
4138*7c356e86SAndroid Build Coastguard Worker int cur, c1, c2;
4139*7c356e86SAndroid Build Coastguard Worker int any;
4140*7c356e86SAndroid Build Coastguard Worker bool b;
4141*7c356e86SAndroid Build Coastguard Worker struct edstate *t;
4142*7c356e86SAndroid Build Coastguard Worker
4143*7c356e86SAndroid Build Coastguard Worker if (argcnt == 0 && !is_zerocount(*cmd))
4144*7c356e86SAndroid Build Coastguard Worker argcnt = 1;
4145*7c356e86SAndroid Build Coastguard Worker
4146*7c356e86SAndroid Build Coastguard Worker if (is_move(*cmd)) {
4147*7c356e86SAndroid Build Coastguard Worker if ((cur = domove(argcnt, cmd, 0)) >= 0) {
4148*7c356e86SAndroid Build Coastguard Worker if (cur == vs->linelen && cur != 0)
4149*7c356e86SAndroid Build Coastguard Worker cur--;
4150*7c356e86SAndroid Build Coastguard Worker vs->cursor = cur;
4151*7c356e86SAndroid Build Coastguard Worker } else
4152*7c356e86SAndroid Build Coastguard Worker return (-1);
4153*7c356e86SAndroid Build Coastguard Worker } else {
4154*7c356e86SAndroid Build Coastguard Worker /* Don't save state in middle of macro.. */
4155*7c356e86SAndroid Build Coastguard Worker if (is_undoable(*cmd) && !macro.p) {
4156*7c356e86SAndroid Build Coastguard Worker undo->winleft = vs->winleft;
4157*7c356e86SAndroid Build Coastguard Worker memmove(undo->cbuf, vs->cbuf, vs->linelen);
4158*7c356e86SAndroid Build Coastguard Worker undo->linelen = vs->linelen;
4159*7c356e86SAndroid Build Coastguard Worker undo->cursor = vs->cursor;
4160*7c356e86SAndroid Build Coastguard Worker lastac = argcnt;
4161*7c356e86SAndroid Build Coastguard Worker memmove(lastcmd, cmd, MAXVICMD);
4162*7c356e86SAndroid Build Coastguard Worker }
4163*7c356e86SAndroid Build Coastguard Worker switch (ord(*cmd)) {
4164*7c356e86SAndroid Build Coastguard Worker
4165*7c356e86SAndroid Build Coastguard Worker case CTRL_L:
4166*7c356e86SAndroid Build Coastguard Worker case CTRL_R:
4167*7c356e86SAndroid Build Coastguard Worker redraw_line(true);
4168*7c356e86SAndroid Build Coastguard Worker break;
4169*7c356e86SAndroid Build Coastguard Worker
4170*7c356e86SAndroid Build Coastguard Worker case ORD('@'):
4171*7c356e86SAndroid Build Coastguard Worker {
4172*7c356e86SAndroid Build Coastguard Worker static char alias[] = "_\0";
4173*7c356e86SAndroid Build Coastguard Worker struct tbl *ap;
4174*7c356e86SAndroid Build Coastguard Worker size_t olen, nlen;
4175*7c356e86SAndroid Build Coastguard Worker char *p, *nbuf;
4176*7c356e86SAndroid Build Coastguard Worker
4177*7c356e86SAndroid Build Coastguard Worker /* lookup letter in alias list... */
4178*7c356e86SAndroid Build Coastguard Worker alias[1] = cmd[1];
4179*7c356e86SAndroid Build Coastguard Worker ap = ktsearch(&aliases, alias, hash(alias));
4180*7c356e86SAndroid Build Coastguard Worker if (!cmd[1] || !ap || !(ap->flag & ISSET))
4181*7c356e86SAndroid Build Coastguard Worker return (-1);
4182*7c356e86SAndroid Build Coastguard Worker /* check if this is a recursive call... */
4183*7c356e86SAndroid Build Coastguard Worker if ((p = (char *)macro.p))
4184*7c356e86SAndroid Build Coastguard Worker while ((p = strnul(p)) && p[1])
4185*7c356e86SAndroid Build Coastguard Worker if (*++p == cmd[1])
4186*7c356e86SAndroid Build Coastguard Worker return (-1);
4187*7c356e86SAndroid Build Coastguard Worker /* insert alias into macro buffer */
4188*7c356e86SAndroid Build Coastguard Worker nlen = strlen(ap->val.s) + 1;
4189*7c356e86SAndroid Build Coastguard Worker olen = !macro.p ? 2 :
4190*7c356e86SAndroid Build Coastguard Worker macro.len - (macro.p - macro.buf);
4191*7c356e86SAndroid Build Coastguard Worker /*
4192*7c356e86SAndroid Build Coastguard Worker * at this point, it's fairly reasonable that
4193*7c356e86SAndroid Build Coastguard Worker * nlen + olen + 2 doesn't overflow
4194*7c356e86SAndroid Build Coastguard Worker */
4195*7c356e86SAndroid Build Coastguard Worker nbuf = alloc(nlen + 1 + olen, AEDIT);
4196*7c356e86SAndroid Build Coastguard Worker memcpy(nbuf, ap->val.s, nlen);
4197*7c356e86SAndroid Build Coastguard Worker nbuf[nlen++] = cmd[1];
4198*7c356e86SAndroid Build Coastguard Worker if (macro.p) {
4199*7c356e86SAndroid Build Coastguard Worker memcpy(nbuf + nlen, macro.p, olen);
4200*7c356e86SAndroid Build Coastguard Worker afree(macro.buf, AEDIT);
4201*7c356e86SAndroid Build Coastguard Worker nlen += olen;
4202*7c356e86SAndroid Build Coastguard Worker } else {
4203*7c356e86SAndroid Build Coastguard Worker nbuf[nlen++] = '\0';
4204*7c356e86SAndroid Build Coastguard Worker nbuf[nlen++] = '\0';
4205*7c356e86SAndroid Build Coastguard Worker }
4206*7c356e86SAndroid Build Coastguard Worker macro.p = macro.buf = (unsigned char *)nbuf;
4207*7c356e86SAndroid Build Coastguard Worker macro.len = nlen;
4208*7c356e86SAndroid Build Coastguard Worker }
4209*7c356e86SAndroid Build Coastguard Worker break;
4210*7c356e86SAndroid Build Coastguard Worker
4211*7c356e86SAndroid Build Coastguard Worker case ORD('a'):
4212*7c356e86SAndroid Build Coastguard Worker modified = 1;
4213*7c356e86SAndroid Build Coastguard Worker hnum = hlast;
4214*7c356e86SAndroid Build Coastguard Worker if (vs->linelen != 0)
4215*7c356e86SAndroid Build Coastguard Worker vs->cursor++;
4216*7c356e86SAndroid Build Coastguard Worker insert = INSERT;
4217*7c356e86SAndroid Build Coastguard Worker break;
4218*7c356e86SAndroid Build Coastguard Worker
4219*7c356e86SAndroid Build Coastguard Worker case ORD('A'):
4220*7c356e86SAndroid Build Coastguard Worker modified = 1;
4221*7c356e86SAndroid Build Coastguard Worker hnum = hlast;
4222*7c356e86SAndroid Build Coastguard Worker del_range(0, 0);
4223*7c356e86SAndroid Build Coastguard Worker vs->cursor = vs->linelen;
4224*7c356e86SAndroid Build Coastguard Worker insert = INSERT;
4225*7c356e86SAndroid Build Coastguard Worker break;
4226*7c356e86SAndroid Build Coastguard Worker
4227*7c356e86SAndroid Build Coastguard Worker case ORD('S'):
4228*7c356e86SAndroid Build Coastguard Worker vs->cursor = domovebeg();
4229*7c356e86SAndroid Build Coastguard Worker del_range(vs->cursor, vs->linelen);
4230*7c356e86SAndroid Build Coastguard Worker modified = 1;
4231*7c356e86SAndroid Build Coastguard Worker hnum = hlast;
4232*7c356e86SAndroid Build Coastguard Worker insert = INSERT;
4233*7c356e86SAndroid Build Coastguard Worker break;
4234*7c356e86SAndroid Build Coastguard Worker
4235*7c356e86SAndroid Build Coastguard Worker case ORD('Y'):
4236*7c356e86SAndroid Build Coastguard Worker cmd = "y$";
4237*7c356e86SAndroid Build Coastguard Worker /* ahhhhhh... */
4238*7c356e86SAndroid Build Coastguard Worker
4239*7c356e86SAndroid Build Coastguard Worker /* FALLTHROUGH */
4240*7c356e86SAndroid Build Coastguard Worker case ORD('c'):
4241*7c356e86SAndroid Build Coastguard Worker case ORD('d'):
4242*7c356e86SAndroid Build Coastguard Worker case ORD('y'):
4243*7c356e86SAndroid Build Coastguard Worker if (*cmd == cmd[1]) {
4244*7c356e86SAndroid Build Coastguard Worker c1 = *cmd == 'c' ? domovebeg() : 0;
4245*7c356e86SAndroid Build Coastguard Worker c2 = vs->linelen;
4246*7c356e86SAndroid Build Coastguard Worker } else if (!is_move(cmd[1]))
4247*7c356e86SAndroid Build Coastguard Worker return (-1);
4248*7c356e86SAndroid Build Coastguard Worker else {
4249*7c356e86SAndroid Build Coastguard Worker if ((ncursor = domove(argcnt, &cmd[1], 1)) < 0)
4250*7c356e86SAndroid Build Coastguard Worker return (-1);
4251*7c356e86SAndroid Build Coastguard Worker if (*cmd == 'c' && ksh_eq(cmd[1], 'W', 'w') &&
4252*7c356e86SAndroid Build Coastguard Worker !ctype(vs->cbuf[vs->cursor], C_SPACE)) {
4253*7c356e86SAndroid Build Coastguard Worker do {
4254*7c356e86SAndroid Build Coastguard Worker --ncursor;
4255*7c356e86SAndroid Build Coastguard Worker } while (ctype(vs->cbuf[ncursor], C_SPACE));
4256*7c356e86SAndroid Build Coastguard Worker ncursor++;
4257*7c356e86SAndroid Build Coastguard Worker }
4258*7c356e86SAndroid Build Coastguard Worker if (ncursor > vs->cursor) {
4259*7c356e86SAndroid Build Coastguard Worker c1 = vs->cursor;
4260*7c356e86SAndroid Build Coastguard Worker c2 = ncursor;
4261*7c356e86SAndroid Build Coastguard Worker } else {
4262*7c356e86SAndroid Build Coastguard Worker c1 = ncursor;
4263*7c356e86SAndroid Build Coastguard Worker c2 = vs->cursor;
4264*7c356e86SAndroid Build Coastguard Worker if (cmd[1] == '%')
4265*7c356e86SAndroid Build Coastguard Worker c2++;
4266*7c356e86SAndroid Build Coastguard Worker }
4267*7c356e86SAndroid Build Coastguard Worker }
4268*7c356e86SAndroid Build Coastguard Worker if (*cmd != 'c' && c1 != c2)
4269*7c356e86SAndroid Build Coastguard Worker yank_range(c1, c2);
4270*7c356e86SAndroid Build Coastguard Worker if (*cmd != 'y') {
4271*7c356e86SAndroid Build Coastguard Worker del_range(c1, c2);
4272*7c356e86SAndroid Build Coastguard Worker vs->cursor = c1;
4273*7c356e86SAndroid Build Coastguard Worker }
4274*7c356e86SAndroid Build Coastguard Worker if (*cmd == 'c') {
4275*7c356e86SAndroid Build Coastguard Worker modified = 1;
4276*7c356e86SAndroid Build Coastguard Worker hnum = hlast;
4277*7c356e86SAndroid Build Coastguard Worker insert = INSERT;
4278*7c356e86SAndroid Build Coastguard Worker }
4279*7c356e86SAndroid Build Coastguard Worker break;
4280*7c356e86SAndroid Build Coastguard Worker
4281*7c356e86SAndroid Build Coastguard Worker case ORD('p'):
4282*7c356e86SAndroid Build Coastguard Worker modified = 1;
4283*7c356e86SAndroid Build Coastguard Worker hnum = hlast;
4284*7c356e86SAndroid Build Coastguard Worker if (vs->linelen != 0)
4285*7c356e86SAndroid Build Coastguard Worker vs->cursor++;
4286*7c356e86SAndroid Build Coastguard Worker while (putbuf(ybuf, yanklen, false) == 0 &&
4287*7c356e86SAndroid Build Coastguard Worker --argcnt > 0)
4288*7c356e86SAndroid Build Coastguard Worker ;
4289*7c356e86SAndroid Build Coastguard Worker if (vs->cursor != 0)
4290*7c356e86SAndroid Build Coastguard Worker vs->cursor--;
4291*7c356e86SAndroid Build Coastguard Worker if (argcnt != 0)
4292*7c356e86SAndroid Build Coastguard Worker return (-1);
4293*7c356e86SAndroid Build Coastguard Worker break;
4294*7c356e86SAndroid Build Coastguard Worker
4295*7c356e86SAndroid Build Coastguard Worker case ORD('P'):
4296*7c356e86SAndroid Build Coastguard Worker modified = 1;
4297*7c356e86SAndroid Build Coastguard Worker hnum = hlast;
4298*7c356e86SAndroid Build Coastguard Worker any = 0;
4299*7c356e86SAndroid Build Coastguard Worker while (putbuf(ybuf, yanklen, false) == 0 &&
4300*7c356e86SAndroid Build Coastguard Worker --argcnt > 0)
4301*7c356e86SAndroid Build Coastguard Worker any = 1;
4302*7c356e86SAndroid Build Coastguard Worker if (any && vs->cursor != 0)
4303*7c356e86SAndroid Build Coastguard Worker vs->cursor--;
4304*7c356e86SAndroid Build Coastguard Worker if (argcnt != 0)
4305*7c356e86SAndroid Build Coastguard Worker return (-1);
4306*7c356e86SAndroid Build Coastguard Worker break;
4307*7c356e86SAndroid Build Coastguard Worker
4308*7c356e86SAndroid Build Coastguard Worker case ORD('C'):
4309*7c356e86SAndroid Build Coastguard Worker modified = 1;
4310*7c356e86SAndroid Build Coastguard Worker hnum = hlast;
4311*7c356e86SAndroid Build Coastguard Worker del_range(vs->cursor, vs->linelen);
4312*7c356e86SAndroid Build Coastguard Worker insert = INSERT;
4313*7c356e86SAndroid Build Coastguard Worker break;
4314*7c356e86SAndroid Build Coastguard Worker
4315*7c356e86SAndroid Build Coastguard Worker case ORD('D'):
4316*7c356e86SAndroid Build Coastguard Worker yank_range(vs->cursor, vs->linelen);
4317*7c356e86SAndroid Build Coastguard Worker del_range(vs->cursor, vs->linelen);
4318*7c356e86SAndroid Build Coastguard Worker if (vs->cursor != 0)
4319*7c356e86SAndroid Build Coastguard Worker vs->cursor--;
4320*7c356e86SAndroid Build Coastguard Worker break;
4321*7c356e86SAndroid Build Coastguard Worker
4322*7c356e86SAndroid Build Coastguard Worker case ORD('g'):
4323*7c356e86SAndroid Build Coastguard Worker if (!argcnt)
4324*7c356e86SAndroid Build Coastguard Worker argcnt = hlast;
4325*7c356e86SAndroid Build Coastguard Worker /* FALLTHROUGH */
4326*7c356e86SAndroid Build Coastguard Worker case ORD('G'):
4327*7c356e86SAndroid Build Coastguard Worker if (!argcnt)
4328*7c356e86SAndroid Build Coastguard Worker argcnt = 1;
4329*7c356e86SAndroid Build Coastguard Worker else
4330*7c356e86SAndroid Build Coastguard Worker argcnt = hlast - (source->line - argcnt);
4331*7c356e86SAndroid Build Coastguard Worker if (grabhist(modified, argcnt - 1) < 0)
4332*7c356e86SAndroid Build Coastguard Worker return (-1);
4333*7c356e86SAndroid Build Coastguard Worker else {
4334*7c356e86SAndroid Build Coastguard Worker modified = 0;
4335*7c356e86SAndroid Build Coastguard Worker hnum = argcnt - 1;
4336*7c356e86SAndroid Build Coastguard Worker }
4337*7c356e86SAndroid Build Coastguard Worker break;
4338*7c356e86SAndroid Build Coastguard Worker
4339*7c356e86SAndroid Build Coastguard Worker case ORD('i'):
4340*7c356e86SAndroid Build Coastguard Worker modified = 1;
4341*7c356e86SAndroid Build Coastguard Worker hnum = hlast;
4342*7c356e86SAndroid Build Coastguard Worker insert = INSERT;
4343*7c356e86SAndroid Build Coastguard Worker break;
4344*7c356e86SAndroid Build Coastguard Worker
4345*7c356e86SAndroid Build Coastguard Worker case ORD('I'):
4346*7c356e86SAndroid Build Coastguard Worker modified = 1;
4347*7c356e86SAndroid Build Coastguard Worker hnum = hlast;
4348*7c356e86SAndroid Build Coastguard Worker vs->cursor = domovebeg();
4349*7c356e86SAndroid Build Coastguard Worker insert = INSERT;
4350*7c356e86SAndroid Build Coastguard Worker break;
4351*7c356e86SAndroid Build Coastguard Worker
4352*7c356e86SAndroid Build Coastguard Worker case ORD('j'):
4353*7c356e86SAndroid Build Coastguard Worker case ORD('+'):
4354*7c356e86SAndroid Build Coastguard Worker case CTRL_N:
4355*7c356e86SAndroid Build Coastguard Worker if (grabhist(modified, hnum + argcnt) < 0)
4356*7c356e86SAndroid Build Coastguard Worker return (-1);
4357*7c356e86SAndroid Build Coastguard Worker else {
4358*7c356e86SAndroid Build Coastguard Worker modified = 0;
4359*7c356e86SAndroid Build Coastguard Worker hnum += argcnt;
4360*7c356e86SAndroid Build Coastguard Worker }
4361*7c356e86SAndroid Build Coastguard Worker break;
4362*7c356e86SAndroid Build Coastguard Worker
4363*7c356e86SAndroid Build Coastguard Worker case ORD('k'):
4364*7c356e86SAndroid Build Coastguard Worker case ORD('-'):
4365*7c356e86SAndroid Build Coastguard Worker case CTRL_P:
4366*7c356e86SAndroid Build Coastguard Worker if (grabhist(modified, hnum - argcnt) < 0)
4367*7c356e86SAndroid Build Coastguard Worker return (-1);
4368*7c356e86SAndroid Build Coastguard Worker else {
4369*7c356e86SAndroid Build Coastguard Worker modified = 0;
4370*7c356e86SAndroid Build Coastguard Worker hnum -= argcnt;
4371*7c356e86SAndroid Build Coastguard Worker }
4372*7c356e86SAndroid Build Coastguard Worker break;
4373*7c356e86SAndroid Build Coastguard Worker
4374*7c356e86SAndroid Build Coastguard Worker case ORD('r'):
4375*7c356e86SAndroid Build Coastguard Worker if (vs->linelen == 0)
4376*7c356e86SAndroid Build Coastguard Worker return (-1);
4377*7c356e86SAndroid Build Coastguard Worker modified = 1;
4378*7c356e86SAndroid Build Coastguard Worker hnum = hlast;
4379*7c356e86SAndroid Build Coastguard Worker if (cmd[1] == 0)
4380*7c356e86SAndroid Build Coastguard Worker vi_error();
4381*7c356e86SAndroid Build Coastguard Worker else {
4382*7c356e86SAndroid Build Coastguard Worker int n;
4383*7c356e86SAndroid Build Coastguard Worker
4384*7c356e86SAndroid Build Coastguard Worker if (vs->cursor + argcnt > vs->linelen)
4385*7c356e86SAndroid Build Coastguard Worker return (-1);
4386*7c356e86SAndroid Build Coastguard Worker for (n = 0; n < argcnt; ++n)
4387*7c356e86SAndroid Build Coastguard Worker vs->cbuf[vs->cursor + n] = cmd[1];
4388*7c356e86SAndroid Build Coastguard Worker vs->cursor += n - 1;
4389*7c356e86SAndroid Build Coastguard Worker }
4390*7c356e86SAndroid Build Coastguard Worker break;
4391*7c356e86SAndroid Build Coastguard Worker
4392*7c356e86SAndroid Build Coastguard Worker case ORD('R'):
4393*7c356e86SAndroid Build Coastguard Worker modified = 1;
4394*7c356e86SAndroid Build Coastguard Worker hnum = hlast;
4395*7c356e86SAndroid Build Coastguard Worker insert = REPLACE;
4396*7c356e86SAndroid Build Coastguard Worker break;
4397*7c356e86SAndroid Build Coastguard Worker
4398*7c356e86SAndroid Build Coastguard Worker case ORD('s'):
4399*7c356e86SAndroid Build Coastguard Worker if (vs->linelen == 0)
4400*7c356e86SAndroid Build Coastguard Worker return (-1);
4401*7c356e86SAndroid Build Coastguard Worker modified = 1;
4402*7c356e86SAndroid Build Coastguard Worker hnum = hlast;
4403*7c356e86SAndroid Build Coastguard Worker if (vs->cursor + argcnt > vs->linelen)
4404*7c356e86SAndroid Build Coastguard Worker argcnt = vs->linelen - vs->cursor;
4405*7c356e86SAndroid Build Coastguard Worker del_range(vs->cursor, vs->cursor + argcnt);
4406*7c356e86SAndroid Build Coastguard Worker insert = INSERT;
4407*7c356e86SAndroid Build Coastguard Worker break;
4408*7c356e86SAndroid Build Coastguard Worker
4409*7c356e86SAndroid Build Coastguard Worker case ORD('v'):
4410*7c356e86SAndroid Build Coastguard Worker if (!argcnt) {
4411*7c356e86SAndroid Build Coastguard Worker if (modified) {
4412*7c356e86SAndroid Build Coastguard Worker vs->cbuf[vs->linelen] = '\0';
4413*7c356e86SAndroid Build Coastguard Worker histsave(&source->line, vs->cbuf,
4414*7c356e86SAndroid Build Coastguard Worker HIST_STORE, true);
4415*7c356e86SAndroid Build Coastguard Worker } else
4416*7c356e86SAndroid Build Coastguard Worker argcnt = source->line + 1 -
4417*7c356e86SAndroid Build Coastguard Worker (hlast - hnum);
4418*7c356e86SAndroid Build Coastguard Worker }
4419*7c356e86SAndroid Build Coastguard Worker if (argcnt)
4420*7c356e86SAndroid Build Coastguard Worker shf_snprintf(vs->cbuf, vs->cbufsize, Tf_sd,
4421*7c356e86SAndroid Build Coastguard Worker ctrl_x_e, argcnt);
4422*7c356e86SAndroid Build Coastguard Worker else
4423*7c356e86SAndroid Build Coastguard Worker strlcpy(vs->cbuf, ctrl_x_e, vs->cbufsize);
4424*7c356e86SAndroid Build Coastguard Worker vs->linelen = strlen(vs->cbuf);
4425*7c356e86SAndroid Build Coastguard Worker return (2);
4426*7c356e86SAndroid Build Coastguard Worker
4427*7c356e86SAndroid Build Coastguard Worker case ORD('x'):
4428*7c356e86SAndroid Build Coastguard Worker if (vs->linelen == 0)
4429*7c356e86SAndroid Build Coastguard Worker return (-1);
4430*7c356e86SAndroid Build Coastguard Worker modified = 1;
4431*7c356e86SAndroid Build Coastguard Worker hnum = hlast;
4432*7c356e86SAndroid Build Coastguard Worker if (vs->cursor + argcnt > vs->linelen)
4433*7c356e86SAndroid Build Coastguard Worker argcnt = vs->linelen - vs->cursor;
4434*7c356e86SAndroid Build Coastguard Worker yank_range(vs->cursor, vs->cursor + argcnt);
4435*7c356e86SAndroid Build Coastguard Worker del_range(vs->cursor, vs->cursor + argcnt);
4436*7c356e86SAndroid Build Coastguard Worker break;
4437*7c356e86SAndroid Build Coastguard Worker
4438*7c356e86SAndroid Build Coastguard Worker case ORD('X'):
4439*7c356e86SAndroid Build Coastguard Worker if (vs->cursor > 0) {
4440*7c356e86SAndroid Build Coastguard Worker modified = 1;
4441*7c356e86SAndroid Build Coastguard Worker hnum = hlast;
4442*7c356e86SAndroid Build Coastguard Worker if (vs->cursor < argcnt)
4443*7c356e86SAndroid Build Coastguard Worker argcnt = vs->cursor;
4444*7c356e86SAndroid Build Coastguard Worker yank_range(vs->cursor - argcnt, vs->cursor);
4445*7c356e86SAndroid Build Coastguard Worker del_range(vs->cursor - argcnt, vs->cursor);
4446*7c356e86SAndroid Build Coastguard Worker vs->cursor -= argcnt;
4447*7c356e86SAndroid Build Coastguard Worker } else
4448*7c356e86SAndroid Build Coastguard Worker return (-1);
4449*7c356e86SAndroid Build Coastguard Worker break;
4450*7c356e86SAndroid Build Coastguard Worker
4451*7c356e86SAndroid Build Coastguard Worker case ORD('u'):
4452*7c356e86SAndroid Build Coastguard Worker t = vs;
4453*7c356e86SAndroid Build Coastguard Worker vs = undo;
4454*7c356e86SAndroid Build Coastguard Worker undo = t;
4455*7c356e86SAndroid Build Coastguard Worker break;
4456*7c356e86SAndroid Build Coastguard Worker
4457*7c356e86SAndroid Build Coastguard Worker case ORD('U'):
4458*7c356e86SAndroid Build Coastguard Worker if (!modified)
4459*7c356e86SAndroid Build Coastguard Worker return (-1);
4460*7c356e86SAndroid Build Coastguard Worker if (grabhist(modified, ohnum) < 0)
4461*7c356e86SAndroid Build Coastguard Worker return (-1);
4462*7c356e86SAndroid Build Coastguard Worker modified = 0;
4463*7c356e86SAndroid Build Coastguard Worker hnum = ohnum;
4464*7c356e86SAndroid Build Coastguard Worker break;
4465*7c356e86SAndroid Build Coastguard Worker
4466*7c356e86SAndroid Build Coastguard Worker case ORD('?'):
4467*7c356e86SAndroid Build Coastguard Worker if (hnum == hlast)
4468*7c356e86SAndroid Build Coastguard Worker hnum = -1;
4469*7c356e86SAndroid Build Coastguard Worker /* ahhh */
4470*7c356e86SAndroid Build Coastguard Worker
4471*7c356e86SAndroid Build Coastguard Worker /* FALLTHROUGH */
4472*7c356e86SAndroid Build Coastguard Worker case ORD('/'):
4473*7c356e86SAndroid Build Coastguard Worker c1 = 1;
4474*7c356e86SAndroid Build Coastguard Worker srchlen = 0;
4475*7c356e86SAndroid Build Coastguard Worker lastsearch = *cmd;
4476*7c356e86SAndroid Build Coastguard Worker if (0)
4477*7c356e86SAndroid Build Coastguard Worker /* FALLTHROUGH */
4478*7c356e86SAndroid Build Coastguard Worker case ORD('n'):
4479*7c356e86SAndroid Build Coastguard Worker case ORD('N'):
4480*7c356e86SAndroid Build Coastguard Worker c1 = 0;
4481*7c356e86SAndroid Build Coastguard Worker if (lastsearch == ORD(' '))
4482*7c356e86SAndroid Build Coastguard Worker return (-1);
4483*7c356e86SAndroid Build Coastguard Worker b = (lastsearch == ORD('?'));
4484*7c356e86SAndroid Build Coastguard Worker if (*cmd == 'N')
4485*7c356e86SAndroid Build Coastguard Worker b = !b;
4486*7c356e86SAndroid Build Coastguard Worker if ((c2 = grabsearch(srchpat, modified, hnum, b)) < 0) {
4487*7c356e86SAndroid Build Coastguard Worker if (c1) {
4488*7c356e86SAndroid Build Coastguard Worker restore_cbuf();
4489*7c356e86SAndroid Build Coastguard Worker refresh(false);
4490*7c356e86SAndroid Build Coastguard Worker }
4491*7c356e86SAndroid Build Coastguard Worker return (-1);
4492*7c356e86SAndroid Build Coastguard Worker } else {
4493*7c356e86SAndroid Build Coastguard Worker modified = 0;
4494*7c356e86SAndroid Build Coastguard Worker hnum = c2;
4495*7c356e86SAndroid Build Coastguard Worker ohnum = hnum;
4496*7c356e86SAndroid Build Coastguard Worker }
4497*7c356e86SAndroid Build Coastguard Worker if (argcnt >= 2) {
4498*7c356e86SAndroid Build Coastguard Worker /* flag from cursor-up command */
4499*7c356e86SAndroid Build Coastguard Worker vs->cursor = argcnt - 2;
4500*7c356e86SAndroid Build Coastguard Worker return (0);
4501*7c356e86SAndroid Build Coastguard Worker }
4502*7c356e86SAndroid Build Coastguard Worker break;
4503*7c356e86SAndroid Build Coastguard Worker case ORD('_'):
4504*7c356e86SAndroid Build Coastguard Worker {
4505*7c356e86SAndroid Build Coastguard Worker bool inspace;
4506*7c356e86SAndroid Build Coastguard Worker char *p, *sp;
4507*7c356e86SAndroid Build Coastguard Worker
4508*7c356e86SAndroid Build Coastguard Worker if (histnum(-1) < 0)
4509*7c356e86SAndroid Build Coastguard Worker return (-1);
4510*7c356e86SAndroid Build Coastguard Worker p = *histpos();
4511*7c356e86SAndroid Build Coastguard Worker if (argcnt) {
4512*7c356e86SAndroid Build Coastguard Worker while (ctype(*p, C_SPACE))
4513*7c356e86SAndroid Build Coastguard Worker p++;
4514*7c356e86SAndroid Build Coastguard Worker while (*p && --argcnt) {
4515*7c356e86SAndroid Build Coastguard Worker while (*p && !ctype(*p, C_SPACE))
4516*7c356e86SAndroid Build Coastguard Worker p++;
4517*7c356e86SAndroid Build Coastguard Worker while (ctype(*p, C_SPACE))
4518*7c356e86SAndroid Build Coastguard Worker p++;
4519*7c356e86SAndroid Build Coastguard Worker }
4520*7c356e86SAndroid Build Coastguard Worker if (!*p)
4521*7c356e86SAndroid Build Coastguard Worker return (-1);
4522*7c356e86SAndroid Build Coastguard Worker sp = p;
4523*7c356e86SAndroid Build Coastguard Worker } else {
4524*7c356e86SAndroid Build Coastguard Worker sp = p;
4525*7c356e86SAndroid Build Coastguard Worker inspace = false;
4526*7c356e86SAndroid Build Coastguard Worker while (*p) {
4527*7c356e86SAndroid Build Coastguard Worker if (ctype(*p, C_SPACE))
4528*7c356e86SAndroid Build Coastguard Worker inspace = true;
4529*7c356e86SAndroid Build Coastguard Worker else if (inspace) {
4530*7c356e86SAndroid Build Coastguard Worker inspace = false;
4531*7c356e86SAndroid Build Coastguard Worker sp = p;
4532*7c356e86SAndroid Build Coastguard Worker }
4533*7c356e86SAndroid Build Coastguard Worker p++;
4534*7c356e86SAndroid Build Coastguard Worker }
4535*7c356e86SAndroid Build Coastguard Worker p = sp;
4536*7c356e86SAndroid Build Coastguard Worker }
4537*7c356e86SAndroid Build Coastguard Worker modified = 1;
4538*7c356e86SAndroid Build Coastguard Worker hnum = hlast;
4539*7c356e86SAndroid Build Coastguard Worker if (vs->cursor != vs->linelen)
4540*7c356e86SAndroid Build Coastguard Worker vs->cursor++;
4541*7c356e86SAndroid Build Coastguard Worker while (*p && !ctype(*p, C_SPACE)) {
4542*7c356e86SAndroid Build Coastguard Worker argcnt++;
4543*7c356e86SAndroid Build Coastguard Worker p++;
4544*7c356e86SAndroid Build Coastguard Worker }
4545*7c356e86SAndroid Build Coastguard Worker if (putbuf(T1space, 1, false) != 0 ||
4546*7c356e86SAndroid Build Coastguard Worker putbuf(sp, argcnt, false) != 0) {
4547*7c356e86SAndroid Build Coastguard Worker if (vs->cursor != 0)
4548*7c356e86SAndroid Build Coastguard Worker vs->cursor--;
4549*7c356e86SAndroid Build Coastguard Worker return (-1);
4550*7c356e86SAndroid Build Coastguard Worker }
4551*7c356e86SAndroid Build Coastguard Worker insert = INSERT;
4552*7c356e86SAndroid Build Coastguard Worker }
4553*7c356e86SAndroid Build Coastguard Worker break;
4554*7c356e86SAndroid Build Coastguard Worker
4555*7c356e86SAndroid Build Coastguard Worker case ORD('~'):
4556*7c356e86SAndroid Build Coastguard Worker {
4557*7c356e86SAndroid Build Coastguard Worker char *p;
4558*7c356e86SAndroid Build Coastguard Worker int i;
4559*7c356e86SAndroid Build Coastguard Worker
4560*7c356e86SAndroid Build Coastguard Worker if (vs->linelen == 0)
4561*7c356e86SAndroid Build Coastguard Worker return (-1);
4562*7c356e86SAndroid Build Coastguard Worker for (i = 0; i < argcnt; i++) {
4563*7c356e86SAndroid Build Coastguard Worker p = &vs->cbuf[vs->cursor];
4564*7c356e86SAndroid Build Coastguard Worker if (ctype(*p, C_LOWER)) {
4565*7c356e86SAndroid Build Coastguard Worker modified = 1;
4566*7c356e86SAndroid Build Coastguard Worker hnum = hlast;
4567*7c356e86SAndroid Build Coastguard Worker *p = ksh_toupper(*p);
4568*7c356e86SAndroid Build Coastguard Worker } else if (ctype(*p, C_UPPER)) {
4569*7c356e86SAndroid Build Coastguard Worker modified = 1;
4570*7c356e86SAndroid Build Coastguard Worker hnum = hlast;
4571*7c356e86SAndroid Build Coastguard Worker *p = ksh_tolower(*p);
4572*7c356e86SAndroid Build Coastguard Worker }
4573*7c356e86SAndroid Build Coastguard Worker if (vs->cursor < vs->linelen - 1)
4574*7c356e86SAndroid Build Coastguard Worker vs->cursor++;
4575*7c356e86SAndroid Build Coastguard Worker }
4576*7c356e86SAndroid Build Coastguard Worker break;
4577*7c356e86SAndroid Build Coastguard Worker }
4578*7c356e86SAndroid Build Coastguard Worker
4579*7c356e86SAndroid Build Coastguard Worker case ORD('#'):
4580*7c356e86SAndroid Build Coastguard Worker {
4581*7c356e86SAndroid Build Coastguard Worker int ret = x_do_comment(vs->cbuf, vs->cbufsize,
4582*7c356e86SAndroid Build Coastguard Worker &vs->linelen);
4583*7c356e86SAndroid Build Coastguard Worker if (ret >= 0)
4584*7c356e86SAndroid Build Coastguard Worker vs->cursor = 0;
4585*7c356e86SAndroid Build Coastguard Worker return (ret);
4586*7c356e86SAndroid Build Coastguard Worker }
4587*7c356e86SAndroid Build Coastguard Worker
4588*7c356e86SAndroid Build Coastguard Worker /* AT&T ksh */
4589*7c356e86SAndroid Build Coastguard Worker case ORD('='):
4590*7c356e86SAndroid Build Coastguard Worker /* Nonstandard vi/ksh */
4591*7c356e86SAndroid Build Coastguard Worker case CTRL_E:
4592*7c356e86SAndroid Build Coastguard Worker print_expansions(vs, 1);
4593*7c356e86SAndroid Build Coastguard Worker break;
4594*7c356e86SAndroid Build Coastguard Worker
4595*7c356e86SAndroid Build Coastguard Worker
4596*7c356e86SAndroid Build Coastguard Worker /* Nonstandard vi/ksh */
4597*7c356e86SAndroid Build Coastguard Worker case CTRL_I:
4598*7c356e86SAndroid Build Coastguard Worker if (!Flag(FVITABCOMPLETE))
4599*7c356e86SAndroid Build Coastguard Worker return (-1);
4600*7c356e86SAndroid Build Coastguard Worker complete_word(1, argcnt);
4601*7c356e86SAndroid Build Coastguard Worker break;
4602*7c356e86SAndroid Build Coastguard Worker
4603*7c356e86SAndroid Build Coastguard Worker /* some annoying AT&T kshs */
4604*7c356e86SAndroid Build Coastguard Worker case CTRL_BO:
4605*7c356e86SAndroid Build Coastguard Worker if (!Flag(FVIESCCOMPLETE))
4606*7c356e86SAndroid Build Coastguard Worker return (-1);
4607*7c356e86SAndroid Build Coastguard Worker /* FALLTHROUGH */
4608*7c356e86SAndroid Build Coastguard Worker /* AT&T ksh */
4609*7c356e86SAndroid Build Coastguard Worker case ORD('\\'):
4610*7c356e86SAndroid Build Coastguard Worker /* Nonstandard vi/ksh */
4611*7c356e86SAndroid Build Coastguard Worker case CTRL_F:
4612*7c356e86SAndroid Build Coastguard Worker complete_word(1, argcnt);
4613*7c356e86SAndroid Build Coastguard Worker break;
4614*7c356e86SAndroid Build Coastguard Worker
4615*7c356e86SAndroid Build Coastguard Worker
4616*7c356e86SAndroid Build Coastguard Worker /* AT&T ksh */
4617*7c356e86SAndroid Build Coastguard Worker case ORD('*'):
4618*7c356e86SAndroid Build Coastguard Worker /* Nonstandard vi/ksh */
4619*7c356e86SAndroid Build Coastguard Worker case CTRL_X:
4620*7c356e86SAndroid Build Coastguard Worker expand_word(1);
4621*7c356e86SAndroid Build Coastguard Worker break;
4622*7c356e86SAndroid Build Coastguard Worker
4623*7c356e86SAndroid Build Coastguard Worker
4624*7c356e86SAndroid Build Coastguard Worker /* mksh: cursor movement */
4625*7c356e86SAndroid Build Coastguard Worker case ORD('['):
4626*7c356e86SAndroid Build Coastguard Worker case ORD('O'):
4627*7c356e86SAndroid Build Coastguard Worker state = VPREFIX2;
4628*7c356e86SAndroid Build Coastguard Worker if (vs->linelen != 0)
4629*7c356e86SAndroid Build Coastguard Worker vs->cursor++;
4630*7c356e86SAndroid Build Coastguard Worker insert = INSERT;
4631*7c356e86SAndroid Build Coastguard Worker return (0);
4632*7c356e86SAndroid Build Coastguard Worker }
4633*7c356e86SAndroid Build Coastguard Worker if (insert == 0 && vs->cursor != 0 && vs->cursor >= vs->linelen)
4634*7c356e86SAndroid Build Coastguard Worker vs->cursor--;
4635*7c356e86SAndroid Build Coastguard Worker }
4636*7c356e86SAndroid Build Coastguard Worker return (0);
4637*7c356e86SAndroid Build Coastguard Worker }
4638*7c356e86SAndroid Build Coastguard Worker
4639*7c356e86SAndroid Build Coastguard Worker static int
domove(int argcnt,const char * cmd,int sub)4640*7c356e86SAndroid Build Coastguard Worker domove(int argcnt, const char *cmd, int sub)
4641*7c356e86SAndroid Build Coastguard Worker {
4642*7c356e86SAndroid Build Coastguard Worker int ncursor = 0, i = 0, t;
4643*7c356e86SAndroid Build Coastguard Worker unsigned int bcount;
4644*7c356e86SAndroid Build Coastguard Worker
4645*7c356e86SAndroid Build Coastguard Worker switch (ord(*cmd)) {
4646*7c356e86SAndroid Build Coastguard Worker case ORD('b'):
4647*7c356e86SAndroid Build Coastguard Worker if (!sub && vs->cursor == 0)
4648*7c356e86SAndroid Build Coastguard Worker return (-1);
4649*7c356e86SAndroid Build Coastguard Worker ncursor = backword(argcnt);
4650*7c356e86SAndroid Build Coastguard Worker break;
4651*7c356e86SAndroid Build Coastguard Worker
4652*7c356e86SAndroid Build Coastguard Worker case ORD('B'):
4653*7c356e86SAndroid Build Coastguard Worker if (!sub && vs->cursor == 0)
4654*7c356e86SAndroid Build Coastguard Worker return (-1);
4655*7c356e86SAndroid Build Coastguard Worker ncursor = Backword(argcnt);
4656*7c356e86SAndroid Build Coastguard Worker break;
4657*7c356e86SAndroid Build Coastguard Worker
4658*7c356e86SAndroid Build Coastguard Worker case ORD('e'):
4659*7c356e86SAndroid Build Coastguard Worker if (!sub && vs->cursor + 1 >= vs->linelen)
4660*7c356e86SAndroid Build Coastguard Worker return (-1);
4661*7c356e86SAndroid Build Coastguard Worker ncursor = endword(argcnt);
4662*7c356e86SAndroid Build Coastguard Worker if (sub && ncursor < vs->linelen)
4663*7c356e86SAndroid Build Coastguard Worker ncursor++;
4664*7c356e86SAndroid Build Coastguard Worker break;
4665*7c356e86SAndroid Build Coastguard Worker
4666*7c356e86SAndroid Build Coastguard Worker case ORD('E'):
4667*7c356e86SAndroid Build Coastguard Worker if (!sub && vs->cursor + 1 >= vs->linelen)
4668*7c356e86SAndroid Build Coastguard Worker return (-1);
4669*7c356e86SAndroid Build Coastguard Worker ncursor = Endword(argcnt);
4670*7c356e86SAndroid Build Coastguard Worker if (sub && ncursor < vs->linelen)
4671*7c356e86SAndroid Build Coastguard Worker ncursor++;
4672*7c356e86SAndroid Build Coastguard Worker break;
4673*7c356e86SAndroid Build Coastguard Worker
4674*7c356e86SAndroid Build Coastguard Worker case ORD('f'):
4675*7c356e86SAndroid Build Coastguard Worker case ORD('F'):
4676*7c356e86SAndroid Build Coastguard Worker case ORD('t'):
4677*7c356e86SAndroid Build Coastguard Worker case ORD('T'):
4678*7c356e86SAndroid Build Coastguard Worker fsavecmd = *cmd;
4679*7c356e86SAndroid Build Coastguard Worker fsavech = cmd[1];
4680*7c356e86SAndroid Build Coastguard Worker /* FALLTHROUGH */
4681*7c356e86SAndroid Build Coastguard Worker case ORD(','):
4682*7c356e86SAndroid Build Coastguard Worker case ORD(';'):
4683*7c356e86SAndroid Build Coastguard Worker if (fsavecmd == ORD(' '))
4684*7c356e86SAndroid Build Coastguard Worker return (-1);
4685*7c356e86SAndroid Build Coastguard Worker i = ksh_eq(fsavecmd, 'F', 'f');
4686*7c356e86SAndroid Build Coastguard Worker t = rtt2asc(fsavecmd) > rtt2asc('a');
4687*7c356e86SAndroid Build Coastguard Worker if (*cmd == ',')
4688*7c356e86SAndroid Build Coastguard Worker t = !t;
4689*7c356e86SAndroid Build Coastguard Worker if ((ncursor = findch(fsavech, argcnt, tobool(t),
4690*7c356e86SAndroid Build Coastguard Worker tobool(i))) < 0)
4691*7c356e86SAndroid Build Coastguard Worker return (-1);
4692*7c356e86SAndroid Build Coastguard Worker if (sub && t)
4693*7c356e86SAndroid Build Coastguard Worker ncursor++;
4694*7c356e86SAndroid Build Coastguard Worker break;
4695*7c356e86SAndroid Build Coastguard Worker
4696*7c356e86SAndroid Build Coastguard Worker case ORD('h'):
4697*7c356e86SAndroid Build Coastguard Worker case CTRL_H:
4698*7c356e86SAndroid Build Coastguard Worker if (!sub && vs->cursor == 0)
4699*7c356e86SAndroid Build Coastguard Worker return (-1);
4700*7c356e86SAndroid Build Coastguard Worker ncursor = vs->cursor - argcnt;
4701*7c356e86SAndroid Build Coastguard Worker if (ncursor < 0)
4702*7c356e86SAndroid Build Coastguard Worker ncursor = 0;
4703*7c356e86SAndroid Build Coastguard Worker break;
4704*7c356e86SAndroid Build Coastguard Worker
4705*7c356e86SAndroid Build Coastguard Worker case ORD(' '):
4706*7c356e86SAndroid Build Coastguard Worker case ORD('l'):
4707*7c356e86SAndroid Build Coastguard Worker if (!sub && vs->cursor + 1 >= vs->linelen)
4708*7c356e86SAndroid Build Coastguard Worker return (-1);
4709*7c356e86SAndroid Build Coastguard Worker if (vs->linelen != 0) {
4710*7c356e86SAndroid Build Coastguard Worker ncursor = vs->cursor + argcnt;
4711*7c356e86SAndroid Build Coastguard Worker if (ncursor > vs->linelen)
4712*7c356e86SAndroid Build Coastguard Worker ncursor = vs->linelen;
4713*7c356e86SAndroid Build Coastguard Worker }
4714*7c356e86SAndroid Build Coastguard Worker break;
4715*7c356e86SAndroid Build Coastguard Worker
4716*7c356e86SAndroid Build Coastguard Worker case ORD('w'):
4717*7c356e86SAndroid Build Coastguard Worker if (!sub && vs->cursor + 1 >= vs->linelen)
4718*7c356e86SAndroid Build Coastguard Worker return (-1);
4719*7c356e86SAndroid Build Coastguard Worker ncursor = forwword(argcnt);
4720*7c356e86SAndroid Build Coastguard Worker break;
4721*7c356e86SAndroid Build Coastguard Worker
4722*7c356e86SAndroid Build Coastguard Worker case ORD('W'):
4723*7c356e86SAndroid Build Coastguard Worker if (!sub && vs->cursor + 1 >= vs->linelen)
4724*7c356e86SAndroid Build Coastguard Worker return (-1);
4725*7c356e86SAndroid Build Coastguard Worker ncursor = Forwword(argcnt);
4726*7c356e86SAndroid Build Coastguard Worker break;
4727*7c356e86SAndroid Build Coastguard Worker
4728*7c356e86SAndroid Build Coastguard Worker case ORD('0'):
4729*7c356e86SAndroid Build Coastguard Worker ncursor = 0;
4730*7c356e86SAndroid Build Coastguard Worker break;
4731*7c356e86SAndroid Build Coastguard Worker
4732*7c356e86SAndroid Build Coastguard Worker case ORD('^'):
4733*7c356e86SAndroid Build Coastguard Worker ncursor = domovebeg();
4734*7c356e86SAndroid Build Coastguard Worker break;
4735*7c356e86SAndroid Build Coastguard Worker
4736*7c356e86SAndroid Build Coastguard Worker case ORD('|'):
4737*7c356e86SAndroid Build Coastguard Worker ncursor = argcnt;
4738*7c356e86SAndroid Build Coastguard Worker if (ncursor > vs->linelen)
4739*7c356e86SAndroid Build Coastguard Worker ncursor = vs->linelen;
4740*7c356e86SAndroid Build Coastguard Worker if (ncursor)
4741*7c356e86SAndroid Build Coastguard Worker ncursor--;
4742*7c356e86SAndroid Build Coastguard Worker break;
4743*7c356e86SAndroid Build Coastguard Worker
4744*7c356e86SAndroid Build Coastguard Worker case ORD('$'):
4745*7c356e86SAndroid Build Coastguard Worker if (vs->linelen != 0)
4746*7c356e86SAndroid Build Coastguard Worker ncursor = vs->linelen;
4747*7c356e86SAndroid Build Coastguard Worker else
4748*7c356e86SAndroid Build Coastguard Worker ncursor = 0;
4749*7c356e86SAndroid Build Coastguard Worker break;
4750*7c356e86SAndroid Build Coastguard Worker
4751*7c356e86SAndroid Build Coastguard Worker case ORD('%'):
4752*7c356e86SAndroid Build Coastguard Worker ncursor = vs->cursor;
4753*7c356e86SAndroid Build Coastguard Worker while (ncursor < vs->linelen &&
4754*7c356e86SAndroid Build Coastguard Worker (i = bracktype(vs->cbuf[ncursor])) == 0)
4755*7c356e86SAndroid Build Coastguard Worker ncursor++;
4756*7c356e86SAndroid Build Coastguard Worker if (ncursor == vs->linelen)
4757*7c356e86SAndroid Build Coastguard Worker return (-1);
4758*7c356e86SAndroid Build Coastguard Worker bcount = 1;
4759*7c356e86SAndroid Build Coastguard Worker do {
4760*7c356e86SAndroid Build Coastguard Worker if (i > 0) {
4761*7c356e86SAndroid Build Coastguard Worker if (++ncursor >= vs->linelen)
4762*7c356e86SAndroid Build Coastguard Worker return (-1);
4763*7c356e86SAndroid Build Coastguard Worker } else {
4764*7c356e86SAndroid Build Coastguard Worker if (--ncursor < 0)
4765*7c356e86SAndroid Build Coastguard Worker return (-1);
4766*7c356e86SAndroid Build Coastguard Worker }
4767*7c356e86SAndroid Build Coastguard Worker t = bracktype(vs->cbuf[ncursor]);
4768*7c356e86SAndroid Build Coastguard Worker if (t == i)
4769*7c356e86SAndroid Build Coastguard Worker bcount++;
4770*7c356e86SAndroid Build Coastguard Worker else if (t == -i)
4771*7c356e86SAndroid Build Coastguard Worker bcount--;
4772*7c356e86SAndroid Build Coastguard Worker } while (bcount != 0);
4773*7c356e86SAndroid Build Coastguard Worker if (sub && i > 0)
4774*7c356e86SAndroid Build Coastguard Worker ncursor++;
4775*7c356e86SAndroid Build Coastguard Worker break;
4776*7c356e86SAndroid Build Coastguard Worker
4777*7c356e86SAndroid Build Coastguard Worker default:
4778*7c356e86SAndroid Build Coastguard Worker return (-1);
4779*7c356e86SAndroid Build Coastguard Worker }
4780*7c356e86SAndroid Build Coastguard Worker return (ncursor);
4781*7c356e86SAndroid Build Coastguard Worker }
4782*7c356e86SAndroid Build Coastguard Worker
4783*7c356e86SAndroid Build Coastguard Worker static int
domovebeg(void)4784*7c356e86SAndroid Build Coastguard Worker domovebeg(void)
4785*7c356e86SAndroid Build Coastguard Worker {
4786*7c356e86SAndroid Build Coastguard Worker int ncursor = 0;
4787*7c356e86SAndroid Build Coastguard Worker
4788*7c356e86SAndroid Build Coastguard Worker while (ncursor < vs->linelen - 1 &&
4789*7c356e86SAndroid Build Coastguard Worker ctype(vs->cbuf[ncursor], C_SPACE))
4790*7c356e86SAndroid Build Coastguard Worker ncursor++;
4791*7c356e86SAndroid Build Coastguard Worker return (ncursor);
4792*7c356e86SAndroid Build Coastguard Worker }
4793*7c356e86SAndroid Build Coastguard Worker
4794*7c356e86SAndroid Build Coastguard Worker static int
redo_insert(int count)4795*7c356e86SAndroid Build Coastguard Worker redo_insert(int count)
4796*7c356e86SAndroid Build Coastguard Worker {
4797*7c356e86SAndroid Build Coastguard Worker while (count-- > 0)
4798*7c356e86SAndroid Build Coastguard Worker if (putbuf(ibuf, inslen, tobool(insert == REPLACE)) != 0)
4799*7c356e86SAndroid Build Coastguard Worker return (-1);
4800*7c356e86SAndroid Build Coastguard Worker if (vs->cursor > 0)
4801*7c356e86SAndroid Build Coastguard Worker vs->cursor--;
4802*7c356e86SAndroid Build Coastguard Worker insert = 0;
4803*7c356e86SAndroid Build Coastguard Worker return (0);
4804*7c356e86SAndroid Build Coastguard Worker }
4805*7c356e86SAndroid Build Coastguard Worker
4806*7c356e86SAndroid Build Coastguard Worker static void
yank_range(int a,int b)4807*7c356e86SAndroid Build Coastguard Worker yank_range(int a, int b)
4808*7c356e86SAndroid Build Coastguard Worker {
4809*7c356e86SAndroid Build Coastguard Worker yanklen = b - a;
4810*7c356e86SAndroid Build Coastguard Worker if (yanklen != 0)
4811*7c356e86SAndroid Build Coastguard Worker memmove(ybuf, &vs->cbuf[a], yanklen);
4812*7c356e86SAndroid Build Coastguard Worker }
4813*7c356e86SAndroid Build Coastguard Worker
4814*7c356e86SAndroid Build Coastguard Worker static int
bracktype(int ch)4815*7c356e86SAndroid Build Coastguard Worker bracktype(int ch)
4816*7c356e86SAndroid Build Coastguard Worker {
4817*7c356e86SAndroid Build Coastguard Worker switch (ord(ch)) {
4818*7c356e86SAndroid Build Coastguard Worker
4819*7c356e86SAndroid Build Coastguard Worker case ORD('('):
4820*7c356e86SAndroid Build Coastguard Worker return (1);
4821*7c356e86SAndroid Build Coastguard Worker
4822*7c356e86SAndroid Build Coastguard Worker case ORD('['):
4823*7c356e86SAndroid Build Coastguard Worker return (2);
4824*7c356e86SAndroid Build Coastguard Worker
4825*7c356e86SAndroid Build Coastguard Worker case ORD('{'):
4826*7c356e86SAndroid Build Coastguard Worker return (3);
4827*7c356e86SAndroid Build Coastguard Worker
4828*7c356e86SAndroid Build Coastguard Worker case ORD(')'):
4829*7c356e86SAndroid Build Coastguard Worker return (-1);
4830*7c356e86SAndroid Build Coastguard Worker
4831*7c356e86SAndroid Build Coastguard Worker case ORD(']'):
4832*7c356e86SAndroid Build Coastguard Worker return (-2);
4833*7c356e86SAndroid Build Coastguard Worker
4834*7c356e86SAndroid Build Coastguard Worker case ORD('}'):
4835*7c356e86SAndroid Build Coastguard Worker return (-3);
4836*7c356e86SAndroid Build Coastguard Worker
4837*7c356e86SAndroid Build Coastguard Worker default:
4838*7c356e86SAndroid Build Coastguard Worker return (0);
4839*7c356e86SAndroid Build Coastguard Worker }
4840*7c356e86SAndroid Build Coastguard Worker }
4841*7c356e86SAndroid Build Coastguard Worker
4842*7c356e86SAndroid Build Coastguard Worker /*
4843*7c356e86SAndroid Build Coastguard Worker * Non user interface editor routines below here
4844*7c356e86SAndroid Build Coastguard Worker */
4845*7c356e86SAndroid Build Coastguard Worker
4846*7c356e86SAndroid Build Coastguard Worker static void
save_cbuf(void)4847*7c356e86SAndroid Build Coastguard Worker save_cbuf(void)
4848*7c356e86SAndroid Build Coastguard Worker {
4849*7c356e86SAndroid Build Coastguard Worker memmove(holdbufp, vs->cbuf, vs->linelen);
4850*7c356e86SAndroid Build Coastguard Worker holdlen = vs->linelen;
4851*7c356e86SAndroid Build Coastguard Worker holdbufp[holdlen] = '\0';
4852*7c356e86SAndroid Build Coastguard Worker }
4853*7c356e86SAndroid Build Coastguard Worker
4854*7c356e86SAndroid Build Coastguard Worker static void
restore_cbuf(void)4855*7c356e86SAndroid Build Coastguard Worker restore_cbuf(void)
4856*7c356e86SAndroid Build Coastguard Worker {
4857*7c356e86SAndroid Build Coastguard Worker vs->cursor = 0;
4858*7c356e86SAndroid Build Coastguard Worker vs->linelen = holdlen;
4859*7c356e86SAndroid Build Coastguard Worker memmove(vs->cbuf, holdbufp, holdlen);
4860*7c356e86SAndroid Build Coastguard Worker }
4861*7c356e86SAndroid Build Coastguard Worker
4862*7c356e86SAndroid Build Coastguard Worker /* return a new edstate */
4863*7c356e86SAndroid Build Coastguard Worker static struct edstate *
save_edstate(struct edstate * old)4864*7c356e86SAndroid Build Coastguard Worker save_edstate(struct edstate *old)
4865*7c356e86SAndroid Build Coastguard Worker {
4866*7c356e86SAndroid Build Coastguard Worker struct edstate *news;
4867*7c356e86SAndroid Build Coastguard Worker
4868*7c356e86SAndroid Build Coastguard Worker news = alloc(sizeof(struct edstate), AEDIT);
4869*7c356e86SAndroid Build Coastguard Worker news->cbuf = alloc(old->cbufsize, AEDIT);
4870*7c356e86SAndroid Build Coastguard Worker memcpy(news->cbuf, old->cbuf, old->linelen);
4871*7c356e86SAndroid Build Coastguard Worker news->cbufsize = old->cbufsize;
4872*7c356e86SAndroid Build Coastguard Worker news->linelen = old->linelen;
4873*7c356e86SAndroid Build Coastguard Worker news->cursor = old->cursor;
4874*7c356e86SAndroid Build Coastguard Worker news->winleft = old->winleft;
4875*7c356e86SAndroid Build Coastguard Worker return (news);
4876*7c356e86SAndroid Build Coastguard Worker }
4877*7c356e86SAndroid Build Coastguard Worker
4878*7c356e86SAndroid Build Coastguard Worker static void
restore_edstate(struct edstate * news,struct edstate * old)4879*7c356e86SAndroid Build Coastguard Worker restore_edstate(struct edstate *news, struct edstate *old)
4880*7c356e86SAndroid Build Coastguard Worker {
4881*7c356e86SAndroid Build Coastguard Worker memcpy(news->cbuf, old->cbuf, old->linelen);
4882*7c356e86SAndroid Build Coastguard Worker news->linelen = old->linelen;
4883*7c356e86SAndroid Build Coastguard Worker news->cursor = old->cursor;
4884*7c356e86SAndroid Build Coastguard Worker news->winleft = old->winleft;
4885*7c356e86SAndroid Build Coastguard Worker free_edstate(old);
4886*7c356e86SAndroid Build Coastguard Worker }
4887*7c356e86SAndroid Build Coastguard Worker
4888*7c356e86SAndroid Build Coastguard Worker static void
free_edstate(struct edstate * old)4889*7c356e86SAndroid Build Coastguard Worker free_edstate(struct edstate *old)
4890*7c356e86SAndroid Build Coastguard Worker {
4891*7c356e86SAndroid Build Coastguard Worker afree(old->cbuf, AEDIT);
4892*7c356e86SAndroid Build Coastguard Worker afree(old, AEDIT);
4893*7c356e86SAndroid Build Coastguard Worker }
4894*7c356e86SAndroid Build Coastguard Worker
4895*7c356e86SAndroid Build Coastguard Worker /*
4896*7c356e86SAndroid Build Coastguard Worker * this is used for calling x_escape() in complete_word()
4897*7c356e86SAndroid Build Coastguard Worker */
4898*7c356e86SAndroid Build Coastguard Worker static int
x_vi_putbuf(const char * s,size_t len)4899*7c356e86SAndroid Build Coastguard Worker x_vi_putbuf(const char *s, size_t len)
4900*7c356e86SAndroid Build Coastguard Worker {
4901*7c356e86SAndroid Build Coastguard Worker return (putbuf(s, len, false));
4902*7c356e86SAndroid Build Coastguard Worker }
4903*7c356e86SAndroid Build Coastguard Worker
4904*7c356e86SAndroid Build Coastguard Worker static int
putbuf(const char * buf,ssize_t len,bool repl)4905*7c356e86SAndroid Build Coastguard Worker putbuf(const char *buf, ssize_t len, bool repl)
4906*7c356e86SAndroid Build Coastguard Worker {
4907*7c356e86SAndroid Build Coastguard Worker if (len == 0)
4908*7c356e86SAndroid Build Coastguard Worker return (0);
4909*7c356e86SAndroid Build Coastguard Worker if (repl) {
4910*7c356e86SAndroid Build Coastguard Worker if (vs->cursor + len >= vs->cbufsize)
4911*7c356e86SAndroid Build Coastguard Worker return (-1);
4912*7c356e86SAndroid Build Coastguard Worker if (vs->cursor + len > vs->linelen)
4913*7c356e86SAndroid Build Coastguard Worker vs->linelen = vs->cursor + len;
4914*7c356e86SAndroid Build Coastguard Worker } else {
4915*7c356e86SAndroid Build Coastguard Worker if (vs->linelen + len >= vs->cbufsize)
4916*7c356e86SAndroid Build Coastguard Worker return (-1);
4917*7c356e86SAndroid Build Coastguard Worker memmove(&vs->cbuf[vs->cursor + len], &vs->cbuf[vs->cursor],
4918*7c356e86SAndroid Build Coastguard Worker vs->linelen - vs->cursor);
4919*7c356e86SAndroid Build Coastguard Worker vs->linelen += len;
4920*7c356e86SAndroid Build Coastguard Worker }
4921*7c356e86SAndroid Build Coastguard Worker memmove(&vs->cbuf[vs->cursor], buf, len);
4922*7c356e86SAndroid Build Coastguard Worker vs->cursor += len;
4923*7c356e86SAndroid Build Coastguard Worker return (0);
4924*7c356e86SAndroid Build Coastguard Worker }
4925*7c356e86SAndroid Build Coastguard Worker
4926*7c356e86SAndroid Build Coastguard Worker static void
del_range(int a,int b)4927*7c356e86SAndroid Build Coastguard Worker del_range(int a, int b)
4928*7c356e86SAndroid Build Coastguard Worker {
4929*7c356e86SAndroid Build Coastguard Worker if (vs->linelen != b)
4930*7c356e86SAndroid Build Coastguard Worker memmove(&vs->cbuf[a], &vs->cbuf[b], vs->linelen - b);
4931*7c356e86SAndroid Build Coastguard Worker vs->linelen -= b - a;
4932*7c356e86SAndroid Build Coastguard Worker }
4933*7c356e86SAndroid Build Coastguard Worker
4934*7c356e86SAndroid Build Coastguard Worker static int
findch(int ch,int cnt,bool forw,bool incl)4935*7c356e86SAndroid Build Coastguard Worker findch(int ch, int cnt, bool forw, bool incl)
4936*7c356e86SAndroid Build Coastguard Worker {
4937*7c356e86SAndroid Build Coastguard Worker int ncursor;
4938*7c356e86SAndroid Build Coastguard Worker
4939*7c356e86SAndroid Build Coastguard Worker if (vs->linelen == 0)
4940*7c356e86SAndroid Build Coastguard Worker return (-1);
4941*7c356e86SAndroid Build Coastguard Worker ncursor = vs->cursor;
4942*7c356e86SAndroid Build Coastguard Worker while (cnt--) {
4943*7c356e86SAndroid Build Coastguard Worker do {
4944*7c356e86SAndroid Build Coastguard Worker if (forw) {
4945*7c356e86SAndroid Build Coastguard Worker if (++ncursor == vs->linelen)
4946*7c356e86SAndroid Build Coastguard Worker return (-1);
4947*7c356e86SAndroid Build Coastguard Worker } else {
4948*7c356e86SAndroid Build Coastguard Worker if (--ncursor < 0)
4949*7c356e86SAndroid Build Coastguard Worker return (-1);
4950*7c356e86SAndroid Build Coastguard Worker }
4951*7c356e86SAndroid Build Coastguard Worker } while (vs->cbuf[ncursor] != ch);
4952*7c356e86SAndroid Build Coastguard Worker }
4953*7c356e86SAndroid Build Coastguard Worker if (!incl) {
4954*7c356e86SAndroid Build Coastguard Worker if (forw)
4955*7c356e86SAndroid Build Coastguard Worker ncursor--;
4956*7c356e86SAndroid Build Coastguard Worker else
4957*7c356e86SAndroid Build Coastguard Worker ncursor++;
4958*7c356e86SAndroid Build Coastguard Worker }
4959*7c356e86SAndroid Build Coastguard Worker return (ncursor);
4960*7c356e86SAndroid Build Coastguard Worker }
4961*7c356e86SAndroid Build Coastguard Worker
4962*7c356e86SAndroid Build Coastguard Worker static int
forwword(int argcnt)4963*7c356e86SAndroid Build Coastguard Worker forwword(int argcnt)
4964*7c356e86SAndroid Build Coastguard Worker {
4965*7c356e86SAndroid Build Coastguard Worker int ncursor;
4966*7c356e86SAndroid Build Coastguard Worker
4967*7c356e86SAndroid Build Coastguard Worker ncursor = vs->cursor;
4968*7c356e86SAndroid Build Coastguard Worker while (ncursor < vs->linelen && argcnt--) {
4969*7c356e86SAndroid Build Coastguard Worker if (ctype(vs->cbuf[ncursor], C_ALNUX))
4970*7c356e86SAndroid Build Coastguard Worker while (ncursor < vs->linelen &&
4971*7c356e86SAndroid Build Coastguard Worker ctype(vs->cbuf[ncursor], C_ALNUX))
4972*7c356e86SAndroid Build Coastguard Worker ncursor++;
4973*7c356e86SAndroid Build Coastguard Worker else if (!ctype(vs->cbuf[ncursor], C_SPACE))
4974*7c356e86SAndroid Build Coastguard Worker while (ncursor < vs->linelen &&
4975*7c356e86SAndroid Build Coastguard Worker !ctype(vs->cbuf[ncursor], C_ALNUX | C_SPACE))
4976*7c356e86SAndroid Build Coastguard Worker ncursor++;
4977*7c356e86SAndroid Build Coastguard Worker while (ncursor < vs->linelen &&
4978*7c356e86SAndroid Build Coastguard Worker ctype(vs->cbuf[ncursor], C_SPACE))
4979*7c356e86SAndroid Build Coastguard Worker ncursor++;
4980*7c356e86SAndroid Build Coastguard Worker }
4981*7c356e86SAndroid Build Coastguard Worker return (ncursor);
4982*7c356e86SAndroid Build Coastguard Worker }
4983*7c356e86SAndroid Build Coastguard Worker
4984*7c356e86SAndroid Build Coastguard Worker static int
backword(int argcnt)4985*7c356e86SAndroid Build Coastguard Worker backword(int argcnt)
4986*7c356e86SAndroid Build Coastguard Worker {
4987*7c356e86SAndroid Build Coastguard Worker int ncursor;
4988*7c356e86SAndroid Build Coastguard Worker
4989*7c356e86SAndroid Build Coastguard Worker ncursor = vs->cursor;
4990*7c356e86SAndroid Build Coastguard Worker while (ncursor > 0 && argcnt--) {
4991*7c356e86SAndroid Build Coastguard Worker while (--ncursor > 0 && ctype(vs->cbuf[ncursor], C_SPACE))
4992*7c356e86SAndroid Build Coastguard Worker ;
4993*7c356e86SAndroid Build Coastguard Worker if (ncursor > 0) {
4994*7c356e86SAndroid Build Coastguard Worker if (ctype(vs->cbuf[ncursor], C_ALNUX))
4995*7c356e86SAndroid Build Coastguard Worker while (--ncursor >= 0 &&
4996*7c356e86SAndroid Build Coastguard Worker ctype(vs->cbuf[ncursor], C_ALNUX))
4997*7c356e86SAndroid Build Coastguard Worker ;
4998*7c356e86SAndroid Build Coastguard Worker else
4999*7c356e86SAndroid Build Coastguard Worker while (--ncursor >= 0 &&
5000*7c356e86SAndroid Build Coastguard Worker !ctype(vs->cbuf[ncursor], C_ALNUX | C_SPACE))
5001*7c356e86SAndroid Build Coastguard Worker ;
5002*7c356e86SAndroid Build Coastguard Worker ncursor++;
5003*7c356e86SAndroid Build Coastguard Worker }
5004*7c356e86SAndroid Build Coastguard Worker }
5005*7c356e86SAndroid Build Coastguard Worker return (ncursor);
5006*7c356e86SAndroid Build Coastguard Worker }
5007*7c356e86SAndroid Build Coastguard Worker
5008*7c356e86SAndroid Build Coastguard Worker static int
endword(int argcnt)5009*7c356e86SAndroid Build Coastguard Worker endword(int argcnt)
5010*7c356e86SAndroid Build Coastguard Worker {
5011*7c356e86SAndroid Build Coastguard Worker int ncursor;
5012*7c356e86SAndroid Build Coastguard Worker
5013*7c356e86SAndroid Build Coastguard Worker ncursor = vs->cursor;
5014*7c356e86SAndroid Build Coastguard Worker while (ncursor < vs->linelen && argcnt--) {
5015*7c356e86SAndroid Build Coastguard Worker while (++ncursor < vs->linelen - 1 &&
5016*7c356e86SAndroid Build Coastguard Worker ctype(vs->cbuf[ncursor], C_SPACE))
5017*7c356e86SAndroid Build Coastguard Worker ;
5018*7c356e86SAndroid Build Coastguard Worker if (ncursor < vs->linelen - 1) {
5019*7c356e86SAndroid Build Coastguard Worker if (ctype(vs->cbuf[ncursor], C_ALNUX))
5020*7c356e86SAndroid Build Coastguard Worker while (++ncursor < vs->linelen &&
5021*7c356e86SAndroid Build Coastguard Worker ctype(vs->cbuf[ncursor], C_ALNUX))
5022*7c356e86SAndroid Build Coastguard Worker ;
5023*7c356e86SAndroid Build Coastguard Worker else
5024*7c356e86SAndroid Build Coastguard Worker while (++ncursor < vs->linelen &&
5025*7c356e86SAndroid Build Coastguard Worker !ctype(vs->cbuf[ncursor], C_ALNUX | C_SPACE))
5026*7c356e86SAndroid Build Coastguard Worker ;
5027*7c356e86SAndroid Build Coastguard Worker ncursor--;
5028*7c356e86SAndroid Build Coastguard Worker }
5029*7c356e86SAndroid Build Coastguard Worker }
5030*7c356e86SAndroid Build Coastguard Worker return (ncursor);
5031*7c356e86SAndroid Build Coastguard Worker }
5032*7c356e86SAndroid Build Coastguard Worker
5033*7c356e86SAndroid Build Coastguard Worker static int
Forwword(int argcnt)5034*7c356e86SAndroid Build Coastguard Worker Forwword(int argcnt)
5035*7c356e86SAndroid Build Coastguard Worker {
5036*7c356e86SAndroid Build Coastguard Worker int ncursor;
5037*7c356e86SAndroid Build Coastguard Worker
5038*7c356e86SAndroid Build Coastguard Worker ncursor = vs->cursor;
5039*7c356e86SAndroid Build Coastguard Worker while (ncursor < vs->linelen && argcnt--) {
5040*7c356e86SAndroid Build Coastguard Worker while (ncursor < vs->linelen &&
5041*7c356e86SAndroid Build Coastguard Worker !ctype(vs->cbuf[ncursor], C_SPACE))
5042*7c356e86SAndroid Build Coastguard Worker ncursor++;
5043*7c356e86SAndroid Build Coastguard Worker while (ncursor < vs->linelen &&
5044*7c356e86SAndroid Build Coastguard Worker ctype(vs->cbuf[ncursor], C_SPACE))
5045*7c356e86SAndroid Build Coastguard Worker ncursor++;
5046*7c356e86SAndroid Build Coastguard Worker }
5047*7c356e86SAndroid Build Coastguard Worker return (ncursor);
5048*7c356e86SAndroid Build Coastguard Worker }
5049*7c356e86SAndroid Build Coastguard Worker
5050*7c356e86SAndroid Build Coastguard Worker static int
Backword(int argcnt)5051*7c356e86SAndroid Build Coastguard Worker Backword(int argcnt)
5052*7c356e86SAndroid Build Coastguard Worker {
5053*7c356e86SAndroid Build Coastguard Worker int ncursor;
5054*7c356e86SAndroid Build Coastguard Worker
5055*7c356e86SAndroid Build Coastguard Worker ncursor = vs->cursor;
5056*7c356e86SAndroid Build Coastguard Worker while (ncursor > 0 && argcnt--) {
5057*7c356e86SAndroid Build Coastguard Worker while (--ncursor >= 0 && ctype(vs->cbuf[ncursor], C_SPACE))
5058*7c356e86SAndroid Build Coastguard Worker ;
5059*7c356e86SAndroid Build Coastguard Worker while (ncursor >= 0 && !ctype(vs->cbuf[ncursor], C_SPACE))
5060*7c356e86SAndroid Build Coastguard Worker ncursor--;
5061*7c356e86SAndroid Build Coastguard Worker ncursor++;
5062*7c356e86SAndroid Build Coastguard Worker }
5063*7c356e86SAndroid Build Coastguard Worker return (ncursor);
5064*7c356e86SAndroid Build Coastguard Worker }
5065*7c356e86SAndroid Build Coastguard Worker
5066*7c356e86SAndroid Build Coastguard Worker static int
Endword(int argcnt)5067*7c356e86SAndroid Build Coastguard Worker Endword(int argcnt)
5068*7c356e86SAndroid Build Coastguard Worker {
5069*7c356e86SAndroid Build Coastguard Worker int ncursor;
5070*7c356e86SAndroid Build Coastguard Worker
5071*7c356e86SAndroid Build Coastguard Worker ncursor = vs->cursor;
5072*7c356e86SAndroid Build Coastguard Worker while (ncursor < vs->linelen - 1 && argcnt--) {
5073*7c356e86SAndroid Build Coastguard Worker while (++ncursor < vs->linelen - 1 &&
5074*7c356e86SAndroid Build Coastguard Worker ctype(vs->cbuf[ncursor], C_SPACE))
5075*7c356e86SAndroid Build Coastguard Worker ;
5076*7c356e86SAndroid Build Coastguard Worker if (ncursor < vs->linelen - 1) {
5077*7c356e86SAndroid Build Coastguard Worker while (++ncursor < vs->linelen &&
5078*7c356e86SAndroid Build Coastguard Worker !ctype(vs->cbuf[ncursor], C_SPACE))
5079*7c356e86SAndroid Build Coastguard Worker ;
5080*7c356e86SAndroid Build Coastguard Worker ncursor--;
5081*7c356e86SAndroid Build Coastguard Worker }
5082*7c356e86SAndroid Build Coastguard Worker }
5083*7c356e86SAndroid Build Coastguard Worker return (ncursor);
5084*7c356e86SAndroid Build Coastguard Worker }
5085*7c356e86SAndroid Build Coastguard Worker
5086*7c356e86SAndroid Build Coastguard Worker static int
grabhist(int save,int n)5087*7c356e86SAndroid Build Coastguard Worker grabhist(int save, int n)
5088*7c356e86SAndroid Build Coastguard Worker {
5089*7c356e86SAndroid Build Coastguard Worker char *hptr;
5090*7c356e86SAndroid Build Coastguard Worker
5091*7c356e86SAndroid Build Coastguard Worker if (n < 0 || n > hlast)
5092*7c356e86SAndroid Build Coastguard Worker return (-1);
5093*7c356e86SAndroid Build Coastguard Worker if (n == hlast) {
5094*7c356e86SAndroid Build Coastguard Worker restore_cbuf();
5095*7c356e86SAndroid Build Coastguard Worker ohnum = n;
5096*7c356e86SAndroid Build Coastguard Worker return (0);
5097*7c356e86SAndroid Build Coastguard Worker }
5098*7c356e86SAndroid Build Coastguard Worker (void)histnum(n);
5099*7c356e86SAndroid Build Coastguard Worker if ((hptr = *histpos()) == NULL) {
5100*7c356e86SAndroid Build Coastguard Worker internal_warningf("grabhist: bad history array");
5101*7c356e86SAndroid Build Coastguard Worker return (-1);
5102*7c356e86SAndroid Build Coastguard Worker }
5103*7c356e86SAndroid Build Coastguard Worker if (save)
5104*7c356e86SAndroid Build Coastguard Worker save_cbuf();
5105*7c356e86SAndroid Build Coastguard Worker if ((vs->linelen = strlen(hptr)) >= vs->cbufsize)
5106*7c356e86SAndroid Build Coastguard Worker vs->linelen = vs->cbufsize - 1;
5107*7c356e86SAndroid Build Coastguard Worker memmove(vs->cbuf, hptr, vs->linelen);
5108*7c356e86SAndroid Build Coastguard Worker vs->cursor = 0;
5109*7c356e86SAndroid Build Coastguard Worker ohnum = n;
5110*7c356e86SAndroid Build Coastguard Worker return (0);
5111*7c356e86SAndroid Build Coastguard Worker }
5112*7c356e86SAndroid Build Coastguard Worker
5113*7c356e86SAndroid Build Coastguard Worker static int
grabsearch(const char * pat,int save,int start,bool fwd)5114*7c356e86SAndroid Build Coastguard Worker grabsearch(const char *pat, int save, int start, bool fwd)
5115*7c356e86SAndroid Build Coastguard Worker {
5116*7c356e86SAndroid Build Coastguard Worker char *hptr;
5117*7c356e86SAndroid Build Coastguard Worker int hist;
5118*7c356e86SAndroid Build Coastguard Worker bool anchored;
5119*7c356e86SAndroid Build Coastguard Worker
5120*7c356e86SAndroid Build Coastguard Worker if ((start == 0 && !fwd) || (start >= hlast - 1 && fwd))
5121*7c356e86SAndroid Build Coastguard Worker return (-1);
5122*7c356e86SAndroid Build Coastguard Worker if (fwd)
5123*7c356e86SAndroid Build Coastguard Worker start++;
5124*7c356e86SAndroid Build Coastguard Worker else
5125*7c356e86SAndroid Build Coastguard Worker start--;
5126*7c356e86SAndroid Build Coastguard Worker anchored = *pat == '^' ? (++pat, true) : false;
5127*7c356e86SAndroid Build Coastguard Worker if ((hist = findhist(start, pat, fwd, anchored)) < 0) {
5128*7c356e86SAndroid Build Coastguard Worker /* (start != 0 && fwd && match(holdbufp, pat) >= 0) */
5129*7c356e86SAndroid Build Coastguard Worker if (start != 0 && fwd && strcmp(holdbufp, pat) >= 0) {
5130*7c356e86SAndroid Build Coastguard Worker restore_cbuf();
5131*7c356e86SAndroid Build Coastguard Worker return (0);
5132*7c356e86SAndroid Build Coastguard Worker } else
5133*7c356e86SAndroid Build Coastguard Worker return (-1);
5134*7c356e86SAndroid Build Coastguard Worker }
5135*7c356e86SAndroid Build Coastguard Worker if (save)
5136*7c356e86SAndroid Build Coastguard Worker save_cbuf();
5137*7c356e86SAndroid Build Coastguard Worker histnum(hist);
5138*7c356e86SAndroid Build Coastguard Worker hptr = *histpos();
5139*7c356e86SAndroid Build Coastguard Worker if ((vs->linelen = strlen(hptr)) >= vs->cbufsize)
5140*7c356e86SAndroid Build Coastguard Worker vs->linelen = vs->cbufsize - 1;
5141*7c356e86SAndroid Build Coastguard Worker memmove(vs->cbuf, hptr, vs->linelen);
5142*7c356e86SAndroid Build Coastguard Worker vs->cursor = 0;
5143*7c356e86SAndroid Build Coastguard Worker return (hist);
5144*7c356e86SAndroid Build Coastguard Worker }
5145*7c356e86SAndroid Build Coastguard Worker
5146*7c356e86SAndroid Build Coastguard Worker static void
redraw_line(bool newl)5147*7c356e86SAndroid Build Coastguard Worker redraw_line(bool newl)
5148*7c356e86SAndroid Build Coastguard Worker {
5149*7c356e86SAndroid Build Coastguard Worker if (wbuf_len)
5150*7c356e86SAndroid Build Coastguard Worker memset(wbuf[win], ' ', wbuf_len);
5151*7c356e86SAndroid Build Coastguard Worker if (newl) {
5152*7c356e86SAndroid Build Coastguard Worker x_putc('\r');
5153*7c356e86SAndroid Build Coastguard Worker x_putc('\n');
5154*7c356e86SAndroid Build Coastguard Worker }
5155*7c356e86SAndroid Build Coastguard Worker x_pprompt();
5156*7c356e86SAndroid Build Coastguard Worker morec = ' ';
5157*7c356e86SAndroid Build Coastguard Worker }
5158*7c356e86SAndroid Build Coastguard Worker
5159*7c356e86SAndroid Build Coastguard Worker static void
refresh(bool leftside)5160*7c356e86SAndroid Build Coastguard Worker refresh(bool leftside)
5161*7c356e86SAndroid Build Coastguard Worker {
5162*7c356e86SAndroid Build Coastguard Worker if (outofwin())
5163*7c356e86SAndroid Build Coastguard Worker rewindow();
5164*7c356e86SAndroid Build Coastguard Worker display(wbuf[1 - win], wbuf[win], leftside);
5165*7c356e86SAndroid Build Coastguard Worker win = 1 - win;
5166*7c356e86SAndroid Build Coastguard Worker }
5167*7c356e86SAndroid Build Coastguard Worker
5168*7c356e86SAndroid Build Coastguard Worker static int
outofwin(void)5169*7c356e86SAndroid Build Coastguard Worker outofwin(void)
5170*7c356e86SAndroid Build Coastguard Worker {
5171*7c356e86SAndroid Build Coastguard Worker int cur, col;
5172*7c356e86SAndroid Build Coastguard Worker
5173*7c356e86SAndroid Build Coastguard Worker if (vs->cursor < vs->winleft)
5174*7c356e86SAndroid Build Coastguard Worker return (1);
5175*7c356e86SAndroid Build Coastguard Worker col = 0;
5176*7c356e86SAndroid Build Coastguard Worker cur = vs->winleft;
5177*7c356e86SAndroid Build Coastguard Worker while (cur < vs->cursor)
5178*7c356e86SAndroid Build Coastguard Worker col = newcol((unsigned char)vs->cbuf[cur++], col);
5179*7c356e86SAndroid Build Coastguard Worker if (col >= winwidth)
5180*7c356e86SAndroid Build Coastguard Worker return (1);
5181*7c356e86SAndroid Build Coastguard Worker return (0);
5182*7c356e86SAndroid Build Coastguard Worker }
5183*7c356e86SAndroid Build Coastguard Worker
5184*7c356e86SAndroid Build Coastguard Worker static void
rewindow(void)5185*7c356e86SAndroid Build Coastguard Worker rewindow(void)
5186*7c356e86SAndroid Build Coastguard Worker {
5187*7c356e86SAndroid Build Coastguard Worker int tcur, tcol;
5188*7c356e86SAndroid Build Coastguard Worker int holdcur1, holdcol1;
5189*7c356e86SAndroid Build Coastguard Worker int holdcur2, holdcol2;
5190*7c356e86SAndroid Build Coastguard Worker
5191*7c356e86SAndroid Build Coastguard Worker holdcur1 = holdcur2 = tcur = 0;
5192*7c356e86SAndroid Build Coastguard Worker holdcol1 = holdcol2 = tcol = 0;
5193*7c356e86SAndroid Build Coastguard Worker while (tcur < vs->cursor) {
5194*7c356e86SAndroid Build Coastguard Worker if (tcol - holdcol2 > winwidth / 2) {
5195*7c356e86SAndroid Build Coastguard Worker holdcur1 = holdcur2;
5196*7c356e86SAndroid Build Coastguard Worker holdcol1 = holdcol2;
5197*7c356e86SAndroid Build Coastguard Worker holdcur2 = tcur;
5198*7c356e86SAndroid Build Coastguard Worker holdcol2 = tcol;
5199*7c356e86SAndroid Build Coastguard Worker }
5200*7c356e86SAndroid Build Coastguard Worker tcol = newcol((unsigned char)vs->cbuf[tcur++], tcol);
5201*7c356e86SAndroid Build Coastguard Worker }
5202*7c356e86SAndroid Build Coastguard Worker while (tcol - holdcol1 > winwidth / 2)
5203*7c356e86SAndroid Build Coastguard Worker holdcol1 = newcol((unsigned char)vs->cbuf[holdcur1++],
5204*7c356e86SAndroid Build Coastguard Worker holdcol1);
5205*7c356e86SAndroid Build Coastguard Worker vs->winleft = holdcur1;
5206*7c356e86SAndroid Build Coastguard Worker }
5207*7c356e86SAndroid Build Coastguard Worker
5208*7c356e86SAndroid Build Coastguard Worker static int
newcol(unsigned char ch,int col)5209*7c356e86SAndroid Build Coastguard Worker newcol(unsigned char ch, int col)
5210*7c356e86SAndroid Build Coastguard Worker {
5211*7c356e86SAndroid Build Coastguard Worker if (ch == '\t')
5212*7c356e86SAndroid Build Coastguard Worker return ((col | 7) + 1);
5213*7c356e86SAndroid Build Coastguard Worker return (col + char_len(ch));
5214*7c356e86SAndroid Build Coastguard Worker }
5215*7c356e86SAndroid Build Coastguard Worker
5216*7c356e86SAndroid Build Coastguard Worker static void
display(char * wb1,char * wb2,bool leftside)5217*7c356e86SAndroid Build Coastguard Worker display(char *wb1, char *wb2, bool leftside)
5218*7c356e86SAndroid Build Coastguard Worker {
5219*7c356e86SAndroid Build Coastguard Worker unsigned char ch;
5220*7c356e86SAndroid Build Coastguard Worker char *twb1, *twb2, mc;
5221*7c356e86SAndroid Build Coastguard Worker int cur, col, cnt;
5222*7c356e86SAndroid Build Coastguard Worker int ncol = 0;
5223*7c356e86SAndroid Build Coastguard Worker int moreright;
5224*7c356e86SAndroid Build Coastguard Worker
5225*7c356e86SAndroid Build Coastguard Worker col = 0;
5226*7c356e86SAndroid Build Coastguard Worker cur = vs->winleft;
5227*7c356e86SAndroid Build Coastguard Worker moreright = 0;
5228*7c356e86SAndroid Build Coastguard Worker twb1 = wb1;
5229*7c356e86SAndroid Build Coastguard Worker while (col < winwidth && cur < vs->linelen) {
5230*7c356e86SAndroid Build Coastguard Worker if (cur == vs->cursor && leftside)
5231*7c356e86SAndroid Build Coastguard Worker ncol = col + pwidth;
5232*7c356e86SAndroid Build Coastguard Worker if ((ch = vs->cbuf[cur]) == '\t')
5233*7c356e86SAndroid Build Coastguard Worker do {
5234*7c356e86SAndroid Build Coastguard Worker *twb1++ = ' ';
5235*7c356e86SAndroid Build Coastguard Worker } while (++col < winwidth && (col & 7) != 0);
5236*7c356e86SAndroid Build Coastguard Worker else if (col < winwidth) {
5237*7c356e86SAndroid Build Coastguard Worker if (ksh_isctrl(ch)) {
5238*7c356e86SAndroid Build Coastguard Worker *twb1++ = '^';
5239*7c356e86SAndroid Build Coastguard Worker if (++col < winwidth) {
5240*7c356e86SAndroid Build Coastguard Worker *twb1++ = ksh_unctrl(ch);
5241*7c356e86SAndroid Build Coastguard Worker col++;
5242*7c356e86SAndroid Build Coastguard Worker }
5243*7c356e86SAndroid Build Coastguard Worker } else {
5244*7c356e86SAndroid Build Coastguard Worker *twb1++ = ch;
5245*7c356e86SAndroid Build Coastguard Worker col++;
5246*7c356e86SAndroid Build Coastguard Worker }
5247*7c356e86SAndroid Build Coastguard Worker }
5248*7c356e86SAndroid Build Coastguard Worker if (cur == vs->cursor && !leftside)
5249*7c356e86SAndroid Build Coastguard Worker ncol = col + pwidth - 1;
5250*7c356e86SAndroid Build Coastguard Worker cur++;
5251*7c356e86SAndroid Build Coastguard Worker }
5252*7c356e86SAndroid Build Coastguard Worker if (cur == vs->cursor)
5253*7c356e86SAndroid Build Coastguard Worker ncol = col + pwidth;
5254*7c356e86SAndroid Build Coastguard Worker if (col < winwidth) {
5255*7c356e86SAndroid Build Coastguard Worker while (col < winwidth) {
5256*7c356e86SAndroid Build Coastguard Worker *twb1++ = ' ';
5257*7c356e86SAndroid Build Coastguard Worker col++;
5258*7c356e86SAndroid Build Coastguard Worker }
5259*7c356e86SAndroid Build Coastguard Worker } else
5260*7c356e86SAndroid Build Coastguard Worker moreright++;
5261*7c356e86SAndroid Build Coastguard Worker *twb1 = ' ';
5262*7c356e86SAndroid Build Coastguard Worker
5263*7c356e86SAndroid Build Coastguard Worker col = pwidth;
5264*7c356e86SAndroid Build Coastguard Worker cnt = winwidth;
5265*7c356e86SAndroid Build Coastguard Worker twb1 = wb1;
5266*7c356e86SAndroid Build Coastguard Worker twb2 = wb2;
5267*7c356e86SAndroid Build Coastguard Worker while (cnt--) {
5268*7c356e86SAndroid Build Coastguard Worker if (*twb1 != *twb2) {
5269*7c356e86SAndroid Build Coastguard Worker if (x_col != col)
5270*7c356e86SAndroid Build Coastguard Worker ed_mov_opt(col, wb1);
5271*7c356e86SAndroid Build Coastguard Worker x_putc(*twb1);
5272*7c356e86SAndroid Build Coastguard Worker x_col++;
5273*7c356e86SAndroid Build Coastguard Worker }
5274*7c356e86SAndroid Build Coastguard Worker twb1++;
5275*7c356e86SAndroid Build Coastguard Worker twb2++;
5276*7c356e86SAndroid Build Coastguard Worker col++;
5277*7c356e86SAndroid Build Coastguard Worker }
5278*7c356e86SAndroid Build Coastguard Worker if (vs->winleft > 0 && moreright)
5279*7c356e86SAndroid Build Coastguard Worker /*
5280*7c356e86SAndroid Build Coastguard Worker * POSIX says to use * for this but that is a globbing
5281*7c356e86SAndroid Build Coastguard Worker * character and may confuse people; + is more innocuous
5282*7c356e86SAndroid Build Coastguard Worker */
5283*7c356e86SAndroid Build Coastguard Worker mc = '+';
5284*7c356e86SAndroid Build Coastguard Worker else if (vs->winleft > 0)
5285*7c356e86SAndroid Build Coastguard Worker mc = '<';
5286*7c356e86SAndroid Build Coastguard Worker else if (moreright)
5287*7c356e86SAndroid Build Coastguard Worker mc = '>';
5288*7c356e86SAndroid Build Coastguard Worker else
5289*7c356e86SAndroid Build Coastguard Worker mc = ' ';
5290*7c356e86SAndroid Build Coastguard Worker if (mc != morec) {
5291*7c356e86SAndroid Build Coastguard Worker ed_mov_opt(pwidth + winwidth + 1, wb1);
5292*7c356e86SAndroid Build Coastguard Worker x_putc(mc);
5293*7c356e86SAndroid Build Coastguard Worker x_col++;
5294*7c356e86SAndroid Build Coastguard Worker morec = mc;
5295*7c356e86SAndroid Build Coastguard Worker }
5296*7c356e86SAndroid Build Coastguard Worker if (x_col != ncol)
5297*7c356e86SAndroid Build Coastguard Worker ed_mov_opt(ncol, wb1);
5298*7c356e86SAndroid Build Coastguard Worker }
5299*7c356e86SAndroid Build Coastguard Worker
5300*7c356e86SAndroid Build Coastguard Worker static void
ed_mov_opt(int col,char * wb)5301*7c356e86SAndroid Build Coastguard Worker ed_mov_opt(int col, char *wb)
5302*7c356e86SAndroid Build Coastguard Worker {
5303*7c356e86SAndroid Build Coastguard Worker if (col < x_col) {
5304*7c356e86SAndroid Build Coastguard Worker if (col + 1 < x_col - col) {
5305*7c356e86SAndroid Build Coastguard Worker x_putc('\r');
5306*7c356e86SAndroid Build Coastguard Worker x_pprompt();
5307*7c356e86SAndroid Build Coastguard Worker while (x_col++ < col)
5308*7c356e86SAndroid Build Coastguard Worker x_putcf(*wb++);
5309*7c356e86SAndroid Build Coastguard Worker } else {
5310*7c356e86SAndroid Build Coastguard Worker while (x_col-- > col)
5311*7c356e86SAndroid Build Coastguard Worker x_putc('\b');
5312*7c356e86SAndroid Build Coastguard Worker }
5313*7c356e86SAndroid Build Coastguard Worker } else {
5314*7c356e86SAndroid Build Coastguard Worker wb = &wb[x_col - pwidth];
5315*7c356e86SAndroid Build Coastguard Worker while (x_col++ < col)
5316*7c356e86SAndroid Build Coastguard Worker x_putcf(*wb++);
5317*7c356e86SAndroid Build Coastguard Worker }
5318*7c356e86SAndroid Build Coastguard Worker x_col = col;
5319*7c356e86SAndroid Build Coastguard Worker }
5320*7c356e86SAndroid Build Coastguard Worker
5321*7c356e86SAndroid Build Coastguard Worker
5322*7c356e86SAndroid Build Coastguard Worker /* replace word with all expansions (ie, expand word*) */
5323*7c356e86SAndroid Build Coastguard Worker static int
expand_word(int cmd)5324*7c356e86SAndroid Build Coastguard Worker expand_word(int cmd)
5325*7c356e86SAndroid Build Coastguard Worker {
5326*7c356e86SAndroid Build Coastguard Worker static struct edstate *buf;
5327*7c356e86SAndroid Build Coastguard Worker int rval = 0, nwords, start, end, i;
5328*7c356e86SAndroid Build Coastguard Worker char **words;
5329*7c356e86SAndroid Build Coastguard Worker
5330*7c356e86SAndroid Build Coastguard Worker /* Undo previous expansion */
5331*7c356e86SAndroid Build Coastguard Worker if (cmd == 0 && expanded == EXPAND && buf) {
5332*7c356e86SAndroid Build Coastguard Worker restore_edstate(vs, buf);
5333*7c356e86SAndroid Build Coastguard Worker buf = 0;
5334*7c356e86SAndroid Build Coastguard Worker expanded = NONE;
5335*7c356e86SAndroid Build Coastguard Worker return (0);
5336*7c356e86SAndroid Build Coastguard Worker }
5337*7c356e86SAndroid Build Coastguard Worker if (buf) {
5338*7c356e86SAndroid Build Coastguard Worker free_edstate(buf);
5339*7c356e86SAndroid Build Coastguard Worker buf = 0;
5340*7c356e86SAndroid Build Coastguard Worker }
5341*7c356e86SAndroid Build Coastguard Worker
5342*7c356e86SAndroid Build Coastguard Worker i = XCF_COMMAND_FILE | XCF_FULLPATH;
5343*7c356e86SAndroid Build Coastguard Worker nwords = x_cf_glob(&i, vs->cbuf, vs->linelen, vs->cursor,
5344*7c356e86SAndroid Build Coastguard Worker &start, &end, &words);
5345*7c356e86SAndroid Build Coastguard Worker if (nwords == 0) {
5346*7c356e86SAndroid Build Coastguard Worker vi_error();
5347*7c356e86SAndroid Build Coastguard Worker return (-1);
5348*7c356e86SAndroid Build Coastguard Worker }
5349*7c356e86SAndroid Build Coastguard Worker
5350*7c356e86SAndroid Build Coastguard Worker buf = save_edstate(vs);
5351*7c356e86SAndroid Build Coastguard Worker expanded = EXPAND;
5352*7c356e86SAndroid Build Coastguard Worker del_range(start, end);
5353*7c356e86SAndroid Build Coastguard Worker vs->cursor = start;
5354*7c356e86SAndroid Build Coastguard Worker i = 0;
5355*7c356e86SAndroid Build Coastguard Worker while (i < nwords) {
5356*7c356e86SAndroid Build Coastguard Worker if (x_escape(words[i], strlen(words[i]), x_vi_putbuf) != 0) {
5357*7c356e86SAndroid Build Coastguard Worker rval = -1;
5358*7c356e86SAndroid Build Coastguard Worker break;
5359*7c356e86SAndroid Build Coastguard Worker }
5360*7c356e86SAndroid Build Coastguard Worker if (++i < nwords && putbuf(T1space, 1, false) != 0) {
5361*7c356e86SAndroid Build Coastguard Worker rval = -1;
5362*7c356e86SAndroid Build Coastguard Worker break;
5363*7c356e86SAndroid Build Coastguard Worker }
5364*7c356e86SAndroid Build Coastguard Worker }
5365*7c356e86SAndroid Build Coastguard Worker i = buf->cursor - end;
5366*7c356e86SAndroid Build Coastguard Worker if (rval == 0 && i > 0)
5367*7c356e86SAndroid Build Coastguard Worker vs->cursor += i;
5368*7c356e86SAndroid Build Coastguard Worker modified = 1;
5369*7c356e86SAndroid Build Coastguard Worker hnum = hlast;
5370*7c356e86SAndroid Build Coastguard Worker insert = INSERT;
5371*7c356e86SAndroid Build Coastguard Worker lastac = 0;
5372*7c356e86SAndroid Build Coastguard Worker refresh(false);
5373*7c356e86SAndroid Build Coastguard Worker return (rval);
5374*7c356e86SAndroid Build Coastguard Worker }
5375*7c356e86SAndroid Build Coastguard Worker
5376*7c356e86SAndroid Build Coastguard Worker static int
complete_word(int cmd,int count)5377*7c356e86SAndroid Build Coastguard Worker complete_word(int cmd, int count)
5378*7c356e86SAndroid Build Coastguard Worker {
5379*7c356e86SAndroid Build Coastguard Worker static struct edstate *buf;
5380*7c356e86SAndroid Build Coastguard Worker int rval, nwords, start, end, flags;
5381*7c356e86SAndroid Build Coastguard Worker size_t match_len;
5382*7c356e86SAndroid Build Coastguard Worker char **words;
5383*7c356e86SAndroid Build Coastguard Worker char *match;
5384*7c356e86SAndroid Build Coastguard Worker bool is_unique;
5385*7c356e86SAndroid Build Coastguard Worker
5386*7c356e86SAndroid Build Coastguard Worker /* Undo previous completion */
5387*7c356e86SAndroid Build Coastguard Worker if (cmd == 0 && expanded == COMPLETE && buf) {
5388*7c356e86SAndroid Build Coastguard Worker print_expansions(buf, 0);
5389*7c356e86SAndroid Build Coastguard Worker expanded = PRINT;
5390*7c356e86SAndroid Build Coastguard Worker return (0);
5391*7c356e86SAndroid Build Coastguard Worker }
5392*7c356e86SAndroid Build Coastguard Worker if (cmd == 0 && expanded == PRINT && buf) {
5393*7c356e86SAndroid Build Coastguard Worker restore_edstate(vs, buf);
5394*7c356e86SAndroid Build Coastguard Worker buf = 0;
5395*7c356e86SAndroid Build Coastguard Worker expanded = NONE;
5396*7c356e86SAndroid Build Coastguard Worker return (0);
5397*7c356e86SAndroid Build Coastguard Worker }
5398*7c356e86SAndroid Build Coastguard Worker if (buf) {
5399*7c356e86SAndroid Build Coastguard Worker free_edstate(buf);
5400*7c356e86SAndroid Build Coastguard Worker buf = 0;
5401*7c356e86SAndroid Build Coastguard Worker }
5402*7c356e86SAndroid Build Coastguard Worker
5403*7c356e86SAndroid Build Coastguard Worker /*
5404*7c356e86SAndroid Build Coastguard Worker * XCF_FULLPATH for count 'cause the menu printed by
5405*7c356e86SAndroid Build Coastguard Worker * print_expansions() was done this way.
5406*7c356e86SAndroid Build Coastguard Worker */
5407*7c356e86SAndroid Build Coastguard Worker flags = XCF_COMMAND_FILE;
5408*7c356e86SAndroid Build Coastguard Worker if (count)
5409*7c356e86SAndroid Build Coastguard Worker flags |= XCF_FULLPATH;
5410*7c356e86SAndroid Build Coastguard Worker nwords = x_cf_glob(&flags, vs->cbuf, vs->linelen, vs->cursor,
5411*7c356e86SAndroid Build Coastguard Worker &start, &end, &words);
5412*7c356e86SAndroid Build Coastguard Worker if (nwords == 0) {
5413*7c356e86SAndroid Build Coastguard Worker vi_error();
5414*7c356e86SAndroid Build Coastguard Worker return (-1);
5415*7c356e86SAndroid Build Coastguard Worker }
5416*7c356e86SAndroid Build Coastguard Worker if (count) {
5417*7c356e86SAndroid Build Coastguard Worker int i;
5418*7c356e86SAndroid Build Coastguard Worker
5419*7c356e86SAndroid Build Coastguard Worker count--;
5420*7c356e86SAndroid Build Coastguard Worker if (count >= nwords) {
5421*7c356e86SAndroid Build Coastguard Worker vi_error();
5422*7c356e86SAndroid Build Coastguard Worker x_print_expansions(nwords, words,
5423*7c356e86SAndroid Build Coastguard Worker tobool(flags & XCF_IS_COMMAND));
5424*7c356e86SAndroid Build Coastguard Worker x_free_words(nwords, words);
5425*7c356e86SAndroid Build Coastguard Worker redraw_line(false);
5426*7c356e86SAndroid Build Coastguard Worker return (-1);
5427*7c356e86SAndroid Build Coastguard Worker }
5428*7c356e86SAndroid Build Coastguard Worker /*
5429*7c356e86SAndroid Build Coastguard Worker * Expand the count'th word to its basename
5430*7c356e86SAndroid Build Coastguard Worker */
5431*7c356e86SAndroid Build Coastguard Worker if (flags & XCF_IS_COMMAND) {
5432*7c356e86SAndroid Build Coastguard Worker match = words[count] +
5433*7c356e86SAndroid Build Coastguard Worker x_basename(words[count], NULL);
5434*7c356e86SAndroid Build Coastguard Worker /* If more than one possible match, use full path */
5435*7c356e86SAndroid Build Coastguard Worker for (i = 0; i < nwords; i++)
5436*7c356e86SAndroid Build Coastguard Worker if (i != count &&
5437*7c356e86SAndroid Build Coastguard Worker strcmp(words[i] + x_basename(words[i],
5438*7c356e86SAndroid Build Coastguard Worker NULL), match) == 0) {
5439*7c356e86SAndroid Build Coastguard Worker match = words[count];
5440*7c356e86SAndroid Build Coastguard Worker break;
5441*7c356e86SAndroid Build Coastguard Worker }
5442*7c356e86SAndroid Build Coastguard Worker } else
5443*7c356e86SAndroid Build Coastguard Worker match = words[count];
5444*7c356e86SAndroid Build Coastguard Worker match_len = strlen(match);
5445*7c356e86SAndroid Build Coastguard Worker is_unique = true;
5446*7c356e86SAndroid Build Coastguard Worker /* expanded = PRINT; next call undo */
5447*7c356e86SAndroid Build Coastguard Worker } else {
5448*7c356e86SAndroid Build Coastguard Worker match = words[0];
5449*7c356e86SAndroid Build Coastguard Worker match_len = x_longest_prefix(nwords, words);
5450*7c356e86SAndroid Build Coastguard Worker /* next call will list completions */
5451*7c356e86SAndroid Build Coastguard Worker expanded = COMPLETE;
5452*7c356e86SAndroid Build Coastguard Worker is_unique = nwords == 1;
5453*7c356e86SAndroid Build Coastguard Worker }
5454*7c356e86SAndroid Build Coastguard Worker
5455*7c356e86SAndroid Build Coastguard Worker buf = save_edstate(vs);
5456*7c356e86SAndroid Build Coastguard Worker del_range(start, end);
5457*7c356e86SAndroid Build Coastguard Worker vs->cursor = start;
5458*7c356e86SAndroid Build Coastguard Worker
5459*7c356e86SAndroid Build Coastguard Worker /*
5460*7c356e86SAndroid Build Coastguard Worker * escape all shell-sensitive characters and put the result into
5461*7c356e86SAndroid Build Coastguard Worker * command buffer
5462*7c356e86SAndroid Build Coastguard Worker */
5463*7c356e86SAndroid Build Coastguard Worker rval = x_escape(match, match_len, x_vi_putbuf);
5464*7c356e86SAndroid Build Coastguard Worker
5465*7c356e86SAndroid Build Coastguard Worker if (rval == 0 && is_unique) {
5466*7c356e86SAndroid Build Coastguard Worker /*
5467*7c356e86SAndroid Build Coastguard Worker * If exact match, don't undo. Allows directory completions
5468*7c356e86SAndroid Build Coastguard Worker * to be used (ie, complete the next portion of the path).
5469*7c356e86SAndroid Build Coastguard Worker */
5470*7c356e86SAndroid Build Coastguard Worker expanded = NONE;
5471*7c356e86SAndroid Build Coastguard Worker
5472*7c356e86SAndroid Build Coastguard Worker /*
5473*7c356e86SAndroid Build Coastguard Worker * append a space if this is a non-directory match
5474*7c356e86SAndroid Build Coastguard Worker * and not a parameter or homedir substitution
5475*7c356e86SAndroid Build Coastguard Worker */
5476*7c356e86SAndroid Build Coastguard Worker if (match_len > 0 && !mksh_cdirsep(match[match_len - 1]) &&
5477*7c356e86SAndroid Build Coastguard Worker !(flags & XCF_IS_NOSPACE))
5478*7c356e86SAndroid Build Coastguard Worker rval = putbuf(T1space, 1, false);
5479*7c356e86SAndroid Build Coastguard Worker }
5480*7c356e86SAndroid Build Coastguard Worker x_free_words(nwords, words);
5481*7c356e86SAndroid Build Coastguard Worker
5482*7c356e86SAndroid Build Coastguard Worker modified = 1;
5483*7c356e86SAndroid Build Coastguard Worker hnum = hlast;
5484*7c356e86SAndroid Build Coastguard Worker insert = INSERT;
5485*7c356e86SAndroid Build Coastguard Worker /* prevent this from being redone... */
5486*7c356e86SAndroid Build Coastguard Worker lastac = 0;
5487*7c356e86SAndroid Build Coastguard Worker refresh(false);
5488*7c356e86SAndroid Build Coastguard Worker
5489*7c356e86SAndroid Build Coastguard Worker return (rval);
5490*7c356e86SAndroid Build Coastguard Worker }
5491*7c356e86SAndroid Build Coastguard Worker
5492*7c356e86SAndroid Build Coastguard Worker static int
print_expansions(struct edstate * est,int cmd MKSH_A_UNUSED)5493*7c356e86SAndroid Build Coastguard Worker print_expansions(struct edstate *est, int cmd MKSH_A_UNUSED)
5494*7c356e86SAndroid Build Coastguard Worker {
5495*7c356e86SAndroid Build Coastguard Worker int start, end, nwords, i;
5496*7c356e86SAndroid Build Coastguard Worker char **words;
5497*7c356e86SAndroid Build Coastguard Worker
5498*7c356e86SAndroid Build Coastguard Worker i = XCF_COMMAND_FILE | XCF_FULLPATH;
5499*7c356e86SAndroid Build Coastguard Worker nwords = x_cf_glob(&i, est->cbuf, est->linelen, est->cursor,
5500*7c356e86SAndroid Build Coastguard Worker &start, &end, &words);
5501*7c356e86SAndroid Build Coastguard Worker if (nwords == 0) {
5502*7c356e86SAndroid Build Coastguard Worker vi_error();
5503*7c356e86SAndroid Build Coastguard Worker return (-1);
5504*7c356e86SAndroid Build Coastguard Worker }
5505*7c356e86SAndroid Build Coastguard Worker x_print_expansions(nwords, words, tobool(i & XCF_IS_COMMAND));
5506*7c356e86SAndroid Build Coastguard Worker x_free_words(nwords, words);
5507*7c356e86SAndroid Build Coastguard Worker redraw_line(false);
5508*7c356e86SAndroid Build Coastguard Worker return (0);
5509*7c356e86SAndroid Build Coastguard Worker }
5510*7c356e86SAndroid Build Coastguard Worker #endif /* !MKSH_S_NOVI */
5511*7c356e86SAndroid Build Coastguard Worker
5512*7c356e86SAndroid Build Coastguard Worker /* Similar to x_zotc(emacs.c), but no tab weirdness */
5513*7c356e86SAndroid Build Coastguard Worker static void
x_vi_zotc(int c)5514*7c356e86SAndroid Build Coastguard Worker x_vi_zotc(int c)
5515*7c356e86SAndroid Build Coastguard Worker {
5516*7c356e86SAndroid Build Coastguard Worker if (ksh_isctrl(c)) {
5517*7c356e86SAndroid Build Coastguard Worker x_putc('^');
5518*7c356e86SAndroid Build Coastguard Worker c = ksh_unctrl(c);
5519*7c356e86SAndroid Build Coastguard Worker }
5520*7c356e86SAndroid Build Coastguard Worker x_putc(c);
5521*7c356e86SAndroid Build Coastguard Worker }
5522*7c356e86SAndroid Build Coastguard Worker
5523*7c356e86SAndroid Build Coastguard Worker #if !MKSH_S_NOVI
5524*7c356e86SAndroid Build Coastguard Worker static void
vi_error(void)5525*7c356e86SAndroid Build Coastguard Worker vi_error(void)
5526*7c356e86SAndroid Build Coastguard Worker {
5527*7c356e86SAndroid Build Coastguard Worker /* Beem out of any macros as soon as an error occurs */
5528*7c356e86SAndroid Build Coastguard Worker vi_macro_reset();
5529*7c356e86SAndroid Build Coastguard Worker x_putc(KSH_BEL);
5530*7c356e86SAndroid Build Coastguard Worker x_flush();
5531*7c356e86SAndroid Build Coastguard Worker }
5532*7c356e86SAndroid Build Coastguard Worker
5533*7c356e86SAndroid Build Coastguard Worker static void
vi_macro_reset(void)5534*7c356e86SAndroid Build Coastguard Worker vi_macro_reset(void)
5535*7c356e86SAndroid Build Coastguard Worker {
5536*7c356e86SAndroid Build Coastguard Worker if (macro.p) {
5537*7c356e86SAndroid Build Coastguard Worker afree(macro.buf, AEDIT);
5538*7c356e86SAndroid Build Coastguard Worker memset((char *)¯o, 0, sizeof(macro));
5539*7c356e86SAndroid Build Coastguard Worker }
5540*7c356e86SAndroid Build Coastguard Worker }
5541*7c356e86SAndroid Build Coastguard Worker #endif /* !MKSH_S_NOVI */
5542*7c356e86SAndroid Build Coastguard Worker
5543*7c356e86SAndroid Build Coastguard Worker /* called from main.c */
5544*7c356e86SAndroid Build Coastguard Worker void
x_init(void)5545*7c356e86SAndroid Build Coastguard Worker x_init(void)
5546*7c356e86SAndroid Build Coastguard Worker {
5547*7c356e86SAndroid Build Coastguard Worker int i, j;
5548*7c356e86SAndroid Build Coastguard Worker
5549*7c356e86SAndroid Build Coastguard Worker /*
5550*7c356e86SAndroid Build Coastguard Worker * set edchars to force initial binding, except we need
5551*7c356e86SAndroid Build Coastguard Worker * default values for ^W for some deficient systems…
5552*7c356e86SAndroid Build Coastguard Worker */
5553*7c356e86SAndroid Build Coastguard Worker edchars.erase = edchars.kill = edchars.intr = edchars.quit =
5554*7c356e86SAndroid Build Coastguard Worker edchars.eof = EDCHAR_INITIAL;
5555*7c356e86SAndroid Build Coastguard Worker edchars.werase = 027;
5556*7c356e86SAndroid Build Coastguard Worker
5557*7c356e86SAndroid Build Coastguard Worker /* command line editing specific memory allocation */
5558*7c356e86SAndroid Build Coastguard Worker ainit(AEDIT);
5559*7c356e86SAndroid Build Coastguard Worker holdbufp = alloc(LINE, AEDIT);
5560*7c356e86SAndroid Build Coastguard Worker
5561*7c356e86SAndroid Build Coastguard Worker /* initialise Emacs command line editing mode */
5562*7c356e86SAndroid Build Coastguard Worker x_nextcmd = -1;
5563*7c356e86SAndroid Build Coastguard Worker
5564*7c356e86SAndroid Build Coastguard Worker x_tab = alloc2(X_NTABS, sizeof(*x_tab), AEDIT);
5565*7c356e86SAndroid Build Coastguard Worker for (j = 0; j < X_TABSZ; j++)
5566*7c356e86SAndroid Build Coastguard Worker x_tab[0][j] = XFUNC_insert;
5567*7c356e86SAndroid Build Coastguard Worker for (i = 1; i < X_NTABS; i++)
5568*7c356e86SAndroid Build Coastguard Worker for (j = 0; j < X_TABSZ; j++)
5569*7c356e86SAndroid Build Coastguard Worker x_tab[i][j] = XFUNC_error;
5570*7c356e86SAndroid Build Coastguard Worker for (i = 0; i < (int)NELEM(x_defbindings); i++)
5571*7c356e86SAndroid Build Coastguard Worker x_tab[x_defbindings[i].xdb_tab][x_defbindings[i].xdb_char]
5572*7c356e86SAndroid Build Coastguard Worker = x_defbindings[i].xdb_func;
5573*7c356e86SAndroid Build Coastguard Worker
5574*7c356e86SAndroid Build Coastguard Worker #ifndef MKSH_SMALL
5575*7c356e86SAndroid Build Coastguard Worker x_atab = alloc2(X_NTABS, sizeof(*x_atab), AEDIT);
5576*7c356e86SAndroid Build Coastguard Worker for (i = 1; i < X_NTABS; i++)
5577*7c356e86SAndroid Build Coastguard Worker for (j = 0; j < X_TABSZ; j++)
5578*7c356e86SAndroid Build Coastguard Worker x_atab[i][j] = NULL;
5579*7c356e86SAndroid Build Coastguard Worker #endif
5580*7c356e86SAndroid Build Coastguard Worker }
5581*7c356e86SAndroid Build Coastguard Worker
5582*7c356e86SAndroid Build Coastguard Worker #ifdef DEBUG_LEAKS
5583*7c356e86SAndroid Build Coastguard Worker void
x_done(void)5584*7c356e86SAndroid Build Coastguard Worker x_done(void)
5585*7c356e86SAndroid Build Coastguard Worker {
5586*7c356e86SAndroid Build Coastguard Worker if (x_tab != NULL)
5587*7c356e86SAndroid Build Coastguard Worker afreeall(AEDIT);
5588*7c356e86SAndroid Build Coastguard Worker }
5589*7c356e86SAndroid Build Coastguard Worker #endif
5590*7c356e86SAndroid Build Coastguard Worker
5591*7c356e86SAndroid Build Coastguard Worker void
x_initterm(const char * termtype)5592*7c356e86SAndroid Build Coastguard Worker x_initterm(const char *termtype)
5593*7c356e86SAndroid Build Coastguard Worker {
5594*7c356e86SAndroid Build Coastguard Worker /* default must be 0 (bss) */
5595*7c356e86SAndroid Build Coastguard Worker x_term_mode = 0;
5596*7c356e86SAndroid Build Coastguard Worker /* catch any of the TERM types tmux uses, don’t ask m̲e̲ about it… */
5597*7c356e86SAndroid Build Coastguard Worker switch (*termtype) {
5598*7c356e86SAndroid Build Coastguard Worker case 's':
5599*7c356e86SAndroid Build Coastguard Worker if (!strncmp(termtype, "screen", 6) &&
5600*7c356e86SAndroid Build Coastguard Worker (termtype[6] == '\0' || termtype[6] == '-'))
5601*7c356e86SAndroid Build Coastguard Worker x_term_mode = 1;
5602*7c356e86SAndroid Build Coastguard Worker break;
5603*7c356e86SAndroid Build Coastguard Worker case 't':
5604*7c356e86SAndroid Build Coastguard Worker if (!strncmp(termtype, "tmux", 4) &&
5605*7c356e86SAndroid Build Coastguard Worker (termtype[4] == '\0' || termtype[4] == '-'))
5606*7c356e86SAndroid Build Coastguard Worker x_term_mode = 1;
5607*7c356e86SAndroid Build Coastguard Worker break;
5608*7c356e86SAndroid Build Coastguard Worker }
5609*7c356e86SAndroid Build Coastguard Worker }
5610*7c356e86SAndroid Build Coastguard Worker
5611*7c356e86SAndroid Build Coastguard Worker #ifndef MKSH_SMALL
5612*7c356e86SAndroid Build Coastguard Worker static char *
x_eval_region_helper(const char * cmd,size_t len)5613*7c356e86SAndroid Build Coastguard Worker x_eval_region_helper(const char *cmd, size_t len)
5614*7c356e86SAndroid Build Coastguard Worker {
5615*7c356e86SAndroid Build Coastguard Worker char * volatile cp;
5616*7c356e86SAndroid Build Coastguard Worker newenv(E_ERRH);
5617*7c356e86SAndroid Build Coastguard Worker
5618*7c356e86SAndroid Build Coastguard Worker if (!kshsetjmp(e->jbuf)) {
5619*7c356e86SAndroid Build Coastguard Worker char *wds = alloc(len + 3, ATEMP);
5620*7c356e86SAndroid Build Coastguard Worker
5621*7c356e86SAndroid Build Coastguard Worker wds[0] = FUNASUB;
5622*7c356e86SAndroid Build Coastguard Worker memcpy(wds + 1, cmd, len);
5623*7c356e86SAndroid Build Coastguard Worker wds[len + 1] = '\0';
5624*7c356e86SAndroid Build Coastguard Worker wds[len + 2] = EOS;
5625*7c356e86SAndroid Build Coastguard Worker
5626*7c356e86SAndroid Build Coastguard Worker cp = evalstr(wds, DOSCALAR);
5627*7c356e86SAndroid Build Coastguard Worker afree(wds, ATEMP);
5628*7c356e86SAndroid Build Coastguard Worker strdupx(cp, cp, AEDIT);
5629*7c356e86SAndroid Build Coastguard Worker } else
5630*7c356e86SAndroid Build Coastguard Worker /* command cannot be parsed */
5631*7c356e86SAndroid Build Coastguard Worker cp = NULL;
5632*7c356e86SAndroid Build Coastguard Worker quitenv(NULL);
5633*7c356e86SAndroid Build Coastguard Worker return (cp);
5634*7c356e86SAndroid Build Coastguard Worker }
5635*7c356e86SAndroid Build Coastguard Worker
5636*7c356e86SAndroid Build Coastguard Worker static int
x_operate_region(char * (* helper)(const char *,size_t))5637*7c356e86SAndroid Build Coastguard Worker x_operate_region(char *(*helper)(const char *, size_t))
5638*7c356e86SAndroid Build Coastguard Worker {
5639*7c356e86SAndroid Build Coastguard Worker char *rgbeg, *rgend, *cp;
5640*7c356e86SAndroid Build Coastguard Worker size_t newlen;
5641*7c356e86SAndroid Build Coastguard Worker /* only for LINE overflow checking */
5642*7c356e86SAndroid Build Coastguard Worker size_t restlen;
5643*7c356e86SAndroid Build Coastguard Worker
5644*7c356e86SAndroid Build Coastguard Worker if (xmp == NULL) {
5645*7c356e86SAndroid Build Coastguard Worker rgbeg = xbuf;
5646*7c356e86SAndroid Build Coastguard Worker rgend = xep;
5647*7c356e86SAndroid Build Coastguard Worker } else if (xmp < xcp) {
5648*7c356e86SAndroid Build Coastguard Worker rgbeg = xmp;
5649*7c356e86SAndroid Build Coastguard Worker rgend = xcp;
5650*7c356e86SAndroid Build Coastguard Worker } else {
5651*7c356e86SAndroid Build Coastguard Worker rgbeg = xcp;
5652*7c356e86SAndroid Build Coastguard Worker rgend = xmp;
5653*7c356e86SAndroid Build Coastguard Worker }
5654*7c356e86SAndroid Build Coastguard Worker
5655*7c356e86SAndroid Build Coastguard Worker x_e_putc2('\r');
5656*7c356e86SAndroid Build Coastguard Worker x_clrtoeol(' ', false);
5657*7c356e86SAndroid Build Coastguard Worker x_flush();
5658*7c356e86SAndroid Build Coastguard Worker x_mode(false);
5659*7c356e86SAndroid Build Coastguard Worker cp = helper(rgbeg, rgend - rgbeg);
5660*7c356e86SAndroid Build Coastguard Worker x_mode(true);
5661*7c356e86SAndroid Build Coastguard Worker
5662*7c356e86SAndroid Build Coastguard Worker if (cp == NULL) {
5663*7c356e86SAndroid Build Coastguard Worker /* error return from helper */
5664*7c356e86SAndroid Build Coastguard Worker x_eval_region_err:
5665*7c356e86SAndroid Build Coastguard Worker x_e_putc2(KSH_BEL);
5666*7c356e86SAndroid Build Coastguard Worker x_redraw('\r');
5667*7c356e86SAndroid Build Coastguard Worker return (KSTD);
5668*7c356e86SAndroid Build Coastguard Worker }
5669*7c356e86SAndroid Build Coastguard Worker
5670*7c356e86SAndroid Build Coastguard Worker newlen = strlen(cp);
5671*7c356e86SAndroid Build Coastguard Worker restlen = xep - rgend;
5672*7c356e86SAndroid Build Coastguard Worker /* check for LINE overflow, until this is dynamically allocated */
5673*7c356e86SAndroid Build Coastguard Worker if (rgbeg + newlen + restlen >= xend)
5674*7c356e86SAndroid Build Coastguard Worker goto x_eval_region_err;
5675*7c356e86SAndroid Build Coastguard Worker
5676*7c356e86SAndroid Build Coastguard Worker xmp = rgbeg;
5677*7c356e86SAndroid Build Coastguard Worker xcp = rgbeg + newlen;
5678*7c356e86SAndroid Build Coastguard Worker xep = xcp + restlen;
5679*7c356e86SAndroid Build Coastguard Worker memmove(xcp, rgend, restlen + /* NUL */ 1);
5680*7c356e86SAndroid Build Coastguard Worker memcpy(xmp, cp, newlen);
5681*7c356e86SAndroid Build Coastguard Worker afree(cp, AEDIT);
5682*7c356e86SAndroid Build Coastguard Worker x_adjust();
5683*7c356e86SAndroid Build Coastguard Worker x_modified();
5684*7c356e86SAndroid Build Coastguard Worker return (KSTD);
5685*7c356e86SAndroid Build Coastguard Worker }
5686*7c356e86SAndroid Build Coastguard Worker
5687*7c356e86SAndroid Build Coastguard Worker static int
x_eval_region(int c MKSH_A_UNUSED)5688*7c356e86SAndroid Build Coastguard Worker x_eval_region(int c MKSH_A_UNUSED)
5689*7c356e86SAndroid Build Coastguard Worker {
5690*7c356e86SAndroid Build Coastguard Worker return (x_operate_region(x_eval_region_helper));
5691*7c356e86SAndroid Build Coastguard Worker }
5692*7c356e86SAndroid Build Coastguard Worker
5693*7c356e86SAndroid Build Coastguard Worker static char *
x_quote_region_helper(const char * cmd,size_t len)5694*7c356e86SAndroid Build Coastguard Worker x_quote_region_helper(const char *cmd, size_t len)
5695*7c356e86SAndroid Build Coastguard Worker {
5696*7c356e86SAndroid Build Coastguard Worker char *s;
5697*7c356e86SAndroid Build Coastguard Worker size_t newlen;
5698*7c356e86SAndroid Build Coastguard Worker struct shf shf;
5699*7c356e86SAndroid Build Coastguard Worker
5700*7c356e86SAndroid Build Coastguard Worker strndupx(s, cmd, len, ATEMP);
5701*7c356e86SAndroid Build Coastguard Worker newlen = len < 256 ? 256 : 4096;
5702*7c356e86SAndroid Build Coastguard Worker shf_sopen(alloc(newlen, AEDIT), newlen, SHF_WR | SHF_DYNAMIC, &shf);
5703*7c356e86SAndroid Build Coastguard Worker shf.areap = AEDIT;
5704*7c356e86SAndroid Build Coastguard Worker shf.flags |= SHF_ALLOCB;
5705*7c356e86SAndroid Build Coastguard Worker print_value_quoted(&shf, s);
5706*7c356e86SAndroid Build Coastguard Worker afree(s, ATEMP);
5707*7c356e86SAndroid Build Coastguard Worker return (shf_sclose(&shf));
5708*7c356e86SAndroid Build Coastguard Worker }
5709*7c356e86SAndroid Build Coastguard Worker
5710*7c356e86SAndroid Build Coastguard Worker static int
x_quote_region(int c MKSH_A_UNUSED)5711*7c356e86SAndroid Build Coastguard Worker x_quote_region(int c MKSH_A_UNUSED)
5712*7c356e86SAndroid Build Coastguard Worker {
5713*7c356e86SAndroid Build Coastguard Worker return (x_operate_region(x_quote_region_helper));
5714*7c356e86SAndroid Build Coastguard Worker }
5715*7c356e86SAndroid Build Coastguard Worker #endif /* !MKSH_SMALL */
5716*7c356e86SAndroid Build Coastguard Worker #endif /* !MKSH_NO_CMDLINE_EDITING */
5717