xref: /freebsd/contrib/less/command.c (revision b7780dbe98fc88da65024e697529ea7883064275)
1a8f92a7cSPaul Saab /* $FreeBSD$ */
2a5f0fb15SPaul Saab /*
3*b7780dbeSXin LI  * Copyright (C) 1984-2019  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;
27a5f0fb15SPaul Saab extern int squished;
28a5f0fb15SPaul Saab extern int sc_width;
29a5f0fb15SPaul Saab extern int sc_height;
30b2ea2440SXin LI extern char *kent;
31a5f0fb15SPaul Saab extern int swindow;
32a5f0fb15SPaul Saab extern int jump_sline;
33a5f0fb15SPaul Saab extern int quitting;
34a5f0fb15SPaul Saab extern int wscroll;
35a5f0fb15SPaul Saab extern int top_scroll;
36a5f0fb15SPaul Saab extern int ignore_eoi;
37a5f0fb15SPaul Saab extern int secure;
38a5f0fb15SPaul Saab extern int hshift;
39a15691bfSXin LI extern int bs_mode;
40a5f0fb15SPaul Saab extern int show_attn;
41720c436cSXin LI extern int less_is_more;
42b2ea2440SXin LI extern int status_col;
4396e55cc7SXin LI extern POSITION highest_hilite;
44b2ea2440SXin LI extern POSITION start_attnpos;
45b2ea2440SXin LI extern POSITION end_attnpos;
46a5f0fb15SPaul Saab extern char *every_first_cmd;
47a5f0fb15SPaul Saab extern char version[];
48a5f0fb15SPaul Saab extern struct scrpos initial_scrpos;
49a5f0fb15SPaul Saab extern IFILE curr_ifile;
50f6b74a7dSXin LI extern void *ml_search;
51f6b74a7dSXin LI extern void *ml_examine;
52*b7780dbeSXin LI extern int wheel_lines;
53a5f0fb15SPaul Saab #if SHELL_ESCAPE || PIPEC
54f6b74a7dSXin LI extern void *ml_shell;
55a5f0fb15SPaul Saab #endif
56a5f0fb15SPaul Saab #if EDITOR
57a5f0fb15SPaul Saab extern char *editor;
58a5f0fb15SPaul Saab extern char *editproto;
59a5f0fb15SPaul Saab #endif
60a5f0fb15SPaul Saab extern int screen_trashed;	/* The screen has been overwritten */
6115596da4SPaul Saab extern int shift_count;
62720c436cSXin LI extern int oldbot;
63720c436cSXin LI extern int forw_prompt;
64*b7780dbeSXin LI #if MSDOS_COMPILER==WIN32C
65*b7780dbeSXin LI extern int utf_mode;
66*b7780dbeSXin LI #endif
67a5f0fb15SPaul Saab 
68a5f0fb15SPaul Saab #if SHELL_ESCAPE
69a5f0fb15SPaul Saab static char *shellcmd = NULL;	/* For holding last shell command for "!!" */
70a5f0fb15SPaul Saab #endif
71a5f0fb15SPaul Saab static int mca;			/* The multicharacter command (action) */
72a5f0fb15SPaul Saab static int search_type;		/* The previous type of search */
731ede1615STim J. Robbins static LINENUM number;		/* The number typed by the user */
74720c436cSXin LI static long fraction;		/* The fractional part of the number */
7533096f16SXin LI static struct loption *curropt;
7633096f16SXin LI static int opt_lower;
77a5f0fb15SPaul Saab static int optflag;
78a5f0fb15SPaul Saab static int optgetname;
79a5f0fb15SPaul Saab static POSITION bottompos;
8089dd99dcSXin LI static int save_hshift;
81a15691bfSXin LI static int save_bs_mode;
82a5f0fb15SPaul Saab #if PIPEC
83a5f0fb15SPaul Saab static char pipec;
84a5f0fb15SPaul Saab #endif
85a5f0fb15SPaul Saab 
86b2ea2440SXin LI /* Stack of ungotten chars (via ungetcc) */
8733096f16SXin LI struct ungot {
8833096f16SXin LI 	struct ungot *ug_next;
89b2ea2440SXin LI 	LWCHAR ug_char;
9033096f16SXin LI };
9133096f16SXin LI static struct ungot* ungot = NULL;
9233096f16SXin LI 
93f6b74a7dSXin LI static void multi_search();
94a5f0fb15SPaul Saab 
95a5f0fb15SPaul Saab /*
96720c436cSXin LI  * Move the cursor to start of prompt line before executing a command.
97a5f0fb15SPaul Saab  * This looks nicer if the command takes a long time before
98a5f0fb15SPaul Saab  * updating the screen.
99a5f0fb15SPaul Saab  */
100a5f0fb15SPaul Saab 	static void
101*b7780dbeSXin LI cmd_exec(VOID_PARAM)
102a5f0fb15SPaul Saab {
103a5f0fb15SPaul Saab 	clear_attn();
104aa22b8b6SXin LI 	clear_bot();
105a5f0fb15SPaul Saab 	flush();
106a5f0fb15SPaul Saab }
107a5f0fb15SPaul Saab 
108a5f0fb15SPaul Saab /*
109*b7780dbeSXin LI  * Indicate we are reading a multi-character command.
110*b7780dbeSXin LI  */
111*b7780dbeSXin LI 	static void
112*b7780dbeSXin LI set_mca(action)
113*b7780dbeSXin LI 	int action;
114*b7780dbeSXin LI {
115*b7780dbeSXin LI 	mca = action;
116*b7780dbeSXin LI 	deinit_mouse(); /* we don't want mouse events while entering a cmd */
117*b7780dbeSXin LI 	clear_bot();
118*b7780dbeSXin LI 	clear_cmd();
119*b7780dbeSXin LI }
120*b7780dbeSXin LI 
121*b7780dbeSXin LI /*
122*b7780dbeSXin LI  * Indicate we are not reading a multi-character command.
123*b7780dbeSXin LI  */
124*b7780dbeSXin LI 	static void
125*b7780dbeSXin LI clear_mca(VOID_PARAM)
126*b7780dbeSXin LI {
127*b7780dbeSXin LI 	if (mca == 0)
128*b7780dbeSXin LI 		return;
129*b7780dbeSXin LI 	mca = 0;
130*b7780dbeSXin LI 	init_mouse();
131*b7780dbeSXin LI }
132*b7780dbeSXin LI 
133*b7780dbeSXin LI /*
134a5f0fb15SPaul Saab  * Set up the display to start a new multi-character command.
135a5f0fb15SPaul Saab  */
136a5f0fb15SPaul Saab 	static void
137f6b74a7dSXin LI start_mca(action, prompt, mlist, cmdflags)
138f6b74a7dSXin LI 	int action;
139f6b74a7dSXin LI 	constant char *prompt;
140f6b74a7dSXin LI 	void *mlist;
141f6b74a7dSXin LI 	int cmdflags;
142a5f0fb15SPaul Saab {
143*b7780dbeSXin LI 	set_mca(action);
144a5f0fb15SPaul Saab 	cmd_putstr(prompt);
145a5f0fb15SPaul Saab 	set_mlist(mlist, cmdflags);
146a5f0fb15SPaul Saab }
147a5f0fb15SPaul Saab 
148a5f0fb15SPaul Saab 	public int
149*b7780dbeSXin LI in_mca(VOID_PARAM)
150a5f0fb15SPaul Saab {
151a5f0fb15SPaul Saab 	return (mca != 0 && mca != A_PREFIX);
152a5f0fb15SPaul Saab }
153a5f0fb15SPaul Saab 
154a5f0fb15SPaul Saab /*
155a5f0fb15SPaul Saab  * Set up the display to start a new search command.
156a5f0fb15SPaul Saab  */
157a5f0fb15SPaul Saab 	static void
158*b7780dbeSXin LI mca_search(VOID_PARAM)
159a5f0fb15SPaul Saab {
1607374caaaSXin LI #if HILITE_SEARCH
1617374caaaSXin LI 	if (search_type & SRCH_FILTER)
162*b7780dbeSXin LI 		set_mca(A_FILTER);
1637374caaaSXin LI 	else
1647374caaaSXin LI #endif
165a5f0fb15SPaul Saab 	if (search_type & SRCH_FORW)
166*b7780dbeSXin LI 		set_mca(A_F_SEARCH);
167a5f0fb15SPaul Saab 	else
168*b7780dbeSXin LI 		set_mca(A_B_SEARCH);
169a5f0fb15SPaul Saab 
170a5f0fb15SPaul Saab 	if (search_type & SRCH_NO_MATCH)
171a5f0fb15SPaul Saab 		cmd_putstr("Non-match ");
172a5f0fb15SPaul Saab 	if (search_type & SRCH_FIRST_FILE)
173a5f0fb15SPaul Saab 		cmd_putstr("First-file ");
174a5f0fb15SPaul Saab 	if (search_type & SRCH_PAST_EOF)
175a5f0fb15SPaul Saab 		cmd_putstr("EOF-ignore ");
176a5f0fb15SPaul Saab 	if (search_type & SRCH_NO_MOVE)
177a5f0fb15SPaul Saab 		cmd_putstr("Keep-pos ");
178a5f0fb15SPaul Saab 	if (search_type & SRCH_NO_REGEX)
179a5f0fb15SPaul Saab 		cmd_putstr("Regex-off ");
180a5f0fb15SPaul Saab 
1817374caaaSXin LI #if HILITE_SEARCH
1827374caaaSXin LI 	if (search_type & SRCH_FILTER)
1837374caaaSXin LI 		cmd_putstr("&/");
1847374caaaSXin LI 	else
1857374caaaSXin LI #endif
186a5f0fb15SPaul Saab 	if (search_type & SRCH_FORW)
187a5f0fb15SPaul Saab 		cmd_putstr("/");
188a5f0fb15SPaul Saab 	else
189a5f0fb15SPaul Saab 		cmd_putstr("?");
190a15691bfSXin LI 	forw_prompt = 0;
191a5f0fb15SPaul Saab 	set_mlist(ml_search, 0);
192a5f0fb15SPaul Saab }
193a5f0fb15SPaul Saab 
194a5f0fb15SPaul Saab /*
195a5f0fb15SPaul Saab  * Set up the display to start a new toggle-option command.
196a5f0fb15SPaul Saab  */
197a5f0fb15SPaul Saab 	static void
198*b7780dbeSXin LI mca_opt_toggle(VOID_PARAM)
199a5f0fb15SPaul Saab {
200a5f0fb15SPaul Saab 	int no_prompt;
201a5f0fb15SPaul Saab 	int flag;
202a5f0fb15SPaul Saab 	char *dash;
203a5f0fb15SPaul Saab 
204a5f0fb15SPaul Saab 	no_prompt = (optflag & OPT_NO_PROMPT);
205a5f0fb15SPaul Saab 	flag = (optflag & ~OPT_NO_PROMPT);
206a5f0fb15SPaul Saab 	dash = (flag == OPT_NO_TOGGLE) ? "_" : "-";
207a5f0fb15SPaul Saab 
208*b7780dbeSXin LI 	set_mca(A_OPT_TOGGLE);
209a5f0fb15SPaul Saab 	cmd_putstr(dash);
210a5f0fb15SPaul Saab 	if (optgetname)
211a5f0fb15SPaul Saab 		cmd_putstr(dash);
212a5f0fb15SPaul Saab 	if (no_prompt)
213a5f0fb15SPaul Saab 		cmd_putstr("(P)");
214a5f0fb15SPaul Saab 	switch (flag)
215a5f0fb15SPaul Saab 	{
216a5f0fb15SPaul Saab 	case OPT_UNSET:
217a5f0fb15SPaul Saab 		cmd_putstr("+");
218a5f0fb15SPaul Saab 		break;
219a5f0fb15SPaul Saab 	case OPT_SET:
220a5f0fb15SPaul Saab 		cmd_putstr("!");
221a5f0fb15SPaul Saab 		break;
222a5f0fb15SPaul Saab 	}
223a15691bfSXin LI 	forw_prompt = 0;
224a5f0fb15SPaul Saab 	set_mlist(NULL, 0);
225a5f0fb15SPaul Saab }
226a5f0fb15SPaul Saab 
227a5f0fb15SPaul Saab /*
228a5f0fb15SPaul Saab  * Execute a multicharacter command.
229a5f0fb15SPaul Saab  */
230a5f0fb15SPaul Saab 	static void
231*b7780dbeSXin LI exec_mca(VOID_PARAM)
232a5f0fb15SPaul Saab {
2331ea31627SRobert Watson 	char *cbuf;
234a5f0fb15SPaul Saab 
235a5f0fb15SPaul Saab 	cmd_exec();
236a5f0fb15SPaul Saab 	cbuf = get_cmdbuf();
237a5f0fb15SPaul Saab 
238a5f0fb15SPaul Saab 	switch (mca)
239a5f0fb15SPaul Saab 	{
240a5f0fb15SPaul Saab 	case A_F_SEARCH:
241a5f0fb15SPaul Saab 	case A_B_SEARCH:
242a15691bfSXin LI 		multi_search(cbuf, (int) number, 0);
243a5f0fb15SPaul Saab 		break;
2447374caaaSXin LI #if HILITE_SEARCH
2457374caaaSXin LI 	case A_FILTER:
2467374caaaSXin LI 		search_type ^= SRCH_NO_MATCH;
2477374caaaSXin LI 		set_filter_pattern(cbuf, search_type);
2487374caaaSXin LI 		break;
2497374caaaSXin LI #endif
250a5f0fb15SPaul Saab 	case A_FIRSTCMD:
251a5f0fb15SPaul Saab 		/*
252a5f0fb15SPaul Saab 		 * Skip leading spaces or + signs in the string.
253a5f0fb15SPaul Saab 		 */
254a5f0fb15SPaul Saab 		while (*cbuf == '+' || *cbuf == ' ')
255a5f0fb15SPaul Saab 			cbuf++;
256a5f0fb15SPaul Saab 		if (every_first_cmd != NULL)
257a5f0fb15SPaul Saab 			free(every_first_cmd);
258a5f0fb15SPaul Saab 		if (*cbuf == '\0')
259a5f0fb15SPaul Saab 			every_first_cmd = NULL;
260a5f0fb15SPaul Saab 		else
261a5f0fb15SPaul Saab 			every_first_cmd = save(cbuf);
262a5f0fb15SPaul Saab 		break;
263a5f0fb15SPaul Saab 	case A_OPT_TOGGLE:
26433096f16SXin LI 		toggle_option(curropt, opt_lower, cbuf, optflag);
26533096f16SXin LI 		curropt = NULL;
266a5f0fb15SPaul Saab 		break;
267a5f0fb15SPaul Saab 	case A_F_BRACKET:
2681ede1615STim J. Robbins 		match_brac(cbuf[0], cbuf[1], 1, (int) number);
269a5f0fb15SPaul Saab 		break;
270a5f0fb15SPaul Saab 	case A_B_BRACKET:
2711ede1615STim J. Robbins 		match_brac(cbuf[1], cbuf[0], 0, (int) number);
272a5f0fb15SPaul Saab 		break;
273a5f0fb15SPaul Saab #if EXAMINE
274a5f0fb15SPaul Saab 	case A_EXAMINE:
275a5f0fb15SPaul Saab 		if (secure)
276a5f0fb15SPaul Saab 			break;
277a5f0fb15SPaul Saab 		edit_list(cbuf);
2781ede1615STim J. Robbins #if TAGS
2798fd4165cSPaul Saab 		/* If tag structure is loaded then clean it up. */
2808fd4165cSPaul Saab 		cleantags();
2811ede1615STim J. Robbins #endif
282a5f0fb15SPaul Saab 		break;
283a5f0fb15SPaul Saab #endif
284a5f0fb15SPaul Saab #if SHELL_ESCAPE
285a5f0fb15SPaul Saab 	case A_SHELL:
286a5f0fb15SPaul Saab 		/*
287a5f0fb15SPaul Saab 		 * !! just uses whatever is in shellcmd.
288a5f0fb15SPaul Saab 		 * Otherwise, copy cmdbuf to shellcmd,
289a5f0fb15SPaul Saab 		 * expanding any special characters ("%" or "#").
290a5f0fb15SPaul Saab 		 */
291a5f0fb15SPaul Saab 		if (*cbuf != '!')
292a5f0fb15SPaul Saab 		{
293a5f0fb15SPaul Saab 			if (shellcmd != NULL)
294a5f0fb15SPaul Saab 				free(shellcmd);
295a5f0fb15SPaul Saab 			shellcmd = fexpand(cbuf);
296a5f0fb15SPaul Saab 		}
297a5f0fb15SPaul Saab 
298a5f0fb15SPaul Saab 		if (secure)
299a5f0fb15SPaul Saab 			break;
300a5f0fb15SPaul Saab 		if (shellcmd == NULL)
301a5f0fb15SPaul Saab 			lsystem("", "!done");
302a5f0fb15SPaul Saab 		else
303a5f0fb15SPaul Saab 			lsystem(shellcmd, "!done");
304a5f0fb15SPaul Saab 		break;
305a5f0fb15SPaul Saab #endif
306a5f0fb15SPaul Saab #if PIPEC
307a5f0fb15SPaul Saab 	case A_PIPE:
308a5f0fb15SPaul Saab 		if (secure)
309a5f0fb15SPaul Saab 			break;
310a5f0fb15SPaul Saab 		(void) pipe_mark(pipec, cbuf);
311a5f0fb15SPaul Saab 		error("|done", NULL_PARG);
312a5f0fb15SPaul Saab 		break;
313a5f0fb15SPaul Saab #endif
314a5f0fb15SPaul Saab 	}
315a5f0fb15SPaul Saab }
316a5f0fb15SPaul Saab 
317a5f0fb15SPaul Saab /*
31833096f16SXin LI  * Is a character an erase or kill char?
319a5f0fb15SPaul Saab  */
320a5f0fb15SPaul Saab 	static int
321f6b74a7dSXin LI is_erase_char(c)
322f6b74a7dSXin LI 	int c;
323a5f0fb15SPaul Saab {
32433096f16SXin LI 	return (c == erase_char || c == erase2_char || c == kill_char);
325a5f0fb15SPaul Saab }
326a5f0fb15SPaul Saab 
327a5f0fb15SPaul Saab /*
328b2ea2440SXin LI  * Is a character a carriage return or newline?
329b2ea2440SXin LI  */
330b2ea2440SXin LI 	static int
331b2ea2440SXin LI is_newline_char(c)
332b2ea2440SXin LI 	int c;
333b2ea2440SXin LI {
334b2ea2440SXin LI 	return (c == '\n' || c == '\r');
335b2ea2440SXin LI }
336b2ea2440SXin LI 
337b2ea2440SXin LI /*
33833096f16SXin LI  * Handle the first char of an option (after the initial dash).
339a5f0fb15SPaul Saab  */
34033096f16SXin LI 	static int
341f6b74a7dSXin LI mca_opt_first_char(c)
342f6b74a7dSXin LI 	int c;
343a5f0fb15SPaul Saab {
34433096f16SXin LI 	int flag = (optflag & ~OPT_NO_PROMPT);
345a5f0fb15SPaul Saab 	if (flag == OPT_NO_TOGGLE)
346a5f0fb15SPaul Saab 	{
347a5f0fb15SPaul Saab 		switch (c)
348a5f0fb15SPaul Saab 		{
349a5f0fb15SPaul Saab 		case '_':
350a5f0fb15SPaul Saab 			/* "__" = long option name. */
351a5f0fb15SPaul Saab 			optgetname = TRUE;
352a5f0fb15SPaul Saab 			mca_opt_toggle();
353a5f0fb15SPaul Saab 			return (MCA_MORE);
354a5f0fb15SPaul Saab 		}
355a5f0fb15SPaul Saab 	} else
356a5f0fb15SPaul Saab 	{
357a5f0fb15SPaul Saab 		switch (c)
358a5f0fb15SPaul Saab 		{
359a5f0fb15SPaul Saab 		case '+':
360a5f0fb15SPaul Saab 			/* "-+" = UNSET. */
361a5f0fb15SPaul Saab 			optflag = (flag == OPT_UNSET) ?
362a5f0fb15SPaul Saab 				OPT_TOGGLE : OPT_UNSET;
363a5f0fb15SPaul Saab 			mca_opt_toggle();
364a5f0fb15SPaul Saab 			return (MCA_MORE);
365a5f0fb15SPaul Saab 		case '!':
366a5f0fb15SPaul Saab 			/* "-!" = SET */
367a5f0fb15SPaul Saab 			optflag = (flag == OPT_SET) ?
368a5f0fb15SPaul Saab 				OPT_TOGGLE : OPT_SET;
369a5f0fb15SPaul Saab 			mca_opt_toggle();
370a5f0fb15SPaul Saab 			return (MCA_MORE);
371a5f0fb15SPaul Saab 		case CONTROL('P'):
372a5f0fb15SPaul Saab 			optflag ^= OPT_NO_PROMPT;
373a5f0fb15SPaul Saab 			mca_opt_toggle();
374a5f0fb15SPaul Saab 			return (MCA_MORE);
375a5f0fb15SPaul Saab 		case '-':
376a5f0fb15SPaul Saab 			/* "--" = long option name. */
377a5f0fb15SPaul Saab 			optgetname = TRUE;
378a5f0fb15SPaul Saab 			mca_opt_toggle();
379a5f0fb15SPaul Saab 			return (MCA_MORE);
380a5f0fb15SPaul Saab 		}
381a5f0fb15SPaul Saab 	}
38233096f16SXin LI 	/* Char was not handled here. */
38333096f16SXin LI 	return (NO_MCA);
384a5f0fb15SPaul Saab }
38533096f16SXin LI 
386a5f0fb15SPaul Saab /*
38733096f16SXin LI  * Add a char to a long option name.
38833096f16SXin LI  * See if we've got a match for an option name yet.
389a5f0fb15SPaul Saab  * If so, display the complete name and stop
390a5f0fb15SPaul Saab  * accepting chars until user hits RETURN.
391a5f0fb15SPaul Saab  */
39233096f16SXin LI 	static int
393f6b74a7dSXin LI mca_opt_nonfirst_char(c)
394f6b74a7dSXin LI 	int c;
39533096f16SXin LI {
39633096f16SXin LI 	char *p;
397a5f0fb15SPaul Saab 	char *oname;
398*b7780dbeSXin LI 	int err;
399a5f0fb15SPaul Saab 
40033096f16SXin LI 	if (curropt != NULL)
401a5f0fb15SPaul Saab 	{
402a5f0fb15SPaul Saab 		/*
403a5f0fb15SPaul Saab 		 * Already have a match for the name.
404a5f0fb15SPaul Saab 		 * Don't accept anything but erase/kill.
405a5f0fb15SPaul Saab 		 */
40633096f16SXin LI 		if (is_erase_char(c))
407a5f0fb15SPaul Saab 			return (MCA_DONE);
408a5f0fb15SPaul Saab 		return (MCA_MORE);
409a5f0fb15SPaul Saab 	}
410a5f0fb15SPaul Saab 	/*
411a5f0fb15SPaul Saab 	 * Add char to cmd buffer and try to match
412a5f0fb15SPaul Saab 	 * the option name.
413a5f0fb15SPaul Saab 	 */
414a5f0fb15SPaul Saab 	if (cmd_char(c) == CC_QUIT)
415a5f0fb15SPaul Saab 		return (MCA_DONE);
416a5f0fb15SPaul Saab 	p = get_cmdbuf();
41733096f16SXin LI 	opt_lower = ASCII_IS_LOWER(p[0]);
418*b7780dbeSXin LI 	err = 0;
419*b7780dbeSXin LI 	curropt = findopt_name(&p, &oname, &err);
42033096f16SXin LI 	if (curropt != NULL)
421a5f0fb15SPaul Saab 	{
422a5f0fb15SPaul Saab 		/*
423a5f0fb15SPaul Saab 		 * Got a match.
42433096f16SXin LI 		 * Remember the option and
425a5f0fb15SPaul Saab 		 * display the full option name.
426a5f0fb15SPaul Saab 		 */
427a5f0fb15SPaul Saab 		cmd_reset();
428a5f0fb15SPaul Saab 		mca_opt_toggle();
429a5f0fb15SPaul Saab 		for (p = oname;  *p != '\0';  p++)
430a5f0fb15SPaul Saab 		{
431a5f0fb15SPaul Saab 			c = *p;
43233096f16SXin LI 			if (!opt_lower && ASCII_IS_LOWER(c))
43389dd99dcSXin LI 				c = ASCII_TO_UPPER(c);
434a5f0fb15SPaul Saab 			if (cmd_char(c) != CC_OK)
435a5f0fb15SPaul Saab 				return (MCA_DONE);
436a5f0fb15SPaul Saab 		}
437*b7780dbeSXin LI 	} else if (err != OPT_AMBIG)
438*b7780dbeSXin LI 	{
439*b7780dbeSXin LI 		bell();
440a5f0fb15SPaul Saab 	}
441a5f0fb15SPaul Saab 	return (MCA_MORE);
442a5f0fb15SPaul Saab }
44333096f16SXin LI 
44433096f16SXin LI /*
44533096f16SXin LI  * Handle a char of an option toggle command.
44633096f16SXin LI  */
44733096f16SXin LI 	static int
448f6b74a7dSXin LI mca_opt_char(c)
449f6b74a7dSXin LI 	int c;
45033096f16SXin LI {
45133096f16SXin LI 	PARG parg;
45233096f16SXin LI 
45333096f16SXin LI 	/*
45433096f16SXin LI 	 * This may be a short option (single char),
45533096f16SXin LI 	 * or one char of a long option name,
45633096f16SXin LI 	 * or one char of the option parameter.
45733096f16SXin LI 	 */
45833096f16SXin LI 	if (curropt == NULL && len_cmdbuf() == 0)
45933096f16SXin LI 	{
46033096f16SXin LI 		int ret = mca_opt_first_char(c);
46133096f16SXin LI 		if (ret != NO_MCA)
46233096f16SXin LI 			return (ret);
46333096f16SXin LI 	}
46433096f16SXin LI 	if (optgetname)
46533096f16SXin LI 	{
46633096f16SXin LI 		/* We're getting a long option name.  */
467b2ea2440SXin LI 		if (!is_newline_char(c))
46833096f16SXin LI 			return (mca_opt_nonfirst_char(c));
46933096f16SXin LI 		if (curropt == NULL)
47033096f16SXin LI 		{
47133096f16SXin LI 			parg.p_string = get_cmdbuf();
47233096f16SXin LI 			error("There is no --%s option", &parg);
47333096f16SXin LI 			return (MCA_DONE);
47433096f16SXin LI 		}
47533096f16SXin LI 		optgetname = FALSE;
47633096f16SXin LI 		cmd_reset();
477a5f0fb15SPaul Saab 	} else
478a5f0fb15SPaul Saab 	{
47933096f16SXin LI 		if (is_erase_char(c))
48033096f16SXin LI 			return (NO_MCA);
48133096f16SXin LI 		if (curropt != NULL)
48233096f16SXin LI 			/* We're getting the option parameter. */
48333096f16SXin LI 			return (NO_MCA);
48433096f16SXin LI 		curropt = findopt(c);
48533096f16SXin LI 		if (curropt == NULL)
486a5f0fb15SPaul Saab 		{
48733096f16SXin LI 			parg.p_string = propt(c);
48833096f16SXin LI 			error("There is no %s option", &parg);
48933096f16SXin LI 			return (MCA_DONE);
49033096f16SXin LI 		}
491*b7780dbeSXin LI 		opt_lower = ASCII_IS_LOWER(c);
49233096f16SXin LI 	}
49333096f16SXin LI 	/*
49433096f16SXin LI 	 * If the option which was entered does not take a
49533096f16SXin LI 	 * parameter, toggle the option immediately,
49633096f16SXin LI 	 * so user doesn't have to hit RETURN.
49733096f16SXin LI 	 */
49833096f16SXin LI 	if ((optflag & ~OPT_NO_PROMPT) != OPT_TOGGLE ||
49933096f16SXin LI 	    !opt_has_param(curropt))
50033096f16SXin LI 	{
501*b7780dbeSXin LI 		toggle_option(curropt, opt_lower, "", optflag);
502a5f0fb15SPaul Saab 		return (MCA_DONE);
503a5f0fb15SPaul Saab 	}
504a5f0fb15SPaul Saab 	/*
50533096f16SXin LI 	 * Display a prompt appropriate for the option parameter.
506a5f0fb15SPaul Saab 	 */
50733096f16SXin LI 	start_mca(A_OPT_TOGGLE, opt_prompt(curropt), (void*)NULL, 0);
508a5f0fb15SPaul Saab 	return (MCA_MORE);
50933096f16SXin LI }
510a5f0fb15SPaul Saab 
511a5f0fb15SPaul Saab /*
51233096f16SXin LI  * Handle a char of a search command.
51333096f16SXin LI  */
51433096f16SXin LI 	static int
515f6b74a7dSXin LI mca_search_char(c)
516f6b74a7dSXin LI 	int c;
51733096f16SXin LI {
51833096f16SXin LI 	int flag = 0;
51933096f16SXin LI 
52033096f16SXin LI 	/*
521a5f0fb15SPaul Saab 	 * Certain characters as the first char of
522a5f0fb15SPaul Saab 	 * the pattern have special meaning:
523a5f0fb15SPaul Saab 	 *	!  Toggle the NO_MATCH flag
524a5f0fb15SPaul Saab 	 *	*  Toggle the PAST_EOF flag
525a5f0fb15SPaul Saab 	 *	@  Toggle the FIRST_FILE flag
526a5f0fb15SPaul Saab 	 */
527a5f0fb15SPaul Saab 	if (len_cmdbuf() > 0)
52833096f16SXin LI 		return (NO_MCA);
529a5f0fb15SPaul Saab 
530a5f0fb15SPaul Saab 	switch (c)
531a5f0fb15SPaul Saab 	{
532a5f0fb15SPaul Saab 	case '*':
533720c436cSXin LI 		if (less_is_more)
534a8f92a7cSPaul Saab 			break;
535a8f92a7cSPaul Saab 	case CONTROL('E'): /* ignore END of file */
5367374caaaSXin LI 		if (mca != A_FILTER)
537a5f0fb15SPaul Saab 			flag = SRCH_PAST_EOF;
538a5f0fb15SPaul Saab 		break;
539a5f0fb15SPaul Saab 	case '@':
540720c436cSXin LI 		if (less_is_more)
541a8f92a7cSPaul Saab 			break;
542a8f92a7cSPaul Saab 	case CONTROL('F'): /* FIRST file */
5437374caaaSXin LI 		if (mca != A_FILTER)
544a5f0fb15SPaul Saab 			flag = SRCH_FIRST_FILE;
545a5f0fb15SPaul Saab 		break;
546a5f0fb15SPaul Saab 	case CONTROL('K'): /* KEEP position */
5477374caaaSXin LI 		if (mca != A_FILTER)
548a5f0fb15SPaul Saab 			flag = SRCH_NO_MOVE;
549a5f0fb15SPaul Saab 		break;
550a5f0fb15SPaul Saab 	case CONTROL('R'): /* Don't use REGULAR EXPRESSIONS */
551a5f0fb15SPaul Saab 		flag = SRCH_NO_REGEX;
552a5f0fb15SPaul Saab 		break;
553a5f0fb15SPaul Saab 	case CONTROL('N'): /* NOT match */
554a5f0fb15SPaul Saab 	case '!':
555a5f0fb15SPaul Saab 		flag = SRCH_NO_MATCH;
556a5f0fb15SPaul Saab 		break;
557a5f0fb15SPaul Saab 	}
55833096f16SXin LI 
559a5f0fb15SPaul Saab 	if (flag != 0)
560a5f0fb15SPaul Saab 	{
561a5f0fb15SPaul Saab 		search_type ^= flag;
562a5f0fb15SPaul Saab 		mca_search();
563a5f0fb15SPaul Saab 		return (MCA_MORE);
564a5f0fb15SPaul Saab 	}
56533096f16SXin LI 	return (NO_MCA);
56633096f16SXin LI }
56733096f16SXin LI 
56833096f16SXin LI /*
56933096f16SXin LI  * Handle a character of a multi-character command.
57033096f16SXin LI  */
57133096f16SXin LI 	static int
572f6b74a7dSXin LI mca_char(c)
573f6b74a7dSXin LI 	int c;
57433096f16SXin LI {
57533096f16SXin LI 	int ret;
57633096f16SXin LI 
57733096f16SXin LI 	switch (mca)
57833096f16SXin LI 	{
57933096f16SXin LI 	case 0:
58033096f16SXin LI 		/*
58133096f16SXin LI 		 * We're not in a multicharacter command.
58233096f16SXin LI 		 */
58333096f16SXin LI 		return (NO_MCA);
58433096f16SXin LI 
58533096f16SXin LI 	case A_PREFIX:
58633096f16SXin LI 		/*
58733096f16SXin LI 		 * In the prefix of a command.
58833096f16SXin LI 		 * This not considered a multichar command
58933096f16SXin LI 		 * (even tho it uses cmdbuf, etc.).
59033096f16SXin LI 		 * It is handled in the commands() switch.
59133096f16SXin LI 		 */
59233096f16SXin LI 		return (NO_MCA);
59333096f16SXin LI 
59433096f16SXin LI 	case A_DIGIT:
59533096f16SXin LI 		/*
59633096f16SXin LI 		 * Entering digits of a number.
59733096f16SXin LI 		 * Terminated by a non-digit.
59833096f16SXin LI 		 */
59933096f16SXin LI 		if (!((c >= '0' && c <= '9') || c == '.') &&
60033096f16SXin LI 		  editchar(c, EC_PEEK|EC_NOHISTORY|EC_NOCOMPLETE|EC_NORIGHTLEFT) == A_INVALID)
60133096f16SXin LI 		{
60233096f16SXin LI 			/*
60333096f16SXin LI 			 * Not part of the number.
60433096f16SXin LI 			 * End the number and treat this char
60533096f16SXin LI 			 * as a normal command character.
60633096f16SXin LI 			 */
60733096f16SXin LI 			number = cmd_int(&fraction);
608*b7780dbeSXin LI 			clear_mca();
60933096f16SXin LI 			cmd_accept();
61033096f16SXin LI 			return (NO_MCA);
61133096f16SXin LI 		}
61233096f16SXin LI 		break;
61333096f16SXin LI 
61433096f16SXin LI 	case A_OPT_TOGGLE:
61533096f16SXin LI 		ret = mca_opt_char(c);
61633096f16SXin LI 		if (ret != NO_MCA)
61733096f16SXin LI 			return (ret);
61833096f16SXin LI 		break;
61933096f16SXin LI 
62033096f16SXin LI 	case A_F_SEARCH:
62133096f16SXin LI 	case A_B_SEARCH:
62233096f16SXin LI 	case A_FILTER:
62333096f16SXin LI 		ret = mca_search_char(c);
62433096f16SXin LI 		if (ret != NO_MCA)
62533096f16SXin LI 			return (ret);
62633096f16SXin LI 		break;
62733096f16SXin LI 
62833096f16SXin LI 	default:
62933096f16SXin LI 		/* Other multicharacter command. */
630a5f0fb15SPaul Saab 		break;
631a5f0fb15SPaul Saab 	}
632a5f0fb15SPaul Saab 
633a5f0fb15SPaul Saab 	/*
63433096f16SXin LI 	 * The multichar command is terminated by a newline.
635a5f0fb15SPaul Saab 	 */
636b2ea2440SXin LI 	if (is_newline_char(c))
637a5f0fb15SPaul Saab 	{
638a5f0fb15SPaul Saab 		/*
639a5f0fb15SPaul Saab 		 * Execute the command.
640a5f0fb15SPaul Saab 		 */
641a5f0fb15SPaul Saab 		exec_mca();
642a5f0fb15SPaul Saab 		return (MCA_DONE);
643a5f0fb15SPaul Saab 	}
644a5f0fb15SPaul Saab 
645a5f0fb15SPaul Saab 	/*
646a5f0fb15SPaul Saab 	 * Append the char to the command buffer.
647a5f0fb15SPaul Saab 	 */
648a5f0fb15SPaul Saab 	if (cmd_char(c) == CC_QUIT)
649a5f0fb15SPaul Saab 		/*
650a5f0fb15SPaul Saab 		 * Abort the multi-char command.
651a5f0fb15SPaul Saab 		 */
652a5f0fb15SPaul Saab 		return (MCA_DONE);
653a5f0fb15SPaul Saab 
654a5f0fb15SPaul Saab 	if ((mca == A_F_BRACKET || mca == A_B_BRACKET) && len_cmdbuf() >= 2)
655a5f0fb15SPaul Saab 	{
656a5f0fb15SPaul Saab 		/*
657a5f0fb15SPaul Saab 		 * Special case for the bracket-matching commands.
658a5f0fb15SPaul Saab 		 * Execute the command after getting exactly two
659a5f0fb15SPaul Saab 		 * characters from the user.
660a5f0fb15SPaul Saab 		 */
661a5f0fb15SPaul Saab 		exec_mca();
662a5f0fb15SPaul Saab 		return (MCA_DONE);
663a5f0fb15SPaul Saab 	}
664a5f0fb15SPaul Saab 
665a5f0fb15SPaul Saab 	/*
666a5f0fb15SPaul Saab 	 * Need another character.
667a5f0fb15SPaul Saab 	 */
668a5f0fb15SPaul Saab 	return (MCA_MORE);
669a5f0fb15SPaul Saab }
670a5f0fb15SPaul Saab 
671a5f0fb15SPaul Saab /*
672423c5ce5SXin LI  * Discard any buffered file data.
673423c5ce5SXin LI  */
674423c5ce5SXin LI 	static void
675*b7780dbeSXin LI clear_buffers(VOID_PARAM)
676423c5ce5SXin LI {
677423c5ce5SXin LI 	if (!(ch_getflags() & CH_CANSEEK))
678423c5ce5SXin LI 		return;
679423c5ce5SXin LI 	ch_flush();
680423c5ce5SXin LI 	clr_linenum();
681423c5ce5SXin LI #if HILITE_SEARCH
682423c5ce5SXin LI 	clr_hilite();
683423c5ce5SXin LI #endif
684423c5ce5SXin LI }
685423c5ce5SXin LI 
686423c5ce5SXin LI /*
687a5f0fb15SPaul Saab  * Make sure the screen is displayed.
688a5f0fb15SPaul Saab  */
689a5f0fb15SPaul Saab 	static void
690*b7780dbeSXin LI make_display(VOID_PARAM)
691a5f0fb15SPaul Saab {
692a5f0fb15SPaul Saab 	/*
693a5f0fb15SPaul Saab 	 * If nothing is displayed yet, display starting from initial_scrpos.
694a5f0fb15SPaul Saab 	 */
695a5f0fb15SPaul Saab 	if (empty_screen())
696a5f0fb15SPaul Saab 	{
697a5f0fb15SPaul Saab 		if (initial_scrpos.pos == NULL_POSITION)
698a5f0fb15SPaul Saab 			/*
699a5f0fb15SPaul Saab 			 * {{ Maybe this should be:
700a5f0fb15SPaul Saab 			 *    jump_loc(ch_zero(), jump_sline);
701a5f0fb15SPaul Saab 			 *    but this behavior seems rather unexpected
702a5f0fb15SPaul Saab 			 *    on the first screen. }}
703a5f0fb15SPaul Saab 			 */
704a5f0fb15SPaul Saab 			jump_loc(ch_zero(), 1);
705a5f0fb15SPaul Saab 		else
706a5f0fb15SPaul Saab 			jump_loc(initial_scrpos.pos, initial_scrpos.ln);
707a5f0fb15SPaul Saab 	} else if (screen_trashed)
708a5f0fb15SPaul Saab 	{
709423c5ce5SXin LI 		int save_top_scroll = top_scroll;
710423c5ce5SXin LI 		int save_ignore_eoi = ignore_eoi;
711a5f0fb15SPaul Saab 		top_scroll = 1;
712423c5ce5SXin LI 		ignore_eoi = 0;
713423c5ce5SXin LI 		if (screen_trashed == 2)
714423c5ce5SXin LI 		{
715423c5ce5SXin LI 			/* Special case used by ignore_eoi: re-open the input file
716423c5ce5SXin LI 			 * and jump to the end of the file. */
717423c5ce5SXin LI 			reopen_curr_ifile();
718423c5ce5SXin LI 			jump_forw();
719423c5ce5SXin LI 		}
720a5f0fb15SPaul Saab 		repaint();
721a5f0fb15SPaul Saab 		top_scroll = save_top_scroll;
722423c5ce5SXin LI 		ignore_eoi = save_ignore_eoi;
723a5f0fb15SPaul Saab 	}
724a5f0fb15SPaul Saab }
725a5f0fb15SPaul Saab 
726a5f0fb15SPaul Saab /*
727a5f0fb15SPaul Saab  * Display the appropriate prompt.
728a5f0fb15SPaul Saab  */
729a5f0fb15SPaul Saab 	static void
730*b7780dbeSXin LI prompt(VOID_PARAM)
731a5f0fb15SPaul Saab {
7321ea31627SRobert Watson 	constant char *p;
733a5f0fb15SPaul Saab 
734b2ea2440SXin LI 	if (ungot != NULL && ungot->ug_char != CHAR_END_COMMAND)
735a5f0fb15SPaul Saab 	{
736a5f0fb15SPaul Saab 		/*
737a5f0fb15SPaul Saab 		 * No prompt necessary if commands are from
738a5f0fb15SPaul Saab 		 * ungotten chars rather than from the user.
739a5f0fb15SPaul Saab 		 */
740a5f0fb15SPaul Saab 		return;
741a5f0fb15SPaul Saab 	}
742a5f0fb15SPaul Saab 
743a5f0fb15SPaul Saab 	/*
744a5f0fb15SPaul Saab 	 * Make sure the screen is displayed.
745a5f0fb15SPaul Saab 	 */
746a5f0fb15SPaul Saab 	make_display();
747a5f0fb15SPaul Saab 	bottompos = position(BOTTOM_PLUS_ONE);
748a5f0fb15SPaul Saab 
749a5f0fb15SPaul Saab 	/*
7507374caaaSXin LI 	 * If we've hit EOF on the last file and the -E flag is set, quit.
751a5f0fb15SPaul Saab 	 */
7527374caaaSXin LI 	if (get_quit_at_eof() == OPT_ONPLUS &&
7537374caaaSXin LI 	    eof_displayed() && !(ch_getflags() & CH_HELPFILE) &&
754a5f0fb15SPaul Saab 	    next_ifile(curr_ifile) == NULL_IFILE)
755a5f0fb15SPaul Saab 		quit(QUIT_OK);
7567374caaaSXin LI 
757a5f0fb15SPaul Saab 	/*
7587374caaaSXin LI 	 * If the entire file is displayed and the -F flag is set, quit.
759a5f0fb15SPaul Saab 	 */
7607374caaaSXin LI 	if (quit_if_one_screen &&
7617374caaaSXin LI 	    entire_file_displayed() && !(ch_getflags() & CH_HELPFILE) &&
762a5f0fb15SPaul Saab 	    next_ifile(curr_ifile) == NULL_IFILE)
763a5f0fb15SPaul Saab 		quit(QUIT_OK);
764a5f0fb15SPaul Saab 
7658fd4165cSPaul Saab #if MSDOS_COMPILER==WIN32C
7668fd4165cSPaul Saab 	/*
7678fd4165cSPaul Saab 	 * In Win32, display the file name in the window title.
7688fd4165cSPaul Saab 	 */
7698fd4165cSPaul Saab 	if (!(ch_getflags() & CH_HELPFILE))
770*b7780dbeSXin LI 	{
771*b7780dbeSXin LI 		WCHAR w[MAX_PATH+16];
772*b7780dbeSXin LI 		p = pr_expand("Less?f - %f.", 0);
773*b7780dbeSXin LI 		MultiByteToWideChar(CP_ACP, 0, p, -1, w, sizeof(w)/sizeof(*w));
774*b7780dbeSXin LI 		SetConsoleTitleW(w);
775*b7780dbeSXin LI 	}
7768fd4165cSPaul Saab #endif
777*b7780dbeSXin LI 
778a5f0fb15SPaul Saab 	/*
779a5f0fb15SPaul Saab 	 * Select the proper prompt and display it.
780a5f0fb15SPaul Saab 	 */
781720c436cSXin LI 	/*
782720c436cSXin LI 	 * If the previous action was a forward movement,
783720c436cSXin LI 	 * don't clear the bottom line of the display;
784720c436cSXin LI 	 * just print the prompt since the forward movement guarantees
785720c436cSXin LI 	 * that we're in the right position to display the prompt.
786720c436cSXin LI 	 * Clearing the line could cause a problem: for example, if the last
787720c436cSXin LI 	 * line displayed ended at the right screen edge without a newline,
788720c436cSXin LI 	 * then clearing would clear the last displayed line rather than
789720c436cSXin LI 	 * the prompt line.
790720c436cSXin LI 	 */
791720c436cSXin LI 	if (!forw_prompt)
792720c436cSXin LI 		clear_bot();
793a5f0fb15SPaul Saab 	clear_cmd();
794720c436cSXin LI 	forw_prompt = 0;
795a5f0fb15SPaul Saab 	p = pr_string();
7967374caaaSXin LI 	if (is_filtering())
7977374caaaSXin LI 		putstr("& ");
79889dd99dcSXin LI 	if (p == NULL || *p == '\0')
799a5f0fb15SPaul Saab 		putchr(':');
800a5f0fb15SPaul Saab 	else
801a5f0fb15SPaul Saab 	{
802*b7780dbeSXin LI #if MSDOS_COMPILER==WIN32C
803*b7780dbeSXin LI 		WCHAR w[MAX_PATH*2];
804*b7780dbeSXin LI 		char  a[MAX_PATH*2];
805*b7780dbeSXin LI 		MultiByteToWideChar(CP_ACP, 0, p, -1, w, sizeof(w)/sizeof(*w));
806*b7780dbeSXin LI 		WideCharToMultiByte(utf_mode ? CP_UTF8 : GetConsoleOutputCP(),
807*b7780dbeSXin LI 		                    0, w, -1, a, sizeof(a), NULL, NULL);
808*b7780dbeSXin LI 		p = a;
809*b7780dbeSXin LI #endif
81089dd99dcSXin LI 		at_enter(AT_STANDOUT);
811a5f0fb15SPaul Saab 		putstr(p);
81289dd99dcSXin LI 		at_exit();
813a5f0fb15SPaul Saab 	}
814720c436cSXin LI 	clear_eol();
815a5f0fb15SPaul Saab }
816a5f0fb15SPaul Saab 
817a5f0fb15SPaul Saab /*
818a5f0fb15SPaul Saab  * Display the less version message.
819a5f0fb15SPaul Saab  */
820a5f0fb15SPaul Saab 	public void
821*b7780dbeSXin LI dispversion(VOID_PARAM)
822a5f0fb15SPaul Saab {
823a5f0fb15SPaul Saab 	PARG parg;
824a5f0fb15SPaul Saab 
825a5f0fb15SPaul Saab 	parg.p_string = version;
826a5f0fb15SPaul Saab 	error("less %s", &parg);
827a5f0fb15SPaul Saab }
828a5f0fb15SPaul Saab 
829a5f0fb15SPaul Saab /*
830b2ea2440SXin LI  * Return a character to complete a partial command, if possible.
831b2ea2440SXin LI  */
832b2ea2440SXin LI 	static LWCHAR
833*b7780dbeSXin LI getcc_end_command(VOID_PARAM)
834b2ea2440SXin LI {
835b2ea2440SXin LI 	switch (mca)
836b2ea2440SXin LI 	{
837b2ea2440SXin LI 	case A_DIGIT:
838b2ea2440SXin LI 		/* We have a number but no command.  Treat as #g. */
839b2ea2440SXin LI 		return ('g');
840b2ea2440SXin LI 	case A_F_SEARCH:
841b2ea2440SXin LI 	case A_B_SEARCH:
842b2ea2440SXin LI 		/* We have "/string" but no newline.  Add the \n. */
843b2ea2440SXin LI 		return ('\n');
844b2ea2440SXin LI 	default:
845b2ea2440SXin LI 		/* Some other incomplete command.  Let user complete it. */
846b2ea2440SXin LI 		return (getchr());
847b2ea2440SXin LI 	}
848b2ea2440SXin LI }
849b2ea2440SXin LI 
850b2ea2440SXin LI /*
851a5f0fb15SPaul Saab  * Get command character.
852a5f0fb15SPaul Saab  * The character normally comes from the keyboard,
853a5f0fb15SPaul Saab  * but may come from ungotten characters
854a5f0fb15SPaul Saab  * (characters previously given to ungetcc or ungetsc).
855a5f0fb15SPaul Saab  */
856b2ea2440SXin LI 	static LWCHAR
85774709ed0SXin LI getccu(VOID_PARAM)
858a5f0fb15SPaul Saab {
859b2ea2440SXin LI 	LWCHAR c;
860a15691bfSXin LI 	if (ungot == NULL)
86133096f16SXin LI 	{
862b2ea2440SXin LI 		/* Normal case: no ungotten chars.
863b2ea2440SXin LI 		 * Get char from the user. */
864b2ea2440SXin LI 		c = getchr();
865b2ea2440SXin LI 	} else
866a15691bfSXin LI 	{
867b2ea2440SXin LI 		/* Ungotten chars available:
868b2ea2440SXin LI 		 * Take the top of stack (most recent). */
869a15691bfSXin LI 		struct ungot *ug = ungot;
870b2ea2440SXin LI 		c = ug->ug_char;
871a15691bfSXin LI 		ungot = ug->ug_next;
872a15691bfSXin LI 		free(ug);
873a5f0fb15SPaul Saab 
874b2ea2440SXin LI 		if (c == CHAR_END_COMMAND)
875b2ea2440SXin LI 			c = getcc_end_command();
876a5f0fb15SPaul Saab 	}
87733096f16SXin LI 	return (c);
87833096f16SXin LI }
879b2ea2440SXin LI 
880b2ea2440SXin LI /*
881b2ea2440SXin LI  * Get a command character, but if we receive the orig sequence,
882b2ea2440SXin LI  * convert it to the repl sequence.
883b2ea2440SXin LI  */
884b2ea2440SXin LI 	static LWCHAR
885b2ea2440SXin LI getcc_repl(orig, repl, gr_getc, gr_ungetc)
886b2ea2440SXin LI 	char const* orig;
887b2ea2440SXin LI 	char const* repl;
888b2ea2440SXin LI 	LWCHAR (*gr_getc)(VOID_PARAM);
889b2ea2440SXin LI 	void (*gr_ungetc)(LWCHAR);
890b2ea2440SXin LI {
891b2ea2440SXin LI 	LWCHAR c;
892b2ea2440SXin LI 	LWCHAR keys[16];
893b2ea2440SXin LI 	int ki = 0;
894b2ea2440SXin LI 
895b2ea2440SXin LI 	c = (*gr_getc)();
896b2ea2440SXin LI 	if (orig == NULL || orig[0] == '\0')
897b2ea2440SXin LI 		return c;
898b2ea2440SXin LI 	for (;;)
899b2ea2440SXin LI 	{
900b2ea2440SXin LI 		keys[ki] = c;
901b2ea2440SXin LI 		if (c != orig[ki] || ki >= sizeof(keys)-1)
902b2ea2440SXin LI 		{
903b2ea2440SXin LI 			/* This is not orig we have been receiving.
904b2ea2440SXin LI 			 * If we have stashed chars in keys[],
905b2ea2440SXin LI 			 * unget them and return the first one. */
906b2ea2440SXin LI 			while (ki > 0)
907b2ea2440SXin LI 				(*gr_ungetc)(keys[ki--]);
908b2ea2440SXin LI 			return keys[0];
909b2ea2440SXin LI 		}
910b2ea2440SXin LI 		if (orig[++ki] == '\0')
911b2ea2440SXin LI 		{
912b2ea2440SXin LI 			/* We've received the full orig sequence.
913b2ea2440SXin LI 			 * Return the repl sequence. */
914b2ea2440SXin LI 			ki = strlen(repl)-1;
915b2ea2440SXin LI 			while (ki > 0)
916b2ea2440SXin LI 				(*gr_ungetc)(repl[ki--]);
917b2ea2440SXin LI 			return repl[0];
918b2ea2440SXin LI 		}
919b2ea2440SXin LI 		/* We've received a partial orig sequence (ki chars of it).
920b2ea2440SXin LI 		 * Get next char and see if it continues to match orig. */
921b2ea2440SXin LI 		c = (*gr_getc)();
922b2ea2440SXin LI 	}
923b2ea2440SXin LI }
924b2ea2440SXin LI 
925b2ea2440SXin LI /*
926b2ea2440SXin LI  * Get command character.
927b2ea2440SXin LI  */
928b2ea2440SXin LI 	public int
929*b7780dbeSXin LI getcc(VOID_PARAM)
930b2ea2440SXin LI {
931b2ea2440SXin LI 	/* Replace kent (keypad Enter) with a newline. */
932b2ea2440SXin LI 	return getcc_repl(kent, "\n", getccu, ungetcc);
93333096f16SXin LI }
93433096f16SXin LI 
935a5f0fb15SPaul Saab /*
936a5f0fb15SPaul Saab  * "Unget" a command character.
937a5f0fb15SPaul Saab  * The next getcc() will return this character.
938a5f0fb15SPaul Saab  */
939a5f0fb15SPaul Saab 	public void
940f6b74a7dSXin LI ungetcc(c)
941b2ea2440SXin LI 	LWCHAR c;
942a5f0fb15SPaul Saab {
94333096f16SXin LI 	struct ungot *ug = (struct ungot *) ecalloc(1, sizeof(struct ungot));
94433096f16SXin LI 
945b2ea2440SXin LI 	ug->ug_char = c;
94633096f16SXin LI 	ug->ug_next = ungot;
94733096f16SXin LI 	ungot = ug;
948a5f0fb15SPaul Saab }
949a5f0fb15SPaul Saab 
950a5f0fb15SPaul Saab /*
951a5f0fb15SPaul Saab  * Unget a whole string of command characters.
952a5f0fb15SPaul Saab  * The next sequence of getcc()'s will return this string.
953a5f0fb15SPaul Saab  */
954a5f0fb15SPaul Saab 	public void
955f6b74a7dSXin LI ungetsc(s)
956f6b74a7dSXin LI 	char *s;
957a5f0fb15SPaul Saab {
9581ea31627SRobert Watson 	char *p;
959a5f0fb15SPaul Saab 
960a5f0fb15SPaul Saab 	for (p = s + strlen(s) - 1;  p >= s;  p--)
961a5f0fb15SPaul Saab 		ungetcc(*p);
962a5f0fb15SPaul Saab }
963a5f0fb15SPaul Saab 
964a5f0fb15SPaul Saab /*
965b2ea2440SXin LI  * Peek the next command character, without consuming it.
966b2ea2440SXin LI  */
967b2ea2440SXin LI 	public LWCHAR
968*b7780dbeSXin LI peekcc(VOID_PARAM)
969b2ea2440SXin LI {
970b2ea2440SXin LI 	LWCHAR c = getcc();
971b2ea2440SXin LI 	ungetcc(c);
972b2ea2440SXin LI 	return c;
973b2ea2440SXin LI }
974b2ea2440SXin LI 
975b2ea2440SXin LI /*
976a5f0fb15SPaul Saab  * Search for a pattern, possibly in multiple files.
977a5f0fb15SPaul Saab  * If SRCH_FIRST_FILE is set, begin searching at the first file.
978a5f0fb15SPaul Saab  * If SRCH_PAST_EOF is set, continue the search thru multiple files.
979a5f0fb15SPaul Saab  */
980a5f0fb15SPaul Saab 	static void
981f6b74a7dSXin LI multi_search(pattern, n, silent)
982f6b74a7dSXin LI 	char *pattern;
983f6b74a7dSXin LI 	int n;
984f6b74a7dSXin LI 	int silent;
985a5f0fb15SPaul Saab {
9861ea31627SRobert Watson 	int nomore;
987a5f0fb15SPaul Saab 	IFILE save_ifile;
988a5f0fb15SPaul Saab 	int changed_file;
989a5f0fb15SPaul Saab 
990a5f0fb15SPaul Saab 	changed_file = 0;
991a5f0fb15SPaul Saab 	save_ifile = save_curr_ifile();
992a5f0fb15SPaul Saab 
993a5f0fb15SPaul Saab 	if (search_type & SRCH_FIRST_FILE)
994a5f0fb15SPaul Saab 	{
995a5f0fb15SPaul Saab 		/*
996a5f0fb15SPaul Saab 		 * Start at the first (or last) file
997a5f0fb15SPaul Saab 		 * in the command line list.
998a5f0fb15SPaul Saab 		 */
999a5f0fb15SPaul Saab 		if (search_type & SRCH_FORW)
1000a5f0fb15SPaul Saab 			nomore = edit_first();
1001a5f0fb15SPaul Saab 		else
1002a5f0fb15SPaul Saab 			nomore = edit_last();
1003a5f0fb15SPaul Saab 		if (nomore)
1004a5f0fb15SPaul Saab 		{
1005a5f0fb15SPaul Saab 			unsave_ifile(save_ifile);
1006a5f0fb15SPaul Saab 			return;
1007a5f0fb15SPaul Saab 		}
1008a5f0fb15SPaul Saab 		changed_file = 1;
1009a5f0fb15SPaul Saab 		search_type &= ~SRCH_FIRST_FILE;
1010a5f0fb15SPaul Saab 	}
1011a5f0fb15SPaul Saab 
1012a5f0fb15SPaul Saab 	for (;;)
1013a5f0fb15SPaul Saab 	{
1014a5f0fb15SPaul Saab 		n = search(search_type, pattern, n);
1015a5f0fb15SPaul Saab 		/*
1016a5f0fb15SPaul Saab 		 * The SRCH_NO_MOVE flag doesn't "stick": it gets cleared
1017a5f0fb15SPaul Saab 		 * after being used once.  This allows "n" to work after
1018a5f0fb15SPaul Saab 		 * using a /@@ search.
1019a5f0fb15SPaul Saab 		 */
1020a5f0fb15SPaul Saab 		search_type &= ~SRCH_NO_MOVE;
1021a5f0fb15SPaul Saab 		if (n == 0)
1022a5f0fb15SPaul Saab 		{
1023a5f0fb15SPaul Saab 			/*
1024a5f0fb15SPaul Saab 			 * Found it.
1025a5f0fb15SPaul Saab 			 */
1026a5f0fb15SPaul Saab 			unsave_ifile(save_ifile);
1027a5f0fb15SPaul Saab 			return;
1028a5f0fb15SPaul Saab 		}
1029a5f0fb15SPaul Saab 
1030a5f0fb15SPaul Saab 		if (n < 0)
1031a5f0fb15SPaul Saab 			/*
1032a5f0fb15SPaul Saab 			 * Some kind of error in the search.
1033a5f0fb15SPaul Saab 			 * Error message has been printed by search().
1034a5f0fb15SPaul Saab 			 */
1035a5f0fb15SPaul Saab 			break;
1036a5f0fb15SPaul Saab 
1037a5f0fb15SPaul Saab 		if ((search_type & SRCH_PAST_EOF) == 0)
1038a5f0fb15SPaul Saab 			/*
1039a5f0fb15SPaul Saab 			 * We didn't find a match, but we're
1040a5f0fb15SPaul Saab 			 * supposed to search only one file.
1041a5f0fb15SPaul Saab 			 */
1042a5f0fb15SPaul Saab 			break;
1043a5f0fb15SPaul Saab 		/*
1044a5f0fb15SPaul Saab 		 * Move on to the next file.
1045a5f0fb15SPaul Saab 		 */
1046a5f0fb15SPaul Saab 		if (search_type & SRCH_FORW)
1047a5f0fb15SPaul Saab 			nomore = edit_next(1);
1048a5f0fb15SPaul Saab 		else
1049a5f0fb15SPaul Saab 			nomore = edit_prev(1);
1050a5f0fb15SPaul Saab 		if (nomore)
1051a5f0fb15SPaul Saab 			break;
1052a5f0fb15SPaul Saab 		changed_file = 1;
1053a5f0fb15SPaul Saab 	}
1054a5f0fb15SPaul Saab 
1055a5f0fb15SPaul Saab 	/*
1056a5f0fb15SPaul Saab 	 * Didn't find it.
1057a5f0fb15SPaul Saab 	 * Print an error message if we haven't already.
1058a5f0fb15SPaul Saab 	 */
1059a15691bfSXin LI 	if (n > 0 && !silent)
1060a5f0fb15SPaul Saab 		error("Pattern not found", NULL_PARG);
1061a5f0fb15SPaul Saab 
1062a5f0fb15SPaul Saab 	if (changed_file)
1063a5f0fb15SPaul Saab 	{
1064a5f0fb15SPaul Saab 		/*
1065a5f0fb15SPaul Saab 		 * Restore the file we were originally viewing.
1066a5f0fb15SPaul Saab 		 */
1067a5f0fb15SPaul Saab 		reedit_ifile(save_ifile);
106889dd99dcSXin LI 	} else
106989dd99dcSXin LI 	{
107089dd99dcSXin LI 		unsave_ifile(save_ifile);
1071a5f0fb15SPaul Saab 	}
1072a5f0fb15SPaul Saab }
1073a5f0fb15SPaul Saab 
1074a5f0fb15SPaul Saab /*
107596e55cc7SXin LI  * Forward forever, or until a highlighted line appears.
107696e55cc7SXin LI  */
107796e55cc7SXin LI 	static int
1078f6b74a7dSXin LI forw_loop(until_hilite)
1079f6b74a7dSXin LI 	int until_hilite;
108096e55cc7SXin LI {
108196e55cc7SXin LI 	POSITION curr_len;
108296e55cc7SXin LI 
108396e55cc7SXin LI 	if (ch_getflags() & CH_HELPFILE)
108496e55cc7SXin LI 		return (A_NOACTION);
108596e55cc7SXin LI 
108696e55cc7SXin LI 	cmd_exec();
1087a15691bfSXin LI 	jump_forw_buffered();
108896e55cc7SXin LI 	curr_len = ch_length();
108996e55cc7SXin LI 	highest_hilite = until_hilite ? curr_len : NULL_POSITION;
109096e55cc7SXin LI 	ignore_eoi = 1;
109196e55cc7SXin LI 	while (!sigs)
109296e55cc7SXin LI 	{
109396e55cc7SXin LI 		if (until_hilite && highest_hilite > curr_len)
109496e55cc7SXin LI 		{
109596e55cc7SXin LI 			bell();
109696e55cc7SXin LI 			break;
109796e55cc7SXin LI 		}
109896e55cc7SXin LI 		make_display();
109996e55cc7SXin LI 		forward(1, 0, 0);
110096e55cc7SXin LI 	}
110196e55cc7SXin LI 	ignore_eoi = 0;
1102e2449719SXin LI 	ch_set_eof();
110396e55cc7SXin LI 
110496e55cc7SXin LI 	/*
110596e55cc7SXin LI 	 * This gets us back in "F mode" after processing
110696e55cc7SXin LI 	 * a non-abort signal (e.g. window-change).
110796e55cc7SXin LI 	 */
110896e55cc7SXin LI 	if (sigs && !ABORT_SIGS())
1109e2449719SXin LI 		return (until_hilite ? A_F_UNTIL_HILITE : A_F_FOREVER);
1110e2449719SXin LI 
111196e55cc7SXin LI 	return (A_NOACTION);
111296e55cc7SXin LI }
111396e55cc7SXin LI 
111496e55cc7SXin LI /*
1115a5f0fb15SPaul Saab  * Main command processor.
1116a5f0fb15SPaul Saab  * Accept and execute commands until a quit command.
1117a5f0fb15SPaul Saab  */
1118a5f0fb15SPaul Saab 	public void
1119*b7780dbeSXin LI commands(VOID_PARAM)
1120a5f0fb15SPaul Saab {
11211ea31627SRobert Watson 	int c;
11221ea31627SRobert Watson 	int action;
11231ea31627SRobert Watson 	char *cbuf;
1124a5f0fb15SPaul Saab 	int newaction;
1125a5f0fb15SPaul Saab 	int save_search_type;
1126a5f0fb15SPaul Saab 	char *extra;
1127a5f0fb15SPaul Saab 	char tbuf[2];
1128a5f0fb15SPaul Saab 	PARG parg;
1129a5f0fb15SPaul Saab 	IFILE old_ifile;
1130a5f0fb15SPaul Saab 	IFILE new_ifile;
11318fd4165cSPaul Saab 	char *tagfile;
1132a5f0fb15SPaul Saab 
1133a5f0fb15SPaul Saab 	search_type = SRCH_FORW;
1134a5f0fb15SPaul Saab 	wscroll = (sc_height + 1) / 2;
1135a5f0fb15SPaul Saab 	newaction = A_NOACTION;
1136a5f0fb15SPaul Saab 
1137a5f0fb15SPaul Saab 	for (;;)
1138a5f0fb15SPaul Saab 	{
1139*b7780dbeSXin LI 		clear_mca();
1140a5f0fb15SPaul Saab 		cmd_accept();
1141a5f0fb15SPaul Saab 		number = 0;
114233096f16SXin LI 		curropt = NULL;
1143a5f0fb15SPaul Saab 
1144a5f0fb15SPaul Saab 		/*
1145a5f0fb15SPaul Saab 		 * See if any signals need processing.
1146a5f0fb15SPaul Saab 		 */
1147a5f0fb15SPaul Saab 		if (sigs)
1148a5f0fb15SPaul Saab 		{
1149a5f0fb15SPaul Saab 			psignals();
1150a5f0fb15SPaul Saab 			if (quitting)
1151a5f0fb15SPaul Saab 				quit(QUIT_SAVED_STATUS);
1152a5f0fb15SPaul Saab 		}
1153a5f0fb15SPaul Saab 
1154a5f0fb15SPaul Saab 		/*
1155a5f0fb15SPaul Saab 		 * See if window size changed, for systems that don't
1156a5f0fb15SPaul Saab 		 * generate SIGWINCH.
1157a5f0fb15SPaul Saab 		 */
1158a5f0fb15SPaul Saab 		check_winch();
1159a5f0fb15SPaul Saab 
1160a5f0fb15SPaul Saab 		/*
1161a5f0fb15SPaul Saab 		 * Display prompt and accept a character.
1162a5f0fb15SPaul Saab 		 */
1163a5f0fb15SPaul Saab 		cmd_reset();
1164a5f0fb15SPaul Saab 		prompt();
1165a5f0fb15SPaul Saab 		if (sigs)
1166a5f0fb15SPaul Saab 			continue;
1167a5f0fb15SPaul Saab 		if (newaction == A_NOACTION)
1168a5f0fb15SPaul Saab 			c = getcc();
1169a5f0fb15SPaul Saab 
1170a5f0fb15SPaul Saab 	again:
1171a5f0fb15SPaul Saab 		if (sigs)
1172a5f0fb15SPaul Saab 			continue;
1173a5f0fb15SPaul Saab 
1174a5f0fb15SPaul Saab 		if (newaction != A_NOACTION)
1175a5f0fb15SPaul Saab 		{
1176a5f0fb15SPaul Saab 			action = newaction;
1177a5f0fb15SPaul Saab 			newaction = A_NOACTION;
1178a5f0fb15SPaul Saab 		} else
1179a5f0fb15SPaul Saab 		{
1180a5f0fb15SPaul Saab 			/*
1181a5f0fb15SPaul Saab 			 * If we are in a multicharacter command, call mca_char.
1182a5f0fb15SPaul Saab 			 * Otherwise we call fcmd_decode to determine the
1183a5f0fb15SPaul Saab 			 * action to be performed.
1184a5f0fb15SPaul Saab 			 */
1185a5f0fb15SPaul Saab 			if (mca)
1186a5f0fb15SPaul Saab 				switch (mca_char(c))
1187a5f0fb15SPaul Saab 				{
1188a5f0fb15SPaul Saab 				case MCA_MORE:
1189a5f0fb15SPaul Saab 					/*
1190a5f0fb15SPaul Saab 					 * Need another character.
1191a5f0fb15SPaul Saab 					 */
1192a5f0fb15SPaul Saab 					c = getcc();
1193a5f0fb15SPaul Saab 					goto again;
1194a5f0fb15SPaul Saab 				case MCA_DONE:
1195a5f0fb15SPaul Saab 					/*
1196a5f0fb15SPaul Saab 					 * Command has been handled by mca_char.
1197a5f0fb15SPaul Saab 					 * Start clean with a prompt.
1198a5f0fb15SPaul Saab 					 */
1199a5f0fb15SPaul Saab 					continue;
1200a5f0fb15SPaul Saab 				case NO_MCA:
1201a5f0fb15SPaul Saab 					/*
1202a5f0fb15SPaul Saab 					 * Not a multi-char command
1203a5f0fb15SPaul Saab 					 * (at least, not anymore).
1204a5f0fb15SPaul Saab 					 */
1205a5f0fb15SPaul Saab 					break;
1206a5f0fb15SPaul Saab 				}
1207a5f0fb15SPaul Saab 
1208a5f0fb15SPaul Saab 			/*
1209a5f0fb15SPaul Saab 			 * Decode the command character and decide what to do.
1210a5f0fb15SPaul Saab 			 */
1211a5f0fb15SPaul Saab 			if (mca)
1212a5f0fb15SPaul Saab 			{
1213a5f0fb15SPaul Saab 				/*
1214a5f0fb15SPaul Saab 				 * We're in a multichar command.
1215a5f0fb15SPaul Saab 				 * Add the character to the command buffer
1216a5f0fb15SPaul Saab 				 * and display it on the screen.
1217a5f0fb15SPaul Saab 				 * If the user backspaces past the start
1218a5f0fb15SPaul Saab 				 * of the line, abort the command.
1219a5f0fb15SPaul Saab 				 */
1220a5f0fb15SPaul Saab 				if (cmd_char(c) == CC_QUIT || len_cmdbuf() == 0)
1221a5f0fb15SPaul Saab 					continue;
1222a5f0fb15SPaul Saab 				cbuf = get_cmdbuf();
1223a5f0fb15SPaul Saab 			} else
1224a5f0fb15SPaul Saab 			{
1225a5f0fb15SPaul Saab 				/*
1226a5f0fb15SPaul Saab 				 * Don't use cmd_char if we're starting fresh
1227a5f0fb15SPaul Saab 				 * at the beginning of a command, because we
1228a5f0fb15SPaul Saab 				 * don't want to echo the command until we know
1229a5f0fb15SPaul Saab 				 * it is a multichar command.  We also don't
1230a5f0fb15SPaul Saab 				 * want erase_char/kill_char to be treated
1231a5f0fb15SPaul Saab 				 * as line editing characters.
1232a5f0fb15SPaul Saab 				 */
1233a5f0fb15SPaul Saab 				tbuf[0] = c;
1234a5f0fb15SPaul Saab 				tbuf[1] = '\0';
1235a5f0fb15SPaul Saab 				cbuf = tbuf;
1236a5f0fb15SPaul Saab 			}
1237a5f0fb15SPaul Saab 			extra = NULL;
1238a5f0fb15SPaul Saab 			action = fcmd_decode(cbuf, &extra);
1239a5f0fb15SPaul Saab 			/*
1240a5f0fb15SPaul Saab 			 * If an "extra" string was returned,
1241a5f0fb15SPaul Saab 			 * process it as a string of command characters.
1242a5f0fb15SPaul Saab 			 */
1243a5f0fb15SPaul Saab 			if (extra != NULL)
1244a5f0fb15SPaul Saab 				ungetsc(extra);
1245a5f0fb15SPaul Saab 		}
1246a5f0fb15SPaul Saab 		/*
1247a5f0fb15SPaul Saab 		 * Clear the cmdbuf string.
1248a5f0fb15SPaul Saab 		 * (But not if we're in the prefix of a command,
1249a5f0fb15SPaul Saab 		 * because the partial command string is kept there.)
1250a5f0fb15SPaul Saab 		 */
1251a5f0fb15SPaul Saab 		if (action != A_PREFIX)
1252a5f0fb15SPaul Saab 			cmd_reset();
1253a5f0fb15SPaul Saab 
1254a5f0fb15SPaul Saab 		switch (action)
1255a5f0fb15SPaul Saab 		{
1256a5f0fb15SPaul Saab 		case A_DIGIT:
1257a5f0fb15SPaul Saab 			/*
1258a5f0fb15SPaul Saab 			 * First digit of a number.
1259a5f0fb15SPaul Saab 			 */
1260a5f0fb15SPaul Saab 			start_mca(A_DIGIT, ":", (void*)NULL, CF_QUIT_ON_ERASE);
1261a5f0fb15SPaul Saab 			goto again;
1262a5f0fb15SPaul Saab 
1263a5f0fb15SPaul Saab 		case A_F_WINDOW:
1264a5f0fb15SPaul Saab 			/*
1265a5f0fb15SPaul Saab 			 * Forward one window (and set the window size).
1266a5f0fb15SPaul Saab 			 */
1267a5f0fb15SPaul Saab 			if (number > 0)
12681ede1615STim J. Robbins 				swindow = (int) number;
1269a5f0fb15SPaul Saab 			/* FALLTHRU */
1270a5f0fb15SPaul Saab 		case A_F_SCREEN:
1271a5f0fb15SPaul Saab 			/*
1272a5f0fb15SPaul Saab 			 * Forward one screen.
1273a5f0fb15SPaul Saab 			 */
1274a5f0fb15SPaul Saab 			if (number <= 0)
1275a5f0fb15SPaul Saab 				number = get_swindow();
1276a5f0fb15SPaul Saab 			cmd_exec();
1277a5f0fb15SPaul Saab 			if (show_attn)
1278a5f0fb15SPaul Saab 				set_attnpos(bottompos);
12791ede1615STim J. Robbins 			forward((int) number, 0, 1);
1280a5f0fb15SPaul Saab 			break;
1281a5f0fb15SPaul Saab 
1282a5f0fb15SPaul Saab 		case A_B_WINDOW:
1283a5f0fb15SPaul Saab 			/*
1284a5f0fb15SPaul Saab 			 * Backward one window (and set the window size).
1285a5f0fb15SPaul Saab 			 */
1286a5f0fb15SPaul Saab 			if (number > 0)
12871ede1615STim J. Robbins 				swindow = (int) number;
1288a5f0fb15SPaul Saab 			/* FALLTHRU */
1289a5f0fb15SPaul Saab 		case A_B_SCREEN:
1290a5f0fb15SPaul Saab 			/*
1291a5f0fb15SPaul Saab 			 * Backward one screen.
1292a5f0fb15SPaul Saab 			 */
1293a5f0fb15SPaul Saab 			if (number <= 0)
1294a5f0fb15SPaul Saab 				number = get_swindow();
1295a5f0fb15SPaul Saab 			cmd_exec();
12961ede1615STim J. Robbins 			backward((int) number, 0, 1);
1297a5f0fb15SPaul Saab 			break;
1298a5f0fb15SPaul Saab 
1299a5f0fb15SPaul Saab 		case A_F_LINE:
1300a5f0fb15SPaul Saab 			/*
1301a5f0fb15SPaul Saab 			 * Forward N (default 1) line.
1302a5f0fb15SPaul Saab 			 */
1303a5f0fb15SPaul Saab 			if (number <= 0)
1304a5f0fb15SPaul Saab 				number = 1;
1305a5f0fb15SPaul Saab 			cmd_exec();
1306a5f0fb15SPaul Saab 			if (show_attn == OPT_ONPLUS && number > 1)
1307a5f0fb15SPaul Saab 				set_attnpos(bottompos);
13081ede1615STim J. Robbins 			forward((int) number, 0, 0);
1309a5f0fb15SPaul Saab 			break;
1310a5f0fb15SPaul Saab 
1311a5f0fb15SPaul Saab 		case A_B_LINE:
1312a5f0fb15SPaul Saab 			/*
1313a5f0fb15SPaul Saab 			 * Backward N (default 1) line.
1314a5f0fb15SPaul Saab 			 */
1315a5f0fb15SPaul Saab 			if (number <= 0)
1316a5f0fb15SPaul Saab 				number = 1;
1317a5f0fb15SPaul Saab 			cmd_exec();
13181ede1615STim J. Robbins 			backward((int) number, 0, 0);
1319a5f0fb15SPaul Saab 			break;
1320a5f0fb15SPaul Saab 
1321*b7780dbeSXin LI 		case A_F_MOUSE:
1322*b7780dbeSXin LI 			/*
1323*b7780dbeSXin LI 			 * Forward wheel_lines lines.
1324*b7780dbeSXin LI 			 */
1325*b7780dbeSXin LI 			cmd_exec();
1326*b7780dbeSXin LI 			forward(wheel_lines, 0, 0);
1327*b7780dbeSXin LI 			break;
1328*b7780dbeSXin LI 
1329*b7780dbeSXin LI 		case A_B_MOUSE:
1330*b7780dbeSXin LI 			/*
1331*b7780dbeSXin LI 			 * Backward wheel_lines lines.
1332*b7780dbeSXin LI 			 */
1333*b7780dbeSXin LI 			cmd_exec();
1334*b7780dbeSXin LI 			backward(wheel_lines, 0, 0);
1335*b7780dbeSXin LI 			break;
1336*b7780dbeSXin LI 
1337a5f0fb15SPaul Saab 		case A_FF_LINE:
1338a5f0fb15SPaul Saab 			/*
1339a5f0fb15SPaul Saab 			 * Force forward N (default 1) line.
1340a5f0fb15SPaul Saab 			 */
1341a5f0fb15SPaul Saab 			if (number <= 0)
1342a5f0fb15SPaul Saab 				number = 1;
1343a5f0fb15SPaul Saab 			cmd_exec();
1344a5f0fb15SPaul Saab 			if (show_attn == OPT_ONPLUS && number > 1)
1345a5f0fb15SPaul Saab 				set_attnpos(bottompos);
13461ede1615STim J. Robbins 			forward((int) number, 1, 0);
1347a5f0fb15SPaul Saab 			break;
1348a5f0fb15SPaul Saab 
1349a5f0fb15SPaul Saab 		case A_BF_LINE:
1350a5f0fb15SPaul Saab 			/*
1351a5f0fb15SPaul Saab 			 * Force backward N (default 1) line.
1352a5f0fb15SPaul Saab 			 */
1353a5f0fb15SPaul Saab 			if (number <= 0)
1354a5f0fb15SPaul Saab 				number = 1;
1355a5f0fb15SPaul Saab 			cmd_exec();
13561ede1615STim J. Robbins 			backward((int) number, 1, 0);
1357a5f0fb15SPaul Saab 			break;
1358a5f0fb15SPaul Saab 
1359a5f0fb15SPaul Saab 		case A_FF_SCREEN:
1360a5f0fb15SPaul Saab 			/*
1361a5f0fb15SPaul Saab 			 * Force forward one screen.
1362a5f0fb15SPaul Saab 			 */
1363a5f0fb15SPaul Saab 			if (number <= 0)
1364a5f0fb15SPaul Saab 				number = get_swindow();
1365a5f0fb15SPaul Saab 			cmd_exec();
1366a5f0fb15SPaul Saab 			if (show_attn == OPT_ONPLUS)
1367a5f0fb15SPaul Saab 				set_attnpos(bottompos);
13681ede1615STim J. Robbins 			forward((int) number, 1, 0);
1369a5f0fb15SPaul Saab 			break;
1370a5f0fb15SPaul Saab 
1371a5f0fb15SPaul Saab 		case A_F_FOREVER:
1372a5f0fb15SPaul Saab 			/*
1373a5f0fb15SPaul Saab 			 * Forward forever, ignoring EOF.
1374a5f0fb15SPaul Saab 			 */
1375a15691bfSXin LI 			if (show_attn)
1376a15691bfSXin LI 				set_attnpos(bottompos);
137796e55cc7SXin LI 			newaction = forw_loop(0);
1378a5f0fb15SPaul Saab 			break;
137996e55cc7SXin LI 
138096e55cc7SXin LI 		case A_F_UNTIL_HILITE:
138196e55cc7SXin LI 			newaction = forw_loop(1);
1382a5f0fb15SPaul Saab 			break;
1383a5f0fb15SPaul Saab 
1384a5f0fb15SPaul Saab 		case A_F_SCROLL:
1385a5f0fb15SPaul Saab 			/*
1386a5f0fb15SPaul Saab 			 * Forward N lines
1387a5f0fb15SPaul Saab 			 * (default same as last 'd' or 'u' command).
1388a5f0fb15SPaul Saab 			 */
1389a5f0fb15SPaul Saab 			if (number > 0)
13901ede1615STim J. Robbins 				wscroll = (int) number;
1391a5f0fb15SPaul Saab 			cmd_exec();
1392a5f0fb15SPaul Saab 			if (show_attn == OPT_ONPLUS)
1393a5f0fb15SPaul Saab 				set_attnpos(bottompos);
1394a5f0fb15SPaul Saab 			forward(wscroll, 0, 0);
1395a5f0fb15SPaul Saab 			break;
1396a5f0fb15SPaul Saab 
1397a5f0fb15SPaul Saab 		case A_B_SCROLL:
1398a5f0fb15SPaul Saab 			/*
1399a5f0fb15SPaul Saab 			 * Forward N lines
1400a5f0fb15SPaul Saab 			 * (default same as last 'd' or 'u' command).
1401a5f0fb15SPaul Saab 			 */
1402a5f0fb15SPaul Saab 			if (number > 0)
14031ede1615STim J. Robbins 				wscroll = (int) number;
1404a5f0fb15SPaul Saab 			cmd_exec();
1405a5f0fb15SPaul Saab 			backward(wscroll, 0, 0);
1406a5f0fb15SPaul Saab 			break;
1407a5f0fb15SPaul Saab 
1408a5f0fb15SPaul Saab 		case A_FREPAINT:
1409a5f0fb15SPaul Saab 			/*
1410a5f0fb15SPaul Saab 			 * Flush buffers, then repaint screen.
1411a5f0fb15SPaul Saab 			 * Don't flush the buffers on a pipe!
1412a5f0fb15SPaul Saab 			 */
1413423c5ce5SXin LI 			clear_buffers();
1414a5f0fb15SPaul Saab 			/* FALLTHRU */
1415a5f0fb15SPaul Saab 		case A_REPAINT:
1416a5f0fb15SPaul Saab 			/*
1417a5f0fb15SPaul Saab 			 * Repaint screen.
1418a5f0fb15SPaul Saab 			 */
1419a5f0fb15SPaul Saab 			cmd_exec();
1420a5f0fb15SPaul Saab 			repaint();
1421a5f0fb15SPaul Saab 			break;
1422a5f0fb15SPaul Saab 
1423a5f0fb15SPaul Saab 		case A_GOLINE:
1424a5f0fb15SPaul Saab 			/*
1425a5f0fb15SPaul Saab 			 * Go to line N, default beginning of file.
1426a5f0fb15SPaul Saab 			 */
1427a5f0fb15SPaul Saab 			if (number <= 0)
1428a5f0fb15SPaul Saab 				number = 1;
1429a5f0fb15SPaul Saab 			cmd_exec();
1430a5f0fb15SPaul Saab 			jump_back(number);
1431a5f0fb15SPaul Saab 			break;
1432a5f0fb15SPaul Saab 
1433a5f0fb15SPaul Saab 		case A_PERCENT:
1434a5f0fb15SPaul Saab 			/*
1435a5f0fb15SPaul Saab 			 * Go to a specified percentage into the file.
1436a5f0fb15SPaul Saab 			 */
1437a5f0fb15SPaul Saab 			if (number < 0)
1438720c436cSXin LI 			{
1439a5f0fb15SPaul Saab 				number = 0;
1440720c436cSXin LI 				fraction = 0;
1441720c436cSXin LI 			}
1442*b7780dbeSXin LI 			if (number > 100 || (number == 100 && fraction != 0))
1443720c436cSXin LI 			{
1444a5f0fb15SPaul Saab 				number = 100;
1445720c436cSXin LI 				fraction = 0;
1446720c436cSXin LI 			}
1447a5f0fb15SPaul Saab 			cmd_exec();
1448720c436cSXin LI 			jump_percent((int) number, fraction);
1449a5f0fb15SPaul Saab 			break;
1450a5f0fb15SPaul Saab 
1451a5f0fb15SPaul Saab 		case A_GOEND:
1452a5f0fb15SPaul Saab 			/*
1453a5f0fb15SPaul Saab 			 * Go to line N, default end of file.
1454a5f0fb15SPaul Saab 			 */
1455a5f0fb15SPaul Saab 			cmd_exec();
1456a5f0fb15SPaul Saab 			if (number <= 0)
1457a5f0fb15SPaul Saab 				jump_forw();
1458a5f0fb15SPaul Saab 			else
1459a5f0fb15SPaul Saab 				jump_back(number);
1460a5f0fb15SPaul Saab 			break;
1461a5f0fb15SPaul Saab 
1462a15691bfSXin LI 		case A_GOEND_BUF:
1463a15691bfSXin LI 			/*
1464a15691bfSXin LI 			 * Go to line N, default last buffered byte.
1465a15691bfSXin LI 			 */
1466a15691bfSXin LI 			cmd_exec();
1467a15691bfSXin LI 			if (number <= 0)
1468a15691bfSXin LI 				jump_forw_buffered();
1469a15691bfSXin LI 			else
1470a15691bfSXin LI 				jump_back(number);
1471a15691bfSXin LI 			break;
1472a15691bfSXin LI 
1473a5f0fb15SPaul Saab 		case A_GOPOS:
1474a5f0fb15SPaul Saab 			/*
1475a5f0fb15SPaul Saab 			 * Go to a specified byte position in the file.
1476a5f0fb15SPaul Saab 			 */
1477a5f0fb15SPaul Saab 			cmd_exec();
1478a5f0fb15SPaul Saab 			if (number < 0)
1479a5f0fb15SPaul Saab 				number = 0;
1480a5f0fb15SPaul Saab 			jump_line_loc((POSITION) number, jump_sline);
1481a5f0fb15SPaul Saab 			break;
1482a5f0fb15SPaul Saab 
1483a5f0fb15SPaul Saab 		case A_STAT:
1484a5f0fb15SPaul Saab 			/*
1485a5f0fb15SPaul Saab 			 * Print file name, etc.
1486a5f0fb15SPaul Saab 			 */
1487a5f0fb15SPaul Saab 			if (ch_getflags() & CH_HELPFILE)
1488a5f0fb15SPaul Saab 				break;
1489a5f0fb15SPaul Saab 			cmd_exec();
1490a5f0fb15SPaul Saab 			parg.p_string = eq_message();
1491a5f0fb15SPaul Saab 			error("%s", &parg);
1492a5f0fb15SPaul Saab 			break;
1493a5f0fb15SPaul Saab 
1494a5f0fb15SPaul Saab 		case A_VERSION:
1495a5f0fb15SPaul Saab 			/*
1496a5f0fb15SPaul Saab 			 * Print version number, without the "@(#)".
1497a5f0fb15SPaul Saab 			 */
1498a5f0fb15SPaul Saab 			cmd_exec();
1499a5f0fb15SPaul Saab 			dispversion();
1500a5f0fb15SPaul Saab 			break;
1501a5f0fb15SPaul Saab 
1502a5f0fb15SPaul Saab 		case A_QUIT:
1503a5f0fb15SPaul Saab 			/*
1504a5f0fb15SPaul Saab 			 * Exit.
1505a5f0fb15SPaul Saab 			 */
1506a5f0fb15SPaul Saab 			if (curr_ifile != NULL_IFILE &&
1507a5f0fb15SPaul Saab 			    ch_getflags() & CH_HELPFILE)
1508a5f0fb15SPaul Saab 			{
1509a5f0fb15SPaul Saab 				/*
1510a5f0fb15SPaul Saab 				 * Quit while viewing the help file
1511a5f0fb15SPaul Saab 				 * just means return to viewing the
1512a5f0fb15SPaul Saab 				 * previous file.
1513a5f0fb15SPaul Saab 				 */
151489dd99dcSXin LI 				hshift = save_hshift;
1515a15691bfSXin LI 				bs_mode = save_bs_mode;
1516a5f0fb15SPaul Saab 				if (edit_prev(1) == 0)
1517a5f0fb15SPaul Saab 					break;
1518a5f0fb15SPaul Saab 			}
1519a5f0fb15SPaul Saab 			if (extra != NULL)
1520a5f0fb15SPaul Saab 				quit(*extra);
1521a5f0fb15SPaul Saab 			quit(QUIT_OK);
1522a5f0fb15SPaul Saab 			break;
1523a5f0fb15SPaul Saab 
1524a5f0fb15SPaul Saab /*
1525a5f0fb15SPaul Saab  * Define abbreviation for a commonly used sequence below.
1526a5f0fb15SPaul Saab  */
1527423c5ce5SXin LI #define	DO_SEARCH() \
1528423c5ce5SXin LI 			if (number <= 0) number = 1;	\
1529a5f0fb15SPaul Saab 			mca_search();			\
1530a5f0fb15SPaul Saab 			cmd_exec();			\
1531a15691bfSXin LI 			multi_search((char *)NULL, (int) number, 0);
1532a5f0fb15SPaul Saab 
1533a5f0fb15SPaul Saab 
1534a5f0fb15SPaul Saab 		case A_F_SEARCH:
1535a5f0fb15SPaul Saab 			/*
1536a5f0fb15SPaul Saab 			 * Search forward for a pattern.
1537a5f0fb15SPaul Saab 			 * Get the first char of the pattern.
1538a5f0fb15SPaul Saab 			 */
1539a5f0fb15SPaul Saab 			search_type = SRCH_FORW;
1540a5f0fb15SPaul Saab 			if (number <= 0)
1541a5f0fb15SPaul Saab 				number = 1;
1542a5f0fb15SPaul Saab 			mca_search();
1543a5f0fb15SPaul Saab 			c = getcc();
1544a5f0fb15SPaul Saab 			goto again;
1545a5f0fb15SPaul Saab 
1546a5f0fb15SPaul Saab 		case A_B_SEARCH:
1547a5f0fb15SPaul Saab 			/*
1548a5f0fb15SPaul Saab 			 * Search backward for a pattern.
1549a5f0fb15SPaul Saab 			 * Get the first char of the pattern.
1550a5f0fb15SPaul Saab 			 */
1551a5f0fb15SPaul Saab 			search_type = SRCH_BACK;
1552a5f0fb15SPaul Saab 			if (number <= 0)
1553a5f0fb15SPaul Saab 				number = 1;
1554a5f0fb15SPaul Saab 			mca_search();
1555a5f0fb15SPaul Saab 			c = getcc();
1556a5f0fb15SPaul Saab 			goto again;
1557a5f0fb15SPaul Saab 
15587374caaaSXin LI 		case A_FILTER:
15597374caaaSXin LI #if HILITE_SEARCH
15607374caaaSXin LI 			search_type = SRCH_FORW | SRCH_FILTER;
15617374caaaSXin LI 			mca_search();
15627374caaaSXin LI 			c = getcc();
15637374caaaSXin LI 			goto again;
15647374caaaSXin LI #else
15657374caaaSXin LI 			error("Command not available", NULL_PARG);
15667374caaaSXin LI 			break;
15677374caaaSXin LI #endif
15687374caaaSXin LI 
1569a5f0fb15SPaul Saab 		case A_AGAIN_SEARCH:
1570a5f0fb15SPaul Saab 			/*
1571a5f0fb15SPaul Saab 			 * Repeat previous search.
1572a5f0fb15SPaul Saab 			 */
1573a5f0fb15SPaul Saab 			DO_SEARCH();
1574a5f0fb15SPaul Saab 			break;
1575a5f0fb15SPaul Saab 
1576a5f0fb15SPaul Saab 		case A_T_AGAIN_SEARCH:
1577a5f0fb15SPaul Saab 			/*
1578a5f0fb15SPaul Saab 			 * Repeat previous search, multiple files.
1579a5f0fb15SPaul Saab 			 */
1580a5f0fb15SPaul Saab 			search_type |= SRCH_PAST_EOF;
1581a5f0fb15SPaul Saab 			DO_SEARCH();
1582a5f0fb15SPaul Saab 			break;
1583a5f0fb15SPaul Saab 
1584a5f0fb15SPaul Saab 		case A_REVERSE_SEARCH:
1585a5f0fb15SPaul Saab 			/*
1586a5f0fb15SPaul Saab 			 * Repeat previous search, in reverse direction.
1587a5f0fb15SPaul Saab 			 */
1588a5f0fb15SPaul Saab 			save_search_type = search_type;
1589a5f0fb15SPaul Saab 			search_type = SRCH_REVERSE(search_type);
1590a5f0fb15SPaul Saab 			DO_SEARCH();
1591a5f0fb15SPaul Saab 			search_type = save_search_type;
1592a5f0fb15SPaul Saab 			break;
1593a5f0fb15SPaul Saab 
1594a5f0fb15SPaul Saab 		case A_T_REVERSE_SEARCH:
1595a5f0fb15SPaul Saab 			/*
1596a5f0fb15SPaul Saab 			 * Repeat previous search,
1597a5f0fb15SPaul Saab 			 * multiple files in reverse direction.
1598a5f0fb15SPaul Saab 			 */
1599a5f0fb15SPaul Saab 			save_search_type = search_type;
1600a5f0fb15SPaul Saab 			search_type = SRCH_REVERSE(search_type);
1601a5f0fb15SPaul Saab 			search_type |= SRCH_PAST_EOF;
1602a5f0fb15SPaul Saab 			DO_SEARCH();
1603a5f0fb15SPaul Saab 			search_type = save_search_type;
1604a5f0fb15SPaul Saab 			break;
1605a5f0fb15SPaul Saab 
1606a5f0fb15SPaul Saab 		case A_UNDO_SEARCH:
1607b2ea2440SXin LI 			/*
1608b2ea2440SXin LI 			 * Clear search string highlighting.
1609b2ea2440SXin LI 			 */
1610a5f0fb15SPaul Saab 			undo_search();
1611a5f0fb15SPaul Saab 			break;
1612a5f0fb15SPaul Saab 
1613a5f0fb15SPaul Saab 		case A_HELP:
1614a5f0fb15SPaul Saab 			/*
1615a5f0fb15SPaul Saab 			 * Help.
1616a5f0fb15SPaul Saab 			 */
1617a5f0fb15SPaul Saab 			if (ch_getflags() & CH_HELPFILE)
1618a5f0fb15SPaul Saab 				break;
1619a5f0fb15SPaul Saab 			cmd_exec();
162089dd99dcSXin LI 			save_hshift = hshift;
162189dd99dcSXin LI 			hshift = 0;
1622a15691bfSXin LI 			save_bs_mode = bs_mode;
1623a15691bfSXin LI 			bs_mode = BS_SPECIAL;
1624a5f0fb15SPaul Saab 			(void) edit(FAKE_HELPFILE);
1625a5f0fb15SPaul Saab 			break;
1626a5f0fb15SPaul Saab 
1627a5f0fb15SPaul Saab 		case A_EXAMINE:
1628a5f0fb15SPaul Saab 			/*
1629a5f0fb15SPaul Saab 			 * Edit a new file.  Get the filename.
1630a5f0fb15SPaul Saab 			 */
1631b2ea2440SXin LI #if EXAMINE
1632b2ea2440SXin LI 			if (!secure)
1633a5f0fb15SPaul Saab 			{
1634dd3bd0edSDimitry Andric 				start_mca(A_EXAMINE, "Examine: ", ml_examine, 0);
1635a5f0fb15SPaul Saab 				c = getcc();
1636a5f0fb15SPaul Saab 				goto again;
1637b2ea2440SXin LI 			}
1638b2ea2440SXin LI #endif
1639a5f0fb15SPaul Saab 			error("Command not available", NULL_PARG);
1640a5f0fb15SPaul Saab 			break;
1641a5f0fb15SPaul Saab 
1642a5f0fb15SPaul Saab 		case A_VISUAL:
1643a5f0fb15SPaul Saab 			/*
1644a5f0fb15SPaul Saab 			 * Invoke an editor on the input file.
1645a5f0fb15SPaul Saab 			 */
1646a5f0fb15SPaul Saab #if EDITOR
1647b2ea2440SXin LI 			if (!secure)
1648a5f0fb15SPaul Saab 			{
1649a5f0fb15SPaul Saab 				if (ch_getflags() & CH_HELPFILE)
1650a5f0fb15SPaul Saab 					break;
1651a5f0fb15SPaul Saab 				if (strcmp(get_filename(curr_ifile), "-") == 0)
1652a5f0fb15SPaul Saab 				{
1653a5f0fb15SPaul Saab 					error("Cannot edit standard input", NULL_PARG);
1654a5f0fb15SPaul Saab 					break;
1655a5f0fb15SPaul Saab 				}
1656b2ea2440SXin LI 				if (get_altfilename(curr_ifile) != NULL)
1657a5f0fb15SPaul Saab 				{
165889dd99dcSXin LI 					error("WARNING: This file was viewed via LESSOPEN",
1659a5f0fb15SPaul Saab 						NULL_PARG);
1660a5f0fb15SPaul Saab 				}
1661dd3bd0edSDimitry Andric 				start_mca(A_SHELL, "!", ml_shell, 0);
1662a5f0fb15SPaul Saab 				/*
1663a5f0fb15SPaul Saab 				 * Expand the editor prototype string
1664a5f0fb15SPaul Saab 				 * and pass it to the system to execute.
1665a5f0fb15SPaul Saab 				 * (Make sure the screen is displayed so the
1666a5f0fb15SPaul Saab 				 * expansion of "+%lm" works.)
1667a5f0fb15SPaul Saab 				 */
1668a5f0fb15SPaul Saab 				make_display();
1669a5f0fb15SPaul Saab 				cmd_exec();
1670a5f0fb15SPaul Saab 				lsystem(pr_expand(editproto, 0), (char*)NULL);
1671a5f0fb15SPaul Saab 				break;
1672b2ea2440SXin LI 			}
1673b2ea2440SXin LI #endif
1674a5f0fb15SPaul Saab 			error("Command not available", NULL_PARG);
1675a5f0fb15SPaul Saab 			break;
1676a5f0fb15SPaul Saab 
1677a5f0fb15SPaul Saab 		case A_NEXT_FILE:
1678a5f0fb15SPaul Saab 			/*
1679a5f0fb15SPaul Saab 			 * Examine next file.
1680a5f0fb15SPaul Saab 			 */
16811ede1615STim J. Robbins #if TAGS
16828fd4165cSPaul Saab 			if (ntags())
16838fd4165cSPaul Saab 			{
16848fd4165cSPaul Saab 				error("No next file", NULL_PARG);
16858fd4165cSPaul Saab 				break;
16868fd4165cSPaul Saab 			}
16871ede1615STim J. Robbins #endif
1688a5f0fb15SPaul Saab 			if (number <= 0)
1689a5f0fb15SPaul Saab 				number = 1;
16901ede1615STim J. Robbins 			if (edit_next((int) number))
1691a5f0fb15SPaul Saab 			{
16927374caaaSXin LI 				if (get_quit_at_eof() && eof_displayed() &&
1693a5f0fb15SPaul Saab 				    !(ch_getflags() & CH_HELPFILE))
1694a5f0fb15SPaul Saab 					quit(QUIT_OK);
1695a5f0fb15SPaul Saab 				parg.p_string = (number > 1) ? "(N-th) " : "";
1696a5f0fb15SPaul Saab 				error("No %snext file", &parg);
1697a5f0fb15SPaul Saab 			}
1698a5f0fb15SPaul Saab 			break;
1699a5f0fb15SPaul Saab 
1700a5f0fb15SPaul Saab 		case A_PREV_FILE:
1701a5f0fb15SPaul Saab 			/*
1702a5f0fb15SPaul Saab 			 * Examine previous file.
1703a5f0fb15SPaul Saab 			 */
17041ede1615STim J. Robbins #if TAGS
17058fd4165cSPaul Saab 			if (ntags())
17068fd4165cSPaul Saab 			{
17078fd4165cSPaul Saab 				error("No previous file", NULL_PARG);
17088fd4165cSPaul Saab 				break;
17098fd4165cSPaul Saab 			}
17101ede1615STim J. Robbins #endif
1711a5f0fb15SPaul Saab 			if (number <= 0)
1712a5f0fb15SPaul Saab 				number = 1;
17131ede1615STim J. Robbins 			if (edit_prev((int) number))
1714a5f0fb15SPaul Saab 			{
1715a5f0fb15SPaul Saab 				parg.p_string = (number > 1) ? "(N-th) " : "";
1716a5f0fb15SPaul Saab 				error("No %sprevious file", &parg);
1717a5f0fb15SPaul Saab 			}
1718a5f0fb15SPaul Saab 			break;
1719a5f0fb15SPaul Saab 
17208fd4165cSPaul Saab 		case A_NEXT_TAG:
1721b2ea2440SXin LI 			/*
1722b2ea2440SXin LI 			 * Jump to the next tag in the current tag list.
1723b2ea2440SXin LI 			 */
17241ede1615STim J. Robbins #if TAGS
17258fd4165cSPaul Saab 			if (number <= 0)
17268fd4165cSPaul Saab 				number = 1;
17271ede1615STim J. Robbins 			tagfile = nexttag((int) number);
17288fd4165cSPaul Saab 			if (tagfile == NULL)
17298fd4165cSPaul Saab 			{
17308fd4165cSPaul Saab 				error("No next tag", NULL_PARG);
17318fd4165cSPaul Saab 				break;
17328fd4165cSPaul Saab 			}
1733b2ea2440SXin LI 			cmd_exec();
17348fd4165cSPaul Saab 			if (edit(tagfile) == 0)
17358fd4165cSPaul Saab 			{
17368fd4165cSPaul Saab 				POSITION pos = tagsearch();
17378fd4165cSPaul Saab 				if (pos != NULL_POSITION)
17388fd4165cSPaul Saab 					jump_loc(pos, jump_sline);
17398fd4165cSPaul Saab 			}
17401ede1615STim J. Robbins #else
17411ede1615STim J. Robbins 			error("Command not available", NULL_PARG);
17421ede1615STim J. Robbins #endif
17438fd4165cSPaul Saab 			break;
17448fd4165cSPaul Saab 
17458fd4165cSPaul Saab 		case A_PREV_TAG:
1746b2ea2440SXin LI 			/*
1747b2ea2440SXin LI 			 * Jump to the previous tag in the current tag list.
1748b2ea2440SXin LI 			 */
17491ede1615STim J. Robbins #if TAGS
17508fd4165cSPaul Saab 			if (number <= 0)
17518fd4165cSPaul Saab 				number = 1;
17521ede1615STim J. Robbins 			tagfile = prevtag((int) number);
17538fd4165cSPaul Saab 			if (tagfile == NULL)
17548fd4165cSPaul Saab 			{
17558fd4165cSPaul Saab 				error("No previous tag", NULL_PARG);
17568fd4165cSPaul Saab 				break;
17578fd4165cSPaul Saab 			}
1758b2ea2440SXin LI 			cmd_exec();
17598fd4165cSPaul Saab 			if (edit(tagfile) == 0)
17608fd4165cSPaul Saab 			{
17618fd4165cSPaul Saab 				POSITION pos = tagsearch();
17628fd4165cSPaul Saab 				if (pos != NULL_POSITION)
17638fd4165cSPaul Saab 					jump_loc(pos, jump_sline);
17648fd4165cSPaul Saab 			}
17651ede1615STim J. Robbins #else
17661ede1615STim J. Robbins 			error("Command not available", NULL_PARG);
17671ede1615STim J. Robbins #endif
17688fd4165cSPaul Saab 			break;
17698fd4165cSPaul Saab 
1770a5f0fb15SPaul Saab 		case A_INDEX_FILE:
1771a5f0fb15SPaul Saab 			/*
1772a5f0fb15SPaul Saab 			 * Examine a particular file.
1773a5f0fb15SPaul Saab 			 */
1774a5f0fb15SPaul Saab 			if (number <= 0)
1775a5f0fb15SPaul Saab 				number = 1;
17761ede1615STim J. Robbins 			if (edit_index((int) number))
1777a5f0fb15SPaul Saab 				error("No such file", NULL_PARG);
1778a5f0fb15SPaul Saab 			break;
1779a5f0fb15SPaul Saab 
1780a5f0fb15SPaul Saab 		case A_REMOVE_FILE:
1781b2ea2440SXin LI 			/*
1782b2ea2440SXin LI 			 * Remove a file from the input file list.
1783b2ea2440SXin LI 			 */
1784a5f0fb15SPaul Saab 			if (ch_getflags() & CH_HELPFILE)
1785a5f0fb15SPaul Saab 				break;
1786a5f0fb15SPaul Saab 			old_ifile = curr_ifile;
1787a5f0fb15SPaul Saab 			new_ifile = getoff_ifile(curr_ifile);
1788a5f0fb15SPaul Saab 			if (new_ifile == NULL_IFILE)
1789a5f0fb15SPaul Saab 			{
1790a5f0fb15SPaul Saab 				bell();
1791a5f0fb15SPaul Saab 				break;
1792a5f0fb15SPaul Saab 			}
1793a5f0fb15SPaul Saab 			if (edit_ifile(new_ifile) != 0)
1794a5f0fb15SPaul Saab 			{
1795a5f0fb15SPaul Saab 				reedit_ifile(old_ifile);
1796a5f0fb15SPaul Saab 				break;
1797a5f0fb15SPaul Saab 			}
1798a5f0fb15SPaul Saab 			del_ifile(old_ifile);
1799a5f0fb15SPaul Saab 			break;
1800a5f0fb15SPaul Saab 
1801a5f0fb15SPaul Saab 		case A_OPT_TOGGLE:
1802b2ea2440SXin LI 			/*
1803b2ea2440SXin LI 			 * Change the setting of an  option.
1804b2ea2440SXin LI 			 */
1805a5f0fb15SPaul Saab 			optflag = OPT_TOGGLE;
1806a5f0fb15SPaul Saab 			optgetname = FALSE;
1807a5f0fb15SPaul Saab 			mca_opt_toggle();
1808a5f0fb15SPaul Saab 			c = getcc();
1809a5f0fb15SPaul Saab 			goto again;
1810a5f0fb15SPaul Saab 
1811a5f0fb15SPaul Saab 		case A_DISP_OPTION:
1812a5f0fb15SPaul Saab 			/*
1813b2ea2440SXin LI 			 * Report the setting of an option.
1814a5f0fb15SPaul Saab 			 */
1815a5f0fb15SPaul Saab 			optflag = OPT_NO_TOGGLE;
1816a5f0fb15SPaul Saab 			optgetname = FALSE;
1817a5f0fb15SPaul Saab 			mca_opt_toggle();
1818a5f0fb15SPaul Saab 			c = getcc();
1819a5f0fb15SPaul Saab 			goto again;
1820a5f0fb15SPaul Saab 
1821a5f0fb15SPaul Saab 		case A_FIRSTCMD:
1822a5f0fb15SPaul Saab 			/*
1823a5f0fb15SPaul Saab 			 * Set an initial command for new files.
1824a5f0fb15SPaul Saab 			 */
1825a5f0fb15SPaul Saab 			start_mca(A_FIRSTCMD, "+", (void*)NULL, 0);
1826a5f0fb15SPaul Saab 			c = getcc();
1827a5f0fb15SPaul Saab 			goto again;
1828a5f0fb15SPaul Saab 
1829a5f0fb15SPaul Saab 		case A_SHELL:
1830a5f0fb15SPaul Saab 			/*
1831a5f0fb15SPaul Saab 			 * Shell escape.
1832a5f0fb15SPaul Saab 			 */
1833a5f0fb15SPaul Saab #if SHELL_ESCAPE
1834b2ea2440SXin LI 			if (!secure)
1835a5f0fb15SPaul Saab 			{
1836dd3bd0edSDimitry Andric 				start_mca(A_SHELL, "!", ml_shell, 0);
1837a5f0fb15SPaul Saab 				c = getcc();
1838a5f0fb15SPaul Saab 				goto again;
1839b2ea2440SXin LI 			}
1840b2ea2440SXin LI #endif
1841a5f0fb15SPaul Saab 			error("Command not available", NULL_PARG);
1842a5f0fb15SPaul Saab 			break;
1843a5f0fb15SPaul Saab 
1844a5f0fb15SPaul Saab 		case A_SETMARK:
1845b2ea2440SXin LI 		case A_SETMARKBOT:
1846a5f0fb15SPaul Saab 			/*
1847a5f0fb15SPaul Saab 			 * Set a mark.
1848a5f0fb15SPaul Saab 			 */
1849a5f0fb15SPaul Saab 			if (ch_getflags() & CH_HELPFILE)
1850a5f0fb15SPaul Saab 				break;
1851b2ea2440SXin LI 			start_mca(A_SETMARK, "set mark: ", (void*)NULL, 0);
1852a5f0fb15SPaul Saab 			c = getcc();
1853b2ea2440SXin LI 			if (is_erase_char(c) || is_newline_char(c))
1854a5f0fb15SPaul Saab 				break;
1855b2ea2440SXin LI 			setmark(c, action == A_SETMARKBOT ? BOTTOM : TOP);
1856b2ea2440SXin LI 			repaint();
1857b2ea2440SXin LI 			break;
1858b2ea2440SXin LI 
1859b2ea2440SXin LI 		case A_CLRMARK:
1860b2ea2440SXin LI 			/*
1861b2ea2440SXin LI 			 * Clear a mark.
1862b2ea2440SXin LI 			 */
1863b2ea2440SXin LI 			start_mca(A_CLRMARK, "clear mark: ", (void*)NULL, 0);
1864b2ea2440SXin LI 			c = getcc();
1865b2ea2440SXin LI 			if (is_erase_char(c) || is_newline_char(c))
1866b2ea2440SXin LI 				break;
1867b2ea2440SXin LI 			clrmark(c);
1868b2ea2440SXin LI 			repaint();
1869a5f0fb15SPaul Saab 			break;
1870a5f0fb15SPaul Saab 
1871a5f0fb15SPaul Saab 		case A_GOMARK:
1872a5f0fb15SPaul Saab 			/*
1873b2ea2440SXin LI 			 * Jump to a marked position.
1874a5f0fb15SPaul Saab 			 */
1875a5f0fb15SPaul Saab 			start_mca(A_GOMARK, "goto mark: ", (void*)NULL, 0);
1876a5f0fb15SPaul Saab 			c = getcc();
1877b2ea2440SXin LI 			if (is_erase_char(c) || is_newline_char(c))
1878a5f0fb15SPaul Saab 				break;
18797374caaaSXin LI 			cmd_exec();
1880a5f0fb15SPaul Saab 			gomark(c);
1881a5f0fb15SPaul Saab 			break;
1882a5f0fb15SPaul Saab 
1883a5f0fb15SPaul Saab 		case A_PIPE:
1884b2ea2440SXin LI 			/*
1885b2ea2440SXin LI 			 * Write part of the input to a pipe to a shell command.
1886b2ea2440SXin LI 			 */
1887a5f0fb15SPaul Saab #if PIPEC
1888b2ea2440SXin LI 			if (!secure)
1889a5f0fb15SPaul Saab 			{
1890a5f0fb15SPaul Saab 				start_mca(A_PIPE, "|mark: ", (void*)NULL, 0);
1891a5f0fb15SPaul Saab 				c = getcc();
1892b2ea2440SXin LI 				if (is_erase_char(c))
1893a5f0fb15SPaul Saab 					break;
1894b2ea2440SXin LI 				if (is_newline_char(c))
1895a5f0fb15SPaul Saab 					c = '.';
1896a5f0fb15SPaul Saab 				if (badmark(c))
1897a5f0fb15SPaul Saab 					break;
1898a5f0fb15SPaul Saab 				pipec = c;
1899dd3bd0edSDimitry Andric 				start_mca(A_PIPE, "!", ml_shell, 0);
1900a5f0fb15SPaul Saab 				c = getcc();
1901a5f0fb15SPaul Saab 				goto again;
1902b2ea2440SXin LI 			}
1903b2ea2440SXin LI #endif
1904a5f0fb15SPaul Saab 			error("Command not available", NULL_PARG);
1905a5f0fb15SPaul Saab 			break;
1906a5f0fb15SPaul Saab 
1907a5f0fb15SPaul Saab 		case A_B_BRACKET:
1908a5f0fb15SPaul Saab 		case A_F_BRACKET:
1909a5f0fb15SPaul Saab 			start_mca(action, "Brackets: ", (void*)NULL, 0);
1910a5f0fb15SPaul Saab 			c = getcc();
1911a5f0fb15SPaul Saab 			goto again;
1912a5f0fb15SPaul Saab 
1913a5f0fb15SPaul Saab 		case A_LSHIFT:
1914b2ea2440SXin LI 			/*
1915b2ea2440SXin LI 			 * Shift view left.
1916b2ea2440SXin LI 			 */
19178fd4165cSPaul Saab 			if (number > 0)
19188fd4165cSPaul Saab 				shift_count = number;
19198fd4165cSPaul Saab 			else
192015596da4SPaul Saab 				number = (shift_count > 0) ?
192115596da4SPaul Saab 					shift_count : sc_width / 2;
1922a5f0fb15SPaul Saab 			if (number > hshift)
1923a5f0fb15SPaul Saab 				number = hshift;
1924a5f0fb15SPaul Saab 			hshift -= number;
1925a5f0fb15SPaul Saab 			screen_trashed = 1;
1926a5f0fb15SPaul Saab 			break;
1927a5f0fb15SPaul Saab 
1928a5f0fb15SPaul Saab 		case A_RSHIFT:
1929b2ea2440SXin LI 			/*
1930b2ea2440SXin LI 			 * Shift view right.
1931b2ea2440SXin LI 			 */
19328fd4165cSPaul Saab 			if (number > 0)
19338fd4165cSPaul Saab 				shift_count = number;
19348fd4165cSPaul Saab 			else
193515596da4SPaul Saab 				number = (shift_count > 0) ?
193615596da4SPaul Saab 					shift_count : sc_width / 2;
1937a5f0fb15SPaul Saab 			hshift += number;
1938a5f0fb15SPaul Saab 			screen_trashed = 1;
1939a5f0fb15SPaul Saab 			break;
1940a5f0fb15SPaul Saab 
1941f6b74a7dSXin LI 		case A_LLSHIFT:
1942b2ea2440SXin LI 			/*
1943b2ea2440SXin LI 			 * Shift view left to margin.
1944b2ea2440SXin LI 			 */
1945f6b74a7dSXin LI 			hshift = 0;
1946f6b74a7dSXin LI 			screen_trashed = 1;
1947f6b74a7dSXin LI 			break;
1948f6b74a7dSXin LI 
1949f6b74a7dSXin LI 		case A_RRSHIFT:
1950b2ea2440SXin LI 			/*
1951b2ea2440SXin LI 			 * Shift view right to view rightmost char on screen.
1952b2ea2440SXin LI 			 */
1953f6b74a7dSXin LI 			hshift = rrshift();
1954f6b74a7dSXin LI 			screen_trashed = 1;
1955f6b74a7dSXin LI 			break;
1956f6b74a7dSXin LI 
1957a5f0fb15SPaul Saab 		case A_PREFIX:
1958a5f0fb15SPaul Saab 			/*
1959a5f0fb15SPaul Saab 			 * The command is incomplete (more chars are needed).
1960a5f0fb15SPaul Saab 			 * Display the current char, so the user knows
1961a5f0fb15SPaul Saab 			 * what's going on, and get another character.
1962a5f0fb15SPaul Saab 			 */
1963a5f0fb15SPaul Saab 			if (mca != A_PREFIX)
1964a5f0fb15SPaul Saab 			{
1965a5f0fb15SPaul Saab 				cmd_reset();
1966a5f0fb15SPaul Saab 				start_mca(A_PREFIX, " ", (void*)NULL,
1967a5f0fb15SPaul Saab 					CF_QUIT_ON_ERASE);
1968a5f0fb15SPaul Saab 				(void) cmd_char(c);
1969a5f0fb15SPaul Saab 			}
1970a5f0fb15SPaul Saab 			c = getcc();
1971a5f0fb15SPaul Saab 			goto again;
1972a5f0fb15SPaul Saab 
1973a5f0fb15SPaul Saab 		case A_NOACTION:
1974a5f0fb15SPaul Saab 			break;
1975a5f0fb15SPaul Saab 
1976a5f0fb15SPaul Saab 		default:
1977a5f0fb15SPaul Saab 			bell();
1978a5f0fb15SPaul Saab 			break;
1979a5f0fb15SPaul Saab 		}
1980a5f0fb15SPaul Saab 	}
1981a5f0fb15SPaul Saab }
1982