xref: /freebsd/contrib/less/command.c (revision d713e0891ff9ab8246245c3206851d486ecfdd37)
1a8f92a7cSPaul Saab /* $FreeBSD$ */
2a5f0fb15SPaul Saab /*
3*d713e089SXin LI  * Copyright (C) 1984-2023  Mark Nudelman
4a5f0fb15SPaul Saab  *
5a5f0fb15SPaul Saab  * You may distribute under the terms of either the GNU General Public
6a5f0fb15SPaul Saab  * License or the Less License, as specified in the README file.
7a5f0fb15SPaul Saab  *
896e55cc7SXin LI  * For more information, see the README file.
9a5f0fb15SPaul Saab  */
10a5f0fb15SPaul Saab 
11a5f0fb15SPaul Saab 
12a5f0fb15SPaul Saab /*
13a5f0fb15SPaul Saab  * User-level command processor.
14a5f0fb15SPaul Saab  */
15a5f0fb15SPaul Saab 
16a5f0fb15SPaul Saab #include "less.h"
178fd4165cSPaul Saab #if MSDOS_COMPILER==WIN32C
188fd4165cSPaul Saab #include <windows.h>
198fd4165cSPaul Saab #endif
20a5f0fb15SPaul Saab #include "position.h"
21a5f0fb15SPaul Saab #include "option.h"
22a5f0fb15SPaul Saab #include "cmd.h"
23a5f0fb15SPaul Saab 
2489dd99dcSXin LI extern int erase_char, erase2_char, kill_char;
25a5f0fb15SPaul Saab extern int sigs;
26a5f0fb15SPaul Saab extern int quit_if_one_screen;
27*d713e089SXin LI extern int one_screen;
28a5f0fb15SPaul Saab extern int squished;
29a5f0fb15SPaul Saab extern int sc_width;
30a5f0fb15SPaul Saab extern int sc_height;
31b2ea2440SXin LI extern char *kent;
32a5f0fb15SPaul Saab extern int swindow;
33a5f0fb15SPaul Saab extern int jump_sline;
34a5f0fb15SPaul Saab extern int quitting;
35a5f0fb15SPaul Saab extern int wscroll;
36a5f0fb15SPaul Saab extern int top_scroll;
37a5f0fb15SPaul Saab extern int ignore_eoi;
38a5f0fb15SPaul Saab extern int secure;
39a5f0fb15SPaul Saab extern int hshift;
40a15691bfSXin LI extern int bs_mode;
41*d713e089SXin LI extern int proc_backspace;
42a5f0fb15SPaul Saab extern int show_attn;
43720c436cSXin LI extern int less_is_more;
44b2ea2440SXin LI extern int status_col;
4596e55cc7SXin LI extern POSITION highest_hilite;
46b2ea2440SXin LI extern POSITION start_attnpos;
47b2ea2440SXin LI extern POSITION end_attnpos;
48a5f0fb15SPaul Saab extern char *every_first_cmd;
49a5f0fb15SPaul Saab extern char version[];
50a5f0fb15SPaul Saab extern struct scrpos initial_scrpos;
51a5f0fb15SPaul Saab extern IFILE curr_ifile;
52f6b74a7dSXin LI extern void *ml_search;
53f6b74a7dSXin LI extern void *ml_examine;
54b7780dbeSXin LI extern int wheel_lines;
5595270f73SXin LI extern int header_lines;
5695270f73SXin LI extern int def_search_type;
5795270f73SXin LI extern int updown_match;
58a5f0fb15SPaul Saab #if SHELL_ESCAPE || PIPEC
59f6b74a7dSXin LI extern void *ml_shell;
60a5f0fb15SPaul Saab #endif
61a5f0fb15SPaul Saab #if EDITOR
62a5f0fb15SPaul Saab extern char *editor;
63a5f0fb15SPaul Saab extern char *editproto;
64a5f0fb15SPaul Saab #endif
65a5f0fb15SPaul Saab extern int screen_trashed;      /* The screen has been overwritten */
6615596da4SPaul Saab extern int shift_count;
67720c436cSXin LI extern int oldbot;
68720c436cSXin LI extern int forw_prompt;
692235c7feSXin LI extern int incr_search;
70*d713e089SXin LI extern int full_screen;
71b7780dbeSXin LI #if MSDOS_COMPILER==WIN32C
72b7780dbeSXin LI extern int utf_mode;
73b7780dbeSXin LI #endif
74a5f0fb15SPaul Saab 
75a5f0fb15SPaul Saab #if SHELL_ESCAPE
76a5f0fb15SPaul Saab static char *shellcmd = NULL;   /* For holding last shell command for "!!" */
77a5f0fb15SPaul Saab #endif
78a5f0fb15SPaul Saab static int mca;                 /* The multicharacter command (action) */
79a5f0fb15SPaul Saab static int search_type;         /* The previous type of search */
80*d713e089SXin LI static int last_search_type;    /* Type of last executed search */
811ede1615STim J. Robbins static LINENUM number;          /* The number typed by the user */
82720c436cSXin LI static long fraction;           /* The fractional part of the number */
8333096f16SXin LI static struct loption *curropt;
8433096f16SXin LI static int opt_lower;
85a5f0fb15SPaul Saab static int optflag;
86a5f0fb15SPaul Saab static int optgetname;
87a5f0fb15SPaul Saab static POSITION bottompos;
8889dd99dcSXin LI static int save_hshift;
89a15691bfSXin LI static int save_bs_mode;
90*d713e089SXin LI static int save_proc_backspace;
91a5f0fb15SPaul Saab #if PIPEC
92a5f0fb15SPaul Saab static char pipec;
93a5f0fb15SPaul Saab #endif
94a5f0fb15SPaul Saab 
95b2ea2440SXin LI /* Stack of ungotten chars (via ungetcc) */
9633096f16SXin LI struct ungot {
9733096f16SXin LI 	struct ungot *ug_next;
98b2ea2440SXin LI 	LWCHAR ug_char;
9933096f16SXin LI };
10033096f16SXin LI static struct ungot* ungot = NULL;
10133096f16SXin LI 
102*d713e089SXin LI static void multi_search (char *pattern, int n, int silent);
103a5f0fb15SPaul Saab 
104a5f0fb15SPaul Saab /*
105720c436cSXin LI  * Move the cursor to start of prompt line before executing a command.
106a5f0fb15SPaul Saab  * This looks nicer if the command takes a long time before
107a5f0fb15SPaul Saab  * updating the screen.
108a5f0fb15SPaul Saab  */
109*d713e089SXin LI static void cmd_exec(void)
110a5f0fb15SPaul Saab {
111a5f0fb15SPaul Saab 	clear_attn();
112aa22b8b6SXin LI 	clear_bot();
113a5f0fb15SPaul Saab 	flush();
114a5f0fb15SPaul Saab }
115a5f0fb15SPaul Saab 
116a5f0fb15SPaul Saab /*
117b7780dbeSXin LI  * Indicate we are reading a multi-character command.
118b7780dbeSXin LI  */
119*d713e089SXin LI static void set_mca(int action)
120b7780dbeSXin LI {
121b7780dbeSXin LI 	mca = action;
122b7780dbeSXin LI 	clear_bot();
123b7780dbeSXin LI 	clear_cmd();
124b7780dbeSXin LI }
125b7780dbeSXin LI 
126b7780dbeSXin LI /*
127b7780dbeSXin LI  * Indicate we are not reading a multi-character command.
128b7780dbeSXin LI  */
129*d713e089SXin LI static void clear_mca(void)
130b7780dbeSXin LI {
131b7780dbeSXin LI 	if (mca == 0)
132b7780dbeSXin LI 		return;
133b7780dbeSXin LI 	mca = 0;
134b7780dbeSXin LI }
135b7780dbeSXin LI 
136b7780dbeSXin LI /*
137a5f0fb15SPaul Saab  * Set up the display to start a new multi-character command.
138a5f0fb15SPaul Saab  */
139*d713e089SXin LI static void start_mca(int action, constant char *prompt, void *mlist, int cmdflags)
140a5f0fb15SPaul Saab {
141b7780dbeSXin LI 	set_mca(action);
142a5f0fb15SPaul Saab 	cmd_putstr(prompt);
143a5f0fb15SPaul Saab 	set_mlist(mlist, cmdflags);
144a5f0fb15SPaul Saab }
145a5f0fb15SPaul Saab 
146*d713e089SXin LI public int in_mca(void)
147a5f0fb15SPaul Saab {
148a5f0fb15SPaul Saab 	return (mca != 0 && mca != A_PREFIX);
149a5f0fb15SPaul Saab }
150a5f0fb15SPaul Saab 
151a5f0fb15SPaul Saab /*
152a5f0fb15SPaul Saab  * Set up the display to start a new search command.
153a5f0fb15SPaul Saab  */
154*d713e089SXin LI static void mca_search1(void)
155a5f0fb15SPaul Saab {
156*d713e089SXin LI 	int i;
157*d713e089SXin LI 
1587374caaaSXin LI #if HILITE_SEARCH
1597374caaaSXin LI 	if (search_type & SRCH_FILTER)
160b7780dbeSXin LI 		set_mca(A_FILTER);
1617374caaaSXin LI 	else
1627374caaaSXin LI #endif
163a5f0fb15SPaul Saab 	if (search_type & SRCH_FORW)
164b7780dbeSXin LI 		set_mca(A_F_SEARCH);
165a5f0fb15SPaul Saab 	else
166b7780dbeSXin LI 		set_mca(A_B_SEARCH);
167a5f0fb15SPaul Saab 
168a5f0fb15SPaul Saab 	if (search_type & SRCH_NO_MATCH)
169a5f0fb15SPaul Saab 		cmd_putstr("Non-match ");
170a5f0fb15SPaul Saab 	if (search_type & SRCH_FIRST_FILE)
171a5f0fb15SPaul Saab 		cmd_putstr("First-file ");
172a5f0fb15SPaul Saab 	if (search_type & SRCH_PAST_EOF)
173a5f0fb15SPaul Saab 		cmd_putstr("EOF-ignore ");
174a5f0fb15SPaul Saab 	if (search_type & SRCH_NO_MOVE)
175a5f0fb15SPaul Saab 		cmd_putstr("Keep-pos ");
176a5f0fb15SPaul Saab 	if (search_type & SRCH_NO_REGEX)
177a5f0fb15SPaul Saab 		cmd_putstr("Regex-off ");
1782235c7feSXin LI 	if (search_type & SRCH_WRAP)
1792235c7feSXin LI 		cmd_putstr("Wrap ");
180*d713e089SXin LI 	for (i = 1; i <= NUM_SEARCH_COLORS; i++)
181*d713e089SXin LI 	{
182*d713e089SXin LI 		if (search_type & SRCH_SUBSEARCH(i))
183*d713e089SXin LI 		{
184*d713e089SXin LI 			char buf[8];
185*d713e089SXin LI 			SNPRINTF1(buf, sizeof(buf), "Sub-%d ", i);
186*d713e089SXin LI 			cmd_putstr(buf);
187*d713e089SXin LI 		}
188*d713e089SXin LI 	}
189a5f0fb15SPaul Saab 
1907374caaaSXin LI #if HILITE_SEARCH
1917374caaaSXin LI 	if (search_type & SRCH_FILTER)
1927374caaaSXin LI 		cmd_putstr("&/");
1937374caaaSXin LI 	else
1947374caaaSXin LI #endif
195a5f0fb15SPaul Saab 	if (search_type & SRCH_FORW)
196a5f0fb15SPaul Saab 		cmd_putstr("/");
197a5f0fb15SPaul Saab 	else
198a5f0fb15SPaul Saab 		cmd_putstr("?");
199a15691bfSXin LI 	forw_prompt = 0;
20095270f73SXin LI }
20195270f73SXin LI 
202*d713e089SXin LI static void mca_search(void)
20395270f73SXin LI {
20495270f73SXin LI 	mca_search1();
205a5f0fb15SPaul Saab 	set_mlist(ml_search, 0);
206a5f0fb15SPaul Saab }
207a5f0fb15SPaul Saab 
208a5f0fb15SPaul Saab /*
209a5f0fb15SPaul Saab  * Set up the display to start a new toggle-option command.
210a5f0fb15SPaul Saab  */
211*d713e089SXin LI static void mca_opt_toggle(void)
212a5f0fb15SPaul Saab {
213a5f0fb15SPaul Saab 	int no_prompt;
214a5f0fb15SPaul Saab 	int flag;
215a5f0fb15SPaul Saab 	char *dash;
216a5f0fb15SPaul Saab 
217a5f0fb15SPaul Saab 	no_prompt = (optflag & OPT_NO_PROMPT);
218a5f0fb15SPaul Saab 	flag = (optflag & ~OPT_NO_PROMPT);
219a5f0fb15SPaul Saab 	dash = (flag == OPT_NO_TOGGLE) ? "_" : "-";
220a5f0fb15SPaul Saab 
221b7780dbeSXin LI 	set_mca(A_OPT_TOGGLE);
222a5f0fb15SPaul Saab 	cmd_putstr(dash);
223a5f0fb15SPaul Saab 	if (optgetname)
224a5f0fb15SPaul Saab 		cmd_putstr(dash);
225a5f0fb15SPaul Saab 	if (no_prompt)
226a5f0fb15SPaul Saab 		cmd_putstr("(P)");
227a5f0fb15SPaul Saab 	switch (flag)
228a5f0fb15SPaul Saab 	{
229a5f0fb15SPaul Saab 	case OPT_UNSET:
230a5f0fb15SPaul Saab 		cmd_putstr("+");
231a5f0fb15SPaul Saab 		break;
232a5f0fb15SPaul Saab 	case OPT_SET:
233a5f0fb15SPaul Saab 		cmd_putstr("!");
234a5f0fb15SPaul Saab 		break;
235a5f0fb15SPaul Saab 	}
236a15691bfSXin LI 	forw_prompt = 0;
237a5f0fb15SPaul Saab 	set_mlist(NULL, 0);
238a5f0fb15SPaul Saab }
239a5f0fb15SPaul Saab 
240a5f0fb15SPaul Saab /*
241a5f0fb15SPaul Saab  * Execute a multicharacter command.
242a5f0fb15SPaul Saab  */
243*d713e089SXin LI static void exec_mca(void)
244a5f0fb15SPaul Saab {
2451ea31627SRobert Watson 	char *cbuf;
246a5f0fb15SPaul Saab 
247a5f0fb15SPaul Saab 	cmd_exec();
248a5f0fb15SPaul Saab 	cbuf = get_cmdbuf();
24995270f73SXin LI 	if (cbuf == NULL)
25095270f73SXin LI 		return;
251a5f0fb15SPaul Saab 
252a5f0fb15SPaul Saab 	switch (mca)
253a5f0fb15SPaul Saab 	{
254a5f0fb15SPaul Saab 	case A_F_SEARCH:
255a5f0fb15SPaul Saab 	case A_B_SEARCH:
256a15691bfSXin LI 		multi_search(cbuf, (int) number, 0);
257a5f0fb15SPaul Saab 		break;
2587374caaaSXin LI #if HILITE_SEARCH
2597374caaaSXin LI 	case A_FILTER:
2607374caaaSXin LI 		search_type ^= SRCH_NO_MATCH;
2617374caaaSXin LI 		set_filter_pattern(cbuf, search_type);
2627374caaaSXin LI 		break;
2637374caaaSXin LI #endif
264a5f0fb15SPaul Saab 	case A_FIRSTCMD:
265a5f0fb15SPaul Saab 		/*
266a5f0fb15SPaul Saab 		 * Skip leading spaces or + signs in the string.
267a5f0fb15SPaul Saab 		 */
268a5f0fb15SPaul Saab 		while (*cbuf == '+' || *cbuf == ' ')
269a5f0fb15SPaul Saab 			cbuf++;
270a5f0fb15SPaul Saab 		if (every_first_cmd != NULL)
271a5f0fb15SPaul Saab 			free(every_first_cmd);
272a5f0fb15SPaul Saab 		if (*cbuf == '\0')
273a5f0fb15SPaul Saab 			every_first_cmd = NULL;
274a5f0fb15SPaul Saab 		else
275a5f0fb15SPaul Saab 			every_first_cmd = save(cbuf);
276a5f0fb15SPaul Saab 		break;
277a5f0fb15SPaul Saab 	case A_OPT_TOGGLE:
27833096f16SXin LI 		toggle_option(curropt, opt_lower, cbuf, optflag);
27933096f16SXin LI 		curropt = NULL;
280a5f0fb15SPaul Saab 		break;
281a5f0fb15SPaul Saab 	case A_F_BRACKET:
2821ede1615STim J. Robbins 		match_brac(cbuf[0], cbuf[1], 1, (int) number);
283a5f0fb15SPaul Saab 		break;
284a5f0fb15SPaul Saab 	case A_B_BRACKET:
2851ede1615STim J. Robbins 		match_brac(cbuf[1], cbuf[0], 0, (int) number);
286a5f0fb15SPaul Saab 		break;
287a5f0fb15SPaul Saab #if EXAMINE
288a5f0fb15SPaul Saab 	case A_EXAMINE:
289a5f0fb15SPaul Saab 		if (secure)
290a5f0fb15SPaul Saab 			break;
291a5f0fb15SPaul Saab 		edit_list(cbuf);
2921ede1615STim J. Robbins #if TAGS
2938fd4165cSPaul Saab 		/* If tag structure is loaded then clean it up. */
2948fd4165cSPaul Saab 		cleantags();
2951ede1615STim J. Robbins #endif
296a5f0fb15SPaul Saab 		break;
297a5f0fb15SPaul Saab #endif
298a5f0fb15SPaul Saab #if SHELL_ESCAPE
299a5f0fb15SPaul Saab 	case A_SHELL:
300a5f0fb15SPaul Saab 		/*
301a5f0fb15SPaul Saab 		 * !! just uses whatever is in shellcmd.
302a5f0fb15SPaul Saab 		 * Otherwise, copy cmdbuf to shellcmd,
303a5f0fb15SPaul Saab 		 * expanding any special characters ("%" or "#").
304a5f0fb15SPaul Saab 		 */
305a5f0fb15SPaul Saab 		if (*cbuf != '!')
306a5f0fb15SPaul Saab 		{
307a5f0fb15SPaul Saab 			if (shellcmd != NULL)
308a5f0fb15SPaul Saab 				free(shellcmd);
309a5f0fb15SPaul Saab 			shellcmd = fexpand(cbuf);
310a5f0fb15SPaul Saab 		}
311a5f0fb15SPaul Saab 
312a5f0fb15SPaul Saab 		if (secure)
313a5f0fb15SPaul Saab 			break;
314a5f0fb15SPaul Saab 		if (shellcmd == NULL)
315a5f0fb15SPaul Saab 			lsystem("", "!done");
316a5f0fb15SPaul Saab 		else
317a5f0fb15SPaul Saab 			lsystem(shellcmd, "!done");
318a5f0fb15SPaul Saab 		break;
319*d713e089SXin LI 	case A_PSHELL:
320*d713e089SXin LI 		if (secure)
321*d713e089SXin LI 			break;
322*d713e089SXin LI 		lsystem(pr_expand(cbuf), "#done");
323*d713e089SXin LI 		break;
324a5f0fb15SPaul Saab #endif
325a5f0fb15SPaul Saab #if PIPEC
326a5f0fb15SPaul Saab 	case A_PIPE:
327a5f0fb15SPaul Saab 		if (secure)
328a5f0fb15SPaul Saab 			break;
329a5f0fb15SPaul Saab 		(void) pipe_mark(pipec, cbuf);
330a5f0fb15SPaul Saab 		error("|done", NULL_PARG);
331a5f0fb15SPaul Saab 		break;
332a5f0fb15SPaul Saab #endif
333a5f0fb15SPaul Saab 	}
334a5f0fb15SPaul Saab }
335a5f0fb15SPaul Saab 
336a5f0fb15SPaul Saab /*
33733096f16SXin LI  * Is a character an erase or kill char?
338a5f0fb15SPaul Saab  */
339*d713e089SXin LI static int is_erase_char(int c)
340a5f0fb15SPaul Saab {
34133096f16SXin LI 	return (c == erase_char || c == erase2_char || c == kill_char);
342a5f0fb15SPaul Saab }
343a5f0fb15SPaul Saab 
344a5f0fb15SPaul Saab /*
345b2ea2440SXin LI  * Is a character a carriage return or newline?
346b2ea2440SXin LI  */
347*d713e089SXin LI static int is_newline_char(int c)
348b2ea2440SXin LI {
349b2ea2440SXin LI 	return (c == '\n' || c == '\r');
350b2ea2440SXin LI }
351b2ea2440SXin LI 
352b2ea2440SXin LI /*
35333096f16SXin LI  * Handle the first char of an option (after the initial dash).
354a5f0fb15SPaul Saab  */
355*d713e089SXin LI static int mca_opt_first_char(int c)
356a5f0fb15SPaul Saab {
35795270f73SXin LI 	int no_prompt = (optflag & OPT_NO_PROMPT);
35833096f16SXin LI 	int flag = (optflag & ~OPT_NO_PROMPT);
359a5f0fb15SPaul Saab 	if (flag == OPT_NO_TOGGLE)
360a5f0fb15SPaul Saab 	{
361a5f0fb15SPaul Saab 		switch (c)
362a5f0fb15SPaul Saab 		{
363a5f0fb15SPaul Saab 		case '_':
364a5f0fb15SPaul Saab 			/* "__" = long option name. */
365a5f0fb15SPaul Saab 			optgetname = TRUE;
366a5f0fb15SPaul Saab 			mca_opt_toggle();
367a5f0fb15SPaul Saab 			return (MCA_MORE);
368a5f0fb15SPaul Saab 		}
369a5f0fb15SPaul Saab 	} else
370a5f0fb15SPaul Saab 	{
371a5f0fb15SPaul Saab 		switch (c)
372a5f0fb15SPaul Saab 		{
373a5f0fb15SPaul Saab 		case '+':
374a5f0fb15SPaul Saab 			/* "-+" = UNSET. */
37595270f73SXin LI 			optflag = no_prompt | ((flag == OPT_UNSET) ?
37695270f73SXin LI 				OPT_TOGGLE : OPT_UNSET);
377a5f0fb15SPaul Saab 			mca_opt_toggle();
378a5f0fb15SPaul Saab 			return (MCA_MORE);
379a5f0fb15SPaul Saab 		case '!':
380a5f0fb15SPaul Saab 			/* "-!" = SET */
38195270f73SXin LI 			optflag = no_prompt | ((flag == OPT_SET) ?
38295270f73SXin LI 				OPT_TOGGLE : OPT_SET);
383a5f0fb15SPaul Saab 			mca_opt_toggle();
384a5f0fb15SPaul Saab 			return (MCA_MORE);
385a5f0fb15SPaul Saab 		case CONTROL('P'):
386a5f0fb15SPaul Saab 			optflag ^= OPT_NO_PROMPT;
387a5f0fb15SPaul Saab 			mca_opt_toggle();
388a5f0fb15SPaul Saab 			return (MCA_MORE);
389a5f0fb15SPaul Saab 		case '-':
390a5f0fb15SPaul Saab 			/* "--" = long option name. */
391a5f0fb15SPaul Saab 			optgetname = TRUE;
392a5f0fb15SPaul Saab 			mca_opt_toggle();
393a5f0fb15SPaul Saab 			return (MCA_MORE);
394a5f0fb15SPaul Saab 		}
395a5f0fb15SPaul Saab 	}
39633096f16SXin LI 	/* Char was not handled here. */
39733096f16SXin LI 	return (NO_MCA);
398a5f0fb15SPaul Saab }
39933096f16SXin LI 
400a5f0fb15SPaul Saab /*
40133096f16SXin LI  * Add a char to a long option name.
40233096f16SXin LI  * See if we've got a match for an option name yet.
403a5f0fb15SPaul Saab  * If so, display the complete name and stop
404a5f0fb15SPaul Saab  * accepting chars until user hits RETURN.
405a5f0fb15SPaul Saab  */
406*d713e089SXin LI static int mca_opt_nonfirst_char(int c)
40733096f16SXin LI {
40833096f16SXin LI 	char *p;
409a5f0fb15SPaul Saab 	char *oname;
410b7780dbeSXin LI 	int err;
411a5f0fb15SPaul Saab 
41233096f16SXin LI 	if (curropt != NULL)
413a5f0fb15SPaul Saab 	{
414a5f0fb15SPaul Saab 		/*
415a5f0fb15SPaul Saab 		 * Already have a match for the name.
416a5f0fb15SPaul Saab 		 * Don't accept anything but erase/kill.
417a5f0fb15SPaul Saab 		 */
41833096f16SXin LI 		if (is_erase_char(c))
419a5f0fb15SPaul Saab 			return (MCA_DONE);
420a5f0fb15SPaul Saab 		return (MCA_MORE);
421a5f0fb15SPaul Saab 	}
422a5f0fb15SPaul Saab 	/*
423a5f0fb15SPaul Saab 	 * Add char to cmd buffer and try to match
424a5f0fb15SPaul Saab 	 * the option name.
425a5f0fb15SPaul Saab 	 */
426a5f0fb15SPaul Saab 	if (cmd_char(c) == CC_QUIT)
427a5f0fb15SPaul Saab 		return (MCA_DONE);
428a5f0fb15SPaul Saab 	p = get_cmdbuf();
42995270f73SXin LI 	if (p == NULL)
43095270f73SXin LI 		return (MCA_MORE);
43133096f16SXin LI 	opt_lower = ASCII_IS_LOWER(p[0]);
432b7780dbeSXin LI 	err = 0;
433b7780dbeSXin LI 	curropt = findopt_name(&p, &oname, &err);
43433096f16SXin LI 	if (curropt != NULL)
435a5f0fb15SPaul Saab 	{
436a5f0fb15SPaul Saab 		/*
437a5f0fb15SPaul Saab 		 * Got a match.
43833096f16SXin LI 		 * Remember the option and
439a5f0fb15SPaul Saab 		 * display the full option name.
440a5f0fb15SPaul Saab 		 */
441a5f0fb15SPaul Saab 		cmd_reset();
442a5f0fb15SPaul Saab 		mca_opt_toggle();
443a5f0fb15SPaul Saab 		for (p = oname;  *p != '\0';  p++)
444a5f0fb15SPaul Saab 		{
445a5f0fb15SPaul Saab 			c = *p;
44633096f16SXin LI 			if (!opt_lower && ASCII_IS_LOWER(c))
44789dd99dcSXin LI 				c = ASCII_TO_UPPER(c);
448a5f0fb15SPaul Saab 			if (cmd_char(c) != CC_OK)
449a5f0fb15SPaul Saab 				return (MCA_DONE);
450a5f0fb15SPaul Saab 		}
451b7780dbeSXin LI 	} else if (err != OPT_AMBIG)
452b7780dbeSXin LI 	{
453b7780dbeSXin LI 		bell();
454a5f0fb15SPaul Saab 	}
455a5f0fb15SPaul Saab 	return (MCA_MORE);
456a5f0fb15SPaul Saab }
45733096f16SXin LI 
45833096f16SXin LI /*
45933096f16SXin LI  * Handle a char of an option toggle command.
46033096f16SXin LI  */
461*d713e089SXin LI static int mca_opt_char(int c)
46233096f16SXin LI {
46333096f16SXin LI 	PARG parg;
46433096f16SXin LI 
46533096f16SXin LI 	/*
46633096f16SXin LI 	 * This may be a short option (single char),
46733096f16SXin LI 	 * or one char of a long option name,
46833096f16SXin LI 	 * or one char of the option parameter.
46933096f16SXin LI 	 */
47033096f16SXin LI 	if (curropt == NULL && len_cmdbuf() == 0)
47133096f16SXin LI 	{
47233096f16SXin LI 		int ret = mca_opt_first_char(c);
47333096f16SXin LI 		if (ret != NO_MCA)
47433096f16SXin LI 			return (ret);
47533096f16SXin LI 	}
47633096f16SXin LI 	if (optgetname)
47733096f16SXin LI 	{
47833096f16SXin LI 		/* We're getting a long option name.  */
47995270f73SXin LI 		if (!is_newline_char(c) && c != '=')
48033096f16SXin LI 			return (mca_opt_nonfirst_char(c));
48133096f16SXin LI 		if (curropt == NULL)
48233096f16SXin LI 		{
48333096f16SXin LI 			parg.p_string = get_cmdbuf();
48495270f73SXin LI 			if (parg.p_string == NULL)
48595270f73SXin LI 				return (MCA_MORE);
48633096f16SXin LI 			error("There is no --%s option", &parg);
48733096f16SXin LI 			return (MCA_DONE);
48833096f16SXin LI 		}
48933096f16SXin LI 		optgetname = FALSE;
49033096f16SXin LI 		cmd_reset();
491a5f0fb15SPaul Saab 	} else
492a5f0fb15SPaul Saab 	{
49333096f16SXin LI 		if (is_erase_char(c))
49433096f16SXin LI 			return (NO_MCA);
49533096f16SXin LI 		if (curropt != NULL)
49633096f16SXin LI 			/* We're getting the option parameter. */
49733096f16SXin LI 			return (NO_MCA);
49833096f16SXin LI 		curropt = findopt(c);
49933096f16SXin LI 		if (curropt == NULL)
500a5f0fb15SPaul Saab 		{
50133096f16SXin LI 			parg.p_string = propt(c);
50233096f16SXin LI 			error("There is no %s option", &parg);
50333096f16SXin LI 			return (MCA_DONE);
50433096f16SXin LI 		}
505b7780dbeSXin LI 		opt_lower = ASCII_IS_LOWER(c);
50633096f16SXin LI 	}
50733096f16SXin LI 	/*
50833096f16SXin LI 	 * If the option which was entered does not take a
50933096f16SXin LI 	 * parameter, toggle the option immediately,
51033096f16SXin LI 	 * so user doesn't have to hit RETURN.
51133096f16SXin LI 	 */
51233096f16SXin LI 	if ((optflag & ~OPT_NO_PROMPT) != OPT_TOGGLE ||
51333096f16SXin LI 	    !opt_has_param(curropt))
51433096f16SXin LI 	{
515b7780dbeSXin LI 		toggle_option(curropt, opt_lower, "", optflag);
516a5f0fb15SPaul Saab 		return (MCA_DONE);
517a5f0fb15SPaul Saab 	}
518a5f0fb15SPaul Saab 	/*
51933096f16SXin LI 	 * Display a prompt appropriate for the option parameter.
520a5f0fb15SPaul Saab 	 */
52133096f16SXin LI 	start_mca(A_OPT_TOGGLE, opt_prompt(curropt), (void*)NULL, 0);
522a5f0fb15SPaul Saab 	return (MCA_MORE);
52333096f16SXin LI }
524a5f0fb15SPaul Saab 
525a5f0fb15SPaul Saab /*
52695270f73SXin LI  * Normalize search type.
52795270f73SXin LI  */
528*d713e089SXin LI public int norm_search_type(int st)
52995270f73SXin LI {
53095270f73SXin LI 	/* WRAP and PAST_EOF are mutually exclusive. */
53195270f73SXin LI 	if ((st & (SRCH_PAST_EOF|SRCH_WRAP)) == (SRCH_PAST_EOF|SRCH_WRAP))
53295270f73SXin LI 		st ^= SRCH_PAST_EOF;
53395270f73SXin LI 	return st;
53495270f73SXin LI }
53595270f73SXin LI 
53695270f73SXin LI /*
53733096f16SXin LI  * Handle a char of a search command.
53833096f16SXin LI  */
539*d713e089SXin LI static int mca_search_char(int c)
54033096f16SXin LI {
54133096f16SXin LI 	int flag = 0;
54233096f16SXin LI 
54333096f16SXin LI 	/*
544a5f0fb15SPaul Saab 	 * Certain characters as the first char of
545a5f0fb15SPaul Saab 	 * the pattern have special meaning:
546a5f0fb15SPaul Saab 	 *      !  Toggle the NO_MATCH flag
547a5f0fb15SPaul Saab 	 *      *  Toggle the PAST_EOF flag
548a5f0fb15SPaul Saab 	 *      @  Toggle the FIRST_FILE flag
549a5f0fb15SPaul Saab 	 */
550a5f0fb15SPaul Saab 	if (len_cmdbuf() > 0)
55133096f16SXin LI 		return (NO_MCA);
552a5f0fb15SPaul Saab 
553a5f0fb15SPaul Saab 	switch (c)
554a5f0fb15SPaul Saab 	{
555a5f0fb15SPaul Saab 	case '*':
556720c436cSXin LI 		if (less_is_more)
557a8f92a7cSPaul Saab 			break;
558a8f92a7cSPaul Saab 	case CONTROL('E'): /* ignore END of file */
5597374caaaSXin LI 		if (mca != A_FILTER)
560a5f0fb15SPaul Saab 			flag = SRCH_PAST_EOF;
561a5f0fb15SPaul Saab 		break;
562a5f0fb15SPaul Saab 	case '@':
563720c436cSXin LI 		if (less_is_more)
564a8f92a7cSPaul Saab 			break;
565a8f92a7cSPaul Saab 	case CONTROL('F'): /* FIRST file */
5667374caaaSXin LI 		if (mca != A_FILTER)
567a5f0fb15SPaul Saab 			flag = SRCH_FIRST_FILE;
568a5f0fb15SPaul Saab 		break;
569a5f0fb15SPaul Saab 	case CONTROL('K'): /* KEEP position */
5707374caaaSXin LI 		if (mca != A_FILTER)
571a5f0fb15SPaul Saab 			flag = SRCH_NO_MOVE;
572a5f0fb15SPaul Saab 		break;
573*d713e089SXin LI 	case CONTROL('S'): { /* SUBSEARCH */
574*d713e089SXin LI 		char buf[32];
575*d713e089SXin LI 		SNPRINTF1(buf, sizeof(buf), "Sub-pattern (1-%d):", NUM_SEARCH_COLORS);
576*d713e089SXin LI 		clear_bot();
577*d713e089SXin LI 		cmd_putstr(buf);
578*d713e089SXin LI 		flush();
579*d713e089SXin LI 		c = getcc();
580*d713e089SXin LI 		if (c >= '1' && c <= '0'+NUM_SEARCH_COLORS)
581*d713e089SXin LI 			flag = SRCH_SUBSEARCH(c-'0');
582*d713e089SXin LI 		else
583*d713e089SXin LI 			flag = -1; /* calls mca_search() below to repaint */
584*d713e089SXin LI 		break; }
5852235c7feSXin LI 	case CONTROL('W'): /* WRAP around */
5862235c7feSXin LI 		if (mca != A_FILTER)
5872235c7feSXin LI 			flag = SRCH_WRAP;
5882235c7feSXin LI 		break;
589a5f0fb15SPaul Saab 	case CONTROL('R'): /* Don't use REGULAR EXPRESSIONS */
590a5f0fb15SPaul Saab 		flag = SRCH_NO_REGEX;
591a5f0fb15SPaul Saab 		break;
592a5f0fb15SPaul Saab 	case CONTROL('N'): /* NOT match */
593a5f0fb15SPaul Saab 	case '!':
594a5f0fb15SPaul Saab 		flag = SRCH_NO_MATCH;
595a5f0fb15SPaul Saab 		break;
596a5f0fb15SPaul Saab 	}
59733096f16SXin LI 
598a5f0fb15SPaul Saab 	if (flag != 0)
599a5f0fb15SPaul Saab 	{
600*d713e089SXin LI 		if (flag != -1)
60195270f73SXin LI 			search_type = norm_search_type(search_type ^ flag);
602a5f0fb15SPaul Saab 		mca_search();
603a5f0fb15SPaul Saab 		return (MCA_MORE);
604a5f0fb15SPaul Saab 	}
60533096f16SXin LI 	return (NO_MCA);
60633096f16SXin LI }
60733096f16SXin LI 
60833096f16SXin LI /*
60933096f16SXin LI  * Handle a character of a multi-character command.
61033096f16SXin LI  */
611*d713e089SXin LI static int mca_char(int c)
61233096f16SXin LI {
61333096f16SXin LI 	int ret;
61433096f16SXin LI 
61533096f16SXin LI 	switch (mca)
61633096f16SXin LI 	{
61733096f16SXin LI 	case 0:
61833096f16SXin LI 		/*
61933096f16SXin LI 		 * We're not in a multicharacter command.
62033096f16SXin LI 		 */
62133096f16SXin LI 		return (NO_MCA);
62233096f16SXin LI 
62333096f16SXin LI 	case A_PREFIX:
62433096f16SXin LI 		/*
62533096f16SXin LI 		 * In the prefix of a command.
62633096f16SXin LI 		 * This not considered a multichar command
62733096f16SXin LI 		 * (even tho it uses cmdbuf, etc.).
62833096f16SXin LI 		 * It is handled in the commands() switch.
62933096f16SXin LI 		 */
63033096f16SXin LI 		return (NO_MCA);
63133096f16SXin LI 
63233096f16SXin LI 	case A_DIGIT:
63333096f16SXin LI 		/*
63433096f16SXin LI 		 * Entering digits of a number.
63533096f16SXin LI 		 * Terminated by a non-digit.
63633096f16SXin LI 		 */
6372235c7feSXin LI 		if ((c >= '0' && c <= '9') || c == '.')
6382235c7feSXin LI 			break;
6392235c7feSXin LI 		switch (editchar(c, ECF_PEEK|ECF_NOHISTORY|ECF_NOCOMPLETE|ECF_NORIGHTLEFT))
64033096f16SXin LI 		{
6412235c7feSXin LI 		case A_NOACTION:
6422235c7feSXin LI 			/*
6432235c7feSXin LI 			 * Ignore this char and get another one.
6442235c7feSXin LI 			 */
6452235c7feSXin LI 			return (MCA_MORE);
6462235c7feSXin LI 		case A_INVALID:
64733096f16SXin LI 			/*
64833096f16SXin LI 			 * Not part of the number.
64933096f16SXin LI 			 * End the number and treat this char
65033096f16SXin LI 			 * as a normal command character.
65133096f16SXin LI 			 */
65233096f16SXin LI 			number = cmd_int(&fraction);
653b7780dbeSXin LI 			clear_mca();
65433096f16SXin LI 			cmd_accept();
65533096f16SXin LI 			return (NO_MCA);
65633096f16SXin LI 		}
65733096f16SXin LI 		break;
65833096f16SXin LI 
65933096f16SXin LI 	case A_OPT_TOGGLE:
66033096f16SXin LI 		ret = mca_opt_char(c);
66133096f16SXin LI 		if (ret != NO_MCA)
66233096f16SXin LI 			return (ret);
66333096f16SXin LI 		break;
66433096f16SXin LI 
66533096f16SXin LI 	case A_F_SEARCH:
66633096f16SXin LI 	case A_B_SEARCH:
66733096f16SXin LI 	case A_FILTER:
66833096f16SXin LI 		ret = mca_search_char(c);
66933096f16SXin LI 		if (ret != NO_MCA)
67033096f16SXin LI 			return (ret);
67133096f16SXin LI 		break;
67233096f16SXin LI 
67333096f16SXin LI 	default:
67433096f16SXin LI 		/* Other multicharacter command. */
675a5f0fb15SPaul Saab 		break;
676a5f0fb15SPaul Saab 	}
677a5f0fb15SPaul Saab 
678a5f0fb15SPaul Saab 	/*
67933096f16SXin LI 	 * The multichar command is terminated by a newline.
680a5f0fb15SPaul Saab 	 */
681b2ea2440SXin LI 	if (is_newline_char(c))
682a5f0fb15SPaul Saab 	{
683a5f0fb15SPaul Saab 		/*
684a5f0fb15SPaul Saab 		 * Execute the command.
685a5f0fb15SPaul Saab 		 */
686a5f0fb15SPaul Saab 		exec_mca();
687a5f0fb15SPaul Saab 		return (MCA_DONE);
688a5f0fb15SPaul Saab 	}
689a5f0fb15SPaul Saab 
690a5f0fb15SPaul Saab 	/*
691a5f0fb15SPaul Saab 	 * Append the char to the command buffer.
692a5f0fb15SPaul Saab 	 */
693a5f0fb15SPaul Saab 	if (cmd_char(c) == CC_QUIT)
694a5f0fb15SPaul Saab 		/*
695a5f0fb15SPaul Saab 		 * Abort the multi-char command.
696a5f0fb15SPaul Saab 		 */
697a5f0fb15SPaul Saab 		return (MCA_DONE);
698a5f0fb15SPaul Saab 
6992235c7feSXin LI 	switch (mca)
7002235c7feSXin LI 	{
7012235c7feSXin LI 	case A_F_BRACKET:
7022235c7feSXin LI 	case A_B_BRACKET:
7032235c7feSXin LI 		if (len_cmdbuf() >= 2)
704a5f0fb15SPaul Saab 		{
705a5f0fb15SPaul Saab 			/*
706a5f0fb15SPaul Saab 			 * Special case for the bracket-matching commands.
707a5f0fb15SPaul Saab 			 * Execute the command after getting exactly two
708a5f0fb15SPaul Saab 			 * characters from the user.
709a5f0fb15SPaul Saab 			 */
710a5f0fb15SPaul Saab 			exec_mca();
711a5f0fb15SPaul Saab 			return (MCA_DONE);
712a5f0fb15SPaul Saab 		}
7132235c7feSXin LI 		break;
7142235c7feSXin LI 	case A_F_SEARCH:
7152235c7feSXin LI 	case A_B_SEARCH:
7162235c7feSXin LI 		if (incr_search)
7172235c7feSXin LI 		{
7182235c7feSXin LI 			/* Incremental search: do a search after every input char. */
719*d713e089SXin LI 			int st = (search_type & (SRCH_FORW|SRCH_BACK|SRCH_NO_MATCH|SRCH_NO_REGEX|SRCH_NO_MOVE|SRCH_WRAP|SRCH_SUBSEARCH_ALL));
7202235c7feSXin LI 			char *pattern = get_cmdbuf();
72195270f73SXin LI 			if (pattern == NULL)
72295270f73SXin LI 				return (MCA_MORE);
72395270f73SXin LI 			/*
72495270f73SXin LI 			 * Must save updown_match because mca_search
72595270f73SXin LI 			 * reinits it. That breaks history scrolling.
72695270f73SXin LI 			 * {{ This is ugly. mca_search probably shouldn't call set_mlist. }}
72795270f73SXin LI 			 */
72895270f73SXin LI 			int save_updown_match = updown_match;
7292235c7feSXin LI 			cmd_exec();
7302235c7feSXin LI 			if (*pattern == '\0')
7312235c7feSXin LI 			{
7322235c7feSXin LI 				/* User has backspaced to an empty pattern. */
7332235c7feSXin LI 				undo_search(1);
7342235c7feSXin LI 			} else
7352235c7feSXin LI 			{
7362235c7feSXin LI 				if (search(st | SRCH_INCR, pattern, 1) != 0)
7372235c7feSXin LI 					/* No match, invalid pattern, etc. */
7382235c7feSXin LI 					undo_search(1);
7392235c7feSXin LI 			}
7402235c7feSXin LI 			/* Redraw the search prompt and search string. */
741*d713e089SXin LI 			if (!full_screen)
742*d713e089SXin LI 			{
743*d713e089SXin LI 				clear();
744*d713e089SXin LI 				repaint();
745*d713e089SXin LI 			}
74695270f73SXin LI 			mca_search1();
74795270f73SXin LI 			updown_match = save_updown_match;
7482235c7feSXin LI 			cmd_repaint(NULL);
7492235c7feSXin LI 		}
7502235c7feSXin LI 		break;
7512235c7feSXin LI 	}
752a5f0fb15SPaul Saab 
753a5f0fb15SPaul Saab 	/*
754a5f0fb15SPaul Saab 	 * Need another character.
755a5f0fb15SPaul Saab 	 */
756a5f0fb15SPaul Saab 	return (MCA_MORE);
757a5f0fb15SPaul Saab }
758a5f0fb15SPaul Saab 
759a5f0fb15SPaul Saab /*
760423c5ce5SXin LI  * Discard any buffered file data.
761423c5ce5SXin LI  */
762*d713e089SXin LI static void clear_buffers(void)
763423c5ce5SXin LI {
764423c5ce5SXin LI 	if (!(ch_getflags() & CH_CANSEEK))
765423c5ce5SXin LI 		return;
766423c5ce5SXin LI 	ch_flush();
767423c5ce5SXin LI 	clr_linenum();
768423c5ce5SXin LI #if HILITE_SEARCH
769423c5ce5SXin LI 	clr_hilite();
770423c5ce5SXin LI #endif
771423c5ce5SXin LI }
772423c5ce5SXin LI 
773423c5ce5SXin LI /*
774a5f0fb15SPaul Saab  * Make sure the screen is displayed.
775a5f0fb15SPaul Saab  */
776*d713e089SXin LI static void make_display(void)
777a5f0fb15SPaul Saab {
778a5f0fb15SPaul Saab 	/*
779*d713e089SXin LI 	 * If not full_screen, we can't rely on scrolling to fill the screen.
780*d713e089SXin LI 	 * We need to clear and repaint screen before any change.
781*d713e089SXin LI 	 */
782*d713e089SXin LI 	if (!full_screen && !(quit_if_one_screen && one_screen))
783*d713e089SXin LI 		clear();
784*d713e089SXin LI 	/*
785a5f0fb15SPaul Saab 	 * If nothing is displayed yet, display starting from initial_scrpos.
786a5f0fb15SPaul Saab 	 */
787a5f0fb15SPaul Saab 	if (empty_screen())
788a5f0fb15SPaul Saab 	{
789a5f0fb15SPaul Saab 		if (initial_scrpos.pos == NULL_POSITION)
790a5f0fb15SPaul Saab 			jump_loc(ch_zero(), 1);
791a5f0fb15SPaul Saab 		else
792a5f0fb15SPaul Saab 			jump_loc(initial_scrpos.pos, initial_scrpos.ln);
793*d713e089SXin LI 	} else if (screen_trashed || !full_screen)
794a5f0fb15SPaul Saab 	{
795423c5ce5SXin LI 		int save_top_scroll = top_scroll;
796423c5ce5SXin LI 		int save_ignore_eoi = ignore_eoi;
797a5f0fb15SPaul Saab 		top_scroll = 1;
798423c5ce5SXin LI 		ignore_eoi = 0;
799423c5ce5SXin LI 		if (screen_trashed == 2)
800423c5ce5SXin LI 		{
801423c5ce5SXin LI 			/* Special case used by ignore_eoi: re-open the input file
802423c5ce5SXin LI 			 * and jump to the end of the file. */
803423c5ce5SXin LI 			reopen_curr_ifile();
804423c5ce5SXin LI 			jump_forw();
805423c5ce5SXin LI 		}
806a5f0fb15SPaul Saab 		repaint();
807a5f0fb15SPaul Saab 		top_scroll = save_top_scroll;
808423c5ce5SXin LI 		ignore_eoi = save_ignore_eoi;
809a5f0fb15SPaul Saab 	}
810a5f0fb15SPaul Saab }
811a5f0fb15SPaul Saab 
812a5f0fb15SPaul Saab /*
813a5f0fb15SPaul Saab  * Display the appropriate prompt.
814a5f0fb15SPaul Saab  */
815*d713e089SXin LI static void prompt(void)
816a5f0fb15SPaul Saab {
8171ea31627SRobert Watson 	constant char *p;
818a5f0fb15SPaul Saab 
819b2ea2440SXin LI 	if (ungot != NULL && ungot->ug_char != CHAR_END_COMMAND)
820a5f0fb15SPaul Saab 	{
821a5f0fb15SPaul Saab 		/*
822a5f0fb15SPaul Saab 		 * No prompt necessary if commands are from
823a5f0fb15SPaul Saab 		 * ungotten chars rather than from the user.
824a5f0fb15SPaul Saab 		 */
825a5f0fb15SPaul Saab 		return;
826a5f0fb15SPaul Saab 	}
827a5f0fb15SPaul Saab 
828a5f0fb15SPaul Saab 	/*
829a5f0fb15SPaul Saab 	 * Make sure the screen is displayed.
830a5f0fb15SPaul Saab 	 */
831a5f0fb15SPaul Saab 	make_display();
832a5f0fb15SPaul Saab 	bottompos = position(BOTTOM_PLUS_ONE);
833a5f0fb15SPaul Saab 
834a5f0fb15SPaul Saab 	/*
8357374caaaSXin LI 	 * If we've hit EOF on the last file and the -E flag is set, quit.
836a5f0fb15SPaul Saab 	 */
8377374caaaSXin LI 	if (get_quit_at_eof() == OPT_ONPLUS &&
8387374caaaSXin LI 	    eof_displayed() && !(ch_getflags() & CH_HELPFILE) &&
839a5f0fb15SPaul Saab 	    next_ifile(curr_ifile) == NULL_IFILE)
840a5f0fb15SPaul Saab 		quit(QUIT_OK);
8417374caaaSXin LI 
842a5f0fb15SPaul Saab 	/*
8437374caaaSXin LI 	 * If the entire file is displayed and the -F flag is set, quit.
844a5f0fb15SPaul Saab 	 */
8457374caaaSXin LI 	if (quit_if_one_screen &&
8467374caaaSXin LI 	    entire_file_displayed() && !(ch_getflags() & CH_HELPFILE) &&
847a5f0fb15SPaul Saab 	    next_ifile(curr_ifile) == NULL_IFILE)
848a5f0fb15SPaul Saab 		quit(QUIT_OK);
84930a1828cSXin LI 	quit_if_one_screen = FALSE; /* only get one chance at this */
850a5f0fb15SPaul Saab 
8518fd4165cSPaul Saab #if MSDOS_COMPILER==WIN32C
8528fd4165cSPaul Saab 	/*
8538fd4165cSPaul Saab 	 * In Win32, display the file name in the window title.
8548fd4165cSPaul Saab 	 */
8558fd4165cSPaul Saab 	if (!(ch_getflags() & CH_HELPFILE))
856b7780dbeSXin LI 	{
857b7780dbeSXin LI 		WCHAR w[MAX_PATH+16];
85895270f73SXin LI 		p = pr_expand("Less?f - %f.");
859b7780dbeSXin LI 		MultiByteToWideChar(CP_ACP, 0, p, -1, w, sizeof(w)/sizeof(*w));
860b7780dbeSXin LI 		SetConsoleTitleW(w);
861b7780dbeSXin LI 	}
8628fd4165cSPaul Saab #endif
863b7780dbeSXin LI 
864a5f0fb15SPaul Saab 	/*
865a5f0fb15SPaul Saab 	 * Select the proper prompt and display it.
866a5f0fb15SPaul Saab 	 */
867720c436cSXin LI 	/*
868720c436cSXin LI 	 * If the previous action was a forward movement,
869720c436cSXin LI 	 * don't clear the bottom line of the display;
870720c436cSXin LI 	 * just print the prompt since the forward movement guarantees
871720c436cSXin LI 	 * that we're in the right position to display the prompt.
872720c436cSXin LI 	 * Clearing the line could cause a problem: for example, if the last
873720c436cSXin LI 	 * line displayed ended at the right screen edge without a newline,
874720c436cSXin LI 	 * then clearing would clear the last displayed line rather than
875720c436cSXin LI 	 * the prompt line.
876720c436cSXin LI 	 */
877720c436cSXin LI 	if (!forw_prompt)
878720c436cSXin LI 		clear_bot();
879a5f0fb15SPaul Saab 	clear_cmd();
880720c436cSXin LI 	forw_prompt = 0;
881a5f0fb15SPaul Saab 	p = pr_string();
8822235c7feSXin LI #if HILITE_SEARCH
8837374caaaSXin LI 	if (is_filtering())
8847374caaaSXin LI 		putstr("& ");
8852235c7feSXin LI #endif
88689dd99dcSXin LI 	if (p == NULL || *p == '\0')
8872235c7feSXin LI 	{
8882235c7feSXin LI 		at_enter(AT_NORMAL|AT_COLOR_PROMPT);
889a5f0fb15SPaul Saab 		putchr(':');
8902235c7feSXin LI 		at_exit();
8912235c7feSXin LI 	} else
892a5f0fb15SPaul Saab 	{
893b7780dbeSXin LI #if MSDOS_COMPILER==WIN32C
894b7780dbeSXin LI 		WCHAR w[MAX_PATH*2];
895b7780dbeSXin LI 		char  a[MAX_PATH*2];
896b7780dbeSXin LI 		MultiByteToWideChar(CP_ACP, 0, p, -1, w, sizeof(w)/sizeof(*w));
897b7780dbeSXin LI 		WideCharToMultiByte(utf_mode ? CP_UTF8 : GetConsoleOutputCP(),
898b7780dbeSXin LI 		                    0, w, -1, a, sizeof(a), NULL, NULL);
899b7780dbeSXin LI 		p = a;
900b7780dbeSXin LI #endif
90195270f73SXin LI 		load_line(p);
90295270f73SXin LI 		put_line();
903a5f0fb15SPaul Saab 	}
904720c436cSXin LI 	clear_eol();
905a5f0fb15SPaul Saab }
906a5f0fb15SPaul Saab 
907a5f0fb15SPaul Saab /*
908a5f0fb15SPaul Saab  * Display the less version message.
909a5f0fb15SPaul Saab  */
910*d713e089SXin LI public void dispversion(void)
911a5f0fb15SPaul Saab {
912a5f0fb15SPaul Saab 	PARG parg;
913a5f0fb15SPaul Saab 
914a5f0fb15SPaul Saab 	parg.p_string = version;
915a5f0fb15SPaul Saab 	error("less %s", &parg);
916a5f0fb15SPaul Saab }
917a5f0fb15SPaul Saab 
918a5f0fb15SPaul Saab /*
919b2ea2440SXin LI  * Return a character to complete a partial command, if possible.
920b2ea2440SXin LI  */
921*d713e089SXin LI static LWCHAR getcc_end_command(void)
922b2ea2440SXin LI {
923b2ea2440SXin LI 	switch (mca)
924b2ea2440SXin LI 	{
925b2ea2440SXin LI 	case A_DIGIT:
926b2ea2440SXin LI 		/* We have a number but no command.  Treat as #g. */
927b2ea2440SXin LI 		return ('g');
928b2ea2440SXin LI 	case A_F_SEARCH:
929b2ea2440SXin LI 	case A_B_SEARCH:
930*d713e089SXin LI 	case A_FILTER:
931b2ea2440SXin LI 		/* We have "/string" but no newline.  Add the \n. */
932b2ea2440SXin LI 		return ('\n');
933b2ea2440SXin LI 	default:
934b2ea2440SXin LI 		/* Some other incomplete command.  Let user complete it. */
9352235c7feSXin LI 		return ((ungot == NULL) ? getchr() : 0);
936b2ea2440SXin LI 	}
937b2ea2440SXin LI }
938b2ea2440SXin LI 
939b2ea2440SXin LI /*
940a5f0fb15SPaul Saab  * Get command character.
941a5f0fb15SPaul Saab  * The character normally comes from the keyboard,
942a5f0fb15SPaul Saab  * but may come from ungotten characters
943a5f0fb15SPaul Saab  * (characters previously given to ungetcc or ungetsc).
944a5f0fb15SPaul Saab  */
945*d713e089SXin LI static LWCHAR getccu(void)
946a5f0fb15SPaul Saab {
9472235c7feSXin LI 	LWCHAR c = 0;
9482235c7feSXin LI 	while (c == 0)
9492235c7feSXin LI 	{
950a15691bfSXin LI 		if (ungot == NULL)
95133096f16SXin LI 		{
952b2ea2440SXin LI 			/* Normal case: no ungotten chars.
953b2ea2440SXin LI 			 * Get char from the user. */
954b2ea2440SXin LI 			c = getchr();
955b2ea2440SXin LI 		} else
956a15691bfSXin LI 		{
957b2ea2440SXin LI 			/* Ungotten chars available:
958b2ea2440SXin LI 			 * Take the top of stack (most recent). */
959a15691bfSXin LI 			struct ungot *ug = ungot;
960b2ea2440SXin LI 			c = ug->ug_char;
961a15691bfSXin LI 			ungot = ug->ug_next;
962a15691bfSXin LI 			free(ug);
963a5f0fb15SPaul Saab 
964b2ea2440SXin LI 			if (c == CHAR_END_COMMAND)
965b2ea2440SXin LI 				c = getcc_end_command();
966a5f0fb15SPaul Saab 		}
9672235c7feSXin LI 	}
96833096f16SXin LI 	return (c);
96933096f16SXin LI }
970b2ea2440SXin LI 
971b2ea2440SXin LI /*
972b2ea2440SXin LI  * Get a command character, but if we receive the orig sequence,
973b2ea2440SXin LI  * convert it to the repl sequence.
974b2ea2440SXin LI  */
975*d713e089SXin LI static LWCHAR getcc_repl(char constant *orig, char constant *repl, LWCHAR (*gr_getc)(void), void (*gr_ungetc)(LWCHAR))
976b2ea2440SXin LI {
977b2ea2440SXin LI 	LWCHAR c;
978b2ea2440SXin LI 	LWCHAR keys[16];
979b2ea2440SXin LI 	int ki = 0;
980b2ea2440SXin LI 
981b2ea2440SXin LI 	c = (*gr_getc)();
982b2ea2440SXin LI 	if (orig == NULL || orig[0] == '\0')
983b2ea2440SXin LI 		return c;
984b2ea2440SXin LI 	for (;;)
985b2ea2440SXin LI 	{
986b2ea2440SXin LI 		keys[ki] = c;
987b2ea2440SXin LI 		if (c != orig[ki] || ki >= sizeof(keys)-1)
988b2ea2440SXin LI 		{
989b2ea2440SXin LI 			/* This is not orig we have been receiving.
990b2ea2440SXin LI 			 * If we have stashed chars in keys[],
991b2ea2440SXin LI 			 * unget them and return the first one. */
992b2ea2440SXin LI 			while (ki > 0)
993b2ea2440SXin LI 				(*gr_ungetc)(keys[ki--]);
994b2ea2440SXin LI 			return keys[0];
995b2ea2440SXin LI 		}
996b2ea2440SXin LI 		if (orig[++ki] == '\0')
997b2ea2440SXin LI 		{
998b2ea2440SXin LI 			/* We've received the full orig sequence.
999b2ea2440SXin LI 			 * Return the repl sequence. */
1000b2ea2440SXin LI 			ki = strlen(repl)-1;
1001b2ea2440SXin LI 			while (ki > 0)
1002b2ea2440SXin LI 				(*gr_ungetc)(repl[ki--]);
1003b2ea2440SXin LI 			return repl[0];
1004b2ea2440SXin LI 		}
1005b2ea2440SXin LI 		/* We've received a partial orig sequence (ki chars of it).
1006b2ea2440SXin LI 		 * Get next char and see if it continues to match orig. */
1007b2ea2440SXin LI 		c = (*gr_getc)();
1008b2ea2440SXin LI 	}
1009b2ea2440SXin LI }
1010b2ea2440SXin LI 
1011b2ea2440SXin LI /*
1012b2ea2440SXin LI  * Get command character.
1013b2ea2440SXin LI  */
1014*d713e089SXin LI public int getcc(void)
1015b2ea2440SXin LI {
1016b2ea2440SXin LI 	/* Replace kent (keypad Enter) with a newline. */
1017b2ea2440SXin LI 	return getcc_repl(kent, "\n", getccu, ungetcc);
101833096f16SXin LI }
101933096f16SXin LI 
1020a5f0fb15SPaul Saab /*
1021a5f0fb15SPaul Saab  * "Unget" a command character.
1022a5f0fb15SPaul Saab  * The next getcc() will return this character.
1023a5f0fb15SPaul Saab  */
1024*d713e089SXin LI public void ungetcc(LWCHAR c)
1025a5f0fb15SPaul Saab {
102633096f16SXin LI 	struct ungot *ug = (struct ungot *) ecalloc(1, sizeof(struct ungot));
102733096f16SXin LI 
1028b2ea2440SXin LI 	ug->ug_char = c;
102933096f16SXin LI 	ug->ug_next = ungot;
103033096f16SXin LI 	ungot = ug;
1031a5f0fb15SPaul Saab }
1032a5f0fb15SPaul Saab 
1033a5f0fb15SPaul Saab /*
10342235c7feSXin LI  * "Unget" a command character.
10352235c7feSXin LI  * If any other chars are already ungotten, put this one after those.
10362235c7feSXin LI  */
1037*d713e089SXin LI public void ungetcc_back(LWCHAR c)
10382235c7feSXin LI {
10392235c7feSXin LI 	struct ungot *ug = (struct ungot *) ecalloc(1, sizeof(struct ungot));
10402235c7feSXin LI 	ug->ug_char = c;
10412235c7feSXin LI 	ug->ug_next = NULL;
10422235c7feSXin LI 	if (ungot == NULL)
10432235c7feSXin LI 		ungot = ug;
10442235c7feSXin LI 	else
10452235c7feSXin LI 	{
10462235c7feSXin LI 		struct ungot *pu;
10472235c7feSXin LI 		for (pu = ungot; pu->ug_next != NULL; pu = pu->ug_next)
10482235c7feSXin LI 			continue;
10492235c7feSXin LI 		pu->ug_next = ug;
10502235c7feSXin LI 	}
10512235c7feSXin LI }
10522235c7feSXin LI 
10532235c7feSXin LI /*
1054a5f0fb15SPaul Saab  * Unget a whole string of command characters.
1055a5f0fb15SPaul Saab  * The next sequence of getcc()'s will return this string.
1056a5f0fb15SPaul Saab  */
1057*d713e089SXin LI public void ungetsc(char *s)
1058a5f0fb15SPaul Saab {
10592235c7feSXin LI 	while (*s != '\0')
10602235c7feSXin LI 		ungetcc_back(*s++);
1061a5f0fb15SPaul Saab }
1062a5f0fb15SPaul Saab 
1063a5f0fb15SPaul Saab /*
1064b2ea2440SXin LI  * Peek the next command character, without consuming it.
1065b2ea2440SXin LI  */
1066*d713e089SXin LI public LWCHAR peekcc(void)
1067b2ea2440SXin LI {
1068b2ea2440SXin LI 	LWCHAR c = getcc();
1069b2ea2440SXin LI 	ungetcc(c);
1070b2ea2440SXin LI 	return c;
1071b2ea2440SXin LI }
1072b2ea2440SXin LI 
1073b2ea2440SXin LI /*
1074a5f0fb15SPaul Saab  * Search for a pattern, possibly in multiple files.
1075a5f0fb15SPaul Saab  * If SRCH_FIRST_FILE is set, begin searching at the first file.
1076a5f0fb15SPaul Saab  * If SRCH_PAST_EOF is set, continue the search thru multiple files.
1077a5f0fb15SPaul Saab  */
1078*d713e089SXin LI static void multi_search(char *pattern, int n, int silent)
1079a5f0fb15SPaul Saab {
10801ea31627SRobert Watson 	int nomore;
1081a5f0fb15SPaul Saab 	IFILE save_ifile;
1082a5f0fb15SPaul Saab 	int changed_file;
1083a5f0fb15SPaul Saab 
1084a5f0fb15SPaul Saab 	changed_file = 0;
1085a5f0fb15SPaul Saab 	save_ifile = save_curr_ifile();
1086a5f0fb15SPaul Saab 
1087*d713e089SXin LI 	if ((search_type & (SRCH_FORW|SRCH_BACK)) == 0)
1088*d713e089SXin LI 		search_type |= SRCH_FORW;
1089a5f0fb15SPaul Saab 	if (search_type & SRCH_FIRST_FILE)
1090a5f0fb15SPaul Saab 	{
1091a5f0fb15SPaul Saab 		/*
1092a5f0fb15SPaul Saab 		 * Start at the first (or last) file
1093a5f0fb15SPaul Saab 		 * in the command line list.
1094a5f0fb15SPaul Saab 		 */
1095a5f0fb15SPaul Saab 		if (search_type & SRCH_FORW)
1096a5f0fb15SPaul Saab 			nomore = edit_first();
1097a5f0fb15SPaul Saab 		else
1098a5f0fb15SPaul Saab 			nomore = edit_last();
1099a5f0fb15SPaul Saab 		if (nomore)
1100a5f0fb15SPaul Saab 		{
1101a5f0fb15SPaul Saab 			unsave_ifile(save_ifile);
1102a5f0fb15SPaul Saab 			return;
1103a5f0fb15SPaul Saab 		}
1104a5f0fb15SPaul Saab 		changed_file = 1;
1105a5f0fb15SPaul Saab 		search_type &= ~SRCH_FIRST_FILE;
1106a5f0fb15SPaul Saab 	}
1107a5f0fb15SPaul Saab 
1108a5f0fb15SPaul Saab 	for (;;)
1109a5f0fb15SPaul Saab 	{
1110a5f0fb15SPaul Saab 		n = search(search_type, pattern, n);
1111a5f0fb15SPaul Saab 		/*
1112a5f0fb15SPaul Saab 		 * The SRCH_NO_MOVE flag doesn't "stick": it gets cleared
1113a5f0fb15SPaul Saab 		 * after being used once.  This allows "n" to work after
1114a5f0fb15SPaul Saab 		 * using a /@@ search.
1115a5f0fb15SPaul Saab 		 */
1116a5f0fb15SPaul Saab 		search_type &= ~SRCH_NO_MOVE;
1117*d713e089SXin LI 		last_search_type = search_type;
1118a5f0fb15SPaul Saab 		if (n == 0)
1119a5f0fb15SPaul Saab 		{
1120a5f0fb15SPaul Saab 			/*
1121a5f0fb15SPaul Saab 			 * Found it.
1122a5f0fb15SPaul Saab 			 */
1123a5f0fb15SPaul Saab 			unsave_ifile(save_ifile);
1124a5f0fb15SPaul Saab 			return;
1125a5f0fb15SPaul Saab 		}
1126a5f0fb15SPaul Saab 
1127a5f0fb15SPaul Saab 		if (n < 0)
1128a5f0fb15SPaul Saab 			/*
1129a5f0fb15SPaul Saab 			 * Some kind of error in the search.
1130a5f0fb15SPaul Saab 			 * Error message has been printed by search().
1131a5f0fb15SPaul Saab 			 */
1132a5f0fb15SPaul Saab 			break;
1133a5f0fb15SPaul Saab 
1134a5f0fb15SPaul Saab 		if ((search_type & SRCH_PAST_EOF) == 0)
1135a5f0fb15SPaul Saab 			/*
1136a5f0fb15SPaul Saab 			 * We didn't find a match, but we're
1137a5f0fb15SPaul Saab 			 * supposed to search only one file.
1138a5f0fb15SPaul Saab 			 */
1139a5f0fb15SPaul Saab 			break;
1140a5f0fb15SPaul Saab 		/*
1141a5f0fb15SPaul Saab 		 * Move on to the next file.
1142a5f0fb15SPaul Saab 		 */
1143a5f0fb15SPaul Saab 		if (search_type & SRCH_FORW)
1144a5f0fb15SPaul Saab 			nomore = edit_next(1);
1145a5f0fb15SPaul Saab 		else
1146a5f0fb15SPaul Saab 			nomore = edit_prev(1);
1147a5f0fb15SPaul Saab 		if (nomore)
1148a5f0fb15SPaul Saab 			break;
1149a5f0fb15SPaul Saab 		changed_file = 1;
1150a5f0fb15SPaul Saab 	}
1151a5f0fb15SPaul Saab 
1152a5f0fb15SPaul Saab 	/*
1153a5f0fb15SPaul Saab 	 * Didn't find it.
1154a5f0fb15SPaul Saab 	 * Print an error message if we haven't already.
1155a5f0fb15SPaul Saab 	 */
1156a15691bfSXin LI 	if (n > 0 && !silent)
1157a5f0fb15SPaul Saab 		error("Pattern not found", NULL_PARG);
1158a5f0fb15SPaul Saab 
1159a5f0fb15SPaul Saab 	if (changed_file)
1160a5f0fb15SPaul Saab 	{
1161a5f0fb15SPaul Saab 		/*
1162a5f0fb15SPaul Saab 		 * Restore the file we were originally viewing.
1163a5f0fb15SPaul Saab 		 */
1164a5f0fb15SPaul Saab 		reedit_ifile(save_ifile);
116589dd99dcSXin LI 	} else
116689dd99dcSXin LI 	{
116789dd99dcSXin LI 		unsave_ifile(save_ifile);
1168a5f0fb15SPaul Saab 	}
1169a5f0fb15SPaul Saab }
1170a5f0fb15SPaul Saab 
1171a5f0fb15SPaul Saab /*
117296e55cc7SXin LI  * Forward forever, or until a highlighted line appears.
117396e55cc7SXin LI  */
1174*d713e089SXin LI static int forw_loop(int until_hilite)
117596e55cc7SXin LI {
117696e55cc7SXin LI 	POSITION curr_len;
117796e55cc7SXin LI 
117896e55cc7SXin LI 	if (ch_getflags() & CH_HELPFILE)
117996e55cc7SXin LI 		return (A_NOACTION);
118096e55cc7SXin LI 
118196e55cc7SXin LI 	cmd_exec();
1182a15691bfSXin LI 	jump_forw_buffered();
118396e55cc7SXin LI 	curr_len = ch_length();
118496e55cc7SXin LI 	highest_hilite = until_hilite ? curr_len : NULL_POSITION;
118596e55cc7SXin LI 	ignore_eoi = 1;
118696e55cc7SXin LI 	while (!sigs)
118796e55cc7SXin LI 	{
118896e55cc7SXin LI 		if (until_hilite && highest_hilite > curr_len)
118996e55cc7SXin LI 		{
119096e55cc7SXin LI 			bell();
119196e55cc7SXin LI 			break;
119296e55cc7SXin LI 		}
119396e55cc7SXin LI 		make_display();
119496e55cc7SXin LI 		forward(1, 0, 0);
119596e55cc7SXin LI 	}
119696e55cc7SXin LI 	ignore_eoi = 0;
1197e2449719SXin LI 	ch_set_eof();
119896e55cc7SXin LI 
119996e55cc7SXin LI 	/*
120096e55cc7SXin LI 	 * This gets us back in "F mode" after processing
120196e55cc7SXin LI 	 * a non-abort signal (e.g. window-change).
120296e55cc7SXin LI 	 */
120396e55cc7SXin LI 	if (sigs && !ABORT_SIGS())
1204e2449719SXin LI 		return (until_hilite ? A_F_UNTIL_HILITE : A_F_FOREVER);
1205e2449719SXin LI 
120696e55cc7SXin LI 	return (A_NOACTION);
120796e55cc7SXin LI }
120896e55cc7SXin LI 
120996e55cc7SXin LI /*
1210a5f0fb15SPaul Saab  * Main command processor.
1211a5f0fb15SPaul Saab  * Accept and execute commands until a quit command.
1212a5f0fb15SPaul Saab  */
1213*d713e089SXin LI public void commands(void)
1214a5f0fb15SPaul Saab {
12151ea31627SRobert Watson 	int c;
12161ea31627SRobert Watson 	int action;
12171ea31627SRobert Watson 	char *cbuf;
1218a5f0fb15SPaul Saab 	int newaction;
12192235c7feSXin LI 	int save_jump_sline;
1220a5f0fb15SPaul Saab 	int save_search_type;
1221a5f0fb15SPaul Saab 	char *extra;
1222a5f0fb15SPaul Saab 	char tbuf[2];
1223a5f0fb15SPaul Saab 	PARG parg;
1224a5f0fb15SPaul Saab 	IFILE old_ifile;
1225a5f0fb15SPaul Saab 	IFILE new_ifile;
12268fd4165cSPaul Saab 	char *tagfile;
1227a5f0fb15SPaul Saab 
1228a5f0fb15SPaul Saab 	search_type = SRCH_FORW;
1229a5f0fb15SPaul Saab 	wscroll = (sc_height + 1) / 2;
1230a5f0fb15SPaul Saab 	newaction = A_NOACTION;
1231a5f0fb15SPaul Saab 
1232a5f0fb15SPaul Saab 	for (;;)
1233a5f0fb15SPaul Saab 	{
1234b7780dbeSXin LI 		clear_mca();
1235a5f0fb15SPaul Saab 		cmd_accept();
1236a5f0fb15SPaul Saab 		number = 0;
123733096f16SXin LI 		curropt = NULL;
1238a5f0fb15SPaul Saab 
1239a5f0fb15SPaul Saab 		/*
1240a5f0fb15SPaul Saab 		 * See if any signals need processing.
1241a5f0fb15SPaul Saab 		 */
1242a5f0fb15SPaul Saab 		if (sigs)
1243a5f0fb15SPaul Saab 		{
1244a5f0fb15SPaul Saab 			psignals();
1245a5f0fb15SPaul Saab 			if (quitting)
1246a5f0fb15SPaul Saab 				quit(QUIT_SAVED_STATUS);
1247a5f0fb15SPaul Saab 		}
1248a5f0fb15SPaul Saab 
1249a5f0fb15SPaul Saab 		/*
1250a5f0fb15SPaul Saab 		 * See if window size changed, for systems that don't
1251a5f0fb15SPaul Saab 		 * generate SIGWINCH.
1252a5f0fb15SPaul Saab 		 */
1253a5f0fb15SPaul Saab 		check_winch();
1254a5f0fb15SPaul Saab 
1255a5f0fb15SPaul Saab 		/*
1256a5f0fb15SPaul Saab 		 * Display prompt and accept a character.
1257a5f0fb15SPaul Saab 		 */
1258a5f0fb15SPaul Saab 		cmd_reset();
1259a5f0fb15SPaul Saab 		prompt();
1260a5f0fb15SPaul Saab 		if (sigs)
1261a5f0fb15SPaul Saab 			continue;
1262a5f0fb15SPaul Saab 		if (newaction == A_NOACTION)
1263a5f0fb15SPaul Saab 			c = getcc();
1264a5f0fb15SPaul Saab 
1265a5f0fb15SPaul Saab 	again:
1266a5f0fb15SPaul Saab 		if (sigs)
1267a5f0fb15SPaul Saab 			continue;
1268a5f0fb15SPaul Saab 
1269a5f0fb15SPaul Saab 		if (newaction != A_NOACTION)
1270a5f0fb15SPaul Saab 		{
1271a5f0fb15SPaul Saab 			action = newaction;
1272a5f0fb15SPaul Saab 			newaction = A_NOACTION;
1273a5f0fb15SPaul Saab 		} else
1274a5f0fb15SPaul Saab 		{
1275a5f0fb15SPaul Saab 			/*
1276a5f0fb15SPaul Saab 			 * If we are in a multicharacter command, call mca_char.
1277a5f0fb15SPaul Saab 			 * Otherwise we call fcmd_decode to determine the
1278a5f0fb15SPaul Saab 			 * action to be performed.
1279a5f0fb15SPaul Saab 			 */
1280a5f0fb15SPaul Saab 			if (mca)
1281a5f0fb15SPaul Saab 				switch (mca_char(c))
1282a5f0fb15SPaul Saab 				{
1283a5f0fb15SPaul Saab 				case MCA_MORE:
1284a5f0fb15SPaul Saab 					/*
1285a5f0fb15SPaul Saab 					 * Need another character.
1286a5f0fb15SPaul Saab 					 */
1287a5f0fb15SPaul Saab 					c = getcc();
1288a5f0fb15SPaul Saab 					goto again;
1289a5f0fb15SPaul Saab 				case MCA_DONE:
1290a5f0fb15SPaul Saab 					/*
1291a5f0fb15SPaul Saab 					 * Command has been handled by mca_char.
1292a5f0fb15SPaul Saab 					 * Start clean with a prompt.
1293a5f0fb15SPaul Saab 					 */
1294a5f0fb15SPaul Saab 					continue;
1295a5f0fb15SPaul Saab 				case NO_MCA:
1296a5f0fb15SPaul Saab 					/*
1297a5f0fb15SPaul Saab 					 * Not a multi-char command
1298a5f0fb15SPaul Saab 					 * (at least, not anymore).
1299a5f0fb15SPaul Saab 					 */
1300a5f0fb15SPaul Saab 					break;
1301a5f0fb15SPaul Saab 				}
1302a5f0fb15SPaul Saab 
1303a5f0fb15SPaul Saab 			/*
1304a5f0fb15SPaul Saab 			 * Decode the command character and decide what to do.
1305a5f0fb15SPaul Saab 			 */
1306a5f0fb15SPaul Saab 			if (mca)
1307a5f0fb15SPaul Saab 			{
1308a5f0fb15SPaul Saab 				/*
1309a5f0fb15SPaul Saab 				 * We're in a multichar command.
1310a5f0fb15SPaul Saab 				 * Add the character to the command buffer
1311a5f0fb15SPaul Saab 				 * and display it on the screen.
1312a5f0fb15SPaul Saab 				 * If the user backspaces past the start
1313a5f0fb15SPaul Saab 				 * of the line, abort the command.
1314a5f0fb15SPaul Saab 				 */
1315a5f0fb15SPaul Saab 				if (cmd_char(c) == CC_QUIT || len_cmdbuf() == 0)
1316a5f0fb15SPaul Saab 					continue;
1317a5f0fb15SPaul Saab 				cbuf = get_cmdbuf();
131895270f73SXin LI 				if (cbuf == NULL)
131995270f73SXin LI 					continue;
1320a5f0fb15SPaul Saab 			} else
1321a5f0fb15SPaul Saab 			{
1322a5f0fb15SPaul Saab 				/*
1323a5f0fb15SPaul Saab 				 * Don't use cmd_char if we're starting fresh
1324a5f0fb15SPaul Saab 				 * at the beginning of a command, because we
1325a5f0fb15SPaul Saab 				 * don't want to echo the command until we know
1326a5f0fb15SPaul Saab 				 * it is a multichar command.  We also don't
1327a5f0fb15SPaul Saab 				 * want erase_char/kill_char to be treated
1328a5f0fb15SPaul Saab 				 * as line editing characters.
1329a5f0fb15SPaul Saab 				 */
1330a5f0fb15SPaul Saab 				tbuf[0] = c;
1331a5f0fb15SPaul Saab 				tbuf[1] = '\0';
1332a5f0fb15SPaul Saab 				cbuf = tbuf;
1333a5f0fb15SPaul Saab 			}
1334a5f0fb15SPaul Saab 			extra = NULL;
1335a5f0fb15SPaul Saab 			action = fcmd_decode(cbuf, &extra);
1336a5f0fb15SPaul Saab 			/*
1337a5f0fb15SPaul Saab 			 * If an "extra" string was returned,
1338a5f0fb15SPaul Saab 			 * process it as a string of command characters.
1339a5f0fb15SPaul Saab 			 */
1340a5f0fb15SPaul Saab 			if (extra != NULL)
1341a5f0fb15SPaul Saab 				ungetsc(extra);
1342a5f0fb15SPaul Saab 		}
1343a5f0fb15SPaul Saab 		/*
1344a5f0fb15SPaul Saab 		 * Clear the cmdbuf string.
1345a5f0fb15SPaul Saab 		 * (But not if we're in the prefix of a command,
1346a5f0fb15SPaul Saab 		 * because the partial command string is kept there.)
1347a5f0fb15SPaul Saab 		 */
1348a5f0fb15SPaul Saab 		if (action != A_PREFIX)
1349a5f0fb15SPaul Saab 			cmd_reset();
1350a5f0fb15SPaul Saab 
1351a5f0fb15SPaul Saab 		switch (action)
1352a5f0fb15SPaul Saab 		{
1353a5f0fb15SPaul Saab 		case A_DIGIT:
1354a5f0fb15SPaul Saab 			/*
1355a5f0fb15SPaul Saab 			 * First digit of a number.
1356a5f0fb15SPaul Saab 			 */
1357a5f0fb15SPaul Saab 			start_mca(A_DIGIT, ":", (void*)NULL, CF_QUIT_ON_ERASE);
1358a5f0fb15SPaul Saab 			goto again;
1359a5f0fb15SPaul Saab 
1360a5f0fb15SPaul Saab 		case A_F_WINDOW:
1361a5f0fb15SPaul Saab 			/*
1362a5f0fb15SPaul Saab 			 * Forward one window (and set the window size).
1363a5f0fb15SPaul Saab 			 */
1364a5f0fb15SPaul Saab 			if (number > 0)
13651ede1615STim J. Robbins 				swindow = (int) number;
1366a5f0fb15SPaul Saab 			/* FALLTHRU */
1367a5f0fb15SPaul Saab 		case A_F_SCREEN:
1368a5f0fb15SPaul Saab 			/*
1369a5f0fb15SPaul Saab 			 * Forward one screen.
1370a5f0fb15SPaul Saab 			 */
1371a5f0fb15SPaul Saab 			if (number <= 0)
1372a5f0fb15SPaul Saab 				number = get_swindow();
1373a5f0fb15SPaul Saab 			cmd_exec();
1374a5f0fb15SPaul Saab 			if (show_attn)
1375a5f0fb15SPaul Saab 				set_attnpos(bottompos);
13761ede1615STim J. Robbins 			forward((int) number, 0, 1);
1377a5f0fb15SPaul Saab 			break;
1378a5f0fb15SPaul Saab 
1379a5f0fb15SPaul Saab 		case A_B_WINDOW:
1380a5f0fb15SPaul Saab 			/*
1381a5f0fb15SPaul Saab 			 * Backward one window (and set the window size).
1382a5f0fb15SPaul Saab 			 */
1383a5f0fb15SPaul Saab 			if (number > 0)
13841ede1615STim J. Robbins 				swindow = (int) number;
1385a5f0fb15SPaul Saab 			/* FALLTHRU */
1386a5f0fb15SPaul Saab 		case A_B_SCREEN:
1387a5f0fb15SPaul Saab 			/*
1388a5f0fb15SPaul Saab 			 * Backward one screen.
1389a5f0fb15SPaul Saab 			 */
1390a5f0fb15SPaul Saab 			if (number <= 0)
1391a5f0fb15SPaul Saab 				number = get_swindow();
1392a5f0fb15SPaul Saab 			cmd_exec();
13931ede1615STim J. Robbins 			backward((int) number, 0, 1);
1394a5f0fb15SPaul Saab 			break;
1395a5f0fb15SPaul Saab 
1396a5f0fb15SPaul Saab 		case A_F_LINE:
1397a5f0fb15SPaul Saab 			/*
1398a5f0fb15SPaul Saab 			 * Forward N (default 1) line.
1399a5f0fb15SPaul Saab 			 */
1400a5f0fb15SPaul Saab 			if (number <= 0)
1401a5f0fb15SPaul Saab 				number = 1;
1402a5f0fb15SPaul Saab 			cmd_exec();
1403a5f0fb15SPaul Saab 			if (show_attn == OPT_ONPLUS && number > 1)
1404a5f0fb15SPaul Saab 				set_attnpos(bottompos);
14051ede1615STim J. Robbins 			forward((int) number, 0, 0);
1406a5f0fb15SPaul Saab 			break;
1407a5f0fb15SPaul Saab 
1408a5f0fb15SPaul Saab 		case A_B_LINE:
1409a5f0fb15SPaul Saab 			/*
1410a5f0fb15SPaul Saab 			 * Backward N (default 1) line.
1411a5f0fb15SPaul Saab 			 */
1412a5f0fb15SPaul Saab 			if (number <= 0)
1413a5f0fb15SPaul Saab 				number = 1;
1414a5f0fb15SPaul Saab 			cmd_exec();
14151ede1615STim J. Robbins 			backward((int) number, 0, 0);
1416a5f0fb15SPaul Saab 			break;
1417a5f0fb15SPaul Saab 
1418b7780dbeSXin LI 		case A_F_MOUSE:
1419b7780dbeSXin LI 			/*
1420b7780dbeSXin LI 			 * Forward wheel_lines lines.
1421b7780dbeSXin LI 			 */
1422b7780dbeSXin LI 			cmd_exec();
1423b7780dbeSXin LI 			forward(wheel_lines, 0, 0);
1424b7780dbeSXin LI 			break;
1425b7780dbeSXin LI 
1426b7780dbeSXin LI 		case A_B_MOUSE:
1427b7780dbeSXin LI 			/*
1428b7780dbeSXin LI 			 * Backward wheel_lines lines.
1429b7780dbeSXin LI 			 */
1430b7780dbeSXin LI 			cmd_exec();
1431b7780dbeSXin LI 			backward(wheel_lines, 0, 0);
1432b7780dbeSXin LI 			break;
1433b7780dbeSXin LI 
1434a5f0fb15SPaul Saab 		case A_FF_LINE:
1435a5f0fb15SPaul Saab 			/*
1436a5f0fb15SPaul Saab 			 * Force forward N (default 1) line.
1437a5f0fb15SPaul Saab 			 */
1438a5f0fb15SPaul Saab 			if (number <= 0)
1439a5f0fb15SPaul Saab 				number = 1;
1440a5f0fb15SPaul Saab 			cmd_exec();
1441a5f0fb15SPaul Saab 			if (show_attn == OPT_ONPLUS && number > 1)
1442a5f0fb15SPaul Saab 				set_attnpos(bottompos);
14431ede1615STim J. Robbins 			forward((int) number, 1, 0);
1444a5f0fb15SPaul Saab 			break;
1445a5f0fb15SPaul Saab 
1446a5f0fb15SPaul Saab 		case A_BF_LINE:
1447a5f0fb15SPaul Saab 			/*
1448a5f0fb15SPaul Saab 			 * Force backward N (default 1) line.
1449a5f0fb15SPaul Saab 			 */
1450a5f0fb15SPaul Saab 			if (number <= 0)
1451a5f0fb15SPaul Saab 				number = 1;
1452a5f0fb15SPaul Saab 			cmd_exec();
14531ede1615STim J. Robbins 			backward((int) number, 1, 0);
1454a5f0fb15SPaul Saab 			break;
1455a5f0fb15SPaul Saab 
1456a5f0fb15SPaul Saab 		case A_FF_SCREEN:
1457a5f0fb15SPaul Saab 			/*
1458a5f0fb15SPaul Saab 			 * Force forward one screen.
1459a5f0fb15SPaul Saab 			 */
1460a5f0fb15SPaul Saab 			if (number <= 0)
1461a5f0fb15SPaul Saab 				number = get_swindow();
1462a5f0fb15SPaul Saab 			cmd_exec();
1463a5f0fb15SPaul Saab 			if (show_attn == OPT_ONPLUS)
1464a5f0fb15SPaul Saab 				set_attnpos(bottompos);
14651ede1615STim J. Robbins 			forward((int) number, 1, 0);
1466a5f0fb15SPaul Saab 			break;
1467a5f0fb15SPaul Saab 
1468a5f0fb15SPaul Saab 		case A_F_FOREVER:
1469a5f0fb15SPaul Saab 			/*
1470a5f0fb15SPaul Saab 			 * Forward forever, ignoring EOF.
1471a5f0fb15SPaul Saab 			 */
1472a15691bfSXin LI 			if (show_attn)
1473a15691bfSXin LI 				set_attnpos(bottompos);
147496e55cc7SXin LI 			newaction = forw_loop(0);
1475a5f0fb15SPaul Saab 			break;
147696e55cc7SXin LI 
147796e55cc7SXin LI 		case A_F_UNTIL_HILITE:
147896e55cc7SXin LI 			newaction = forw_loop(1);
1479a5f0fb15SPaul Saab 			break;
1480a5f0fb15SPaul Saab 
1481a5f0fb15SPaul Saab 		case A_F_SCROLL:
1482a5f0fb15SPaul Saab 			/*
1483a5f0fb15SPaul Saab 			 * Forward N lines
1484a5f0fb15SPaul Saab 			 * (default same as last 'd' or 'u' command).
1485a5f0fb15SPaul Saab 			 */
1486a5f0fb15SPaul Saab 			if (number > 0)
14871ede1615STim J. Robbins 				wscroll = (int) number;
1488a5f0fb15SPaul Saab 			cmd_exec();
1489a5f0fb15SPaul Saab 			if (show_attn == OPT_ONPLUS)
1490a5f0fb15SPaul Saab 				set_attnpos(bottompos);
1491a5f0fb15SPaul Saab 			forward(wscroll, 0, 0);
1492a5f0fb15SPaul Saab 			break;
1493a5f0fb15SPaul Saab 
1494a5f0fb15SPaul Saab 		case A_B_SCROLL:
1495a5f0fb15SPaul Saab 			/*
1496a5f0fb15SPaul Saab 			 * Forward N lines
1497a5f0fb15SPaul Saab 			 * (default same as last 'd' or 'u' command).
1498a5f0fb15SPaul Saab 			 */
1499a5f0fb15SPaul Saab 			if (number > 0)
15001ede1615STim J. Robbins 				wscroll = (int) number;
1501a5f0fb15SPaul Saab 			cmd_exec();
1502a5f0fb15SPaul Saab 			backward(wscroll, 0, 0);
1503a5f0fb15SPaul Saab 			break;
1504a5f0fb15SPaul Saab 
1505a5f0fb15SPaul Saab 		case A_FREPAINT:
1506a5f0fb15SPaul Saab 			/*
1507a5f0fb15SPaul Saab 			 * Flush buffers, then repaint screen.
1508a5f0fb15SPaul Saab 			 * Don't flush the buffers on a pipe!
1509a5f0fb15SPaul Saab 			 */
1510423c5ce5SXin LI 			clear_buffers();
1511a5f0fb15SPaul Saab 			/* FALLTHRU */
1512a5f0fb15SPaul Saab 		case A_REPAINT:
1513a5f0fb15SPaul Saab 			/*
1514a5f0fb15SPaul Saab 			 * Repaint screen.
1515a5f0fb15SPaul Saab 			 */
1516a5f0fb15SPaul Saab 			cmd_exec();
1517a5f0fb15SPaul Saab 			repaint();
1518a5f0fb15SPaul Saab 			break;
1519a5f0fb15SPaul Saab 
1520a5f0fb15SPaul Saab 		case A_GOLINE:
1521a5f0fb15SPaul Saab 			/*
1522a5f0fb15SPaul Saab 			 * Go to line N, default beginning of file.
15232235c7feSXin LI 			 * If N <= 0, ignore jump_sline in order to avoid
15242235c7feSXin LI 			 * empty lines before the beginning of the file.
1525a5f0fb15SPaul Saab 			 */
15262235c7feSXin LI 			save_jump_sline = jump_sline;
1527a5f0fb15SPaul Saab 			if (number <= 0)
15282235c7feSXin LI 			{
1529a5f0fb15SPaul Saab 				number = 1;
15302235c7feSXin LI 				jump_sline = 0;
15312235c7feSXin LI 			}
1532a5f0fb15SPaul Saab 			cmd_exec();
1533a5f0fb15SPaul Saab 			jump_back(number);
15342235c7feSXin LI 			jump_sline = save_jump_sline;
1535a5f0fb15SPaul Saab 			break;
1536a5f0fb15SPaul Saab 
1537a5f0fb15SPaul Saab 		case A_PERCENT:
1538a5f0fb15SPaul Saab 			/*
1539a5f0fb15SPaul Saab 			 * Go to a specified percentage into the file.
1540a5f0fb15SPaul Saab 			 */
1541a5f0fb15SPaul Saab 			if (number < 0)
1542720c436cSXin LI 			{
1543a5f0fb15SPaul Saab 				number = 0;
1544720c436cSXin LI 				fraction = 0;
1545720c436cSXin LI 			}
1546b7780dbeSXin LI 			if (number > 100 || (number == 100 && fraction != 0))
1547720c436cSXin LI 			{
1548a5f0fb15SPaul Saab 				number = 100;
1549720c436cSXin LI 				fraction = 0;
1550720c436cSXin LI 			}
1551a5f0fb15SPaul Saab 			cmd_exec();
1552720c436cSXin LI 			jump_percent((int) number, fraction);
1553a5f0fb15SPaul Saab 			break;
1554a5f0fb15SPaul Saab 
1555a5f0fb15SPaul Saab 		case A_GOEND:
1556a5f0fb15SPaul Saab 			/*
1557a5f0fb15SPaul Saab 			 * Go to line N, default end of file.
1558a5f0fb15SPaul Saab 			 */
1559a5f0fb15SPaul Saab 			cmd_exec();
1560a5f0fb15SPaul Saab 			if (number <= 0)
1561a5f0fb15SPaul Saab 				jump_forw();
1562a5f0fb15SPaul Saab 			else
1563a5f0fb15SPaul Saab 				jump_back(number);
1564a5f0fb15SPaul Saab 			break;
1565a5f0fb15SPaul Saab 
1566a15691bfSXin LI 		case A_GOEND_BUF:
1567a15691bfSXin LI 			/*
1568a15691bfSXin LI 			 * Go to line N, default last buffered byte.
1569a15691bfSXin LI 			 */
1570a15691bfSXin LI 			cmd_exec();
1571a15691bfSXin LI 			if (number <= 0)
1572a15691bfSXin LI 				jump_forw_buffered();
1573a15691bfSXin LI 			else
1574a15691bfSXin LI 				jump_back(number);
1575a15691bfSXin LI 			break;
1576a15691bfSXin LI 
1577a5f0fb15SPaul Saab 		case A_GOPOS:
1578a5f0fb15SPaul Saab 			/*
1579a5f0fb15SPaul Saab 			 * Go to a specified byte position in the file.
1580a5f0fb15SPaul Saab 			 */
1581a5f0fb15SPaul Saab 			cmd_exec();
1582a5f0fb15SPaul Saab 			if (number < 0)
1583a5f0fb15SPaul Saab 				number = 0;
1584a5f0fb15SPaul Saab 			jump_line_loc((POSITION) number, jump_sline);
1585a5f0fb15SPaul Saab 			break;
1586a5f0fb15SPaul Saab 
1587a5f0fb15SPaul Saab 		case A_STAT:
1588a5f0fb15SPaul Saab 			/*
1589a5f0fb15SPaul Saab 			 * Print file name, etc.
1590a5f0fb15SPaul Saab 			 */
1591a5f0fb15SPaul Saab 			if (ch_getflags() & CH_HELPFILE)
1592a5f0fb15SPaul Saab 				break;
1593a5f0fb15SPaul Saab 			cmd_exec();
1594a5f0fb15SPaul Saab 			parg.p_string = eq_message();
1595a5f0fb15SPaul Saab 			error("%s", &parg);
1596a5f0fb15SPaul Saab 			break;
1597a5f0fb15SPaul Saab 
1598a5f0fb15SPaul Saab 		case A_VERSION:
1599a5f0fb15SPaul Saab 			/*
16002235c7feSXin LI 			 * Print version number.
1601a5f0fb15SPaul Saab 			 */
1602a5f0fb15SPaul Saab 			cmd_exec();
1603a5f0fb15SPaul Saab 			dispversion();
1604a5f0fb15SPaul Saab 			break;
1605a5f0fb15SPaul Saab 
1606a5f0fb15SPaul Saab 		case A_QUIT:
1607a5f0fb15SPaul Saab 			/*
1608a5f0fb15SPaul Saab 			 * Exit.
1609a5f0fb15SPaul Saab 			 */
1610a5f0fb15SPaul Saab 			if (curr_ifile != NULL_IFILE &&
1611a5f0fb15SPaul Saab 			    ch_getflags() & CH_HELPFILE)
1612a5f0fb15SPaul Saab 			{
1613a5f0fb15SPaul Saab 				/*
1614a5f0fb15SPaul Saab 				 * Quit while viewing the help file
1615a5f0fb15SPaul Saab 				 * just means return to viewing the
1616a5f0fb15SPaul Saab 				 * previous file.
1617a5f0fb15SPaul Saab 				 */
161889dd99dcSXin LI 				hshift = save_hshift;
1619a15691bfSXin LI 				bs_mode = save_bs_mode;
1620*d713e089SXin LI 				proc_backspace = save_proc_backspace;
1621a5f0fb15SPaul Saab 				if (edit_prev(1) == 0)
1622a5f0fb15SPaul Saab 					break;
1623a5f0fb15SPaul Saab 			}
1624a5f0fb15SPaul Saab 			if (extra != NULL)
1625a5f0fb15SPaul Saab 				quit(*extra);
1626a5f0fb15SPaul Saab 			quit(QUIT_OK);
1627a5f0fb15SPaul Saab 			break;
1628a5f0fb15SPaul Saab 
1629a5f0fb15SPaul Saab /*
1630a5f0fb15SPaul Saab  * Define abbreviation for a commonly used sequence below.
1631a5f0fb15SPaul Saab  */
1632423c5ce5SXin LI #define DO_SEARCH() \
1633423c5ce5SXin LI 			if (number <= 0) number = 1;    \
1634a5f0fb15SPaul Saab 			mca_search();                   \
1635a5f0fb15SPaul Saab 			cmd_exec();                     \
1636a15691bfSXin LI 			multi_search((char *)NULL, (int) number, 0);
1637a5f0fb15SPaul Saab 
1638a5f0fb15SPaul Saab 		case A_F_SEARCH:
1639a5f0fb15SPaul Saab 			/*
1640a5f0fb15SPaul Saab 			 * Search forward for a pattern.
1641a5f0fb15SPaul Saab 			 * Get the first char of the pattern.
1642a5f0fb15SPaul Saab 			 */
164395270f73SXin LI 			search_type = SRCH_FORW | def_search_type;
1644a5f0fb15SPaul Saab 			if (number <= 0)
1645a5f0fb15SPaul Saab 				number = 1;
1646a5f0fb15SPaul Saab 			mca_search();
1647a5f0fb15SPaul Saab 			c = getcc();
1648a5f0fb15SPaul Saab 			goto again;
1649a5f0fb15SPaul Saab 
1650a5f0fb15SPaul Saab 		case A_B_SEARCH:
1651a5f0fb15SPaul Saab 			/*
1652a5f0fb15SPaul Saab 			 * Search backward for a pattern.
1653a5f0fb15SPaul Saab 			 * Get the first char of the pattern.
1654a5f0fb15SPaul Saab 			 */
165595270f73SXin LI 			search_type = SRCH_BACK | def_search_type;
1656a5f0fb15SPaul Saab 			if (number <= 0)
1657a5f0fb15SPaul Saab 				number = 1;
1658a5f0fb15SPaul Saab 			mca_search();
1659a5f0fb15SPaul Saab 			c = getcc();
1660a5f0fb15SPaul Saab 			goto again;
1661a5f0fb15SPaul Saab 
16627374caaaSXin LI 		case A_FILTER:
16637374caaaSXin LI #if HILITE_SEARCH
16647374caaaSXin LI 			search_type = SRCH_FORW | SRCH_FILTER;
16657374caaaSXin LI 			mca_search();
16667374caaaSXin LI 			c = getcc();
16677374caaaSXin LI 			goto again;
16687374caaaSXin LI #else
16697374caaaSXin LI 			error("Command not available", NULL_PARG);
16707374caaaSXin LI 			break;
16717374caaaSXin LI #endif
16727374caaaSXin LI 
1673a5f0fb15SPaul Saab 		case A_AGAIN_SEARCH:
1674a5f0fb15SPaul Saab 			/*
1675a5f0fb15SPaul Saab 			 * Repeat previous search.
1676a5f0fb15SPaul Saab 			 */
1677*d713e089SXin LI 			search_type = last_search_type;
1678a5f0fb15SPaul Saab 			DO_SEARCH();
1679a5f0fb15SPaul Saab 			break;
1680a5f0fb15SPaul Saab 
1681a5f0fb15SPaul Saab 		case A_T_AGAIN_SEARCH:
1682a5f0fb15SPaul Saab 			/*
1683a5f0fb15SPaul Saab 			 * Repeat previous search, multiple files.
1684a5f0fb15SPaul Saab 			 */
1685*d713e089SXin LI 			search_type = last_search_type | SRCH_PAST_EOF;
1686a5f0fb15SPaul Saab 			DO_SEARCH();
1687a5f0fb15SPaul Saab 			break;
1688a5f0fb15SPaul Saab 
1689a5f0fb15SPaul Saab 		case A_REVERSE_SEARCH:
1690a5f0fb15SPaul Saab 			/*
1691a5f0fb15SPaul Saab 			 * Repeat previous search, in reverse direction.
1692a5f0fb15SPaul Saab 			 */
1693*d713e089SXin LI 			save_search_type = search_type = last_search_type;
1694a5f0fb15SPaul Saab 			search_type = SRCH_REVERSE(search_type);
1695a5f0fb15SPaul Saab 			DO_SEARCH();
1696*d713e089SXin LI 			last_search_type = save_search_type;
1697a5f0fb15SPaul Saab 			break;
1698a5f0fb15SPaul Saab 
1699a5f0fb15SPaul Saab 		case A_T_REVERSE_SEARCH:
1700a5f0fb15SPaul Saab 			/*
1701a5f0fb15SPaul Saab 			 * Repeat previous search,
1702a5f0fb15SPaul Saab 			 * multiple files in reverse direction.
1703a5f0fb15SPaul Saab 			 */
1704*d713e089SXin LI 			save_search_type = search_type = last_search_type;
1705*d713e089SXin LI 			search_type = SRCH_REVERSE(search_type) | SRCH_PAST_EOF;
1706a5f0fb15SPaul Saab 			DO_SEARCH();
1707*d713e089SXin LI 			last_search_type = save_search_type;
1708a5f0fb15SPaul Saab 			break;
1709a5f0fb15SPaul Saab 
1710a5f0fb15SPaul Saab 		case A_UNDO_SEARCH:
17112235c7feSXin LI 		case A_CLR_SEARCH:
1712b2ea2440SXin LI 			/*
1713b2ea2440SXin LI 			 * Clear search string highlighting.
1714b2ea2440SXin LI 			 */
17152235c7feSXin LI 			undo_search(action == A_CLR_SEARCH);
1716a5f0fb15SPaul Saab 			break;
1717a5f0fb15SPaul Saab 
1718a5f0fb15SPaul Saab 		case A_HELP:
1719a5f0fb15SPaul Saab 			/*
1720a5f0fb15SPaul Saab 			 * Help.
1721a5f0fb15SPaul Saab 			 */
1722a5f0fb15SPaul Saab 			if (ch_getflags() & CH_HELPFILE)
1723a5f0fb15SPaul Saab 				break;
1724a5f0fb15SPaul Saab 			cmd_exec();
172589dd99dcSXin LI 			save_hshift = hshift;
172689dd99dcSXin LI 			hshift = 0;
1727a15691bfSXin LI 			save_bs_mode = bs_mode;
1728a15691bfSXin LI 			bs_mode = BS_SPECIAL;
1729*d713e089SXin LI 			save_proc_backspace = proc_backspace;
1730*d713e089SXin LI 			proc_backspace = OPT_OFF;
1731a5f0fb15SPaul Saab 			(void) edit(FAKE_HELPFILE);
1732a5f0fb15SPaul Saab 			break;
1733a5f0fb15SPaul Saab 
1734a5f0fb15SPaul Saab 		case A_EXAMINE:
1735a5f0fb15SPaul Saab 			/*
1736a5f0fb15SPaul Saab 			 * Edit a new file.  Get the filename.
1737a5f0fb15SPaul Saab 			 */
1738b2ea2440SXin LI #if EXAMINE
1739b2ea2440SXin LI 			if (!secure)
1740a5f0fb15SPaul Saab 			{
1741dd3bd0edSDimitry Andric 				start_mca(A_EXAMINE, "Examine: ", ml_examine, 0);
1742a5f0fb15SPaul Saab 				c = getcc();
1743a5f0fb15SPaul Saab 				goto again;
1744b2ea2440SXin LI 			}
1745b2ea2440SXin LI #endif
1746a5f0fb15SPaul Saab 			error("Command not available", NULL_PARG);
1747a5f0fb15SPaul Saab 			break;
1748a5f0fb15SPaul Saab 
1749a5f0fb15SPaul Saab 		case A_VISUAL:
1750a5f0fb15SPaul Saab 			/*
1751a5f0fb15SPaul Saab 			 * Invoke an editor on the input file.
1752a5f0fb15SPaul Saab 			 */
1753a5f0fb15SPaul Saab #if EDITOR
1754b2ea2440SXin LI 			if (!secure)
1755a5f0fb15SPaul Saab 			{
1756a5f0fb15SPaul Saab 				if (ch_getflags() & CH_HELPFILE)
1757a5f0fb15SPaul Saab 					break;
1758a5f0fb15SPaul Saab 				if (strcmp(get_filename(curr_ifile), "-") == 0)
1759a5f0fb15SPaul Saab 				{
1760a5f0fb15SPaul Saab 					error("Cannot edit standard input", NULL_PARG);
1761a5f0fb15SPaul Saab 					break;
1762a5f0fb15SPaul Saab 				}
1763b2ea2440SXin LI 				if (get_altfilename(curr_ifile) != NULL)
1764a5f0fb15SPaul Saab 				{
176589dd99dcSXin LI 					error("WARNING: This file was viewed via LESSOPEN",
1766a5f0fb15SPaul Saab 						NULL_PARG);
1767a5f0fb15SPaul Saab 				}
1768dd3bd0edSDimitry Andric 				start_mca(A_SHELL, "!", ml_shell, 0);
1769a5f0fb15SPaul Saab 				/*
1770a5f0fb15SPaul Saab 				 * Expand the editor prototype string
1771a5f0fb15SPaul Saab 				 * and pass it to the system to execute.
1772a5f0fb15SPaul Saab 				 * (Make sure the screen is displayed so the
1773a5f0fb15SPaul Saab 				 * expansion of "+%lm" works.)
1774a5f0fb15SPaul Saab 				 */
1775a5f0fb15SPaul Saab 				make_display();
1776a5f0fb15SPaul Saab 				cmd_exec();
177795270f73SXin LI 				lsystem(pr_expand(editproto), (char*)NULL);
1778a5f0fb15SPaul Saab 				break;
1779b2ea2440SXin LI 			}
1780b2ea2440SXin LI #endif
1781a5f0fb15SPaul Saab 			error("Command not available", NULL_PARG);
1782a5f0fb15SPaul Saab 			break;
1783a5f0fb15SPaul Saab 
1784a5f0fb15SPaul Saab 		case A_NEXT_FILE:
1785a5f0fb15SPaul Saab 			/*
1786a5f0fb15SPaul Saab 			 * Examine next file.
1787a5f0fb15SPaul Saab 			 */
17881ede1615STim J. Robbins #if TAGS
17898fd4165cSPaul Saab 			if (ntags())
17908fd4165cSPaul Saab 			{
17918fd4165cSPaul Saab 				error("No next file", NULL_PARG);
17928fd4165cSPaul Saab 				break;
17938fd4165cSPaul Saab 			}
17941ede1615STim J. Robbins #endif
1795a5f0fb15SPaul Saab 			if (number <= 0)
1796a5f0fb15SPaul Saab 				number = 1;
17971ede1615STim J. Robbins 			if (edit_next((int) number))
1798a5f0fb15SPaul Saab 			{
17997374caaaSXin LI 				if (get_quit_at_eof() && eof_displayed() &&
1800a5f0fb15SPaul Saab 				    !(ch_getflags() & CH_HELPFILE))
1801a5f0fb15SPaul Saab 					quit(QUIT_OK);
1802a5f0fb15SPaul Saab 				parg.p_string = (number > 1) ? "(N-th) " : "";
1803a5f0fb15SPaul Saab 				error("No %snext file", &parg);
1804a5f0fb15SPaul Saab 			}
1805a5f0fb15SPaul Saab 			break;
1806a5f0fb15SPaul Saab 
1807a5f0fb15SPaul Saab 		case A_PREV_FILE:
1808a5f0fb15SPaul Saab 			/*
1809a5f0fb15SPaul Saab 			 * Examine previous file.
1810a5f0fb15SPaul Saab 			 */
18111ede1615STim J. Robbins #if TAGS
18128fd4165cSPaul Saab 			if (ntags())
18138fd4165cSPaul Saab 			{
18148fd4165cSPaul Saab 				error("No previous file", NULL_PARG);
18158fd4165cSPaul Saab 				break;
18168fd4165cSPaul Saab 			}
18171ede1615STim J. Robbins #endif
1818a5f0fb15SPaul Saab 			if (number <= 0)
1819a5f0fb15SPaul Saab 				number = 1;
18201ede1615STim J. Robbins 			if (edit_prev((int) number))
1821a5f0fb15SPaul Saab 			{
1822a5f0fb15SPaul Saab 				parg.p_string = (number > 1) ? "(N-th) " : "";
1823a5f0fb15SPaul Saab 				error("No %sprevious file", &parg);
1824a5f0fb15SPaul Saab 			}
1825a5f0fb15SPaul Saab 			break;
1826a5f0fb15SPaul Saab 
18278fd4165cSPaul Saab 		case A_NEXT_TAG:
1828b2ea2440SXin LI 			/*
1829b2ea2440SXin LI 			 * Jump to the next tag in the current tag list.
1830b2ea2440SXin LI 			 */
18311ede1615STim J. Robbins #if TAGS
18328fd4165cSPaul Saab 			if (number <= 0)
18338fd4165cSPaul Saab 				number = 1;
18341ede1615STim J. Robbins 			tagfile = nexttag((int) number);
18358fd4165cSPaul Saab 			if (tagfile == NULL)
18368fd4165cSPaul Saab 			{
18378fd4165cSPaul Saab 				error("No next tag", NULL_PARG);
18388fd4165cSPaul Saab 				break;
18398fd4165cSPaul Saab 			}
1840b2ea2440SXin LI 			cmd_exec();
18418fd4165cSPaul Saab 			if (edit(tagfile) == 0)
18428fd4165cSPaul Saab 			{
18438fd4165cSPaul Saab 				POSITION pos = tagsearch();
18448fd4165cSPaul Saab 				if (pos != NULL_POSITION)
18458fd4165cSPaul Saab 					jump_loc(pos, jump_sline);
18468fd4165cSPaul Saab 			}
18471ede1615STim J. Robbins #else
18481ede1615STim J. Robbins 			error("Command not available", NULL_PARG);
18491ede1615STim J. Robbins #endif
18508fd4165cSPaul Saab 			break;
18518fd4165cSPaul Saab 
18528fd4165cSPaul Saab 		case A_PREV_TAG:
1853b2ea2440SXin LI 			/*
1854b2ea2440SXin LI 			 * Jump to the previous tag in the current tag list.
1855b2ea2440SXin LI 			 */
18561ede1615STim J. Robbins #if TAGS
18578fd4165cSPaul Saab 			if (number <= 0)
18588fd4165cSPaul Saab 				number = 1;
18591ede1615STim J. Robbins 			tagfile = prevtag((int) number);
18608fd4165cSPaul Saab 			if (tagfile == NULL)
18618fd4165cSPaul Saab 			{
18628fd4165cSPaul Saab 				error("No previous tag", NULL_PARG);
18638fd4165cSPaul Saab 				break;
18648fd4165cSPaul Saab 			}
1865b2ea2440SXin LI 			cmd_exec();
18668fd4165cSPaul Saab 			if (edit(tagfile) == 0)
18678fd4165cSPaul Saab 			{
18688fd4165cSPaul Saab 				POSITION pos = tagsearch();
18698fd4165cSPaul Saab 				if (pos != NULL_POSITION)
18708fd4165cSPaul Saab 					jump_loc(pos, jump_sline);
18718fd4165cSPaul Saab 			}
18721ede1615STim J. Robbins #else
18731ede1615STim J. Robbins 			error("Command not available", NULL_PARG);
18741ede1615STim J. Robbins #endif
18758fd4165cSPaul Saab 			break;
18768fd4165cSPaul Saab 
1877a5f0fb15SPaul Saab 		case A_INDEX_FILE:
1878a5f0fb15SPaul Saab 			/*
1879a5f0fb15SPaul Saab 			 * Examine a particular file.
1880a5f0fb15SPaul Saab 			 */
1881a5f0fb15SPaul Saab 			if (number <= 0)
1882a5f0fb15SPaul Saab 				number = 1;
18831ede1615STim J. Robbins 			if (edit_index((int) number))
1884a5f0fb15SPaul Saab 				error("No such file", NULL_PARG);
1885a5f0fb15SPaul Saab 			break;
1886a5f0fb15SPaul Saab 
1887a5f0fb15SPaul Saab 		case A_REMOVE_FILE:
1888b2ea2440SXin LI 			/*
1889b2ea2440SXin LI 			 * Remove a file from the input file list.
1890b2ea2440SXin LI 			 */
1891a5f0fb15SPaul Saab 			if (ch_getflags() & CH_HELPFILE)
1892a5f0fb15SPaul Saab 				break;
1893a5f0fb15SPaul Saab 			old_ifile = curr_ifile;
1894a5f0fb15SPaul Saab 			new_ifile = getoff_ifile(curr_ifile);
1895a5f0fb15SPaul Saab 			if (new_ifile == NULL_IFILE)
1896a5f0fb15SPaul Saab 			{
1897a5f0fb15SPaul Saab 				bell();
1898a5f0fb15SPaul Saab 				break;
1899a5f0fb15SPaul Saab 			}
1900a5f0fb15SPaul Saab 			if (edit_ifile(new_ifile) != 0)
1901a5f0fb15SPaul Saab 			{
1902a5f0fb15SPaul Saab 				reedit_ifile(old_ifile);
1903a5f0fb15SPaul Saab 				break;
1904a5f0fb15SPaul Saab 			}
1905a5f0fb15SPaul Saab 			del_ifile(old_ifile);
1906a5f0fb15SPaul Saab 			break;
1907a5f0fb15SPaul Saab 
1908a5f0fb15SPaul Saab 		case A_OPT_TOGGLE:
1909b2ea2440SXin LI 			/*
1910b2ea2440SXin LI 			 * Change the setting of an  option.
1911b2ea2440SXin LI 			 */
1912a5f0fb15SPaul Saab 			optflag = OPT_TOGGLE;
1913a5f0fb15SPaul Saab 			optgetname = FALSE;
1914a5f0fb15SPaul Saab 			mca_opt_toggle();
1915a5f0fb15SPaul Saab 			c = getcc();
19166f26c71dSXin LI 			cbuf = opt_toggle_disallowed(c);
19176f26c71dSXin LI 			if (cbuf != NULL)
19186f26c71dSXin LI 			{
19196f26c71dSXin LI 				error(cbuf, NULL_PARG);
19206f26c71dSXin LI 				break;
19216f26c71dSXin LI 			}
1922a5f0fb15SPaul Saab 			goto again;
1923a5f0fb15SPaul Saab 
1924a5f0fb15SPaul Saab 		case A_DISP_OPTION:
1925a5f0fb15SPaul Saab 			/*
1926b2ea2440SXin LI 			 * Report the setting of an option.
1927a5f0fb15SPaul Saab 			 */
1928a5f0fb15SPaul Saab 			optflag = OPT_NO_TOGGLE;
1929a5f0fb15SPaul Saab 			optgetname = FALSE;
1930a5f0fb15SPaul Saab 			mca_opt_toggle();
1931a5f0fb15SPaul Saab 			c = getcc();
1932a5f0fb15SPaul Saab 			goto again;
1933a5f0fb15SPaul Saab 
1934a5f0fb15SPaul Saab 		case A_FIRSTCMD:
1935a5f0fb15SPaul Saab 			/*
1936a5f0fb15SPaul Saab 			 * Set an initial command for new files.
1937a5f0fb15SPaul Saab 			 */
1938a5f0fb15SPaul Saab 			start_mca(A_FIRSTCMD, "+", (void*)NULL, 0);
1939a5f0fb15SPaul Saab 			c = getcc();
1940a5f0fb15SPaul Saab 			goto again;
1941a5f0fb15SPaul Saab 
1942a5f0fb15SPaul Saab 		case A_SHELL:
1943*d713e089SXin LI 		case A_PSHELL:
1944a5f0fb15SPaul Saab 			/*
1945a5f0fb15SPaul Saab 			 * Shell escape.
1946a5f0fb15SPaul Saab 			 */
1947a5f0fb15SPaul Saab #if SHELL_ESCAPE
1948b2ea2440SXin LI 			if (!secure)
1949a5f0fb15SPaul Saab 			{
1950*d713e089SXin LI 				start_mca(action, (action == A_SHELL) ? "!" : "#", ml_shell, 0);
1951a5f0fb15SPaul Saab 				c = getcc();
1952a5f0fb15SPaul Saab 				goto again;
1953b2ea2440SXin LI 			}
1954b2ea2440SXin LI #endif
1955a5f0fb15SPaul Saab 			error("Command not available", NULL_PARG);
1956a5f0fb15SPaul Saab 			break;
1957a5f0fb15SPaul Saab 
1958a5f0fb15SPaul Saab 		case A_SETMARK:
1959b2ea2440SXin LI 		case A_SETMARKBOT:
1960a5f0fb15SPaul Saab 			/*
1961a5f0fb15SPaul Saab 			 * Set a mark.
1962a5f0fb15SPaul Saab 			 */
1963a5f0fb15SPaul Saab 			if (ch_getflags() & CH_HELPFILE)
1964a5f0fb15SPaul Saab 				break;
1965b2ea2440SXin LI 			start_mca(A_SETMARK, "set mark: ", (void*)NULL, 0);
1966a5f0fb15SPaul Saab 			c = getcc();
1967b2ea2440SXin LI 			if (is_erase_char(c) || is_newline_char(c))
1968a5f0fb15SPaul Saab 				break;
1969b2ea2440SXin LI 			setmark(c, action == A_SETMARKBOT ? BOTTOM : TOP);
1970b2ea2440SXin LI 			repaint();
1971b2ea2440SXin LI 			break;
1972b2ea2440SXin LI 
1973b2ea2440SXin LI 		case A_CLRMARK:
1974b2ea2440SXin LI 			/*
1975b2ea2440SXin LI 			 * Clear a mark.
1976b2ea2440SXin LI 			 */
1977b2ea2440SXin LI 			start_mca(A_CLRMARK, "clear mark: ", (void*)NULL, 0);
1978b2ea2440SXin LI 			c = getcc();
1979b2ea2440SXin LI 			if (is_erase_char(c) || is_newline_char(c))
1980b2ea2440SXin LI 				break;
1981b2ea2440SXin LI 			clrmark(c);
1982b2ea2440SXin LI 			repaint();
1983a5f0fb15SPaul Saab 			break;
1984a5f0fb15SPaul Saab 
1985a5f0fb15SPaul Saab 		case A_GOMARK:
1986a5f0fb15SPaul Saab 			/*
1987b2ea2440SXin LI 			 * Jump to a marked position.
1988a5f0fb15SPaul Saab 			 */
1989a5f0fb15SPaul Saab 			start_mca(A_GOMARK, "goto mark: ", (void*)NULL, 0);
1990a5f0fb15SPaul Saab 			c = getcc();
1991b2ea2440SXin LI 			if (is_erase_char(c) || is_newline_char(c))
1992a5f0fb15SPaul Saab 				break;
19937374caaaSXin LI 			cmd_exec();
1994a5f0fb15SPaul Saab 			gomark(c);
1995a5f0fb15SPaul Saab 			break;
1996a5f0fb15SPaul Saab 
1997a5f0fb15SPaul Saab 		case A_PIPE:
1998b2ea2440SXin LI 			/*
1999b2ea2440SXin LI 			 * Write part of the input to a pipe to a shell command.
2000b2ea2440SXin LI 			 */
2001a5f0fb15SPaul Saab #if PIPEC
2002b2ea2440SXin LI 			if (!secure)
2003a5f0fb15SPaul Saab 			{
2004a5f0fb15SPaul Saab 				start_mca(A_PIPE, "|mark: ", (void*)NULL, 0);
2005a5f0fb15SPaul Saab 				c = getcc();
2006b2ea2440SXin LI 				if (is_erase_char(c))
2007a5f0fb15SPaul Saab 					break;
2008b2ea2440SXin LI 				if (is_newline_char(c))
2009a5f0fb15SPaul Saab 					c = '.';
2010a5f0fb15SPaul Saab 				if (badmark(c))
2011a5f0fb15SPaul Saab 					break;
2012a5f0fb15SPaul Saab 				pipec = c;
2013dd3bd0edSDimitry Andric 				start_mca(A_PIPE, "!", ml_shell, 0);
2014a5f0fb15SPaul Saab 				c = getcc();
2015a5f0fb15SPaul Saab 				goto again;
2016b2ea2440SXin LI 			}
2017b2ea2440SXin LI #endif
2018a5f0fb15SPaul Saab 			error("Command not available", NULL_PARG);
2019a5f0fb15SPaul Saab 			break;
2020a5f0fb15SPaul Saab 
2021a5f0fb15SPaul Saab 		case A_B_BRACKET:
2022a5f0fb15SPaul Saab 		case A_F_BRACKET:
2023a5f0fb15SPaul Saab 			start_mca(action, "Brackets: ", (void*)NULL, 0);
2024a5f0fb15SPaul Saab 			c = getcc();
2025a5f0fb15SPaul Saab 			goto again;
2026a5f0fb15SPaul Saab 
2027a5f0fb15SPaul Saab 		case A_LSHIFT:
2028b2ea2440SXin LI 			/*
2029b2ea2440SXin LI 			 * Shift view left.
2030b2ea2440SXin LI 			 */
20318fd4165cSPaul Saab 			if (number > 0)
20328fd4165cSPaul Saab 				shift_count = number;
20338fd4165cSPaul Saab 			else
203415596da4SPaul Saab 				number = (shift_count > 0) ?
203515596da4SPaul Saab 					shift_count : sc_width / 2;
2036a5f0fb15SPaul Saab 			if (number > hshift)
2037a5f0fb15SPaul Saab 				number = hshift;
2038a5f0fb15SPaul Saab 			hshift -= number;
2039a5f0fb15SPaul Saab 			screen_trashed = 1;
2040a5f0fb15SPaul Saab 			break;
2041a5f0fb15SPaul Saab 
2042a5f0fb15SPaul Saab 		case A_RSHIFT:
2043b2ea2440SXin LI 			/*
2044b2ea2440SXin LI 			 * Shift view right.
2045b2ea2440SXin LI 			 */
20468fd4165cSPaul Saab 			if (number > 0)
20478fd4165cSPaul Saab 				shift_count = number;
20488fd4165cSPaul Saab 			else
204915596da4SPaul Saab 				number = (shift_count > 0) ?
205015596da4SPaul Saab 					shift_count : sc_width / 2;
2051a5f0fb15SPaul Saab 			hshift += number;
2052a5f0fb15SPaul Saab 			screen_trashed = 1;
2053a5f0fb15SPaul Saab 			break;
2054a5f0fb15SPaul Saab 
2055f6b74a7dSXin LI 		case A_LLSHIFT:
2056b2ea2440SXin LI 			/*
2057b2ea2440SXin LI 			 * Shift view left to margin.
2058b2ea2440SXin LI 			 */
2059f6b74a7dSXin LI 			hshift = 0;
2060f6b74a7dSXin LI 			screen_trashed = 1;
2061f6b74a7dSXin LI 			break;
2062f6b74a7dSXin LI 
2063f6b74a7dSXin LI 		case A_RRSHIFT:
2064b2ea2440SXin LI 			/*
2065b2ea2440SXin LI 			 * Shift view right to view rightmost char on screen.
2066b2ea2440SXin LI 			 */
2067f6b74a7dSXin LI 			hshift = rrshift();
2068f6b74a7dSXin LI 			screen_trashed = 1;
2069f6b74a7dSXin LI 			break;
2070f6b74a7dSXin LI 
2071a5f0fb15SPaul Saab 		case A_PREFIX:
2072a5f0fb15SPaul Saab 			/*
2073a5f0fb15SPaul Saab 			 * The command is incomplete (more chars are needed).
2074a5f0fb15SPaul Saab 			 * Display the current char, so the user knows
2075a5f0fb15SPaul Saab 			 * what's going on, and get another character.
2076a5f0fb15SPaul Saab 			 */
2077a5f0fb15SPaul Saab 			if (mca != A_PREFIX)
2078a5f0fb15SPaul Saab 			{
2079a5f0fb15SPaul Saab 				cmd_reset();
2080a5f0fb15SPaul Saab 				start_mca(A_PREFIX, " ", (void*)NULL,
2081a5f0fb15SPaul Saab 					CF_QUIT_ON_ERASE);
2082a5f0fb15SPaul Saab 				(void) cmd_char(c);
2083a5f0fb15SPaul Saab 			}
2084a5f0fb15SPaul Saab 			c = getcc();
2085a5f0fb15SPaul Saab 			goto again;
2086a5f0fb15SPaul Saab 
2087a5f0fb15SPaul Saab 		case A_NOACTION:
2088a5f0fb15SPaul Saab 			break;
2089a5f0fb15SPaul Saab 
2090a5f0fb15SPaul Saab 		default:
2091a5f0fb15SPaul Saab 			bell();
2092a5f0fb15SPaul Saab 			break;
2093a5f0fb15SPaul Saab 		}
2094a5f0fb15SPaul Saab 	}
2095a5f0fb15SPaul Saab }
2096