xref: /freebsd/contrib/less/command.c (revision f6b74a7d164b5fada266d00e723155a178a4529f)
1a8f92a7cSPaul Saab /* $FreeBSD$ */
2a5f0fb15SPaul Saab /*
3*f6b74a7dSXin LI  * Copyright (C) 1984-2017  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;
30a5f0fb15SPaul Saab extern int swindow;
31a5f0fb15SPaul Saab extern int jump_sline;
32a5f0fb15SPaul Saab extern int quitting;
33a5f0fb15SPaul Saab extern int wscroll;
34a5f0fb15SPaul Saab extern int top_scroll;
35a5f0fb15SPaul Saab extern int ignore_eoi;
36a5f0fb15SPaul Saab extern int secure;
37a5f0fb15SPaul Saab extern int hshift;
38a15691bfSXin LI extern int bs_mode;
39a5f0fb15SPaul Saab extern int show_attn;
40720c436cSXin LI extern int less_is_more;
4196e55cc7SXin LI extern POSITION highest_hilite;
42a5f0fb15SPaul Saab extern char *every_first_cmd;
43a5f0fb15SPaul Saab extern char *curr_altfilename;
44a5f0fb15SPaul Saab extern char version[];
45a5f0fb15SPaul Saab extern struct scrpos initial_scrpos;
46a5f0fb15SPaul Saab extern IFILE curr_ifile;
47*f6b74a7dSXin LI extern void *ml_search;
48*f6b74a7dSXin LI extern void *ml_examine;
49a5f0fb15SPaul Saab #if SHELL_ESCAPE || PIPEC
50*f6b74a7dSXin LI extern void *ml_shell;
51a5f0fb15SPaul Saab #endif
52a5f0fb15SPaul Saab #if EDITOR
53a5f0fb15SPaul Saab extern char *editor;
54a5f0fb15SPaul Saab extern char *editproto;
55a5f0fb15SPaul Saab #endif
56a5f0fb15SPaul Saab extern int screen_trashed;	/* The screen has been overwritten */
5715596da4SPaul Saab extern int shift_count;
58720c436cSXin LI extern int oldbot;
59720c436cSXin LI extern int forw_prompt;
60a15691bfSXin LI extern int same_pos_bell;
61a5f0fb15SPaul Saab 
62a5f0fb15SPaul Saab #if SHELL_ESCAPE
63a5f0fb15SPaul Saab static char *shellcmd = NULL;	/* For holding last shell command for "!!" */
64a5f0fb15SPaul Saab #endif
65a5f0fb15SPaul Saab static int mca;			/* The multicharacter command (action) */
66a5f0fb15SPaul Saab static int search_type;		/* The previous type of search */
671ede1615STim J. Robbins static LINENUM number;		/* The number typed by the user */
68720c436cSXin LI static long fraction;		/* The fractional part of the number */
6933096f16SXin LI static struct loption *curropt;
7033096f16SXin LI static int opt_lower;
71a5f0fb15SPaul Saab static int optflag;
72a5f0fb15SPaul Saab static int optgetname;
73a5f0fb15SPaul Saab static POSITION bottompos;
7489dd99dcSXin LI static int save_hshift;
75a15691bfSXin LI static int save_bs_mode;
76a5f0fb15SPaul Saab #if PIPEC
77a5f0fb15SPaul Saab static char pipec;
78a5f0fb15SPaul Saab #endif
79a5f0fb15SPaul Saab 
8033096f16SXin LI struct ungot {
8133096f16SXin LI 	struct ungot *ug_next;
8233096f16SXin LI 	char ug_char;
83a15691bfSXin LI 	char ug_end_command;
8433096f16SXin LI };
8533096f16SXin LI static struct ungot* ungot = NULL;
8633096f16SXin LI 
87*f6b74a7dSXin LI static void multi_search();
88a5f0fb15SPaul Saab 
89a5f0fb15SPaul Saab /*
90720c436cSXin LI  * Move the cursor to start of prompt line before executing a command.
91a5f0fb15SPaul Saab  * This looks nicer if the command takes a long time before
92a5f0fb15SPaul Saab  * updating the screen.
93a5f0fb15SPaul Saab  */
94a5f0fb15SPaul Saab 	static void
95*f6b74a7dSXin LI cmd_exec()
96a5f0fb15SPaul Saab {
977374caaaSXin LI #if HILITE_SEARCH
98a5f0fb15SPaul Saab 	clear_attn();
997374caaaSXin LI #endif
100aa22b8b6SXin LI 	clear_bot();
101a5f0fb15SPaul Saab 	flush();
102a5f0fb15SPaul Saab }
103a5f0fb15SPaul Saab 
104a5f0fb15SPaul Saab /*
105a5f0fb15SPaul Saab  * Set up the display to start a new multi-character command.
106a5f0fb15SPaul Saab  */
107a5f0fb15SPaul Saab 	static void
108*f6b74a7dSXin LI start_mca(action, prompt, mlist, cmdflags)
109*f6b74a7dSXin LI 	int action;
110*f6b74a7dSXin LI 	constant char *prompt;
111*f6b74a7dSXin LI 	void *mlist;
112*f6b74a7dSXin LI 	int cmdflags;
113a5f0fb15SPaul Saab {
114a5f0fb15SPaul Saab 	mca = action;
115720c436cSXin LI 	clear_bot();
116a5f0fb15SPaul Saab 	clear_cmd();
117a5f0fb15SPaul Saab 	cmd_putstr(prompt);
118a5f0fb15SPaul Saab 	set_mlist(mlist, cmdflags);
119a5f0fb15SPaul Saab }
120a5f0fb15SPaul Saab 
121a5f0fb15SPaul Saab 	public int
122*f6b74a7dSXin LI in_mca()
123a5f0fb15SPaul Saab {
124a5f0fb15SPaul Saab 	return (mca != 0 && mca != A_PREFIX);
125a5f0fb15SPaul Saab }
126a5f0fb15SPaul Saab 
127a5f0fb15SPaul Saab /*
128a5f0fb15SPaul Saab  * Set up the display to start a new search command.
129a5f0fb15SPaul Saab  */
130a5f0fb15SPaul Saab 	static void
131*f6b74a7dSXin LI mca_search()
132a5f0fb15SPaul Saab {
1337374caaaSXin LI #if HILITE_SEARCH
1347374caaaSXin LI 	if (search_type & SRCH_FILTER)
1357374caaaSXin LI 		mca = A_FILTER;
1367374caaaSXin LI 	else
1377374caaaSXin LI #endif
138a5f0fb15SPaul Saab 	if (search_type & SRCH_FORW)
139a5f0fb15SPaul Saab 		mca = A_F_SEARCH;
140a5f0fb15SPaul Saab 	else
141a5f0fb15SPaul Saab 		mca = A_B_SEARCH;
142a5f0fb15SPaul Saab 
143720c436cSXin LI 	clear_bot();
144a5f0fb15SPaul Saab 	clear_cmd();
145a5f0fb15SPaul Saab 
146a5f0fb15SPaul Saab 	if (search_type & SRCH_NO_MATCH)
147a5f0fb15SPaul Saab 		cmd_putstr("Non-match ");
148a5f0fb15SPaul Saab 	if (search_type & SRCH_FIRST_FILE)
149a5f0fb15SPaul Saab 		cmd_putstr("First-file ");
150a5f0fb15SPaul Saab 	if (search_type & SRCH_PAST_EOF)
151a5f0fb15SPaul Saab 		cmd_putstr("EOF-ignore ");
152a5f0fb15SPaul Saab 	if (search_type & SRCH_NO_MOVE)
153a5f0fb15SPaul Saab 		cmd_putstr("Keep-pos ");
154a5f0fb15SPaul Saab 	if (search_type & SRCH_NO_REGEX)
155a5f0fb15SPaul Saab 		cmd_putstr("Regex-off ");
156a5f0fb15SPaul Saab 
1577374caaaSXin LI #if HILITE_SEARCH
1587374caaaSXin LI 	if (search_type & SRCH_FILTER)
1597374caaaSXin LI 		cmd_putstr("&/");
1607374caaaSXin LI 	else
1617374caaaSXin LI #endif
162a5f0fb15SPaul Saab 	if (search_type & SRCH_FORW)
163a5f0fb15SPaul Saab 		cmd_putstr("/");
164a5f0fb15SPaul Saab 	else
165a5f0fb15SPaul Saab 		cmd_putstr("?");
166a15691bfSXin LI 	forw_prompt = 0;
167a5f0fb15SPaul Saab 	set_mlist(ml_search, 0);
168a5f0fb15SPaul Saab }
169a5f0fb15SPaul Saab 
170a5f0fb15SPaul Saab /*
171a5f0fb15SPaul Saab  * Set up the display to start a new toggle-option command.
172a5f0fb15SPaul Saab  */
173a5f0fb15SPaul Saab 	static void
174*f6b74a7dSXin LI mca_opt_toggle()
175a5f0fb15SPaul Saab {
176a5f0fb15SPaul Saab 	int no_prompt;
177a5f0fb15SPaul Saab 	int flag;
178a5f0fb15SPaul Saab 	char *dash;
179a5f0fb15SPaul Saab 
180a5f0fb15SPaul Saab 	no_prompt = (optflag & OPT_NO_PROMPT);
181a5f0fb15SPaul Saab 	flag = (optflag & ~OPT_NO_PROMPT);
182a5f0fb15SPaul Saab 	dash = (flag == OPT_NO_TOGGLE) ? "_" : "-";
183a5f0fb15SPaul Saab 
184a5f0fb15SPaul Saab 	mca = A_OPT_TOGGLE;
185720c436cSXin LI 	clear_bot();
186a5f0fb15SPaul Saab 	clear_cmd();
187a5f0fb15SPaul Saab 	cmd_putstr(dash);
188a5f0fb15SPaul Saab 	if (optgetname)
189a5f0fb15SPaul Saab 		cmd_putstr(dash);
190a5f0fb15SPaul Saab 	if (no_prompt)
191a5f0fb15SPaul Saab 		cmd_putstr("(P)");
192a5f0fb15SPaul Saab 	switch (flag)
193a5f0fb15SPaul Saab 	{
194a5f0fb15SPaul Saab 	case OPT_UNSET:
195a5f0fb15SPaul Saab 		cmd_putstr("+");
196a5f0fb15SPaul Saab 		break;
197a5f0fb15SPaul Saab 	case OPT_SET:
198a5f0fb15SPaul Saab 		cmd_putstr("!");
199a5f0fb15SPaul Saab 		break;
200a5f0fb15SPaul Saab 	}
201a15691bfSXin LI 	forw_prompt = 0;
202a5f0fb15SPaul Saab 	set_mlist(NULL, 0);
203a5f0fb15SPaul Saab }
204a5f0fb15SPaul Saab 
205a5f0fb15SPaul Saab /*
206a5f0fb15SPaul Saab  * Execute a multicharacter command.
207a5f0fb15SPaul Saab  */
208a5f0fb15SPaul Saab 	static void
209*f6b74a7dSXin LI exec_mca()
210a5f0fb15SPaul Saab {
2111ea31627SRobert Watson 	char *cbuf;
212a5f0fb15SPaul Saab 
213a5f0fb15SPaul Saab 	cmd_exec();
214a5f0fb15SPaul Saab 	cbuf = get_cmdbuf();
215a5f0fb15SPaul Saab 
216a5f0fb15SPaul Saab 	switch (mca)
217a5f0fb15SPaul Saab 	{
218a5f0fb15SPaul Saab 	case A_F_SEARCH:
219a5f0fb15SPaul Saab 	case A_B_SEARCH:
220a15691bfSXin LI 		multi_search(cbuf, (int) number, 0);
221a5f0fb15SPaul Saab 		break;
2227374caaaSXin LI #if HILITE_SEARCH
2237374caaaSXin LI 	case A_FILTER:
2247374caaaSXin LI 		search_type ^= SRCH_NO_MATCH;
2257374caaaSXin LI 		set_filter_pattern(cbuf, search_type);
2267374caaaSXin LI 		break;
2277374caaaSXin LI #endif
228a5f0fb15SPaul Saab 	case A_FIRSTCMD:
229a5f0fb15SPaul Saab 		/*
230a5f0fb15SPaul Saab 		 * Skip leading spaces or + signs in the string.
231a5f0fb15SPaul Saab 		 */
232a5f0fb15SPaul Saab 		while (*cbuf == '+' || *cbuf == ' ')
233a5f0fb15SPaul Saab 			cbuf++;
234a5f0fb15SPaul Saab 		if (every_first_cmd != NULL)
235a5f0fb15SPaul Saab 			free(every_first_cmd);
236a5f0fb15SPaul Saab 		if (*cbuf == '\0')
237a5f0fb15SPaul Saab 			every_first_cmd = NULL;
238a5f0fb15SPaul Saab 		else
239a5f0fb15SPaul Saab 			every_first_cmd = save(cbuf);
240a5f0fb15SPaul Saab 		break;
241a5f0fb15SPaul Saab 	case A_OPT_TOGGLE:
24233096f16SXin LI 		toggle_option(curropt, opt_lower, cbuf, optflag);
24333096f16SXin LI 		curropt = NULL;
244a5f0fb15SPaul Saab 		break;
245a5f0fb15SPaul Saab 	case A_F_BRACKET:
2461ede1615STim J. Robbins 		match_brac(cbuf[0], cbuf[1], 1, (int) number);
247a5f0fb15SPaul Saab 		break;
248a5f0fb15SPaul Saab 	case A_B_BRACKET:
2491ede1615STim J. Robbins 		match_brac(cbuf[1], cbuf[0], 0, (int) number);
250a5f0fb15SPaul Saab 		break;
251a5f0fb15SPaul Saab #if EXAMINE
252a5f0fb15SPaul Saab 	case A_EXAMINE:
253a5f0fb15SPaul Saab 		if (secure)
254a5f0fb15SPaul Saab 			break;
255a5f0fb15SPaul Saab 		edit_list(cbuf);
2561ede1615STim J. Robbins #if TAGS
2578fd4165cSPaul Saab 		/* If tag structure is loaded then clean it up. */
2588fd4165cSPaul Saab 		cleantags();
2591ede1615STim J. Robbins #endif
260a5f0fb15SPaul Saab 		break;
261a5f0fb15SPaul Saab #endif
262a5f0fb15SPaul Saab #if SHELL_ESCAPE
263a5f0fb15SPaul Saab 	case A_SHELL:
264a5f0fb15SPaul Saab 		/*
265a5f0fb15SPaul Saab 		 * !! just uses whatever is in shellcmd.
266a5f0fb15SPaul Saab 		 * Otherwise, copy cmdbuf to shellcmd,
267a5f0fb15SPaul Saab 		 * expanding any special characters ("%" or "#").
268a5f0fb15SPaul Saab 		 */
269a5f0fb15SPaul Saab 		if (*cbuf != '!')
270a5f0fb15SPaul Saab 		{
271a5f0fb15SPaul Saab 			if (shellcmd != NULL)
272a5f0fb15SPaul Saab 				free(shellcmd);
273a5f0fb15SPaul Saab 			shellcmd = fexpand(cbuf);
274a5f0fb15SPaul Saab 		}
275a5f0fb15SPaul Saab 
276a5f0fb15SPaul Saab 		if (secure)
277a5f0fb15SPaul Saab 			break;
278a5f0fb15SPaul Saab 		if (shellcmd == NULL)
279a5f0fb15SPaul Saab 			lsystem("", "!done");
280a5f0fb15SPaul Saab 		else
281a5f0fb15SPaul Saab 			lsystem(shellcmd, "!done");
282a5f0fb15SPaul Saab 		break;
283a5f0fb15SPaul Saab #endif
284a5f0fb15SPaul Saab #if PIPEC
285a5f0fb15SPaul Saab 	case A_PIPE:
286a5f0fb15SPaul Saab 		if (secure)
287a5f0fb15SPaul Saab 			break;
288a5f0fb15SPaul Saab 		(void) pipe_mark(pipec, cbuf);
289a5f0fb15SPaul Saab 		error("|done", NULL_PARG);
290a5f0fb15SPaul Saab 		break;
291a5f0fb15SPaul Saab #endif
292a5f0fb15SPaul Saab 	}
293a5f0fb15SPaul Saab }
294a5f0fb15SPaul Saab 
295a5f0fb15SPaul Saab /*
29633096f16SXin LI  * Is a character an erase or kill char?
297a5f0fb15SPaul Saab  */
298a5f0fb15SPaul Saab 	static int
299*f6b74a7dSXin LI is_erase_char(c)
300*f6b74a7dSXin LI 	int c;
301a5f0fb15SPaul Saab {
30233096f16SXin LI 	return (c == erase_char || c == erase2_char || c == kill_char);
303a5f0fb15SPaul Saab }
304a5f0fb15SPaul Saab 
305a5f0fb15SPaul Saab /*
30633096f16SXin LI  * Handle the first char of an option (after the initial dash).
307a5f0fb15SPaul Saab  */
30833096f16SXin LI 	static int
309*f6b74a7dSXin LI mca_opt_first_char(c)
310*f6b74a7dSXin LI     int c;
311a5f0fb15SPaul Saab {
31233096f16SXin LI 	int flag = (optflag & ~OPT_NO_PROMPT);
313a5f0fb15SPaul Saab 	if (flag == OPT_NO_TOGGLE)
314a5f0fb15SPaul Saab 	{
315a5f0fb15SPaul Saab 		switch (c)
316a5f0fb15SPaul Saab 		{
317a5f0fb15SPaul Saab 		case '_':
318a5f0fb15SPaul Saab 			/* "__" = long option name. */
319a5f0fb15SPaul Saab 			optgetname = TRUE;
320a5f0fb15SPaul Saab 			mca_opt_toggle();
321a5f0fb15SPaul Saab 			return (MCA_MORE);
322a5f0fb15SPaul Saab 		}
323a5f0fb15SPaul Saab 	} else
324a5f0fb15SPaul Saab 	{
325a5f0fb15SPaul Saab 		switch (c)
326a5f0fb15SPaul Saab 		{
327a5f0fb15SPaul Saab 		case '+':
328a5f0fb15SPaul Saab 			/* "-+" = UNSET. */
329a5f0fb15SPaul Saab 			optflag = (flag == OPT_UNSET) ?
330a5f0fb15SPaul Saab 				OPT_TOGGLE : OPT_UNSET;
331a5f0fb15SPaul Saab 			mca_opt_toggle();
332a5f0fb15SPaul Saab 			return (MCA_MORE);
333a5f0fb15SPaul Saab 		case '!':
334a5f0fb15SPaul Saab 			/* "-!" = SET */
335a5f0fb15SPaul Saab 			optflag = (flag == OPT_SET) ?
336a5f0fb15SPaul Saab 				OPT_TOGGLE : OPT_SET;
337a5f0fb15SPaul Saab 			mca_opt_toggle();
338a5f0fb15SPaul Saab 			return (MCA_MORE);
339a5f0fb15SPaul Saab 		case CONTROL('P'):
340a5f0fb15SPaul Saab 			optflag ^= OPT_NO_PROMPT;
341a5f0fb15SPaul Saab 			mca_opt_toggle();
342a5f0fb15SPaul Saab 			return (MCA_MORE);
343a5f0fb15SPaul Saab 		case '-':
344a5f0fb15SPaul Saab 			/* "--" = long option name. */
345a5f0fb15SPaul Saab 			optgetname = TRUE;
346a5f0fb15SPaul Saab 			mca_opt_toggle();
347a5f0fb15SPaul Saab 			return (MCA_MORE);
348a5f0fb15SPaul Saab 		}
349a5f0fb15SPaul Saab 	}
35033096f16SXin LI 	/* Char was not handled here. */
35133096f16SXin LI 	return (NO_MCA);
352a5f0fb15SPaul Saab }
35333096f16SXin LI 
354a5f0fb15SPaul Saab /*
35533096f16SXin LI  * Add a char to a long option name.
35633096f16SXin LI  * See if we've got a match for an option name yet.
357a5f0fb15SPaul Saab  * If so, display the complete name and stop
358a5f0fb15SPaul Saab  * accepting chars until user hits RETURN.
359a5f0fb15SPaul Saab  */
36033096f16SXin LI 	static int
361*f6b74a7dSXin LI mca_opt_nonfirst_char(c)
362*f6b74a7dSXin LI 	int c;
36333096f16SXin LI {
36433096f16SXin LI 	char *p;
365a5f0fb15SPaul Saab 	char *oname;
366a5f0fb15SPaul Saab 
36733096f16SXin LI 	if (curropt != NULL)
368a5f0fb15SPaul Saab 	{
369a5f0fb15SPaul Saab 		/*
370a5f0fb15SPaul Saab 		 * Already have a match for the name.
371a5f0fb15SPaul Saab 		 * Don't accept anything but erase/kill.
372a5f0fb15SPaul Saab 		 */
37333096f16SXin LI 		if (is_erase_char(c))
374a5f0fb15SPaul Saab 			return (MCA_DONE);
375a5f0fb15SPaul Saab 		return (MCA_MORE);
376a5f0fb15SPaul Saab 	}
377a5f0fb15SPaul Saab 	/*
378a5f0fb15SPaul Saab 	 * Add char to cmd buffer and try to match
379a5f0fb15SPaul Saab 	 * the option name.
380a5f0fb15SPaul Saab 	 */
381a5f0fb15SPaul Saab 	if (cmd_char(c) == CC_QUIT)
382a5f0fb15SPaul Saab 		return (MCA_DONE);
383a5f0fb15SPaul Saab 	p = get_cmdbuf();
38433096f16SXin LI 	opt_lower = ASCII_IS_LOWER(p[0]);
38533096f16SXin LI 	curropt = findopt_name(&p, &oname, NULL);
38633096f16SXin LI 	if (curropt != NULL)
387a5f0fb15SPaul Saab 	{
388a5f0fb15SPaul Saab 		/*
389a5f0fb15SPaul Saab 		 * Got a match.
39033096f16SXin LI 		 * Remember the option and
391a5f0fb15SPaul Saab 		 * display the full option name.
392a5f0fb15SPaul Saab 		 */
393a5f0fb15SPaul Saab 		cmd_reset();
394a5f0fb15SPaul Saab 		mca_opt_toggle();
395a5f0fb15SPaul Saab 		for (p = oname;  *p != '\0';  p++)
396a5f0fb15SPaul Saab 		{
397a5f0fb15SPaul Saab 			c = *p;
39833096f16SXin LI 			if (!opt_lower && ASCII_IS_LOWER(c))
39989dd99dcSXin LI 				c = ASCII_TO_UPPER(c);
400a5f0fb15SPaul Saab 			if (cmd_char(c) != CC_OK)
401a5f0fb15SPaul Saab 				return (MCA_DONE);
402a5f0fb15SPaul Saab 		}
403a5f0fb15SPaul Saab 	}
404a5f0fb15SPaul Saab 	return (MCA_MORE);
405a5f0fb15SPaul Saab }
40633096f16SXin LI 
40733096f16SXin LI /*
40833096f16SXin LI  * Handle a char of an option toggle command.
40933096f16SXin LI  */
41033096f16SXin LI 	static int
411*f6b74a7dSXin LI mca_opt_char(c)
412*f6b74a7dSXin LI 	int c;
41333096f16SXin LI {
41433096f16SXin LI 	PARG parg;
41533096f16SXin LI 
41633096f16SXin LI 	/*
41733096f16SXin LI 	 * This may be a short option (single char),
41833096f16SXin LI 	 * or one char of a long option name,
41933096f16SXin LI 	 * or one char of the option parameter.
42033096f16SXin LI 	 */
42133096f16SXin LI 	if (curropt == NULL && len_cmdbuf() == 0)
42233096f16SXin LI 	{
42333096f16SXin LI 		int ret = mca_opt_first_char(c);
42433096f16SXin LI 		if (ret != NO_MCA)
42533096f16SXin LI 			return (ret);
42633096f16SXin LI 	}
42733096f16SXin LI 	if (optgetname)
42833096f16SXin LI 	{
42933096f16SXin LI 		/* We're getting a long option name.  */
43033096f16SXin LI 		if (c != '\n' && c != '\r')
43133096f16SXin LI 			return (mca_opt_nonfirst_char(c));
43233096f16SXin LI 		if (curropt == NULL)
43333096f16SXin LI 		{
43433096f16SXin LI 			parg.p_string = get_cmdbuf();
43533096f16SXin LI 			error("There is no --%s option", &parg);
43633096f16SXin LI 			return (MCA_DONE);
43733096f16SXin LI 		}
43833096f16SXin LI 		optgetname = FALSE;
43933096f16SXin LI 		cmd_reset();
440a5f0fb15SPaul Saab 	} else
441a5f0fb15SPaul Saab 	{
44233096f16SXin LI 		if (is_erase_char(c))
44333096f16SXin LI 			return (NO_MCA);
44433096f16SXin LI 		if (curropt != NULL)
44533096f16SXin LI 			/* We're getting the option parameter. */
44633096f16SXin LI 			return (NO_MCA);
44733096f16SXin LI 		curropt = findopt(c);
44833096f16SXin LI 		if (curropt == NULL)
449a5f0fb15SPaul Saab 		{
45033096f16SXin LI 			parg.p_string = propt(c);
45133096f16SXin LI 			error("There is no %s option", &parg);
45233096f16SXin LI 			return (MCA_DONE);
45333096f16SXin LI 		}
45433096f16SXin LI 	}
45533096f16SXin LI 	/*
45633096f16SXin LI 	 * If the option which was entered does not take a
45733096f16SXin LI 	 * parameter, toggle the option immediately,
45833096f16SXin LI 	 * so user doesn't have to hit RETURN.
45933096f16SXin LI 	 */
46033096f16SXin LI 	if ((optflag & ~OPT_NO_PROMPT) != OPT_TOGGLE ||
46133096f16SXin LI 	    !opt_has_param(curropt))
46233096f16SXin LI 	{
46333096f16SXin LI 		toggle_option(curropt, ASCII_IS_LOWER(c), "", optflag);
464a5f0fb15SPaul Saab 		return (MCA_DONE);
465a5f0fb15SPaul Saab 	}
466a5f0fb15SPaul Saab 	/*
46733096f16SXin LI 	 * Display a prompt appropriate for the option parameter.
468a5f0fb15SPaul Saab 	 */
46933096f16SXin LI 	start_mca(A_OPT_TOGGLE, opt_prompt(curropt), (void*)NULL, 0);
470a5f0fb15SPaul Saab 	return (MCA_MORE);
47133096f16SXin LI }
472a5f0fb15SPaul Saab 
473a5f0fb15SPaul Saab /*
47433096f16SXin LI  * Handle a char of a search command.
47533096f16SXin LI  */
47633096f16SXin LI 	static int
477*f6b74a7dSXin LI mca_search_char(c)
478*f6b74a7dSXin LI 	int c;
47933096f16SXin LI {
48033096f16SXin LI 	int flag = 0;
48133096f16SXin LI 
48233096f16SXin LI 	/*
483a5f0fb15SPaul Saab 	 * Certain characters as the first char of
484a5f0fb15SPaul Saab 	 * the pattern have special meaning:
485a5f0fb15SPaul Saab 	 *	!  Toggle the NO_MATCH flag
486a5f0fb15SPaul Saab 	 *	*  Toggle the PAST_EOF flag
487a5f0fb15SPaul Saab 	 *	@  Toggle the FIRST_FILE flag
488a5f0fb15SPaul Saab 	 */
489a5f0fb15SPaul Saab 	if (len_cmdbuf() > 0)
49033096f16SXin LI 		return (NO_MCA);
491a5f0fb15SPaul Saab 
492a5f0fb15SPaul Saab 	switch (c)
493a5f0fb15SPaul Saab 	{
494a5f0fb15SPaul Saab 	case '*':
495720c436cSXin LI 		if (less_is_more)
496a8f92a7cSPaul Saab 			break;
497a8f92a7cSPaul Saab 	case CONTROL('E'): /* ignore END of file */
4987374caaaSXin LI 		if (mca != A_FILTER)
499a5f0fb15SPaul Saab 			flag = SRCH_PAST_EOF;
500a5f0fb15SPaul Saab 		break;
501a5f0fb15SPaul Saab 	case '@':
502720c436cSXin LI 		if (less_is_more)
503a8f92a7cSPaul Saab 			break;
504a8f92a7cSPaul Saab 	case CONTROL('F'): /* FIRST file */
5057374caaaSXin LI 		if (mca != A_FILTER)
506a5f0fb15SPaul Saab 			flag = SRCH_FIRST_FILE;
507a5f0fb15SPaul Saab 		break;
508a5f0fb15SPaul Saab 	case CONTROL('K'): /* KEEP position */
5097374caaaSXin LI 		if (mca != A_FILTER)
510a5f0fb15SPaul Saab 			flag = SRCH_NO_MOVE;
511a5f0fb15SPaul Saab 		break;
512a5f0fb15SPaul Saab 	case CONTROL('R'): /* Don't use REGULAR EXPRESSIONS */
513a5f0fb15SPaul Saab 		flag = SRCH_NO_REGEX;
514a5f0fb15SPaul Saab 		break;
515a5f0fb15SPaul Saab 	case CONTROL('N'): /* NOT match */
516a5f0fb15SPaul Saab 	case '!':
517a5f0fb15SPaul Saab 		flag = SRCH_NO_MATCH;
518a5f0fb15SPaul Saab 		break;
519a5f0fb15SPaul Saab 	}
52033096f16SXin LI 
521a5f0fb15SPaul Saab 	if (flag != 0)
522a5f0fb15SPaul Saab 	{
523a5f0fb15SPaul Saab 		search_type ^= flag;
524a5f0fb15SPaul Saab 		mca_search();
525a5f0fb15SPaul Saab 		return (MCA_MORE);
526a5f0fb15SPaul Saab 	}
52733096f16SXin LI 	return (NO_MCA);
52833096f16SXin LI }
52933096f16SXin LI 
53033096f16SXin LI /*
53133096f16SXin LI  * Handle a character of a multi-character command.
53233096f16SXin LI  */
53333096f16SXin LI 	static int
534*f6b74a7dSXin LI mca_char(c)
535*f6b74a7dSXin LI 	int c;
53633096f16SXin LI {
53733096f16SXin LI 	int ret;
53833096f16SXin LI 
53933096f16SXin LI 	switch (mca)
54033096f16SXin LI 	{
54133096f16SXin LI 	case 0:
54233096f16SXin LI 		/*
54333096f16SXin LI 		 * We're not in a multicharacter command.
54433096f16SXin LI 		 */
54533096f16SXin LI 		return (NO_MCA);
54633096f16SXin LI 
54733096f16SXin LI 	case A_PREFIX:
54833096f16SXin LI 		/*
54933096f16SXin LI 		 * In the prefix of a command.
55033096f16SXin LI 		 * This not considered a multichar command
55133096f16SXin LI 		 * (even tho it uses cmdbuf, etc.).
55233096f16SXin LI 		 * It is handled in the commands() switch.
55333096f16SXin LI 		 */
55433096f16SXin LI 		return (NO_MCA);
55533096f16SXin LI 
55633096f16SXin LI 	case A_DIGIT:
55733096f16SXin LI 		/*
55833096f16SXin LI 		 * Entering digits of a number.
55933096f16SXin LI 		 * Terminated by a non-digit.
56033096f16SXin LI 		 */
56133096f16SXin LI 		if (!((c >= '0' && c <= '9') || c == '.') &&
56233096f16SXin LI 		  editchar(c, EC_PEEK|EC_NOHISTORY|EC_NOCOMPLETE|EC_NORIGHTLEFT) == A_INVALID)
56333096f16SXin LI 		{
56433096f16SXin LI 			/*
56533096f16SXin LI 			 * Not part of the number.
56633096f16SXin LI 			 * End the number and treat this char
56733096f16SXin LI 			 * as a normal command character.
56833096f16SXin LI 			 */
56933096f16SXin LI 			number = cmd_int(&fraction);
57033096f16SXin LI 			mca = 0;
57133096f16SXin LI 			cmd_accept();
57233096f16SXin LI 			return (NO_MCA);
57333096f16SXin LI 		}
57433096f16SXin LI 		break;
57533096f16SXin LI 
57633096f16SXin LI 	case A_OPT_TOGGLE:
57733096f16SXin LI 		ret = mca_opt_char(c);
57833096f16SXin LI 		if (ret != NO_MCA)
57933096f16SXin LI 			return (ret);
58033096f16SXin LI 		break;
58133096f16SXin LI 
58233096f16SXin LI 	case A_F_SEARCH:
58333096f16SXin LI 	case A_B_SEARCH:
58433096f16SXin LI 	case A_FILTER:
58533096f16SXin LI 		ret = mca_search_char(c);
58633096f16SXin LI 		if (ret != NO_MCA)
58733096f16SXin LI 			return (ret);
58833096f16SXin LI 		break;
58933096f16SXin LI 
59033096f16SXin LI 	default:
59133096f16SXin LI 		/* Other multicharacter command. */
592a5f0fb15SPaul Saab 		break;
593a5f0fb15SPaul Saab 	}
594a5f0fb15SPaul Saab 
595a5f0fb15SPaul Saab 	/*
59633096f16SXin LI 	 * The multichar command is terminated by a newline.
597a5f0fb15SPaul Saab 	 */
598a5f0fb15SPaul Saab 	if (c == '\n' || c == '\r')
599a5f0fb15SPaul Saab 	{
600a5f0fb15SPaul Saab 		/*
601a5f0fb15SPaul Saab 		 * Execute the command.
602a5f0fb15SPaul Saab 		 */
603a5f0fb15SPaul Saab 		exec_mca();
604a5f0fb15SPaul Saab 		return (MCA_DONE);
605a5f0fb15SPaul Saab 	}
606a5f0fb15SPaul Saab 
607a5f0fb15SPaul Saab 	/*
608a5f0fb15SPaul Saab 	 * Append the char to the command buffer.
609a5f0fb15SPaul Saab 	 */
610a5f0fb15SPaul Saab 	if (cmd_char(c) == CC_QUIT)
611a5f0fb15SPaul Saab 		/*
612a5f0fb15SPaul Saab 		 * Abort the multi-char command.
613a5f0fb15SPaul Saab 		 */
614a5f0fb15SPaul Saab 		return (MCA_DONE);
615a5f0fb15SPaul Saab 
616a5f0fb15SPaul Saab 	if ((mca == A_F_BRACKET || mca == A_B_BRACKET) && len_cmdbuf() >= 2)
617a5f0fb15SPaul Saab 	{
618a5f0fb15SPaul Saab 		/*
619a5f0fb15SPaul Saab 		 * Special case for the bracket-matching commands.
620a5f0fb15SPaul Saab 		 * Execute the command after getting exactly two
621a5f0fb15SPaul Saab 		 * characters from the user.
622a5f0fb15SPaul Saab 		 */
623a5f0fb15SPaul Saab 		exec_mca();
624a5f0fb15SPaul Saab 		return (MCA_DONE);
625a5f0fb15SPaul Saab 	}
626a5f0fb15SPaul Saab 
627a5f0fb15SPaul Saab 	/*
628a5f0fb15SPaul Saab 	 * Need another character.
629a5f0fb15SPaul Saab 	 */
630a5f0fb15SPaul Saab 	return (MCA_MORE);
631a5f0fb15SPaul Saab }
632a5f0fb15SPaul Saab 
633a5f0fb15SPaul Saab /*
634423c5ce5SXin LI  * Discard any buffered file data.
635423c5ce5SXin LI  */
636423c5ce5SXin LI 	static void
637*f6b74a7dSXin LI clear_buffers()
638423c5ce5SXin LI {
639423c5ce5SXin LI 	if (!(ch_getflags() & CH_CANSEEK))
640423c5ce5SXin LI 		return;
641423c5ce5SXin LI 	ch_flush();
642423c5ce5SXin LI 	clr_linenum();
643423c5ce5SXin LI #if HILITE_SEARCH
644423c5ce5SXin LI 	clr_hilite();
645423c5ce5SXin LI #endif
646423c5ce5SXin LI }
647423c5ce5SXin LI 
648423c5ce5SXin LI /*
649a5f0fb15SPaul Saab  * Make sure the screen is displayed.
650a5f0fb15SPaul Saab  */
651a5f0fb15SPaul Saab 	static void
652*f6b74a7dSXin LI make_display()
653a5f0fb15SPaul Saab {
654a5f0fb15SPaul Saab 	/*
655a5f0fb15SPaul Saab 	 * If nothing is displayed yet, display starting from initial_scrpos.
656a5f0fb15SPaul Saab 	 */
657a5f0fb15SPaul Saab 	if (empty_screen())
658a5f0fb15SPaul Saab 	{
659a5f0fb15SPaul Saab 		if (initial_scrpos.pos == NULL_POSITION)
660a5f0fb15SPaul Saab 			/*
661a5f0fb15SPaul Saab 			 * {{ Maybe this should be:
662a5f0fb15SPaul Saab 			 *    jump_loc(ch_zero(), jump_sline);
663a5f0fb15SPaul Saab 			 *    but this behavior seems rather unexpected
664a5f0fb15SPaul Saab 			 *    on the first screen. }}
665a5f0fb15SPaul Saab 			 */
666a5f0fb15SPaul Saab 			jump_loc(ch_zero(), 1);
667a5f0fb15SPaul Saab 		else
668a5f0fb15SPaul Saab 			jump_loc(initial_scrpos.pos, initial_scrpos.ln);
669a5f0fb15SPaul Saab 	} else if (screen_trashed)
670a5f0fb15SPaul Saab 	{
671423c5ce5SXin LI 		int save_top_scroll = top_scroll;
672423c5ce5SXin LI 		int save_ignore_eoi = ignore_eoi;
673a5f0fb15SPaul Saab 		top_scroll = 1;
674423c5ce5SXin LI 		ignore_eoi = 0;
675423c5ce5SXin LI 		if (screen_trashed == 2)
676423c5ce5SXin LI 		{
677423c5ce5SXin LI 			/* Special case used by ignore_eoi: re-open the input file
678423c5ce5SXin LI 			 * and jump to the end of the file. */
679423c5ce5SXin LI 			reopen_curr_ifile();
680423c5ce5SXin LI 			jump_forw();
681423c5ce5SXin LI 		}
682a5f0fb15SPaul Saab 		repaint();
683a5f0fb15SPaul Saab 		top_scroll = save_top_scroll;
684423c5ce5SXin LI 		ignore_eoi = save_ignore_eoi;
685a5f0fb15SPaul Saab 	}
686a5f0fb15SPaul Saab }
687a5f0fb15SPaul Saab 
688a5f0fb15SPaul Saab /*
689a5f0fb15SPaul Saab  * Display the appropriate prompt.
690a5f0fb15SPaul Saab  */
691a5f0fb15SPaul Saab 	static void
692*f6b74a7dSXin LI prompt()
693a5f0fb15SPaul Saab {
6941ea31627SRobert Watson 	constant char *p;
695a5f0fb15SPaul Saab 
696a15691bfSXin LI 	if (ungot != NULL && !ungot->ug_end_command)
697a5f0fb15SPaul Saab 	{
698a5f0fb15SPaul Saab 		/*
699a5f0fb15SPaul Saab 		 * No prompt necessary if commands are from
700a5f0fb15SPaul Saab 		 * ungotten chars rather than from the user.
701a5f0fb15SPaul Saab 		 */
702a5f0fb15SPaul Saab 		return;
703a5f0fb15SPaul Saab 	}
704a5f0fb15SPaul Saab 
705a5f0fb15SPaul Saab 	/*
706a5f0fb15SPaul Saab 	 * Make sure the screen is displayed.
707a5f0fb15SPaul Saab 	 */
708a5f0fb15SPaul Saab 	make_display();
709a5f0fb15SPaul Saab 	bottompos = position(BOTTOM_PLUS_ONE);
710a5f0fb15SPaul Saab 
711a5f0fb15SPaul Saab 	/*
7127374caaaSXin LI 	 * If we've hit EOF on the last file and the -E flag is set, quit.
713a5f0fb15SPaul Saab 	 */
7147374caaaSXin LI 	if (get_quit_at_eof() == OPT_ONPLUS &&
7157374caaaSXin LI 	    eof_displayed() && !(ch_getflags() & CH_HELPFILE) &&
716a5f0fb15SPaul Saab 	    next_ifile(curr_ifile) == NULL_IFILE)
717a5f0fb15SPaul Saab 		quit(QUIT_OK);
7187374caaaSXin LI 
719a5f0fb15SPaul Saab 	/*
7207374caaaSXin LI 	 * If the entire file is displayed and the -F flag is set, quit.
721a5f0fb15SPaul Saab 	 */
7227374caaaSXin LI 	if (quit_if_one_screen &&
7237374caaaSXin LI 	    entire_file_displayed() && !(ch_getflags() & CH_HELPFILE) &&
724a5f0fb15SPaul Saab 	    next_ifile(curr_ifile) == NULL_IFILE)
725a5f0fb15SPaul Saab 		quit(QUIT_OK);
726a5f0fb15SPaul Saab 
7278fd4165cSPaul Saab #if MSDOS_COMPILER==WIN32C
7288fd4165cSPaul Saab 	/*
7298fd4165cSPaul Saab 	 * In Win32, display the file name in the window title.
7308fd4165cSPaul Saab 	 */
7318fd4165cSPaul Saab 	if (!(ch_getflags() & CH_HELPFILE))
7328fd4165cSPaul Saab 		SetConsoleTitle(pr_expand("Less?f - %f.", 0));
7338fd4165cSPaul Saab #endif
734a5f0fb15SPaul Saab 	/*
735a5f0fb15SPaul Saab 	 * Select the proper prompt and display it.
736a5f0fb15SPaul Saab 	 */
737720c436cSXin LI 	/*
738720c436cSXin LI 	 * If the previous action was a forward movement,
739720c436cSXin LI 	 * don't clear the bottom line of the display;
740720c436cSXin LI 	 * just print the prompt since the forward movement guarantees
741720c436cSXin LI 	 * that we're in the right position to display the prompt.
742720c436cSXin LI 	 * Clearing the line could cause a problem: for example, if the last
743720c436cSXin LI 	 * line displayed ended at the right screen edge without a newline,
744720c436cSXin LI 	 * then clearing would clear the last displayed line rather than
745720c436cSXin LI 	 * the prompt line.
746720c436cSXin LI 	 */
747720c436cSXin LI 	if (!forw_prompt)
748720c436cSXin LI 		clear_bot();
749a5f0fb15SPaul Saab 	clear_cmd();
750720c436cSXin LI 	forw_prompt = 0;
751a5f0fb15SPaul Saab 	p = pr_string();
7527374caaaSXin LI 	if (is_filtering())
7537374caaaSXin LI 		putstr("& ");
75489dd99dcSXin LI 	if (p == NULL || *p == '\0')
755a5f0fb15SPaul Saab 		putchr(':');
756a5f0fb15SPaul Saab 	else
757a5f0fb15SPaul Saab 	{
75889dd99dcSXin LI 		at_enter(AT_STANDOUT);
759a5f0fb15SPaul Saab 		putstr(p);
76089dd99dcSXin LI 		at_exit();
761a5f0fb15SPaul Saab 	}
762720c436cSXin LI 	clear_eol();
763a5f0fb15SPaul Saab }
764a5f0fb15SPaul Saab 
765a5f0fb15SPaul Saab /*
766a5f0fb15SPaul Saab  * Display the less version message.
767a5f0fb15SPaul Saab  */
768a5f0fb15SPaul Saab 	public void
769*f6b74a7dSXin LI dispversion()
770a5f0fb15SPaul Saab {
771a5f0fb15SPaul Saab 	PARG parg;
772a5f0fb15SPaul Saab 
773a5f0fb15SPaul Saab 	parg.p_string = version;
774a5f0fb15SPaul Saab 	error("less %s", &parg);
775a5f0fb15SPaul Saab }
776a5f0fb15SPaul Saab 
777a5f0fb15SPaul Saab /*
778a5f0fb15SPaul Saab  * Get command character.
779a5f0fb15SPaul Saab  * The character normally comes from the keyboard,
780a5f0fb15SPaul Saab  * but may come from ungotten characters
781a5f0fb15SPaul Saab  * (characters previously given to ungetcc or ungetsc).
782a5f0fb15SPaul Saab  */
783a5f0fb15SPaul Saab 	public int
784*f6b74a7dSXin LI getcc()
785a5f0fb15SPaul Saab {
786a15691bfSXin LI 	if (ungot == NULL)
78733096f16SXin LI 	{
788a5f0fb15SPaul Saab 		/*
789a15691bfSXin LI 		 * Normal case: no ungotten chars, so get one from the user.
790a5f0fb15SPaul Saab 		 */
791a5f0fb15SPaul Saab 		return (getchr());
792a15691bfSXin LI 	}
793a15691bfSXin LI 
794a15691bfSXin LI 	/*
795a15691bfSXin LI 	 * Return the next ungotten char.
796a15691bfSXin LI 	 */
797a15691bfSXin LI 	{
798a15691bfSXin LI 		struct ungot *ug = ungot;
799a15691bfSXin LI 		char c = ug->ug_char;
800a15691bfSXin LI 		int end_command = ug->ug_end_command;
801a15691bfSXin LI 		ungot = ug->ug_next;
802a15691bfSXin LI 		free(ug);
803a15691bfSXin LI 		if (end_command)
804a15691bfSXin LI 		{
805a5f0fb15SPaul Saab 			/*
806a5f0fb15SPaul Saab 			 * Command is incomplete, so try to complete it.
807a5f0fb15SPaul Saab 			 */
808a5f0fb15SPaul Saab 			switch (mca)
809a5f0fb15SPaul Saab 			{
810a5f0fb15SPaul Saab 			case A_DIGIT:
811a5f0fb15SPaul Saab 				/*
812a5f0fb15SPaul Saab 				 * We have a number but no command.  Treat as #g.
813a5f0fb15SPaul Saab 				 */
814a5f0fb15SPaul Saab 				return ('g');
815a5f0fb15SPaul Saab 
816a5f0fb15SPaul Saab 			case A_F_SEARCH:
817a5f0fb15SPaul Saab 			case A_B_SEARCH:
818a5f0fb15SPaul Saab 				/*
819a5f0fb15SPaul Saab 				 * We have "/string" but no newline.  Add the \n.
820a5f0fb15SPaul Saab 				 */
821a5f0fb15SPaul Saab 				return ('\n');
822a5f0fb15SPaul Saab 
823a5f0fb15SPaul Saab 			default:
824a5f0fb15SPaul Saab 				/*
825a5f0fb15SPaul Saab 				 * Some other incomplete command.  Let user complete it.
826a5f0fb15SPaul Saab 				 */
827a5f0fb15SPaul Saab 				return (getchr());
828a5f0fb15SPaul Saab 			}
829a5f0fb15SPaul Saab 		}
83033096f16SXin LI 		return (c);
83133096f16SXin LI 	}
83233096f16SXin LI }
83333096f16SXin LI 
834a5f0fb15SPaul Saab /*
835a5f0fb15SPaul Saab  * "Unget" a command character.
836a5f0fb15SPaul Saab  * The next getcc() will return this character.
837a5f0fb15SPaul Saab  */
838a5f0fb15SPaul Saab 	public void
839*f6b74a7dSXin LI ungetcc(c)
840*f6b74a7dSXin LI 	int c;
841a5f0fb15SPaul Saab {
84233096f16SXin LI 	struct ungot *ug = (struct ungot *) ecalloc(1, sizeof(struct ungot));
84333096f16SXin LI 
844a15691bfSXin LI 	ug->ug_char = (char) c;
845a15691bfSXin LI 	ug->ug_end_command = (c == CHAR_END_COMMAND);
84633096f16SXin LI 	ug->ug_next = ungot;
84733096f16SXin LI 	ungot = ug;
848a5f0fb15SPaul Saab }
849a5f0fb15SPaul Saab 
850a5f0fb15SPaul Saab /*
851a5f0fb15SPaul Saab  * Unget a whole string of command characters.
852a5f0fb15SPaul Saab  * The next sequence of getcc()'s will return this string.
853a5f0fb15SPaul Saab  */
854a5f0fb15SPaul Saab 	public void
855*f6b74a7dSXin LI ungetsc(s)
856*f6b74a7dSXin LI 	char *s;
857a5f0fb15SPaul Saab {
8581ea31627SRobert Watson 	char *p;
859a5f0fb15SPaul Saab 
860a5f0fb15SPaul Saab 	for (p = s + strlen(s) - 1;  p >= s;  p--)
861a5f0fb15SPaul Saab 		ungetcc(*p);
862a5f0fb15SPaul Saab }
863a5f0fb15SPaul Saab 
864a5f0fb15SPaul Saab /*
865a5f0fb15SPaul Saab  * Search for a pattern, possibly in multiple files.
866a5f0fb15SPaul Saab  * If SRCH_FIRST_FILE is set, begin searching at the first file.
867a5f0fb15SPaul Saab  * If SRCH_PAST_EOF is set, continue the search thru multiple files.
868a5f0fb15SPaul Saab  */
869a5f0fb15SPaul Saab 	static void
870*f6b74a7dSXin LI multi_search(pattern, n, silent)
871*f6b74a7dSXin LI 	char *pattern;
872*f6b74a7dSXin LI 	int n;
873*f6b74a7dSXin LI 	int silent;
874a5f0fb15SPaul Saab {
8751ea31627SRobert Watson 	int nomore;
876a5f0fb15SPaul Saab 	IFILE save_ifile;
877a5f0fb15SPaul Saab 	int changed_file;
878a5f0fb15SPaul Saab 
879a5f0fb15SPaul Saab 	changed_file = 0;
880a5f0fb15SPaul Saab 	save_ifile = save_curr_ifile();
881a5f0fb15SPaul Saab 
882a5f0fb15SPaul Saab 	if (search_type & SRCH_FIRST_FILE)
883a5f0fb15SPaul Saab 	{
884a5f0fb15SPaul Saab 		/*
885a5f0fb15SPaul Saab 		 * Start at the first (or last) file
886a5f0fb15SPaul Saab 		 * in the command line list.
887a5f0fb15SPaul Saab 		 */
888a5f0fb15SPaul Saab 		if (search_type & SRCH_FORW)
889a5f0fb15SPaul Saab 			nomore = edit_first();
890a5f0fb15SPaul Saab 		else
891a5f0fb15SPaul Saab 			nomore = edit_last();
892a5f0fb15SPaul Saab 		if (nomore)
893a5f0fb15SPaul Saab 		{
894a5f0fb15SPaul Saab 			unsave_ifile(save_ifile);
895a5f0fb15SPaul Saab 			return;
896a5f0fb15SPaul Saab 		}
897a5f0fb15SPaul Saab 		changed_file = 1;
898a5f0fb15SPaul Saab 		search_type &= ~SRCH_FIRST_FILE;
899a5f0fb15SPaul Saab 	}
900a5f0fb15SPaul Saab 
901a5f0fb15SPaul Saab 	for (;;)
902a5f0fb15SPaul Saab 	{
903a5f0fb15SPaul Saab 		n = search(search_type, pattern, n);
904a5f0fb15SPaul Saab 		/*
905a5f0fb15SPaul Saab 		 * The SRCH_NO_MOVE flag doesn't "stick": it gets cleared
906a5f0fb15SPaul Saab 		 * after being used once.  This allows "n" to work after
907a5f0fb15SPaul Saab 		 * using a /@@ search.
908a5f0fb15SPaul Saab 		 */
909a5f0fb15SPaul Saab 		search_type &= ~SRCH_NO_MOVE;
910a5f0fb15SPaul Saab 		if (n == 0)
911a5f0fb15SPaul Saab 		{
912a5f0fb15SPaul Saab 			/*
913a5f0fb15SPaul Saab 			 * Found it.
914a5f0fb15SPaul Saab 			 */
915a5f0fb15SPaul Saab 			unsave_ifile(save_ifile);
916a5f0fb15SPaul Saab 			return;
917a5f0fb15SPaul Saab 		}
918a5f0fb15SPaul Saab 
919a5f0fb15SPaul Saab 		if (n < 0)
920a5f0fb15SPaul Saab 			/*
921a5f0fb15SPaul Saab 			 * Some kind of error in the search.
922a5f0fb15SPaul Saab 			 * Error message has been printed by search().
923a5f0fb15SPaul Saab 			 */
924a5f0fb15SPaul Saab 			break;
925a5f0fb15SPaul Saab 
926a5f0fb15SPaul Saab 		if ((search_type & SRCH_PAST_EOF) == 0)
927a5f0fb15SPaul Saab 			/*
928a5f0fb15SPaul Saab 			 * We didn't find a match, but we're
929a5f0fb15SPaul Saab 			 * supposed to search only one file.
930a5f0fb15SPaul Saab 			 */
931a5f0fb15SPaul Saab 			break;
932a5f0fb15SPaul Saab 		/*
933a5f0fb15SPaul Saab 		 * Move on to the next file.
934a5f0fb15SPaul Saab 		 */
935a5f0fb15SPaul Saab 		if (search_type & SRCH_FORW)
936a5f0fb15SPaul Saab 			nomore = edit_next(1);
937a5f0fb15SPaul Saab 		else
938a5f0fb15SPaul Saab 			nomore = edit_prev(1);
939a5f0fb15SPaul Saab 		if (nomore)
940a5f0fb15SPaul Saab 			break;
941a5f0fb15SPaul Saab 		changed_file = 1;
942a5f0fb15SPaul Saab 	}
943a5f0fb15SPaul Saab 
944a5f0fb15SPaul Saab 	/*
945a5f0fb15SPaul Saab 	 * Didn't find it.
946a5f0fb15SPaul Saab 	 * Print an error message if we haven't already.
947a5f0fb15SPaul Saab 	 */
948a15691bfSXin LI 	if (n > 0 && !silent)
949a5f0fb15SPaul Saab 		error("Pattern not found", NULL_PARG);
950a5f0fb15SPaul Saab 
951a5f0fb15SPaul Saab 	if (changed_file)
952a5f0fb15SPaul Saab 	{
953a5f0fb15SPaul Saab 		/*
954a5f0fb15SPaul Saab 		 * Restore the file we were originally viewing.
955a5f0fb15SPaul Saab 		 */
956a5f0fb15SPaul Saab 		reedit_ifile(save_ifile);
95789dd99dcSXin LI 	} else
95889dd99dcSXin LI 	{
95989dd99dcSXin LI 		unsave_ifile(save_ifile);
960a5f0fb15SPaul Saab 	}
961a5f0fb15SPaul Saab }
962a5f0fb15SPaul Saab 
963a5f0fb15SPaul Saab /*
96496e55cc7SXin LI  * Forward forever, or until a highlighted line appears.
96596e55cc7SXin LI  */
96696e55cc7SXin LI 	static int
967*f6b74a7dSXin LI forw_loop(until_hilite)
968*f6b74a7dSXin LI 	int until_hilite;
96996e55cc7SXin LI {
97096e55cc7SXin LI 	POSITION curr_len;
97196e55cc7SXin LI 
97296e55cc7SXin LI 	if (ch_getflags() & CH_HELPFILE)
97396e55cc7SXin LI 		return (A_NOACTION);
97496e55cc7SXin LI 
97596e55cc7SXin LI 	cmd_exec();
976a15691bfSXin LI 	jump_forw_buffered();
97796e55cc7SXin LI 	curr_len = ch_length();
97896e55cc7SXin LI 	highest_hilite = until_hilite ? curr_len : NULL_POSITION;
97996e55cc7SXin LI 	ignore_eoi = 1;
98096e55cc7SXin LI 	while (!sigs)
98196e55cc7SXin LI 	{
98296e55cc7SXin LI 		if (until_hilite && highest_hilite > curr_len)
98396e55cc7SXin LI 		{
98496e55cc7SXin LI 			bell();
98596e55cc7SXin LI 			break;
98696e55cc7SXin LI 		}
98796e55cc7SXin LI 		make_display();
98896e55cc7SXin LI 		forward(1, 0, 0);
98996e55cc7SXin LI 	}
99096e55cc7SXin LI 	ignore_eoi = 0;
991e2449719SXin LI 	ch_set_eof();
99296e55cc7SXin LI 
99396e55cc7SXin LI 	/*
99496e55cc7SXin LI 	 * This gets us back in "F mode" after processing
99596e55cc7SXin LI 	 * a non-abort signal (e.g. window-change).
99696e55cc7SXin LI 	 */
99796e55cc7SXin LI 	if (sigs && !ABORT_SIGS())
998e2449719SXin LI 		return (until_hilite ? A_F_UNTIL_HILITE : A_F_FOREVER);
999e2449719SXin LI 
100096e55cc7SXin LI 	return (A_NOACTION);
100196e55cc7SXin LI }
100296e55cc7SXin LI 
100396e55cc7SXin LI /*
1004a5f0fb15SPaul Saab  * Main command processor.
1005a5f0fb15SPaul Saab  * Accept and execute commands until a quit command.
1006a5f0fb15SPaul Saab  */
1007a5f0fb15SPaul Saab 	public void
1008*f6b74a7dSXin LI commands()
1009a5f0fb15SPaul Saab {
10101ea31627SRobert Watson 	int c;
10111ea31627SRobert Watson 	int action;
10121ea31627SRobert Watson 	char *cbuf;
1013a5f0fb15SPaul Saab 	int newaction;
1014a5f0fb15SPaul Saab 	int save_search_type;
1015a5f0fb15SPaul Saab 	char *extra;
1016a5f0fb15SPaul Saab 	char tbuf[2];
1017a5f0fb15SPaul Saab 	PARG parg;
1018a5f0fb15SPaul Saab 	IFILE old_ifile;
1019a5f0fb15SPaul Saab 	IFILE new_ifile;
10208fd4165cSPaul Saab 	char *tagfile;
1021a5f0fb15SPaul Saab 
1022a5f0fb15SPaul Saab 	search_type = SRCH_FORW;
1023a5f0fb15SPaul Saab 	wscroll = (sc_height + 1) / 2;
1024a5f0fb15SPaul Saab 	newaction = A_NOACTION;
1025a5f0fb15SPaul Saab 
1026a5f0fb15SPaul Saab 	for (;;)
1027a5f0fb15SPaul Saab 	{
1028a5f0fb15SPaul Saab 		mca = 0;
1029a5f0fb15SPaul Saab 		cmd_accept();
1030a5f0fb15SPaul Saab 		number = 0;
103133096f16SXin LI 		curropt = NULL;
1032a5f0fb15SPaul Saab 
1033a5f0fb15SPaul Saab 		/*
1034a5f0fb15SPaul Saab 		 * See if any signals need processing.
1035a5f0fb15SPaul Saab 		 */
1036a5f0fb15SPaul Saab 		if (sigs)
1037a5f0fb15SPaul Saab 		{
1038a5f0fb15SPaul Saab 			psignals();
1039a5f0fb15SPaul Saab 			if (quitting)
1040a5f0fb15SPaul Saab 				quit(QUIT_SAVED_STATUS);
1041a5f0fb15SPaul Saab 		}
1042a5f0fb15SPaul Saab 
1043a5f0fb15SPaul Saab 		/*
1044a5f0fb15SPaul Saab 		 * See if window size changed, for systems that don't
1045a5f0fb15SPaul Saab 		 * generate SIGWINCH.
1046a5f0fb15SPaul Saab 		 */
1047a5f0fb15SPaul Saab 		check_winch();
1048a5f0fb15SPaul Saab 
1049a5f0fb15SPaul Saab 		/*
1050a5f0fb15SPaul Saab 		 * Display prompt and accept a character.
1051a5f0fb15SPaul Saab 		 */
1052a5f0fb15SPaul Saab 		cmd_reset();
1053a5f0fb15SPaul Saab 		prompt();
1054a5f0fb15SPaul Saab 		if (sigs)
1055a5f0fb15SPaul Saab 			continue;
1056a5f0fb15SPaul Saab 		if (newaction == A_NOACTION)
1057a5f0fb15SPaul Saab 			c = getcc();
1058a5f0fb15SPaul Saab 
1059a5f0fb15SPaul Saab 	again:
1060a5f0fb15SPaul Saab 		if (sigs)
1061a5f0fb15SPaul Saab 			continue;
1062a5f0fb15SPaul Saab 
1063a5f0fb15SPaul Saab 		if (newaction != A_NOACTION)
1064a5f0fb15SPaul Saab 		{
1065a5f0fb15SPaul Saab 			action = newaction;
1066a5f0fb15SPaul Saab 			newaction = A_NOACTION;
1067a5f0fb15SPaul Saab 		} else
1068a5f0fb15SPaul Saab 		{
1069a5f0fb15SPaul Saab 			/*
1070a5f0fb15SPaul Saab 			 * If we are in a multicharacter command, call mca_char.
1071a5f0fb15SPaul Saab 			 * Otherwise we call fcmd_decode to determine the
1072a5f0fb15SPaul Saab 			 * action to be performed.
1073a5f0fb15SPaul Saab 			 */
1074a5f0fb15SPaul Saab 			if (mca)
1075a5f0fb15SPaul Saab 				switch (mca_char(c))
1076a5f0fb15SPaul Saab 				{
1077a5f0fb15SPaul Saab 				case MCA_MORE:
1078a5f0fb15SPaul Saab 					/*
1079a5f0fb15SPaul Saab 					 * Need another character.
1080a5f0fb15SPaul Saab 					 */
1081a5f0fb15SPaul Saab 					c = getcc();
1082a5f0fb15SPaul Saab 					goto again;
1083a5f0fb15SPaul Saab 				case MCA_DONE:
1084a5f0fb15SPaul Saab 					/*
1085a5f0fb15SPaul Saab 					 * Command has been handled by mca_char.
1086a5f0fb15SPaul Saab 					 * Start clean with a prompt.
1087a5f0fb15SPaul Saab 					 */
1088a5f0fb15SPaul Saab 					continue;
1089a5f0fb15SPaul Saab 				case NO_MCA:
1090a5f0fb15SPaul Saab 					/*
1091a5f0fb15SPaul Saab 					 * Not a multi-char command
1092a5f0fb15SPaul Saab 					 * (at least, not anymore).
1093a5f0fb15SPaul Saab 					 */
1094a5f0fb15SPaul Saab 					break;
1095a5f0fb15SPaul Saab 				}
1096a5f0fb15SPaul Saab 
1097a5f0fb15SPaul Saab 			/*
1098a5f0fb15SPaul Saab 			 * Decode the command character and decide what to do.
1099a5f0fb15SPaul Saab 			 */
1100a5f0fb15SPaul Saab 			if (mca)
1101a5f0fb15SPaul Saab 			{
1102a5f0fb15SPaul Saab 				/*
1103a5f0fb15SPaul Saab 				 * We're in a multichar command.
1104a5f0fb15SPaul Saab 				 * Add the character to the command buffer
1105a5f0fb15SPaul Saab 				 * and display it on the screen.
1106a5f0fb15SPaul Saab 				 * If the user backspaces past the start
1107a5f0fb15SPaul Saab 				 * of the line, abort the command.
1108a5f0fb15SPaul Saab 				 */
1109a5f0fb15SPaul Saab 				if (cmd_char(c) == CC_QUIT || len_cmdbuf() == 0)
1110a5f0fb15SPaul Saab 					continue;
1111a5f0fb15SPaul Saab 				cbuf = get_cmdbuf();
1112a5f0fb15SPaul Saab 			} else
1113a5f0fb15SPaul Saab 			{
1114a5f0fb15SPaul Saab 				/*
1115a5f0fb15SPaul Saab 				 * Don't use cmd_char if we're starting fresh
1116a5f0fb15SPaul Saab 				 * at the beginning of a command, because we
1117a5f0fb15SPaul Saab 				 * don't want to echo the command until we know
1118a5f0fb15SPaul Saab 				 * it is a multichar command.  We also don't
1119a5f0fb15SPaul Saab 				 * want erase_char/kill_char to be treated
1120a5f0fb15SPaul Saab 				 * as line editing characters.
1121a5f0fb15SPaul Saab 				 */
1122a5f0fb15SPaul Saab 				tbuf[0] = c;
1123a5f0fb15SPaul Saab 				tbuf[1] = '\0';
1124a5f0fb15SPaul Saab 				cbuf = tbuf;
1125a5f0fb15SPaul Saab 			}
1126a5f0fb15SPaul Saab 			extra = NULL;
1127a5f0fb15SPaul Saab 			action = fcmd_decode(cbuf, &extra);
1128a5f0fb15SPaul Saab 			/*
1129a5f0fb15SPaul Saab 			 * If an "extra" string was returned,
1130a5f0fb15SPaul Saab 			 * process it as a string of command characters.
1131a5f0fb15SPaul Saab 			 */
1132a5f0fb15SPaul Saab 			if (extra != NULL)
1133a5f0fb15SPaul Saab 				ungetsc(extra);
1134a5f0fb15SPaul Saab 		}
1135a5f0fb15SPaul Saab 		/*
1136a5f0fb15SPaul Saab 		 * Clear the cmdbuf string.
1137a5f0fb15SPaul Saab 		 * (But not if we're in the prefix of a command,
1138a5f0fb15SPaul Saab 		 * because the partial command string is kept there.)
1139a5f0fb15SPaul Saab 		 */
1140a5f0fb15SPaul Saab 		if (action != A_PREFIX)
1141a5f0fb15SPaul Saab 			cmd_reset();
1142a5f0fb15SPaul Saab 
1143a5f0fb15SPaul Saab 		switch (action)
1144a5f0fb15SPaul Saab 		{
1145a5f0fb15SPaul Saab 		case A_DIGIT:
1146a5f0fb15SPaul Saab 			/*
1147a5f0fb15SPaul Saab 			 * First digit of a number.
1148a5f0fb15SPaul Saab 			 */
1149a5f0fb15SPaul Saab 			start_mca(A_DIGIT, ":", (void*)NULL, CF_QUIT_ON_ERASE);
1150a5f0fb15SPaul Saab 			goto again;
1151a5f0fb15SPaul Saab 
1152a5f0fb15SPaul Saab 		case A_F_WINDOW:
1153a5f0fb15SPaul Saab 			/*
1154a5f0fb15SPaul Saab 			 * Forward one window (and set the window size).
1155a5f0fb15SPaul Saab 			 */
1156a5f0fb15SPaul Saab 			if (number > 0)
11571ede1615STim J. Robbins 				swindow = (int) number;
1158a5f0fb15SPaul Saab 			/* FALLTHRU */
1159a5f0fb15SPaul Saab 		case A_F_SCREEN:
1160a5f0fb15SPaul Saab 			/*
1161a5f0fb15SPaul Saab 			 * Forward one screen.
1162a5f0fb15SPaul Saab 			 */
1163a5f0fb15SPaul Saab 			if (number <= 0)
1164a5f0fb15SPaul Saab 				number = get_swindow();
1165a5f0fb15SPaul Saab 			cmd_exec();
1166a5f0fb15SPaul Saab 			if (show_attn)
1167a5f0fb15SPaul Saab 				set_attnpos(bottompos);
11681ede1615STim J. Robbins 			forward((int) number, 0, 1);
1169a5f0fb15SPaul Saab 			break;
1170a5f0fb15SPaul Saab 
1171a5f0fb15SPaul Saab 		case A_B_WINDOW:
1172a5f0fb15SPaul Saab 			/*
1173a5f0fb15SPaul Saab 			 * Backward one window (and set the window size).
1174a5f0fb15SPaul Saab 			 */
1175a5f0fb15SPaul Saab 			if (number > 0)
11761ede1615STim J. Robbins 				swindow = (int) number;
1177a5f0fb15SPaul Saab 			/* FALLTHRU */
1178a5f0fb15SPaul Saab 		case A_B_SCREEN:
1179a5f0fb15SPaul Saab 			/*
1180a5f0fb15SPaul Saab 			 * Backward one screen.
1181a5f0fb15SPaul Saab 			 */
1182a5f0fb15SPaul Saab 			if (number <= 0)
1183a5f0fb15SPaul Saab 				number = get_swindow();
1184a5f0fb15SPaul Saab 			cmd_exec();
11851ede1615STim J. Robbins 			backward((int) number, 0, 1);
1186a5f0fb15SPaul Saab 			break;
1187a5f0fb15SPaul Saab 
1188a5f0fb15SPaul Saab 		case A_F_LINE:
1189a5f0fb15SPaul Saab 			/*
1190a5f0fb15SPaul Saab 			 * Forward N (default 1) line.
1191a5f0fb15SPaul Saab 			 */
1192a5f0fb15SPaul Saab 			if (number <= 0)
1193a5f0fb15SPaul Saab 				number = 1;
1194a5f0fb15SPaul Saab 			cmd_exec();
1195a5f0fb15SPaul Saab 			if (show_attn == OPT_ONPLUS && number > 1)
1196a5f0fb15SPaul Saab 				set_attnpos(bottompos);
11971ede1615STim J. Robbins 			forward((int) number, 0, 0);
1198a5f0fb15SPaul Saab 			break;
1199a5f0fb15SPaul Saab 
1200a5f0fb15SPaul Saab 		case A_B_LINE:
1201a5f0fb15SPaul Saab 			/*
1202a5f0fb15SPaul Saab 			 * Backward N (default 1) line.
1203a5f0fb15SPaul Saab 			 */
1204a5f0fb15SPaul Saab 			if (number <= 0)
1205a5f0fb15SPaul Saab 				number = 1;
1206a5f0fb15SPaul Saab 			cmd_exec();
12071ede1615STim J. Robbins 			backward((int) number, 0, 0);
1208a5f0fb15SPaul Saab 			break;
1209a5f0fb15SPaul Saab 
1210a5f0fb15SPaul Saab 		case A_FF_LINE:
1211a5f0fb15SPaul Saab 			/*
1212a5f0fb15SPaul Saab 			 * Force forward N (default 1) line.
1213a5f0fb15SPaul Saab 			 */
1214a5f0fb15SPaul Saab 			if (number <= 0)
1215a5f0fb15SPaul Saab 				number = 1;
1216a5f0fb15SPaul Saab 			cmd_exec();
1217a5f0fb15SPaul Saab 			if (show_attn == OPT_ONPLUS && number > 1)
1218a5f0fb15SPaul Saab 				set_attnpos(bottompos);
12191ede1615STim J. Robbins 			forward((int) number, 1, 0);
1220a5f0fb15SPaul Saab 			break;
1221a5f0fb15SPaul Saab 
1222a5f0fb15SPaul Saab 		case A_BF_LINE:
1223a5f0fb15SPaul Saab 			/*
1224a5f0fb15SPaul Saab 			 * Force backward N (default 1) line.
1225a5f0fb15SPaul Saab 			 */
1226a5f0fb15SPaul Saab 			if (number <= 0)
1227a5f0fb15SPaul Saab 				number = 1;
1228a5f0fb15SPaul Saab 			cmd_exec();
12291ede1615STim J. Robbins 			backward((int) number, 1, 0);
1230a5f0fb15SPaul Saab 			break;
1231a5f0fb15SPaul Saab 
1232a5f0fb15SPaul Saab 		case A_FF_SCREEN:
1233a5f0fb15SPaul Saab 			/*
1234a5f0fb15SPaul Saab 			 * Force forward one screen.
1235a5f0fb15SPaul Saab 			 */
1236a5f0fb15SPaul Saab 			if (number <= 0)
1237a5f0fb15SPaul Saab 				number = get_swindow();
1238a5f0fb15SPaul Saab 			cmd_exec();
1239a5f0fb15SPaul Saab 			if (show_attn == OPT_ONPLUS)
1240a5f0fb15SPaul Saab 				set_attnpos(bottompos);
12411ede1615STim J. Robbins 			forward((int) number, 1, 0);
1242a5f0fb15SPaul Saab 			break;
1243a5f0fb15SPaul Saab 
1244a5f0fb15SPaul Saab 		case A_F_FOREVER:
1245a5f0fb15SPaul Saab 			/*
1246a5f0fb15SPaul Saab 			 * Forward forever, ignoring EOF.
1247a5f0fb15SPaul Saab 			 */
1248a15691bfSXin LI 			if (show_attn)
1249a15691bfSXin LI 				set_attnpos(bottompos);
125096e55cc7SXin LI 			newaction = forw_loop(0);
1251a5f0fb15SPaul Saab 			break;
125296e55cc7SXin LI 
125396e55cc7SXin LI 		case A_F_UNTIL_HILITE:
125496e55cc7SXin LI 			newaction = forw_loop(1);
1255a5f0fb15SPaul Saab 			break;
1256a5f0fb15SPaul Saab 
1257a5f0fb15SPaul Saab 		case A_F_SCROLL:
1258a5f0fb15SPaul Saab 			/*
1259a5f0fb15SPaul Saab 			 * Forward N lines
1260a5f0fb15SPaul Saab 			 * (default same as last 'd' or 'u' command).
1261a5f0fb15SPaul Saab 			 */
1262a5f0fb15SPaul Saab 			if (number > 0)
12631ede1615STim J. Robbins 				wscroll = (int) number;
1264a5f0fb15SPaul Saab 			cmd_exec();
1265a5f0fb15SPaul Saab 			if (show_attn == OPT_ONPLUS)
1266a5f0fb15SPaul Saab 				set_attnpos(bottompos);
1267a5f0fb15SPaul Saab 			forward(wscroll, 0, 0);
1268a5f0fb15SPaul Saab 			break;
1269a5f0fb15SPaul Saab 
1270a5f0fb15SPaul Saab 		case A_B_SCROLL:
1271a5f0fb15SPaul Saab 			/*
1272a5f0fb15SPaul Saab 			 * Forward N lines
1273a5f0fb15SPaul Saab 			 * (default same as last 'd' or 'u' command).
1274a5f0fb15SPaul Saab 			 */
1275a5f0fb15SPaul Saab 			if (number > 0)
12761ede1615STim J. Robbins 				wscroll = (int) number;
1277a5f0fb15SPaul Saab 			cmd_exec();
1278a5f0fb15SPaul Saab 			backward(wscroll, 0, 0);
1279a5f0fb15SPaul Saab 			break;
1280a5f0fb15SPaul Saab 
1281a5f0fb15SPaul Saab 		case A_FREPAINT:
1282a5f0fb15SPaul Saab 			/*
1283a5f0fb15SPaul Saab 			 * Flush buffers, then repaint screen.
1284a5f0fb15SPaul Saab 			 * Don't flush the buffers on a pipe!
1285a5f0fb15SPaul Saab 			 */
1286423c5ce5SXin LI 			clear_buffers();
1287a5f0fb15SPaul Saab 			/* FALLTHRU */
1288a5f0fb15SPaul Saab 		case A_REPAINT:
1289a5f0fb15SPaul Saab 			/*
1290a5f0fb15SPaul Saab 			 * Repaint screen.
1291a5f0fb15SPaul Saab 			 */
1292a5f0fb15SPaul Saab 			cmd_exec();
1293a5f0fb15SPaul Saab 			repaint();
1294a5f0fb15SPaul Saab 			break;
1295a5f0fb15SPaul Saab 
1296a5f0fb15SPaul Saab 		case A_GOLINE:
1297a5f0fb15SPaul Saab 			/*
1298a5f0fb15SPaul Saab 			 * Go to line N, default beginning of file.
1299a5f0fb15SPaul Saab 			 */
1300a5f0fb15SPaul Saab 			if (number <= 0)
1301a5f0fb15SPaul Saab 				number = 1;
1302a5f0fb15SPaul Saab 			cmd_exec();
1303a5f0fb15SPaul Saab 			jump_back(number);
1304a5f0fb15SPaul Saab 			break;
1305a5f0fb15SPaul Saab 
1306a5f0fb15SPaul Saab 		case A_PERCENT:
1307a5f0fb15SPaul Saab 			/*
1308a5f0fb15SPaul Saab 			 * Go to a specified percentage into the file.
1309a5f0fb15SPaul Saab 			 */
1310a5f0fb15SPaul Saab 			if (number < 0)
1311720c436cSXin LI 			{
1312a5f0fb15SPaul Saab 				number = 0;
1313720c436cSXin LI 				fraction = 0;
1314720c436cSXin LI 			}
1315a5f0fb15SPaul Saab 			if (number > 100)
1316720c436cSXin LI 			{
1317a5f0fb15SPaul Saab 				number = 100;
1318720c436cSXin LI 				fraction = 0;
1319720c436cSXin LI 			}
1320a5f0fb15SPaul Saab 			cmd_exec();
1321720c436cSXin LI 			jump_percent((int) number, fraction);
1322a5f0fb15SPaul Saab 			break;
1323a5f0fb15SPaul Saab 
1324a5f0fb15SPaul Saab 		case A_GOEND:
1325a5f0fb15SPaul Saab 			/*
1326a5f0fb15SPaul Saab 			 * Go to line N, default end of file.
1327a5f0fb15SPaul Saab 			 */
1328a5f0fb15SPaul Saab 			cmd_exec();
1329a5f0fb15SPaul Saab 			if (number <= 0)
1330a5f0fb15SPaul Saab 				jump_forw();
1331a5f0fb15SPaul Saab 			else
1332a5f0fb15SPaul Saab 				jump_back(number);
1333a5f0fb15SPaul Saab 			break;
1334a5f0fb15SPaul Saab 
1335a15691bfSXin LI 		case A_GOEND_BUF:
1336a15691bfSXin LI 			/*
1337a15691bfSXin LI 			 * Go to line N, default last buffered byte.
1338a15691bfSXin LI 			 */
1339a15691bfSXin LI 			cmd_exec();
1340a15691bfSXin LI 			if (number <= 0)
1341a15691bfSXin LI 				jump_forw_buffered();
1342a15691bfSXin LI 			else
1343a15691bfSXin LI 				jump_back(number);
1344a15691bfSXin LI 			break;
1345a15691bfSXin LI 
1346a5f0fb15SPaul Saab 		case A_GOPOS:
1347a5f0fb15SPaul Saab 			/*
1348a5f0fb15SPaul Saab 			 * Go to a specified byte position in the file.
1349a5f0fb15SPaul Saab 			 */
1350a5f0fb15SPaul Saab 			cmd_exec();
1351a5f0fb15SPaul Saab 			if (number < 0)
1352a5f0fb15SPaul Saab 				number = 0;
1353a5f0fb15SPaul Saab 			jump_line_loc((POSITION) number, jump_sline);
1354a5f0fb15SPaul Saab 			break;
1355a5f0fb15SPaul Saab 
1356a5f0fb15SPaul Saab 		case A_STAT:
1357a5f0fb15SPaul Saab 			/*
1358a5f0fb15SPaul Saab 			 * Print file name, etc.
1359a5f0fb15SPaul Saab 			 */
1360a5f0fb15SPaul Saab 			if (ch_getflags() & CH_HELPFILE)
1361a5f0fb15SPaul Saab 				break;
1362a5f0fb15SPaul Saab 			cmd_exec();
1363a5f0fb15SPaul Saab 			parg.p_string = eq_message();
1364a5f0fb15SPaul Saab 			error("%s", &parg);
1365a5f0fb15SPaul Saab 			break;
1366a5f0fb15SPaul Saab 
1367a5f0fb15SPaul Saab 		case A_VERSION:
1368a5f0fb15SPaul Saab 			/*
1369a5f0fb15SPaul Saab 			 * Print version number, without the "@(#)".
1370a5f0fb15SPaul Saab 			 */
1371a5f0fb15SPaul Saab 			cmd_exec();
1372a5f0fb15SPaul Saab 			dispversion();
1373a5f0fb15SPaul Saab 			break;
1374a5f0fb15SPaul Saab 
1375a5f0fb15SPaul Saab 		case A_QUIT:
1376a5f0fb15SPaul Saab 			/*
1377a5f0fb15SPaul Saab 			 * Exit.
1378a5f0fb15SPaul Saab 			 */
1379a5f0fb15SPaul Saab 			if (curr_ifile != NULL_IFILE &&
1380a5f0fb15SPaul Saab 			    ch_getflags() & CH_HELPFILE)
1381a5f0fb15SPaul Saab 			{
1382a5f0fb15SPaul Saab 				/*
1383a5f0fb15SPaul Saab 				 * Quit while viewing the help file
1384a5f0fb15SPaul Saab 				 * just means return to viewing the
1385a5f0fb15SPaul Saab 				 * previous file.
1386a5f0fb15SPaul Saab 				 */
138789dd99dcSXin LI 				hshift = save_hshift;
1388a15691bfSXin LI 				bs_mode = save_bs_mode;
1389a5f0fb15SPaul Saab 				if (edit_prev(1) == 0)
1390a5f0fb15SPaul Saab 					break;
1391a5f0fb15SPaul Saab 			}
1392a5f0fb15SPaul Saab 			if (extra != NULL)
1393a5f0fb15SPaul Saab 				quit(*extra);
1394a5f0fb15SPaul Saab 			quit(QUIT_OK);
1395a5f0fb15SPaul Saab 			break;
1396a5f0fb15SPaul Saab 
1397a5f0fb15SPaul Saab /*
1398a5f0fb15SPaul Saab  * Define abbreviation for a commonly used sequence below.
1399a5f0fb15SPaul Saab  */
1400423c5ce5SXin LI #define	DO_SEARCH() \
1401423c5ce5SXin LI 			if (number <= 0) number = 1;	\
1402a5f0fb15SPaul Saab 			mca_search();			\
1403a5f0fb15SPaul Saab 			cmd_exec();			\
1404a15691bfSXin LI 			multi_search((char *)NULL, (int) number, 0);
1405a5f0fb15SPaul Saab 
1406a5f0fb15SPaul Saab 
1407a5f0fb15SPaul Saab 		case A_F_SEARCH:
1408a5f0fb15SPaul Saab 			/*
1409a5f0fb15SPaul Saab 			 * Search forward for a pattern.
1410a5f0fb15SPaul Saab 			 * Get the first char of the pattern.
1411a5f0fb15SPaul Saab 			 */
1412a5f0fb15SPaul Saab 			search_type = SRCH_FORW;
1413a5f0fb15SPaul Saab 			if (number <= 0)
1414a5f0fb15SPaul Saab 				number = 1;
1415a5f0fb15SPaul Saab 			mca_search();
1416a5f0fb15SPaul Saab 			c = getcc();
1417a5f0fb15SPaul Saab 			goto again;
1418a5f0fb15SPaul Saab 
1419a5f0fb15SPaul Saab 		case A_B_SEARCH:
1420a5f0fb15SPaul Saab 			/*
1421a5f0fb15SPaul Saab 			 * Search backward for a pattern.
1422a5f0fb15SPaul Saab 			 * Get the first char of the pattern.
1423a5f0fb15SPaul Saab 			 */
1424a5f0fb15SPaul Saab 			search_type = SRCH_BACK;
1425a5f0fb15SPaul Saab 			if (number <= 0)
1426a5f0fb15SPaul Saab 				number = 1;
1427a5f0fb15SPaul Saab 			mca_search();
1428a5f0fb15SPaul Saab 			c = getcc();
1429a5f0fb15SPaul Saab 			goto again;
1430a5f0fb15SPaul Saab 
14317374caaaSXin LI 		case A_FILTER:
14327374caaaSXin LI #if HILITE_SEARCH
14337374caaaSXin LI 			search_type = SRCH_FORW | SRCH_FILTER;
14347374caaaSXin LI 			mca_search();
14357374caaaSXin LI 			c = getcc();
14367374caaaSXin LI 			goto again;
14377374caaaSXin LI #else
14387374caaaSXin LI 			error("Command not available", NULL_PARG);
14397374caaaSXin LI 			break;
14407374caaaSXin LI #endif
14417374caaaSXin LI 
1442a5f0fb15SPaul Saab 		case A_AGAIN_SEARCH:
1443a5f0fb15SPaul Saab 			/*
1444a5f0fb15SPaul Saab 			 * Repeat previous search.
1445a5f0fb15SPaul Saab 			 */
1446a5f0fb15SPaul Saab 			DO_SEARCH();
1447a5f0fb15SPaul Saab 			break;
1448a5f0fb15SPaul Saab 
1449a5f0fb15SPaul Saab 		case A_T_AGAIN_SEARCH:
1450a5f0fb15SPaul Saab 			/*
1451a5f0fb15SPaul Saab 			 * Repeat previous search, multiple files.
1452a5f0fb15SPaul Saab 			 */
1453a5f0fb15SPaul Saab 			search_type |= SRCH_PAST_EOF;
1454a5f0fb15SPaul Saab 			DO_SEARCH();
1455a5f0fb15SPaul Saab 			break;
1456a5f0fb15SPaul Saab 
1457a5f0fb15SPaul Saab 		case A_REVERSE_SEARCH:
1458a5f0fb15SPaul Saab 			/*
1459a5f0fb15SPaul Saab 			 * Repeat previous search, in reverse direction.
1460a5f0fb15SPaul Saab 			 */
1461a5f0fb15SPaul Saab 			save_search_type = search_type;
1462a5f0fb15SPaul Saab 			search_type = SRCH_REVERSE(search_type);
1463a5f0fb15SPaul Saab 			DO_SEARCH();
1464a5f0fb15SPaul Saab 			search_type = save_search_type;
1465a5f0fb15SPaul Saab 			break;
1466a5f0fb15SPaul Saab 
1467a5f0fb15SPaul Saab 		case A_T_REVERSE_SEARCH:
1468a5f0fb15SPaul Saab 			/*
1469a5f0fb15SPaul Saab 			 * Repeat previous search,
1470a5f0fb15SPaul Saab 			 * multiple files in reverse direction.
1471a5f0fb15SPaul Saab 			 */
1472a5f0fb15SPaul Saab 			save_search_type = search_type;
1473a5f0fb15SPaul Saab 			search_type = SRCH_REVERSE(search_type);
1474a5f0fb15SPaul Saab 			search_type |= SRCH_PAST_EOF;
1475a5f0fb15SPaul Saab 			DO_SEARCH();
1476a5f0fb15SPaul Saab 			search_type = save_search_type;
1477a5f0fb15SPaul Saab 			break;
1478a5f0fb15SPaul Saab 
1479a5f0fb15SPaul Saab 		case A_UNDO_SEARCH:
1480a5f0fb15SPaul Saab 			undo_search();
1481a5f0fb15SPaul Saab 			break;
1482a5f0fb15SPaul Saab 
1483a5f0fb15SPaul Saab 		case A_HELP:
1484a5f0fb15SPaul Saab 			/*
1485a5f0fb15SPaul Saab 			 * Help.
1486a5f0fb15SPaul Saab 			 */
1487a5f0fb15SPaul Saab 			if (ch_getflags() & CH_HELPFILE)
1488a5f0fb15SPaul Saab 				break;
1489a5f0fb15SPaul Saab 			cmd_exec();
149089dd99dcSXin LI 			save_hshift = hshift;
149189dd99dcSXin LI 			hshift = 0;
1492a15691bfSXin LI 			save_bs_mode = bs_mode;
1493a15691bfSXin LI 			bs_mode = BS_SPECIAL;
1494a5f0fb15SPaul Saab 			(void) edit(FAKE_HELPFILE);
1495a5f0fb15SPaul Saab 			break;
1496a5f0fb15SPaul Saab 
1497a5f0fb15SPaul Saab 		case A_EXAMINE:
1498a5f0fb15SPaul Saab #if EXAMINE
1499a5f0fb15SPaul Saab 			/*
1500a5f0fb15SPaul Saab 			 * Edit a new file.  Get the filename.
1501a5f0fb15SPaul Saab 			 */
1502a5f0fb15SPaul Saab 			if (secure)
1503a5f0fb15SPaul Saab 			{
1504a5f0fb15SPaul Saab 				error("Command not available", NULL_PARG);
1505a5f0fb15SPaul Saab 				break;
1506a5f0fb15SPaul Saab 			}
1507dd3bd0edSDimitry Andric 			start_mca(A_EXAMINE, "Examine: ", ml_examine, 0);
1508a5f0fb15SPaul Saab 			c = getcc();
1509a5f0fb15SPaul Saab 			goto again;
1510a5f0fb15SPaul Saab #else
1511a5f0fb15SPaul Saab 			error("Command not available", NULL_PARG);
1512a5f0fb15SPaul Saab 			break;
1513a5f0fb15SPaul Saab #endif
1514a5f0fb15SPaul Saab 
1515a5f0fb15SPaul Saab 		case A_VISUAL:
1516a5f0fb15SPaul Saab 			/*
1517a5f0fb15SPaul Saab 			 * Invoke an editor on the input file.
1518a5f0fb15SPaul Saab 			 */
1519a5f0fb15SPaul Saab #if EDITOR
1520a5f0fb15SPaul Saab 			if (secure)
1521a5f0fb15SPaul Saab 			{
1522a5f0fb15SPaul Saab 				error("Command not available", NULL_PARG);
1523a5f0fb15SPaul Saab 				break;
1524a5f0fb15SPaul Saab 			}
1525a5f0fb15SPaul Saab 			if (ch_getflags() & CH_HELPFILE)
1526a5f0fb15SPaul Saab 				break;
1527a5f0fb15SPaul Saab 			if (strcmp(get_filename(curr_ifile), "-") == 0)
1528a5f0fb15SPaul Saab 			{
1529a5f0fb15SPaul Saab 				error("Cannot edit standard input", NULL_PARG);
1530a5f0fb15SPaul Saab 				break;
1531a5f0fb15SPaul Saab 			}
1532a5f0fb15SPaul Saab 			if (curr_altfilename != NULL)
1533a5f0fb15SPaul Saab 			{
153489dd99dcSXin LI 				error("WARNING: This file was viewed via LESSOPEN",
1535a5f0fb15SPaul Saab 					NULL_PARG);
1536a5f0fb15SPaul Saab 			}
1537dd3bd0edSDimitry Andric 			start_mca(A_SHELL, "!", ml_shell, 0);
1538a5f0fb15SPaul Saab 			/*
1539a5f0fb15SPaul Saab 			 * Expand the editor prototype string
1540a5f0fb15SPaul Saab 			 * and pass it to the system to execute.
1541a5f0fb15SPaul Saab 			 * (Make sure the screen is displayed so the
1542a5f0fb15SPaul Saab 			 * expansion of "+%lm" works.)
1543a5f0fb15SPaul Saab 			 */
1544a5f0fb15SPaul Saab 			make_display();
1545a5f0fb15SPaul Saab 			cmd_exec();
1546a5f0fb15SPaul Saab 			lsystem(pr_expand(editproto, 0), (char*)NULL);
1547a5f0fb15SPaul Saab 			break;
1548a5f0fb15SPaul Saab #else
1549a5f0fb15SPaul Saab 			error("Command not available", NULL_PARG);
1550a5f0fb15SPaul Saab 			break;
1551a5f0fb15SPaul Saab #endif
1552a5f0fb15SPaul Saab 
1553a5f0fb15SPaul Saab 		case A_NEXT_FILE:
1554a5f0fb15SPaul Saab 			/*
1555a5f0fb15SPaul Saab 			 * Examine next file.
1556a5f0fb15SPaul Saab 			 */
15571ede1615STim J. Robbins #if TAGS
15588fd4165cSPaul Saab 			if (ntags())
15598fd4165cSPaul Saab 			{
15608fd4165cSPaul Saab 				error("No next file", NULL_PARG);
15618fd4165cSPaul Saab 				break;
15628fd4165cSPaul Saab 			}
15631ede1615STim J. Robbins #endif
1564a5f0fb15SPaul Saab 			if (number <= 0)
1565a5f0fb15SPaul Saab 				number = 1;
15661ede1615STim J. Robbins 			if (edit_next((int) number))
1567a5f0fb15SPaul Saab 			{
15687374caaaSXin LI 				if (get_quit_at_eof() && eof_displayed() &&
1569a5f0fb15SPaul Saab 				    !(ch_getflags() & CH_HELPFILE))
1570a5f0fb15SPaul Saab 					quit(QUIT_OK);
1571a5f0fb15SPaul Saab 				parg.p_string = (number > 1) ? "(N-th) " : "";
1572a5f0fb15SPaul Saab 				error("No %snext file", &parg);
1573a5f0fb15SPaul Saab 			}
1574a5f0fb15SPaul Saab 			break;
1575a5f0fb15SPaul Saab 
1576a5f0fb15SPaul Saab 		case A_PREV_FILE:
1577a5f0fb15SPaul Saab 			/*
1578a5f0fb15SPaul Saab 			 * Examine previous file.
1579a5f0fb15SPaul Saab 			 */
15801ede1615STim J. Robbins #if TAGS
15818fd4165cSPaul Saab 			if (ntags())
15828fd4165cSPaul Saab 			{
15838fd4165cSPaul Saab 				error("No previous file", NULL_PARG);
15848fd4165cSPaul Saab 				break;
15858fd4165cSPaul Saab 			}
15861ede1615STim J. Robbins #endif
1587a5f0fb15SPaul Saab 			if (number <= 0)
1588a5f0fb15SPaul Saab 				number = 1;
15891ede1615STim J. Robbins 			if (edit_prev((int) number))
1590a5f0fb15SPaul Saab 			{
1591a5f0fb15SPaul Saab 				parg.p_string = (number > 1) ? "(N-th) " : "";
1592a5f0fb15SPaul Saab 				error("No %sprevious file", &parg);
1593a5f0fb15SPaul Saab 			}
1594a5f0fb15SPaul Saab 			break;
1595a5f0fb15SPaul Saab 
15968fd4165cSPaul Saab 		case A_NEXT_TAG:
15971ede1615STim J. Robbins #if TAGS
15988fd4165cSPaul Saab 			if (number <= 0)
15998fd4165cSPaul Saab 				number = 1;
16001ede1615STim J. Robbins 			tagfile = nexttag((int) number);
16018fd4165cSPaul Saab 			if (tagfile == NULL)
16028fd4165cSPaul Saab 			{
16038fd4165cSPaul Saab 				error("No next tag", NULL_PARG);
16048fd4165cSPaul Saab 				break;
16058fd4165cSPaul Saab 			}
16068fd4165cSPaul Saab 			if (edit(tagfile) == 0)
16078fd4165cSPaul Saab 			{
16088fd4165cSPaul Saab 				POSITION pos = tagsearch();
16098fd4165cSPaul Saab 				if (pos != NULL_POSITION)
16108fd4165cSPaul Saab 					jump_loc(pos, jump_sline);
16118fd4165cSPaul Saab 			}
16121ede1615STim J. Robbins #else
16131ede1615STim J. Robbins 			error("Command not available", NULL_PARG);
16141ede1615STim J. Robbins #endif
16158fd4165cSPaul Saab 			break;
16168fd4165cSPaul Saab 
16178fd4165cSPaul Saab 		case A_PREV_TAG:
16181ede1615STim J. Robbins #if TAGS
16198fd4165cSPaul Saab 			if (number <= 0)
16208fd4165cSPaul Saab 				number = 1;
16211ede1615STim J. Robbins 			tagfile = prevtag((int) number);
16228fd4165cSPaul Saab 			if (tagfile == NULL)
16238fd4165cSPaul Saab 			{
16248fd4165cSPaul Saab 				error("No previous tag", NULL_PARG);
16258fd4165cSPaul Saab 				break;
16268fd4165cSPaul Saab 			}
16278fd4165cSPaul Saab 			if (edit(tagfile) == 0)
16288fd4165cSPaul Saab 			{
16298fd4165cSPaul Saab 				POSITION pos = tagsearch();
16308fd4165cSPaul Saab 				if (pos != NULL_POSITION)
16318fd4165cSPaul Saab 					jump_loc(pos, jump_sline);
16328fd4165cSPaul Saab 			}
16331ede1615STim J. Robbins #else
16341ede1615STim J. Robbins 			error("Command not available", NULL_PARG);
16351ede1615STim J. Robbins #endif
16368fd4165cSPaul Saab 			break;
16378fd4165cSPaul Saab 
1638a5f0fb15SPaul Saab 		case A_INDEX_FILE:
1639a5f0fb15SPaul Saab 			/*
1640a5f0fb15SPaul Saab 			 * Examine a particular file.
1641a5f0fb15SPaul Saab 			 */
1642a5f0fb15SPaul Saab 			if (number <= 0)
1643a5f0fb15SPaul Saab 				number = 1;
16441ede1615STim J. Robbins 			if (edit_index((int) number))
1645a5f0fb15SPaul Saab 				error("No such file", NULL_PARG);
1646a5f0fb15SPaul Saab 			break;
1647a5f0fb15SPaul Saab 
1648a5f0fb15SPaul Saab 		case A_REMOVE_FILE:
1649a5f0fb15SPaul Saab 			if (ch_getflags() & CH_HELPFILE)
1650a5f0fb15SPaul Saab 				break;
1651a5f0fb15SPaul Saab 			old_ifile = curr_ifile;
1652a5f0fb15SPaul Saab 			new_ifile = getoff_ifile(curr_ifile);
1653a5f0fb15SPaul Saab 			if (new_ifile == NULL_IFILE)
1654a5f0fb15SPaul Saab 			{
1655a5f0fb15SPaul Saab 				bell();
1656a5f0fb15SPaul Saab 				break;
1657a5f0fb15SPaul Saab 			}
1658a5f0fb15SPaul Saab 			if (edit_ifile(new_ifile) != 0)
1659a5f0fb15SPaul Saab 			{
1660a5f0fb15SPaul Saab 				reedit_ifile(old_ifile);
1661a5f0fb15SPaul Saab 				break;
1662a5f0fb15SPaul Saab 			}
1663a5f0fb15SPaul Saab 			del_ifile(old_ifile);
1664a5f0fb15SPaul Saab 			break;
1665a5f0fb15SPaul Saab 
1666a5f0fb15SPaul Saab 		case A_OPT_TOGGLE:
1667a5f0fb15SPaul Saab 			optflag = OPT_TOGGLE;
1668a5f0fb15SPaul Saab 			optgetname = FALSE;
1669a5f0fb15SPaul Saab 			mca_opt_toggle();
1670a5f0fb15SPaul Saab 			c = getcc();
1671a5f0fb15SPaul Saab 			goto again;
1672a5f0fb15SPaul Saab 
1673a5f0fb15SPaul Saab 		case A_DISP_OPTION:
1674a5f0fb15SPaul Saab 			/*
1675a5f0fb15SPaul Saab 			 * Report a flag setting.
1676a5f0fb15SPaul Saab 			 */
1677a5f0fb15SPaul Saab 			optflag = OPT_NO_TOGGLE;
1678a5f0fb15SPaul Saab 			optgetname = FALSE;
1679a5f0fb15SPaul Saab 			mca_opt_toggle();
1680a5f0fb15SPaul Saab 			c = getcc();
1681a5f0fb15SPaul Saab 			goto again;
1682a5f0fb15SPaul Saab 
1683a5f0fb15SPaul Saab 		case A_FIRSTCMD:
1684a5f0fb15SPaul Saab 			/*
1685a5f0fb15SPaul Saab 			 * Set an initial command for new files.
1686a5f0fb15SPaul Saab 			 */
1687a5f0fb15SPaul Saab 			start_mca(A_FIRSTCMD, "+", (void*)NULL, 0);
1688a5f0fb15SPaul Saab 			c = getcc();
1689a5f0fb15SPaul Saab 			goto again;
1690a5f0fb15SPaul Saab 
1691a5f0fb15SPaul Saab 		case A_SHELL:
1692a5f0fb15SPaul Saab 			/*
1693a5f0fb15SPaul Saab 			 * Shell escape.
1694a5f0fb15SPaul Saab 			 */
1695a5f0fb15SPaul Saab #if SHELL_ESCAPE
1696a5f0fb15SPaul Saab 			if (secure)
1697a5f0fb15SPaul Saab 			{
1698a5f0fb15SPaul Saab 				error("Command not available", NULL_PARG);
1699a5f0fb15SPaul Saab 				break;
1700a5f0fb15SPaul Saab 			}
1701dd3bd0edSDimitry Andric 			start_mca(A_SHELL, "!", ml_shell, 0);
1702a5f0fb15SPaul Saab 			c = getcc();
1703a5f0fb15SPaul Saab 			goto again;
1704a5f0fb15SPaul Saab #else
1705a5f0fb15SPaul Saab 			error("Command not available", NULL_PARG);
1706a5f0fb15SPaul Saab 			break;
1707a5f0fb15SPaul Saab #endif
1708a5f0fb15SPaul Saab 
1709a5f0fb15SPaul Saab 		case A_SETMARK:
1710a5f0fb15SPaul Saab 			/*
1711a5f0fb15SPaul Saab 			 * Set a mark.
1712a5f0fb15SPaul Saab 			 */
1713a5f0fb15SPaul Saab 			if (ch_getflags() & CH_HELPFILE)
1714a5f0fb15SPaul Saab 				break;
1715a5f0fb15SPaul Saab 			start_mca(A_SETMARK, "mark: ", (void*)NULL, 0);
1716a5f0fb15SPaul Saab 			c = getcc();
171789dd99dcSXin LI 			if (c == erase_char || c == erase2_char ||
171889dd99dcSXin LI 			    c == kill_char || c == '\n' || c == '\r')
1719a5f0fb15SPaul Saab 				break;
1720a5f0fb15SPaul Saab 			setmark(c);
1721a5f0fb15SPaul Saab 			break;
1722a5f0fb15SPaul Saab 
1723a5f0fb15SPaul Saab 		case A_GOMARK:
1724a5f0fb15SPaul Saab 			/*
1725a5f0fb15SPaul Saab 			 * Go to a mark.
1726a5f0fb15SPaul Saab 			 */
1727a5f0fb15SPaul Saab 			start_mca(A_GOMARK, "goto mark: ", (void*)NULL, 0);
1728a5f0fb15SPaul Saab 			c = getcc();
172989dd99dcSXin LI 			if (c == erase_char || c == erase2_char ||
173089dd99dcSXin LI 			    c == kill_char || c == '\n' || c == '\r')
1731a5f0fb15SPaul Saab 				break;
17327374caaaSXin LI 			cmd_exec();
1733a5f0fb15SPaul Saab 			gomark(c);
1734a5f0fb15SPaul Saab 			break;
1735a5f0fb15SPaul Saab 
1736a5f0fb15SPaul Saab 		case A_PIPE:
1737a5f0fb15SPaul Saab #if PIPEC
1738a5f0fb15SPaul Saab 			if (secure)
1739a5f0fb15SPaul Saab 			{
1740a5f0fb15SPaul Saab 				error("Command not available", NULL_PARG);
1741a5f0fb15SPaul Saab 				break;
1742a5f0fb15SPaul Saab 			}
1743a5f0fb15SPaul Saab 			start_mca(A_PIPE, "|mark: ", (void*)NULL, 0);
1744a5f0fb15SPaul Saab 			c = getcc();
174589dd99dcSXin LI 			if (c == erase_char || c == erase2_char || c == kill_char)
1746a5f0fb15SPaul Saab 				break;
1747a5f0fb15SPaul Saab 			if (c == '\n' || c == '\r')
1748a5f0fb15SPaul Saab 				c = '.';
1749a5f0fb15SPaul Saab 			if (badmark(c))
1750a5f0fb15SPaul Saab 				break;
1751a5f0fb15SPaul Saab 			pipec = c;
1752dd3bd0edSDimitry Andric 			start_mca(A_PIPE, "!", ml_shell, 0);
1753a5f0fb15SPaul Saab 			c = getcc();
1754a5f0fb15SPaul Saab 			goto again;
1755a5f0fb15SPaul Saab #else
1756a5f0fb15SPaul Saab 			error("Command not available", NULL_PARG);
1757a5f0fb15SPaul Saab 			break;
1758a5f0fb15SPaul Saab #endif
1759a5f0fb15SPaul Saab 
1760a5f0fb15SPaul Saab 		case A_B_BRACKET:
1761a5f0fb15SPaul Saab 		case A_F_BRACKET:
1762a5f0fb15SPaul Saab 			start_mca(action, "Brackets: ", (void*)NULL, 0);
1763a5f0fb15SPaul Saab 			c = getcc();
1764a5f0fb15SPaul Saab 			goto again;
1765a5f0fb15SPaul Saab 
1766a5f0fb15SPaul Saab 		case A_LSHIFT:
17678fd4165cSPaul Saab 			if (number > 0)
17688fd4165cSPaul Saab 				shift_count = number;
17698fd4165cSPaul Saab 			else
177015596da4SPaul Saab 				number = (shift_count > 0) ?
177115596da4SPaul Saab 					shift_count : sc_width / 2;
1772a5f0fb15SPaul Saab 			if (number > hshift)
1773a5f0fb15SPaul Saab 				number = hshift;
1774a5f0fb15SPaul Saab 			hshift -= number;
1775a5f0fb15SPaul Saab 			screen_trashed = 1;
1776a5f0fb15SPaul Saab 			break;
1777a5f0fb15SPaul Saab 
1778a5f0fb15SPaul Saab 		case A_RSHIFT:
17798fd4165cSPaul Saab 			if (number > 0)
17808fd4165cSPaul Saab 				shift_count = number;
17818fd4165cSPaul Saab 			else
178215596da4SPaul Saab 				number = (shift_count > 0) ?
178315596da4SPaul Saab 					shift_count : sc_width / 2;
1784a5f0fb15SPaul Saab 			hshift += number;
1785a5f0fb15SPaul Saab 			screen_trashed = 1;
1786a5f0fb15SPaul Saab 			break;
1787a5f0fb15SPaul Saab 
1788*f6b74a7dSXin LI 		case A_LLSHIFT:
1789*f6b74a7dSXin LI 			hshift = 0;
1790*f6b74a7dSXin LI 			screen_trashed = 1;
1791*f6b74a7dSXin LI 			break;
1792*f6b74a7dSXin LI 
1793*f6b74a7dSXin LI 		case A_RRSHIFT:
1794*f6b74a7dSXin LI 			hshift = rrshift();
1795*f6b74a7dSXin LI 			screen_trashed = 1;
1796*f6b74a7dSXin LI 			break;
1797*f6b74a7dSXin LI 
1798a5f0fb15SPaul Saab 		case A_PREFIX:
1799a5f0fb15SPaul Saab 			/*
1800a5f0fb15SPaul Saab 			 * The command is incomplete (more chars are needed).
1801a5f0fb15SPaul Saab 			 * Display the current char, so the user knows
1802a5f0fb15SPaul Saab 			 * what's going on, and get another character.
1803a5f0fb15SPaul Saab 			 */
1804a5f0fb15SPaul Saab 			if (mca != A_PREFIX)
1805a5f0fb15SPaul Saab 			{
1806a5f0fb15SPaul Saab 				cmd_reset();
1807a5f0fb15SPaul Saab 				start_mca(A_PREFIX, " ", (void*)NULL,
1808a5f0fb15SPaul Saab 					CF_QUIT_ON_ERASE);
1809a5f0fb15SPaul Saab 				(void) cmd_char(c);
1810a5f0fb15SPaul Saab 			}
1811a5f0fb15SPaul Saab 			c = getcc();
1812a5f0fb15SPaul Saab 			goto again;
1813a5f0fb15SPaul Saab 
1814a5f0fb15SPaul Saab 		case A_NOACTION:
1815a5f0fb15SPaul Saab 			break;
1816a5f0fb15SPaul Saab 
1817a5f0fb15SPaul Saab 		default:
1818a5f0fb15SPaul Saab 			bell();
1819a5f0fb15SPaul Saab 			break;
1820a5f0fb15SPaul Saab 		}
1821a5f0fb15SPaul Saab 	}
1822a5f0fb15SPaul Saab }
1823