xref: /dflybsd-src/contrib/less/command.c (revision e0f238eda64c20d98364903e0c003825fd0b66dd)
11133e27eSPeter Avalos /*
2*e433da38SAaron LI  * Copyright (C) 1984-2024  Mark Nudelman
31133e27eSPeter Avalos  *
41133e27eSPeter Avalos  * You may distribute under the terms of either the GNU General Public
51133e27eSPeter Avalos  * License or the Less License, as specified in the README file.
61133e27eSPeter Avalos  *
7e639dc31SJohn Marino  * For more information, see the README file.
81133e27eSPeter Avalos  */
91133e27eSPeter Avalos 
101133e27eSPeter Avalos 
111133e27eSPeter Avalos /*
121133e27eSPeter Avalos  * User-level command processor.
131133e27eSPeter Avalos  */
141133e27eSPeter Avalos 
151133e27eSPeter Avalos #include "less.h"
161133e27eSPeter Avalos #if MSDOS_COMPILER==WIN32C
171133e27eSPeter Avalos #include <windows.h>
181133e27eSPeter Avalos #endif
191133e27eSPeter Avalos #include "position.h"
201133e27eSPeter Avalos #include "option.h"
211133e27eSPeter Avalos #include "cmd.h"
221133e27eSPeter Avalos 
231133e27eSPeter Avalos extern int erase_char, erase2_char, kill_char;
241133e27eSPeter Avalos extern int sigs;
251133e27eSPeter Avalos extern int quit_if_one_screen;
26320d7c8aSAaron LI extern int one_screen;
271133e27eSPeter Avalos extern int sc_width;
281133e27eSPeter Avalos extern int sc_height;
2902d62a0fSDaniel Fojt extern char *kent;
301133e27eSPeter Avalos extern int swindow;
311133e27eSPeter Avalos extern int jump_sline;
321133e27eSPeter Avalos extern int quitting;
331133e27eSPeter Avalos extern int wscroll;
341133e27eSPeter Avalos extern int top_scroll;
351133e27eSPeter Avalos extern int ignore_eoi;
361133e27eSPeter Avalos extern int hshift;
37fa0be7c5SJohn Marino extern int bs_mode;
38320d7c8aSAaron LI extern int proc_backspace;
391133e27eSPeter Avalos extern int show_attn;
40e639dc31SJohn Marino extern POSITION highest_hilite;
411133e27eSPeter Avalos extern char *every_first_cmd;
421133e27eSPeter Avalos extern char version[];
431133e27eSPeter Avalos extern struct scrpos initial_scrpos;
441133e27eSPeter Avalos extern IFILE curr_ifile;
4502d62a0fSDaniel Fojt extern void *ml_search;
4602d62a0fSDaniel Fojt extern void *ml_examine;
4702d62a0fSDaniel Fojt extern int wheel_lines;
480c7ad07eSAntonio Huete Jimenez extern int def_search_type;
49*e433da38SAaron LI extern lbool search_wrapped;
501133e27eSPeter Avalos #if SHELL_ESCAPE || PIPEC
5102d62a0fSDaniel Fojt extern void *ml_shell;
521133e27eSPeter Avalos #endif
531133e27eSPeter Avalos #if EDITOR
54*e433da38SAaron LI extern constant char *editproto;
551133e27eSPeter Avalos #endif
56*e433da38SAaron LI #if OSC8_LINK
57*e433da38SAaron LI extern char *osc8_uri;
58*e433da38SAaron LI #endif
591133e27eSPeter Avalos extern int shift_count;
601133e27eSPeter Avalos extern int forw_prompt;
610c7ad07eSAntonio Huete Jimenez extern int incr_search;
62320d7c8aSAaron LI extern int full_screen;
6302d62a0fSDaniel Fojt #if MSDOS_COMPILER==WIN32C
6402d62a0fSDaniel Fojt extern int utf_mode;
65*e433da38SAaron LI extern unsigned less_acp;
6602d62a0fSDaniel Fojt #endif
671133e27eSPeter Avalos 
681133e27eSPeter Avalos #if SHELL_ESCAPE
691133e27eSPeter Avalos static char *shellcmd = NULL;   /* For holding last shell command for "!!" */
701133e27eSPeter Avalos #endif
711133e27eSPeter Avalos static int mca;                 /* The multicharacter command (action) */
721133e27eSPeter Avalos static int search_type;         /* The previous type of search */
73320d7c8aSAaron LI static int last_search_type;    /* Type of last executed search */
741133e27eSPeter Avalos static LINENUM number;          /* The number typed by the user */
751133e27eSPeter Avalos static long fraction;           /* The fractional part of the number */
7625ce721eSPeter Avalos static struct loption *curropt;
7725ce721eSPeter Avalos static int opt_lower;
781133e27eSPeter Avalos static int optflag;
79*e433da38SAaron LI static lbool optgetname;
801133e27eSPeter Avalos static POSITION bottompos;
811133e27eSPeter Avalos static int save_hshift;
82fa0be7c5SJohn Marino static int save_bs_mode;
83320d7c8aSAaron LI static int save_proc_backspace;
84*e433da38SAaron LI static int screen_trashed_value = 0;
85*e433da38SAaron LI static lbool literal_char = FALSE;
861133e27eSPeter Avalos #if PIPEC
871133e27eSPeter Avalos static char pipec;
881133e27eSPeter Avalos #endif
891133e27eSPeter Avalos 
9002d62a0fSDaniel Fojt /* Stack of ungotten chars (via ungetcc) */
9125ce721eSPeter Avalos struct ungot {
9225ce721eSPeter Avalos 	struct ungot *ug_next;
93*e433da38SAaron LI 	char ug_char;
94*e433da38SAaron LI 	lbool ug_end_command;
9525ce721eSPeter Avalos };
9625ce721eSPeter Avalos static struct ungot* ungot = NULL;
9725ce721eSPeter Avalos 
98*e433da38SAaron LI static void multi_search(constant char *pattern, int n, int silent);
991133e27eSPeter Avalos 
1001133e27eSPeter Avalos /*
1011133e27eSPeter Avalos  * Move the cursor to start of prompt line before executing a command.
1021133e27eSPeter Avalos  * This looks nicer if the command takes a long time before
1031133e27eSPeter Avalos  * updating the screen.
1041133e27eSPeter Avalos  */
cmd_exec(void)105320d7c8aSAaron LI static void cmd_exec(void)
1061133e27eSPeter Avalos {
1071133e27eSPeter Avalos 	clear_attn();
1081133e27eSPeter Avalos 	clear_bot();
1091133e27eSPeter Avalos 	flush();
1101133e27eSPeter Avalos }
1111133e27eSPeter Avalos 
1121133e27eSPeter Avalos /*
11302d62a0fSDaniel Fojt  * Indicate we are reading a multi-character command.
11402d62a0fSDaniel Fojt  */
set_mca(int action)115320d7c8aSAaron LI static void set_mca(int action)
11602d62a0fSDaniel Fojt {
11702d62a0fSDaniel Fojt 	mca = action;
11802d62a0fSDaniel Fojt 	clear_bot();
11902d62a0fSDaniel Fojt 	clear_cmd();
12002d62a0fSDaniel Fojt }
12102d62a0fSDaniel Fojt 
12202d62a0fSDaniel Fojt /*
12302d62a0fSDaniel Fojt  * Indicate we are not reading a multi-character command.
12402d62a0fSDaniel Fojt  */
clear_mca(void)125320d7c8aSAaron LI static void clear_mca(void)
12602d62a0fSDaniel Fojt {
12702d62a0fSDaniel Fojt 	if (mca == 0)
12802d62a0fSDaniel Fojt 		return;
12902d62a0fSDaniel Fojt 	mca = 0;
13002d62a0fSDaniel Fojt }
13102d62a0fSDaniel Fojt 
13202d62a0fSDaniel Fojt /*
1331133e27eSPeter Avalos  * Set up the display to start a new multi-character command.
1341133e27eSPeter Avalos  */
start_mca(int action,constant char * prompt,void * mlist,int cmdflags)135320d7c8aSAaron LI static void start_mca(int action, constant char *prompt, void *mlist, int cmdflags)
1361133e27eSPeter Avalos {
13702d62a0fSDaniel Fojt 	set_mca(action);
1381133e27eSPeter Avalos 	cmd_putstr(prompt);
1391133e27eSPeter Avalos 	set_mlist(mlist, cmdflags);
1401133e27eSPeter Avalos }
1411133e27eSPeter Avalos 
in_mca(void)142320d7c8aSAaron LI public int in_mca(void)
1431133e27eSPeter Avalos {
1441133e27eSPeter Avalos 	return (mca != 0 && mca != A_PREFIX);
1451133e27eSPeter Avalos }
1461133e27eSPeter Avalos 
1471133e27eSPeter Avalos /*
1481133e27eSPeter Avalos  * Set up the display to start a new search command.
1491133e27eSPeter Avalos  */
mca_search1(void)150320d7c8aSAaron LI static void mca_search1(void)
1511133e27eSPeter Avalos {
152320d7c8aSAaron LI 	int i;
153320d7c8aSAaron LI 
1548be36e5bSPeter Avalos #if HILITE_SEARCH
1558be36e5bSPeter Avalos 	if (search_type & SRCH_FILTER)
15602d62a0fSDaniel Fojt 		set_mca(A_FILTER);
1578be36e5bSPeter Avalos 	else
1588be36e5bSPeter Avalos #endif
1591133e27eSPeter Avalos 	if (search_type & SRCH_FORW)
16002d62a0fSDaniel Fojt 		set_mca(A_F_SEARCH);
1611133e27eSPeter Avalos 	else
16202d62a0fSDaniel Fojt 		set_mca(A_B_SEARCH);
1631133e27eSPeter Avalos 
1641133e27eSPeter Avalos 	if (search_type & SRCH_NO_MATCH)
1651133e27eSPeter Avalos 		cmd_putstr("Non-match ");
1661133e27eSPeter Avalos 	if (search_type & SRCH_FIRST_FILE)
1671133e27eSPeter Avalos 		cmd_putstr("First-file ");
1681133e27eSPeter Avalos 	if (search_type & SRCH_PAST_EOF)
1691133e27eSPeter Avalos 		cmd_putstr("EOF-ignore ");
1701133e27eSPeter Avalos 	if (search_type & SRCH_NO_MOVE)
1711133e27eSPeter Avalos 		cmd_putstr("Keep-pos ");
1721133e27eSPeter Avalos 	if (search_type & SRCH_NO_REGEX)
1731133e27eSPeter Avalos 		cmd_putstr("Regex-off ");
1740c7ad07eSAntonio Huete Jimenez 	if (search_type & SRCH_WRAP)
1750c7ad07eSAntonio Huete Jimenez 		cmd_putstr("Wrap ");
176320d7c8aSAaron LI 	for (i = 1; i <= NUM_SEARCH_COLORS; i++)
177320d7c8aSAaron LI 	{
178320d7c8aSAaron LI 		if (search_type & SRCH_SUBSEARCH(i))
179320d7c8aSAaron LI 		{
180320d7c8aSAaron LI 			char buf[INT_STRLEN_BOUND(int)+8];
181320d7c8aSAaron LI 			SNPRINTF1(buf, sizeof(buf), "Sub-%d ", i);
182320d7c8aSAaron LI 			cmd_putstr(buf);
183320d7c8aSAaron LI 		}
184320d7c8aSAaron LI 	}
185*e433da38SAaron LI 	if (literal_char)
186*e433da38SAaron LI 		cmd_putstr("Lit ");
1871133e27eSPeter Avalos 
1888be36e5bSPeter Avalos #if HILITE_SEARCH
1898be36e5bSPeter Avalos 	if (search_type & SRCH_FILTER)
1908be36e5bSPeter Avalos 		cmd_putstr("&/");
1918be36e5bSPeter Avalos 	else
1928be36e5bSPeter Avalos #endif
1931133e27eSPeter Avalos 	if (search_type & SRCH_FORW)
1941133e27eSPeter Avalos 		cmd_putstr("/");
1951133e27eSPeter Avalos 	else
1961133e27eSPeter Avalos 		cmd_putstr("?");
1979b760066SJohn Marino 	forw_prompt = 0;
1980c7ad07eSAntonio Huete Jimenez }
1990c7ad07eSAntonio Huete Jimenez 
mca_search(void)200320d7c8aSAaron LI static void mca_search(void)
2010c7ad07eSAntonio Huete Jimenez {
2020c7ad07eSAntonio Huete Jimenez 	mca_search1();
2031133e27eSPeter Avalos 	set_mlist(ml_search, 0);
2041133e27eSPeter Avalos }
2051133e27eSPeter Avalos 
2061133e27eSPeter Avalos /*
2071133e27eSPeter Avalos  * Set up the display to start a new toggle-option command.
2081133e27eSPeter Avalos  */
mca_opt_toggle(void)209320d7c8aSAaron LI static void mca_opt_toggle(void)
2101133e27eSPeter Avalos {
211*e433da38SAaron LI 	int no_prompt = (optflag & OPT_NO_PROMPT);
212*e433da38SAaron LI 	int flag = (optflag & ~OPT_NO_PROMPT);
213*e433da38SAaron LI 	constant char *dash = (flag == OPT_NO_TOGGLE) ? "_" : "-";
2141133e27eSPeter Avalos 
21502d62a0fSDaniel Fojt 	set_mca(A_OPT_TOGGLE);
2161133e27eSPeter Avalos 	cmd_putstr(dash);
2171133e27eSPeter Avalos 	if (optgetname)
2181133e27eSPeter Avalos 		cmd_putstr(dash);
2191133e27eSPeter Avalos 	if (no_prompt)
2201133e27eSPeter Avalos 		cmd_putstr("(P)");
2211133e27eSPeter Avalos 	switch (flag)
2221133e27eSPeter Avalos 	{
2231133e27eSPeter Avalos 	case OPT_UNSET:
2241133e27eSPeter Avalos 		cmd_putstr("+");
2251133e27eSPeter Avalos 		break;
2261133e27eSPeter Avalos 	case OPT_SET:
2271133e27eSPeter Avalos 		cmd_putstr("!");
2281133e27eSPeter Avalos 		break;
2291133e27eSPeter Avalos 	}
2309b760066SJohn Marino 	forw_prompt = 0;
2311133e27eSPeter Avalos 	set_mlist(NULL, 0);
2321133e27eSPeter Avalos }
2331133e27eSPeter Avalos 
2341133e27eSPeter Avalos /*
2351133e27eSPeter Avalos  * Execute a multicharacter command.
2361133e27eSPeter Avalos  */
exec_mca(void)237320d7c8aSAaron LI static void exec_mca(void)
2381133e27eSPeter Avalos {
239*e433da38SAaron LI 	constant char *cbuf;
240*e433da38SAaron LI 	char *p;
2411133e27eSPeter Avalos 
2421133e27eSPeter Avalos 	cmd_exec();
2431133e27eSPeter Avalos 	cbuf = get_cmdbuf();
2440c7ad07eSAntonio Huete Jimenez 	if (cbuf == NULL)
2450c7ad07eSAntonio Huete Jimenez 		return;
2461133e27eSPeter Avalos 
2471133e27eSPeter Avalos 	switch (mca)
2481133e27eSPeter Avalos 	{
2491133e27eSPeter Avalos 	case A_F_SEARCH:
2501133e27eSPeter Avalos 	case A_B_SEARCH:
251fa0be7c5SJohn Marino 		multi_search(cbuf, (int) number, 0);
2521133e27eSPeter Avalos 		break;
2538be36e5bSPeter Avalos #if HILITE_SEARCH
2548be36e5bSPeter Avalos 	case A_FILTER:
2558be36e5bSPeter Avalos 		search_type ^= SRCH_NO_MATCH;
2568be36e5bSPeter Avalos 		set_filter_pattern(cbuf, search_type);
2578be36e5bSPeter Avalos 		break;
2588be36e5bSPeter Avalos #endif
2591133e27eSPeter Avalos 	case A_FIRSTCMD:
2601133e27eSPeter Avalos 		/*
2611133e27eSPeter Avalos 		 * Skip leading spaces or + signs in the string.
2621133e27eSPeter Avalos 		 */
2631133e27eSPeter Avalos 		while (*cbuf == '+' || *cbuf == ' ')
2641133e27eSPeter Avalos 			cbuf++;
2651133e27eSPeter Avalos 		if (every_first_cmd != NULL)
2661133e27eSPeter Avalos 			free(every_first_cmd);
2671133e27eSPeter Avalos 		if (*cbuf == '\0')
2681133e27eSPeter Avalos 			every_first_cmd = NULL;
2691133e27eSPeter Avalos 		else
2701133e27eSPeter Avalos 			every_first_cmd = save(cbuf);
2711133e27eSPeter Avalos 		break;
2721133e27eSPeter Avalos 	case A_OPT_TOGGLE:
27325ce721eSPeter Avalos 		toggle_option(curropt, opt_lower, cbuf, optflag);
27425ce721eSPeter Avalos 		curropt = NULL;
2751133e27eSPeter Avalos 		break;
2761133e27eSPeter Avalos 	case A_F_BRACKET:
2771133e27eSPeter Avalos 		match_brac(cbuf[0], cbuf[1], 1, (int) number);
2781133e27eSPeter Avalos 		break;
2791133e27eSPeter Avalos 	case A_B_BRACKET:
2801133e27eSPeter Avalos 		match_brac(cbuf[1], cbuf[0], 0, (int) number);
2811133e27eSPeter Avalos 		break;
2821133e27eSPeter Avalos #if EXAMINE
2831133e27eSPeter Avalos 	case A_EXAMINE:
284*e433da38SAaron LI 		if (!secure_allow(SF_EXAMINE))
2851133e27eSPeter Avalos 			break;
286*e433da38SAaron LI 		p = save(cbuf);
287*e433da38SAaron LI 		edit_list(p);
288*e433da38SAaron LI 		free(p);
2891133e27eSPeter Avalos #if TAGS
2901133e27eSPeter Avalos 		/* If tag structure is loaded then clean it up. */
2911133e27eSPeter Avalos 		cleantags();
2921133e27eSPeter Avalos #endif
2931133e27eSPeter Avalos 		break;
2941133e27eSPeter Avalos #endif
2951133e27eSPeter Avalos #if SHELL_ESCAPE
296*e433da38SAaron LI 	case A_SHELL: {
2971133e27eSPeter Avalos 		/*
2981133e27eSPeter Avalos 		 * !! just uses whatever is in shellcmd.
2991133e27eSPeter Avalos 		 * Otherwise, copy cmdbuf to shellcmd,
3001133e27eSPeter Avalos 		 * expanding any special characters ("%" or "#").
3011133e27eSPeter Avalos 		 */
302*e433da38SAaron LI 		constant char *done_msg = (*cbuf == CONTROL('P')) ? NULL : "!done";
303*e433da38SAaron LI 		if (done_msg == NULL)
304*e433da38SAaron LI 			++cbuf;
3051133e27eSPeter Avalos 		if (*cbuf != '!')
3061133e27eSPeter Avalos 		{
3071133e27eSPeter Avalos 			if (shellcmd != NULL)
3081133e27eSPeter Avalos 				free(shellcmd);
3091133e27eSPeter Avalos 			shellcmd = fexpand(cbuf);
3101133e27eSPeter Avalos 		}
311*e433da38SAaron LI 		if (!secure_allow(SF_SHELL))
3121133e27eSPeter Avalos 			break;
3131133e27eSPeter Avalos 		if (shellcmd == NULL)
314*e433da38SAaron LI 			shellcmd = "";
315*e433da38SAaron LI 		lsystem(shellcmd, done_msg);
316*e433da38SAaron LI 		break; }
317*e433da38SAaron LI 	case A_PSHELL: {
318*e433da38SAaron LI 		constant char *done_msg = (*cbuf == CONTROL('P')) ? NULL : "#done";
319*e433da38SAaron LI 		if (done_msg == NULL)
320*e433da38SAaron LI 			++cbuf;
321*e433da38SAaron LI 		if (!secure_allow(SF_SHELL))
3221133e27eSPeter Avalos 			break;
323*e433da38SAaron LI 		lsystem(pr_expand(cbuf), done_msg);
324*e433da38SAaron LI 		break; }
3251133e27eSPeter Avalos #endif
3261133e27eSPeter Avalos #if PIPEC
327*e433da38SAaron LI 	case A_PIPE: {
328*e433da38SAaron LI 		constant char *done_msg = (*cbuf == CONTROL('P')) ? NULL : "|done";
329*e433da38SAaron LI 		if (done_msg == NULL)
330*e433da38SAaron LI 			++cbuf;
331*e433da38SAaron LI 		if (!secure_allow(SF_PIPE))
3321133e27eSPeter Avalos 			break;
3331133e27eSPeter Avalos 		(void) pipe_mark(pipec, cbuf);
334*e433da38SAaron LI 		if (done_msg != NULL)
335*e433da38SAaron LI 			error(done_msg, NULL_PARG);
336*e433da38SAaron LI 		break; }
3371133e27eSPeter Avalos #endif
3381133e27eSPeter Avalos 	}
3391133e27eSPeter Avalos }
3401133e27eSPeter Avalos 
3411133e27eSPeter Avalos /*
34225ce721eSPeter Avalos  * Is a character an erase or kill char?
3431133e27eSPeter Avalos  */
is_erase_char(char c)344*e433da38SAaron LI static lbool is_erase_char(char c)
3451133e27eSPeter Avalos {
34625ce721eSPeter Avalos 	return (c == erase_char || c == erase2_char || c == kill_char);
3471133e27eSPeter Avalos }
3481133e27eSPeter Avalos 
3491133e27eSPeter Avalos /*
35002d62a0fSDaniel Fojt  * Is a character a carriage return or newline?
35102d62a0fSDaniel Fojt  */
is_newline_char(char c)352*e433da38SAaron LI static lbool is_newline_char(char c)
35302d62a0fSDaniel Fojt {
35402d62a0fSDaniel Fojt 	return (c == '\n' || c == '\r');
35502d62a0fSDaniel Fojt }
35602d62a0fSDaniel Fojt 
35702d62a0fSDaniel Fojt /*
35825ce721eSPeter Avalos  * Handle the first char of an option (after the initial dash).
3591133e27eSPeter Avalos  */
mca_opt_first_char(char c)360*e433da38SAaron LI static int mca_opt_first_char(char c)
3611133e27eSPeter Avalos {
3620c7ad07eSAntonio Huete Jimenez 	int no_prompt = (optflag & OPT_NO_PROMPT);
36325ce721eSPeter Avalos 	int flag = (optflag & ~OPT_NO_PROMPT);
3641133e27eSPeter Avalos 	if (flag == OPT_NO_TOGGLE)
3651133e27eSPeter Avalos 	{
3661133e27eSPeter Avalos 		switch (c)
3671133e27eSPeter Avalos 		{
3681133e27eSPeter Avalos 		case '_':
3691133e27eSPeter Avalos 			/* "__" = long option name. */
3701133e27eSPeter Avalos 			optgetname = TRUE;
3711133e27eSPeter Avalos 			mca_opt_toggle();
3721133e27eSPeter Avalos 			return (MCA_MORE);
3731133e27eSPeter Avalos 		}
3741133e27eSPeter Avalos 	} else
3751133e27eSPeter Avalos 	{
3761133e27eSPeter Avalos 		switch (c)
3771133e27eSPeter Avalos 		{
3781133e27eSPeter Avalos 		case '+':
3791133e27eSPeter Avalos 			/* "-+" = UNSET. */
3800c7ad07eSAntonio Huete Jimenez 			optflag = no_prompt | ((flag == OPT_UNSET) ?
3810c7ad07eSAntonio Huete Jimenez 				OPT_TOGGLE : OPT_UNSET);
3821133e27eSPeter Avalos 			mca_opt_toggle();
3831133e27eSPeter Avalos 			return (MCA_MORE);
3841133e27eSPeter Avalos 		case '!':
3851133e27eSPeter Avalos 			/* "-!" = SET */
3860c7ad07eSAntonio Huete Jimenez 			optflag = no_prompt | ((flag == OPT_SET) ?
3870c7ad07eSAntonio Huete Jimenez 				OPT_TOGGLE : OPT_SET);
3881133e27eSPeter Avalos 			mca_opt_toggle();
3891133e27eSPeter Avalos 			return (MCA_MORE);
3901133e27eSPeter Avalos 		case CONTROL('P'):
3911133e27eSPeter Avalos 			optflag ^= OPT_NO_PROMPT;
3921133e27eSPeter Avalos 			mca_opt_toggle();
3931133e27eSPeter Avalos 			return (MCA_MORE);
3941133e27eSPeter Avalos 		case '-':
3951133e27eSPeter Avalos 			/* "--" = long option name. */
3961133e27eSPeter Avalos 			optgetname = TRUE;
3971133e27eSPeter Avalos 			mca_opt_toggle();
3981133e27eSPeter Avalos 			return (MCA_MORE);
3991133e27eSPeter Avalos 		}
4001133e27eSPeter Avalos 	}
40125ce721eSPeter Avalos 	/* Char was not handled here. */
40225ce721eSPeter Avalos 	return (NO_MCA);
4031133e27eSPeter Avalos }
40425ce721eSPeter Avalos 
4051133e27eSPeter Avalos /*
40625ce721eSPeter Avalos  * Add a char to a long option name.
40725ce721eSPeter Avalos  * See if we've got a match for an option name yet.
4081133e27eSPeter Avalos  * If so, display the complete name and stop
4091133e27eSPeter Avalos  * accepting chars until user hits RETURN.
4101133e27eSPeter Avalos  */
mca_opt_nonfirst_char(char c)411*e433da38SAaron LI static int mca_opt_nonfirst_char(char c)
41225ce721eSPeter Avalos {
413*e433da38SAaron LI 	constant char *p;
414*e433da38SAaron LI 	constant char *oname;
415*e433da38SAaron LI 	lbool ambig;
4161133e27eSPeter Avalos 
41725ce721eSPeter Avalos 	if (curropt != NULL)
4181133e27eSPeter Avalos 	{
4191133e27eSPeter Avalos 		/*
4201133e27eSPeter Avalos 		 * Already have a match for the name.
4211133e27eSPeter Avalos 		 * Don't accept anything but erase/kill.
4221133e27eSPeter Avalos 		 */
42325ce721eSPeter Avalos 		if (is_erase_char(c))
4241133e27eSPeter Avalos 			return (MCA_DONE);
4251133e27eSPeter Avalos 		return (MCA_MORE);
4261133e27eSPeter Avalos 	}
4271133e27eSPeter Avalos 	/*
4281133e27eSPeter Avalos 	 * Add char to cmd buffer and try to match
4291133e27eSPeter Avalos 	 * the option name.
4301133e27eSPeter Avalos 	 */
4311133e27eSPeter Avalos 	if (cmd_char(c) == CC_QUIT)
4321133e27eSPeter Avalos 		return (MCA_DONE);
4331133e27eSPeter Avalos 	p = get_cmdbuf();
4340c7ad07eSAntonio Huete Jimenez 	if (p == NULL)
4350c7ad07eSAntonio Huete Jimenez 		return (MCA_MORE);
43625ce721eSPeter Avalos 	opt_lower = ASCII_IS_LOWER(p[0]);
437*e433da38SAaron LI 	curropt = findopt_name(&p, &oname, &ambig);
43825ce721eSPeter Avalos 	if (curropt != NULL)
4391133e27eSPeter Avalos 	{
4401133e27eSPeter Avalos 		/*
4411133e27eSPeter Avalos 		 * Got a match.
44225ce721eSPeter Avalos 		 * Remember the option and
4431133e27eSPeter Avalos 		 * display the full option name.
4441133e27eSPeter Avalos 		 */
4451133e27eSPeter Avalos 		cmd_reset();
4461133e27eSPeter Avalos 		mca_opt_toggle();
4471133e27eSPeter Avalos 		for (p = oname;  *p != '\0';  p++)
4481133e27eSPeter Avalos 		{
4491133e27eSPeter Avalos 			c = *p;
45025ce721eSPeter Avalos 			if (!opt_lower && ASCII_IS_LOWER(c))
4511133e27eSPeter Avalos 				c = ASCII_TO_UPPER(c);
4521133e27eSPeter Avalos 			if (cmd_char(c) != CC_OK)
4531133e27eSPeter Avalos 				return (MCA_DONE);
4541133e27eSPeter Avalos 		}
455*e433da38SAaron LI 	} else if (!ambig)
45602d62a0fSDaniel Fojt 	{
45702d62a0fSDaniel Fojt 		bell();
4581133e27eSPeter Avalos 	}
4591133e27eSPeter Avalos 	return (MCA_MORE);
4601133e27eSPeter Avalos }
46125ce721eSPeter Avalos 
46225ce721eSPeter Avalos /*
46325ce721eSPeter Avalos  * Handle a char of an option toggle command.
46425ce721eSPeter Avalos  */
mca_opt_char(char c)465*e433da38SAaron LI static int mca_opt_char(char c)
46625ce721eSPeter Avalos {
46725ce721eSPeter Avalos 	PARG parg;
46825ce721eSPeter Avalos 
46925ce721eSPeter Avalos 	/*
47025ce721eSPeter Avalos 	 * This may be a short option (single char),
47125ce721eSPeter Avalos 	 * or one char of a long option name,
47225ce721eSPeter Avalos 	 * or one char of the option parameter.
47325ce721eSPeter Avalos 	 */
47425ce721eSPeter Avalos 	if (curropt == NULL && len_cmdbuf() == 0)
47525ce721eSPeter Avalos 	{
47625ce721eSPeter Avalos 		int ret = mca_opt_first_char(c);
47725ce721eSPeter Avalos 		if (ret != NO_MCA)
47825ce721eSPeter Avalos 			return (ret);
47925ce721eSPeter Avalos 	}
48025ce721eSPeter Avalos 	if (optgetname)
48125ce721eSPeter Avalos 	{
48225ce721eSPeter Avalos 		/* We're getting a long option name.  */
4830c7ad07eSAntonio Huete Jimenez 		if (!is_newline_char(c) && c != '=')
48425ce721eSPeter Avalos 			return (mca_opt_nonfirst_char(c));
48525ce721eSPeter Avalos 		if (curropt == NULL)
48625ce721eSPeter Avalos 		{
48725ce721eSPeter Avalos 			parg.p_string = get_cmdbuf();
4880c7ad07eSAntonio Huete Jimenez 			if (parg.p_string == NULL)
4890c7ad07eSAntonio Huete Jimenez 				return (MCA_MORE);
49025ce721eSPeter Avalos 			error("There is no --%s option", &parg);
49125ce721eSPeter Avalos 			return (MCA_DONE);
49225ce721eSPeter Avalos 		}
49325ce721eSPeter Avalos 		optgetname = FALSE;
49425ce721eSPeter Avalos 		cmd_reset();
4951133e27eSPeter Avalos 	} else
4961133e27eSPeter Avalos 	{
49725ce721eSPeter Avalos 		if (is_erase_char(c))
49825ce721eSPeter Avalos 			return (NO_MCA);
49925ce721eSPeter Avalos 		if (curropt != NULL)
50025ce721eSPeter Avalos 			/* We're getting the option parameter. */
50125ce721eSPeter Avalos 			return (NO_MCA);
50225ce721eSPeter Avalos 		curropt = findopt(c);
50325ce721eSPeter Avalos 		if (curropt == NULL)
5041133e27eSPeter Avalos 		{
50525ce721eSPeter Avalos 			parg.p_string = propt(c);
50625ce721eSPeter Avalos 			error("There is no %s option", &parg);
50725ce721eSPeter Avalos 			return (MCA_DONE);
50825ce721eSPeter Avalos 		}
50902d62a0fSDaniel Fojt 		opt_lower = ASCII_IS_LOWER(c);
51025ce721eSPeter Avalos 	}
51125ce721eSPeter Avalos 	/*
51225ce721eSPeter Avalos 	 * If the option which was entered does not take a
51325ce721eSPeter Avalos 	 * parameter, toggle the option immediately,
51425ce721eSPeter Avalos 	 * so user doesn't have to hit RETURN.
51525ce721eSPeter Avalos 	 */
51625ce721eSPeter Avalos 	if ((optflag & ~OPT_NO_PROMPT) != OPT_TOGGLE ||
51725ce721eSPeter Avalos 	    !opt_has_param(curropt))
51825ce721eSPeter Avalos 	{
51902d62a0fSDaniel Fojt 		toggle_option(curropt, opt_lower, "", optflag);
5201133e27eSPeter Avalos 		return (MCA_DONE);
5211133e27eSPeter Avalos 	}
5221133e27eSPeter Avalos 	/*
52325ce721eSPeter Avalos 	 * Display a prompt appropriate for the option parameter.
5241133e27eSPeter Avalos 	 */
525*e433da38SAaron LI 	start_mca(A_OPT_TOGGLE, opt_prompt(curropt), NULL, 0);
5261133e27eSPeter Avalos 	return (MCA_MORE);
52725ce721eSPeter Avalos }
5281133e27eSPeter Avalos 
5291133e27eSPeter Avalos /*
5300c7ad07eSAntonio Huete Jimenez  * Normalize search type.
5310c7ad07eSAntonio Huete Jimenez  */
norm_search_type(int st)532320d7c8aSAaron LI public int norm_search_type(int st)
5330c7ad07eSAntonio Huete Jimenez {
5340c7ad07eSAntonio Huete Jimenez 	/* WRAP and PAST_EOF are mutually exclusive. */
5350c7ad07eSAntonio Huete Jimenez 	if ((st & (SRCH_PAST_EOF|SRCH_WRAP)) == (SRCH_PAST_EOF|SRCH_WRAP))
5360c7ad07eSAntonio Huete Jimenez 		st ^= SRCH_PAST_EOF;
5370c7ad07eSAntonio Huete Jimenez 	return st;
5380c7ad07eSAntonio Huete Jimenez }
5390c7ad07eSAntonio Huete Jimenez 
5400c7ad07eSAntonio Huete Jimenez /*
54125ce721eSPeter Avalos  * Handle a char of a search command.
54225ce721eSPeter Avalos  */
mca_search_char(char c)543*e433da38SAaron LI static int mca_search_char(char c)
54425ce721eSPeter Avalos {
54525ce721eSPeter Avalos 	int flag = 0;
54625ce721eSPeter Avalos 
54725ce721eSPeter Avalos 	/*
5481133e27eSPeter Avalos 	 * Certain characters as the first char of
5491133e27eSPeter Avalos 	 * the pattern have special meaning:
5501133e27eSPeter Avalos 	 *      !  Toggle the NO_MATCH flag
5511133e27eSPeter Avalos 	 *      *  Toggle the PAST_EOF flag
5521133e27eSPeter Avalos 	 *      @  Toggle the FIRST_FILE flag
5531133e27eSPeter Avalos 	 */
554*e433da38SAaron LI 	if (len_cmdbuf() > 0 || literal_char)
555*e433da38SAaron LI 	{
556*e433da38SAaron LI 		literal_char = FALSE;
55725ce721eSPeter Avalos 		return (NO_MCA);
558*e433da38SAaron LI 	}
5591133e27eSPeter Avalos 
5601133e27eSPeter Avalos 	switch (c)
5611133e27eSPeter Avalos 	{
5621133e27eSPeter Avalos 	case CONTROL('E'): /* ignore END of file */
5631133e27eSPeter Avalos 	case '*':
5648be36e5bSPeter Avalos 		if (mca != A_FILTER)
5651133e27eSPeter Avalos 			flag = SRCH_PAST_EOF;
566320d7c8aSAaron LI 		search_type &= ~SRCH_WRAP;
5671133e27eSPeter Avalos 		break;
5681133e27eSPeter Avalos 	case CONTROL('F'): /* FIRST file */
5691133e27eSPeter Avalos 	case '@':
5708be36e5bSPeter Avalos 		if (mca != A_FILTER)
5711133e27eSPeter Avalos 			flag = SRCH_FIRST_FILE;
5721133e27eSPeter Avalos 		break;
5731133e27eSPeter Avalos 	case CONTROL('K'): /* KEEP position */
5748be36e5bSPeter Avalos 		if (mca != A_FILTER)
5751133e27eSPeter Avalos 			flag = SRCH_NO_MOVE;
5761133e27eSPeter Avalos 		break;
577320d7c8aSAaron LI 	case CONTROL('S'): { /* SUBSEARCH */
578320d7c8aSAaron LI 		char buf[INT_STRLEN_BOUND(int)+24];
579320d7c8aSAaron LI 		SNPRINTF1(buf, sizeof(buf), "Sub-pattern (1-%d):", NUM_SEARCH_COLORS);
580320d7c8aSAaron LI 		clear_bot();
581320d7c8aSAaron LI 		cmd_putstr(buf);
582320d7c8aSAaron LI 		flush();
583320d7c8aSAaron LI 		c = getcc();
584320d7c8aSAaron LI 		if (c >= '1' && c <= '0'+NUM_SEARCH_COLORS)
585320d7c8aSAaron LI 			flag = SRCH_SUBSEARCH(c-'0');
586320d7c8aSAaron LI 		else
587320d7c8aSAaron LI 			flag = -1; /* calls mca_search() below to repaint */
588320d7c8aSAaron LI 		break; }
5890c7ad07eSAntonio Huete Jimenez 	case CONTROL('W'): /* WRAP around */
5900c7ad07eSAntonio Huete Jimenez 		if (mca != A_FILTER)
5910c7ad07eSAntonio Huete Jimenez 			flag = SRCH_WRAP;
5920c7ad07eSAntonio Huete Jimenez 		break;
5931133e27eSPeter Avalos 	case CONTROL('R'): /* Don't use REGULAR EXPRESSIONS */
5941133e27eSPeter Avalos 		flag = SRCH_NO_REGEX;
5951133e27eSPeter Avalos 		break;
5961133e27eSPeter Avalos 	case CONTROL('N'): /* NOT match */
5971133e27eSPeter Avalos 	case '!':
5981133e27eSPeter Avalos 		flag = SRCH_NO_MATCH;
5991133e27eSPeter Avalos 		break;
600*e433da38SAaron LI 	case CONTROL('L'):
601*e433da38SAaron LI 		literal_char = TRUE;
602*e433da38SAaron LI 		flag = -1;
603*e433da38SAaron LI 		break;
6041133e27eSPeter Avalos 	}
60525ce721eSPeter Avalos 
6061133e27eSPeter Avalos 	if (flag != 0)
6071133e27eSPeter Avalos 	{
608320d7c8aSAaron LI 		if (flag != -1)
6090c7ad07eSAntonio Huete Jimenez 			search_type = norm_search_type(search_type ^ flag);
6101133e27eSPeter Avalos 		mca_search();
6111133e27eSPeter Avalos 		return (MCA_MORE);
6121133e27eSPeter Avalos 	}
61325ce721eSPeter Avalos 	return (NO_MCA);
61425ce721eSPeter Avalos }
61525ce721eSPeter Avalos 
61625ce721eSPeter Avalos /*
61725ce721eSPeter Avalos  * Handle a character of a multi-character command.
61825ce721eSPeter Avalos  */
mca_char(char c)619*e433da38SAaron LI static int mca_char(char c)
62025ce721eSPeter Avalos {
62125ce721eSPeter Avalos 	int ret;
62225ce721eSPeter Avalos 
62325ce721eSPeter Avalos 	switch (mca)
62425ce721eSPeter Avalos 	{
62525ce721eSPeter Avalos 	case 0:
62625ce721eSPeter Avalos 		/*
62725ce721eSPeter Avalos 		 * We're not in a multicharacter command.
62825ce721eSPeter Avalos 		 */
62925ce721eSPeter Avalos 		return (NO_MCA);
63025ce721eSPeter Avalos 
63125ce721eSPeter Avalos 	case A_PREFIX:
63225ce721eSPeter Avalos 		/*
63325ce721eSPeter Avalos 		 * In the prefix of a command.
63425ce721eSPeter Avalos 		 * This not considered a multichar command
63525ce721eSPeter Avalos 		 * (even tho it uses cmdbuf, etc.).
63625ce721eSPeter Avalos 		 * It is handled in the commands() switch.
63725ce721eSPeter Avalos 		 */
63825ce721eSPeter Avalos 		return (NO_MCA);
63925ce721eSPeter Avalos 
64025ce721eSPeter Avalos 	case A_DIGIT:
64125ce721eSPeter Avalos 		/*
64225ce721eSPeter Avalos 		 * Entering digits of a number.
64325ce721eSPeter Avalos 		 * Terminated by a non-digit.
64425ce721eSPeter Avalos 		 */
6450c7ad07eSAntonio Huete Jimenez 		if ((c >= '0' && c <= '9') || c == '.')
6460c7ad07eSAntonio Huete Jimenez 			break;
6470c7ad07eSAntonio Huete Jimenez 		switch (editchar(c, ECF_PEEK|ECF_NOHISTORY|ECF_NOCOMPLETE|ECF_NORIGHTLEFT))
64825ce721eSPeter Avalos 		{
6490c7ad07eSAntonio Huete Jimenez 		case A_NOACTION:
6500c7ad07eSAntonio Huete Jimenez 			/*
6510c7ad07eSAntonio Huete Jimenez 			 * Ignore this char and get another one.
6520c7ad07eSAntonio Huete Jimenez 			 */
6530c7ad07eSAntonio Huete Jimenez 			return (MCA_MORE);
6540c7ad07eSAntonio Huete Jimenez 		case A_INVALID:
65525ce721eSPeter Avalos 			/*
65625ce721eSPeter Avalos 			 * Not part of the number.
65725ce721eSPeter Avalos 			 * End the number and treat this char
65825ce721eSPeter Avalos 			 * as a normal command character.
65925ce721eSPeter Avalos 			 */
66025ce721eSPeter Avalos 			number = cmd_int(&fraction);
66102d62a0fSDaniel Fojt 			clear_mca();
66225ce721eSPeter Avalos 			cmd_accept();
66325ce721eSPeter Avalos 			return (NO_MCA);
66425ce721eSPeter Avalos 		}
66525ce721eSPeter Avalos 		break;
66625ce721eSPeter Avalos 
66725ce721eSPeter Avalos 	case A_OPT_TOGGLE:
66825ce721eSPeter Avalos 		ret = mca_opt_char(c);
66925ce721eSPeter Avalos 		if (ret != NO_MCA)
67025ce721eSPeter Avalos 			return (ret);
67125ce721eSPeter Avalos 		break;
67225ce721eSPeter Avalos 
67325ce721eSPeter Avalos 	case A_F_SEARCH:
67425ce721eSPeter Avalos 	case A_B_SEARCH:
67525ce721eSPeter Avalos 	case A_FILTER:
67625ce721eSPeter Avalos 		ret = mca_search_char(c);
67725ce721eSPeter Avalos 		if (ret != NO_MCA)
67825ce721eSPeter Avalos 			return (ret);
67925ce721eSPeter Avalos 		break;
68025ce721eSPeter Avalos 
68125ce721eSPeter Avalos 	default:
68225ce721eSPeter Avalos 		/* Other multicharacter command. */
6831133e27eSPeter Avalos 		break;
6841133e27eSPeter Avalos 	}
6851133e27eSPeter Avalos 
6861133e27eSPeter Avalos 	/*
68725ce721eSPeter Avalos 	 * The multichar command is terminated by a newline.
6881133e27eSPeter Avalos 	 */
68902d62a0fSDaniel Fojt 	if (is_newline_char(c))
6901133e27eSPeter Avalos 	{
6911133e27eSPeter Avalos 		/*
6921133e27eSPeter Avalos 		 * Execute the command.
6931133e27eSPeter Avalos 		 */
6941133e27eSPeter Avalos 		exec_mca();
6951133e27eSPeter Avalos 		return (MCA_DONE);
6961133e27eSPeter Avalos 	}
6971133e27eSPeter Avalos 
6981133e27eSPeter Avalos 	/*
6991133e27eSPeter Avalos 	 * Append the char to the command buffer.
7001133e27eSPeter Avalos 	 */
7011133e27eSPeter Avalos 	if (cmd_char(c) == CC_QUIT)
7021133e27eSPeter Avalos 		/*
7031133e27eSPeter Avalos 		 * Abort the multi-char command.
7041133e27eSPeter Avalos 		 */
7051133e27eSPeter Avalos 		return (MCA_DONE);
7061133e27eSPeter Avalos 
7070c7ad07eSAntonio Huete Jimenez 	switch (mca)
7080c7ad07eSAntonio Huete Jimenez 	{
7090c7ad07eSAntonio Huete Jimenez 	case A_F_BRACKET:
7100c7ad07eSAntonio Huete Jimenez 	case A_B_BRACKET:
7110c7ad07eSAntonio Huete Jimenez 		if (len_cmdbuf() >= 2)
7121133e27eSPeter Avalos 		{
7131133e27eSPeter Avalos 			/*
7141133e27eSPeter Avalos 			 * Special case for the bracket-matching commands.
7151133e27eSPeter Avalos 			 * Execute the command after getting exactly two
7161133e27eSPeter Avalos 			 * characters from the user.
7171133e27eSPeter Avalos 			 */
7181133e27eSPeter Avalos 			exec_mca();
7191133e27eSPeter Avalos 			return (MCA_DONE);
7201133e27eSPeter Avalos 		}
7210c7ad07eSAntonio Huete Jimenez 		break;
7220c7ad07eSAntonio Huete Jimenez 	case A_F_SEARCH:
7230c7ad07eSAntonio Huete Jimenez 	case A_B_SEARCH:
7240c7ad07eSAntonio Huete Jimenez 		if (incr_search)
7250c7ad07eSAntonio Huete Jimenez 		{
7260c7ad07eSAntonio Huete Jimenez 			/* Incremental search: do a search after every input char. */
727320d7c8aSAaron LI 			int st = (search_type & (SRCH_FORW|SRCH_BACK|SRCH_NO_MATCH|SRCH_NO_REGEX|SRCH_NO_MOVE|SRCH_WRAP|SRCH_SUBSEARCH_ALL));
728*e433da38SAaron LI 			ssize_t save_updown;
729*e433da38SAaron LI 			constant char *pattern = get_cmdbuf();
7300c7ad07eSAntonio Huete Jimenez 			if (pattern == NULL)
7310c7ad07eSAntonio Huete Jimenez 				return (MCA_MORE);
7320c7ad07eSAntonio Huete Jimenez 			/*
7330c7ad07eSAntonio Huete Jimenez 			 * Must save updown_match because mca_search
7340c7ad07eSAntonio Huete Jimenez 			 * reinits it. That breaks history scrolling.
7350c7ad07eSAntonio Huete Jimenez 			 * {{ This is ugly. mca_search probably shouldn't call set_mlist. }}
7360c7ad07eSAntonio Huete Jimenez 			 */
737*e433da38SAaron LI 			save_updown = save_updown_match();
7380c7ad07eSAntonio Huete Jimenez 			cmd_exec();
7390c7ad07eSAntonio Huete Jimenez 			if (*pattern == '\0')
7400c7ad07eSAntonio Huete Jimenez 			{
7410c7ad07eSAntonio Huete Jimenez 				/* User has backspaced to an empty pattern. */
7420c7ad07eSAntonio Huete Jimenez 				undo_search(1);
7430c7ad07eSAntonio Huete Jimenez 			} else
7440c7ad07eSAntonio Huete Jimenez 			{
7450c7ad07eSAntonio Huete Jimenez 				if (search(st | SRCH_INCR, pattern, 1) != 0)
7460c7ad07eSAntonio Huete Jimenez 					/* No match, invalid pattern, etc. */
7470c7ad07eSAntonio Huete Jimenez 					undo_search(1);
7480c7ad07eSAntonio Huete Jimenez 			}
7490c7ad07eSAntonio Huete Jimenez 			/* Redraw the search prompt and search string. */
750*e433da38SAaron LI 			if (is_screen_trashed() || !full_screen)
751320d7c8aSAaron LI 			{
752320d7c8aSAaron LI 				clear();
753320d7c8aSAaron LI 				repaint();
754320d7c8aSAaron LI 			}
7550c7ad07eSAntonio Huete Jimenez 			mca_search1();
756*e433da38SAaron LI 			restore_updown_match(save_updown);
7570c7ad07eSAntonio Huete Jimenez 			cmd_repaint(NULL);
7580c7ad07eSAntonio Huete Jimenez 		}
7590c7ad07eSAntonio Huete Jimenez 		break;
7600c7ad07eSAntonio Huete Jimenez 	}
7611133e27eSPeter Avalos 
7621133e27eSPeter Avalos 	/*
7631133e27eSPeter Avalos 	 * Need another character.
7641133e27eSPeter Avalos 	 */
7651133e27eSPeter Avalos 	return (MCA_MORE);
7661133e27eSPeter Avalos }
7671133e27eSPeter Avalos 
7681133e27eSPeter Avalos /*
7691133e27eSPeter Avalos  * Discard any buffered file data.
7701133e27eSPeter Avalos  */
clear_buffers(void)771320d7c8aSAaron LI static void clear_buffers(void)
7721133e27eSPeter Avalos {
7731133e27eSPeter Avalos 	if (!(ch_getflags() & CH_CANSEEK))
7741133e27eSPeter Avalos 		return;
7751133e27eSPeter Avalos 	ch_flush();
7761133e27eSPeter Avalos 	clr_linenum();
7771133e27eSPeter Avalos #if HILITE_SEARCH
7781133e27eSPeter Avalos 	clr_hilite();
7791133e27eSPeter Avalos #endif
7801133e27eSPeter Avalos }
7811133e27eSPeter Avalos 
screen_trashed_num(int trashed)782*e433da38SAaron LI public void screen_trashed_num(int trashed)
783*e433da38SAaron LI {
784*e433da38SAaron LI 	screen_trashed_value = trashed;
785*e433da38SAaron LI }
786*e433da38SAaron LI 
screen_trashed(void)787*e433da38SAaron LI public void screen_trashed(void)
788*e433da38SAaron LI {
789*e433da38SAaron LI 	screen_trashed_num(1);
790*e433da38SAaron LI }
791*e433da38SAaron LI 
is_screen_trashed(void)792*e433da38SAaron LI public int is_screen_trashed(void)
793*e433da38SAaron LI {
794*e433da38SAaron LI 	return screen_trashed_value;
795*e433da38SAaron LI }
796*e433da38SAaron LI 
7971133e27eSPeter Avalos /*
7981133e27eSPeter Avalos  * Make sure the screen is displayed.
7991133e27eSPeter Avalos  */
make_display(void)800320d7c8aSAaron LI static void make_display(void)
8011133e27eSPeter Avalos {
8021133e27eSPeter Avalos 	/*
803320d7c8aSAaron LI 	 * If not full_screen, we can't rely on scrolling to fill the screen.
804320d7c8aSAaron LI 	 * We need to clear and repaint screen before any change.
805320d7c8aSAaron LI 	 */
806320d7c8aSAaron LI 	if (!full_screen && !(quit_if_one_screen && one_screen))
807320d7c8aSAaron LI 		clear();
808320d7c8aSAaron LI 	/*
8091133e27eSPeter Avalos 	 * If nothing is displayed yet, display starting from initial_scrpos.
8101133e27eSPeter Avalos 	 */
8111133e27eSPeter Avalos 	if (empty_screen())
8121133e27eSPeter Avalos 	{
8131133e27eSPeter Avalos 		if (initial_scrpos.pos == NULL_POSITION)
8141133e27eSPeter Avalos 			jump_loc(ch_zero(), 1);
8151133e27eSPeter Avalos 		else
8161133e27eSPeter Avalos 			jump_loc(initial_scrpos.pos, initial_scrpos.ln);
817*e433da38SAaron LI 	} else if (is_screen_trashed() || !full_screen)
8181133e27eSPeter Avalos 	{
8191133e27eSPeter Avalos 		int save_top_scroll = top_scroll;
8201133e27eSPeter Avalos 		int save_ignore_eoi = ignore_eoi;
8211133e27eSPeter Avalos 		top_scroll = 1;
8221133e27eSPeter Avalos 		ignore_eoi = 0;
823*e433da38SAaron LI 		if (is_screen_trashed() == 2)
8241133e27eSPeter Avalos 		{
8251133e27eSPeter Avalos 			/* Special case used by ignore_eoi: re-open the input file
8261133e27eSPeter Avalos 			 * and jump to the end of the file. */
8271133e27eSPeter Avalos 			reopen_curr_ifile();
8281133e27eSPeter Avalos 			jump_forw();
8291133e27eSPeter Avalos 		}
8301133e27eSPeter Avalos 		repaint();
8311133e27eSPeter Avalos 		top_scroll = save_top_scroll;
8321133e27eSPeter Avalos 		ignore_eoi = save_ignore_eoi;
8331133e27eSPeter Avalos 	}
8341133e27eSPeter Avalos }
8351133e27eSPeter Avalos 
8361133e27eSPeter Avalos /*
8371133e27eSPeter Avalos  * Display the appropriate prompt.
8381133e27eSPeter Avalos  */
prompt(void)839320d7c8aSAaron LI static void prompt(void)
8401133e27eSPeter Avalos {
84102d62a0fSDaniel Fojt 	constant char *p;
8421133e27eSPeter Avalos 
843*e433da38SAaron LI 	if (ungot != NULL && !ungot->ug_end_command)
8441133e27eSPeter Avalos 	{
8451133e27eSPeter Avalos 		/*
8461133e27eSPeter Avalos 		 * No prompt necessary if commands are from
8471133e27eSPeter Avalos 		 * ungotten chars rather than from the user.
8481133e27eSPeter Avalos 		 */
8491133e27eSPeter Avalos 		return;
8501133e27eSPeter Avalos 	}
8511133e27eSPeter Avalos 
8521133e27eSPeter Avalos 	/*
8531133e27eSPeter Avalos 	 * Make sure the screen is displayed.
8541133e27eSPeter Avalos 	 */
8551133e27eSPeter Avalos 	make_display();
8561133e27eSPeter Avalos 	bottompos = position(BOTTOM_PLUS_ONE);
8571133e27eSPeter Avalos 
8581133e27eSPeter Avalos 	/*
8598be36e5bSPeter Avalos 	 * If we've hit EOF on the last file and the -E flag is set, quit.
8601133e27eSPeter Avalos 	 */
8618be36e5bSPeter Avalos 	if (get_quit_at_eof() == OPT_ONPLUS &&
8628be36e5bSPeter Avalos 	    eof_displayed() && !(ch_getflags() & CH_HELPFILE) &&
8631133e27eSPeter Avalos 	    next_ifile(curr_ifile) == NULL_IFILE)
8641133e27eSPeter Avalos 		quit(QUIT_OK);
8658be36e5bSPeter Avalos 
8661133e27eSPeter Avalos 	/*
8678be36e5bSPeter Avalos 	 * If the entire file is displayed and the -F flag is set, quit.
8681133e27eSPeter Avalos 	 */
8698be36e5bSPeter Avalos 	if (quit_if_one_screen &&
8708be36e5bSPeter Avalos 	    entire_file_displayed() && !(ch_getflags() & CH_HELPFILE) &&
8711133e27eSPeter Avalos 	    next_ifile(curr_ifile) == NULL_IFILE)
8721133e27eSPeter Avalos 		quit(QUIT_OK);
8730c7ad07eSAntonio Huete Jimenez 	quit_if_one_screen = FALSE; /* only get one chance at this */
8741133e27eSPeter Avalos 
8751133e27eSPeter Avalos #if MSDOS_COMPILER==WIN32C
8761133e27eSPeter Avalos 	/*
8771133e27eSPeter Avalos 	 * In Win32, display the file name in the window title.
8781133e27eSPeter Avalos 	 */
8791133e27eSPeter Avalos 	if (!(ch_getflags() & CH_HELPFILE))
88002d62a0fSDaniel Fojt 	{
88102d62a0fSDaniel Fojt 		WCHAR w[MAX_PATH+16];
8820c7ad07eSAntonio Huete Jimenez 		p = pr_expand("Less?f - %f.");
883*e433da38SAaron LI 		MultiByteToWideChar(less_acp, 0, p, -1, w, countof(w));
88402d62a0fSDaniel Fojt 		SetConsoleTitleW(w);
88502d62a0fSDaniel Fojt 	}
8861133e27eSPeter Avalos #endif
88702d62a0fSDaniel Fojt 
8881133e27eSPeter Avalos 	/*
8891133e27eSPeter Avalos 	 * Select the proper prompt and display it.
8901133e27eSPeter Avalos 	 */
8911133e27eSPeter Avalos 	/*
8921133e27eSPeter Avalos 	 * If the previous action was a forward movement,
8931133e27eSPeter Avalos 	 * don't clear the bottom line of the display;
8941133e27eSPeter Avalos 	 * just print the prompt since the forward movement guarantees
8951133e27eSPeter Avalos 	 * that we're in the right position to display the prompt.
8961133e27eSPeter Avalos 	 * Clearing the line could cause a problem: for example, if the last
8971133e27eSPeter Avalos 	 * line displayed ended at the right screen edge without a newline,
8981133e27eSPeter Avalos 	 * then clearing would clear the last displayed line rather than
8991133e27eSPeter Avalos 	 * the prompt line.
9001133e27eSPeter Avalos 	 */
9011133e27eSPeter Avalos 	if (!forw_prompt)
9021133e27eSPeter Avalos 		clear_bot();
9031133e27eSPeter Avalos 	clear_cmd();
9041133e27eSPeter Avalos 	forw_prompt = 0;
9051133e27eSPeter Avalos 	p = pr_string();
9060c7ad07eSAntonio Huete Jimenez #if HILITE_SEARCH
9078be36e5bSPeter Avalos 	if (is_filtering())
9088be36e5bSPeter Avalos 		putstr("& ");
9090c7ad07eSAntonio Huete Jimenez #endif
910*e433da38SAaron LI 	if (search_wrapped)
911*e433da38SAaron LI 	{
912*e433da38SAaron LI 		if (search_type & SRCH_BACK)
913*e433da38SAaron LI 			error("Search hit top; continuing at bottom", NULL_PARG);
914*e433da38SAaron LI 		else
915*e433da38SAaron LI 			error("Search hit bottom; continuing at top", NULL_PARG);
916*e433da38SAaron LI 		search_wrapped = FALSE;
917*e433da38SAaron LI 	}
918*e433da38SAaron LI #if OSC8_LINK
919*e433da38SAaron LI 	if (osc8_uri != NULL)
920*e433da38SAaron LI 	{
921*e433da38SAaron LI 		PARG parg;
922*e433da38SAaron LI 		parg.p_string = osc8_uri;
923*e433da38SAaron LI 		error("Link: %s", &parg);
924*e433da38SAaron LI 		free(osc8_uri);
925*e433da38SAaron LI 		osc8_uri = NULL;
926*e433da38SAaron LI 	}
927*e433da38SAaron LI #endif
9281133e27eSPeter Avalos 	if (p == NULL || *p == '\0')
9290c7ad07eSAntonio Huete Jimenez 	{
9300c7ad07eSAntonio Huete Jimenez 		at_enter(AT_NORMAL|AT_COLOR_PROMPT);
9311133e27eSPeter Avalos 		putchr(':');
9320c7ad07eSAntonio Huete Jimenez 		at_exit();
9330c7ad07eSAntonio Huete Jimenez 	} else
9341133e27eSPeter Avalos 	{
93502d62a0fSDaniel Fojt #if MSDOS_COMPILER==WIN32C
93602d62a0fSDaniel Fojt 		WCHAR w[MAX_PATH*2];
93702d62a0fSDaniel Fojt 		char  a[MAX_PATH*2];
938*e433da38SAaron LI 		MultiByteToWideChar(less_acp, 0, p, -1, w, countof(w));
93902d62a0fSDaniel Fojt 		WideCharToMultiByte(utf_mode ? CP_UTF8 : GetConsoleOutputCP(),
94002d62a0fSDaniel Fojt 		                    0, w, -1, a, sizeof(a), NULL, NULL);
94102d62a0fSDaniel Fojt 		p = a;
94202d62a0fSDaniel Fojt #endif
9430c7ad07eSAntonio Huete Jimenez 		load_line(p);
9440c7ad07eSAntonio Huete Jimenez 		put_line();
9451133e27eSPeter Avalos 	}
9461133e27eSPeter Avalos 	clear_eol();
9471133e27eSPeter Avalos }
9481133e27eSPeter Avalos 
9491133e27eSPeter Avalos /*
9501133e27eSPeter Avalos  * Display the less version message.
9511133e27eSPeter Avalos  */
dispversion(void)952320d7c8aSAaron LI public void dispversion(void)
9531133e27eSPeter Avalos {
9541133e27eSPeter Avalos 	PARG parg;
9551133e27eSPeter Avalos 
9561133e27eSPeter Avalos 	parg.p_string = version;
9571133e27eSPeter Avalos 	error("less %s", &parg);
9581133e27eSPeter Avalos }
9591133e27eSPeter Avalos 
9601133e27eSPeter Avalos /*
96102d62a0fSDaniel Fojt  * Return a character to complete a partial command, if possible.
96202d62a0fSDaniel Fojt  */
getcc_end_command(void)963*e433da38SAaron LI static char getcc_end_command(void)
96402d62a0fSDaniel Fojt {
965*e433da38SAaron LI 	int ch;
96602d62a0fSDaniel Fojt 	switch (mca)
96702d62a0fSDaniel Fojt 	{
96802d62a0fSDaniel Fojt 	case A_DIGIT:
96902d62a0fSDaniel Fojt 		/* We have a number but no command.  Treat as #g. */
97002d62a0fSDaniel Fojt 		return ('g');
97102d62a0fSDaniel Fojt 	case A_F_SEARCH:
97202d62a0fSDaniel Fojt 	case A_B_SEARCH:
973320d7c8aSAaron LI 	case A_FILTER:
97402d62a0fSDaniel Fojt 		/* We have "/string" but no newline.  Add the \n. */
97502d62a0fSDaniel Fojt 		return ('\n');
97602d62a0fSDaniel Fojt 	default:
97702d62a0fSDaniel Fojt 		/* Some other incomplete command.  Let user complete it. */
978*e433da38SAaron LI 		if (ungot != NULL)
979*e433da38SAaron LI 			return ('\0');
980*e433da38SAaron LI 		ch = getchr();
981*e433da38SAaron LI 		if (ch < 0) ch = '\0';
982*e433da38SAaron LI 		return (char) ch;
98302d62a0fSDaniel Fojt 	}
98402d62a0fSDaniel Fojt }
98502d62a0fSDaniel Fojt 
98602d62a0fSDaniel Fojt /*
987*e433da38SAaron LI  * Get a command character from the ungotten stack.
988*e433da38SAaron LI  */
get_ungot(lbool * p_end_command)989*e433da38SAaron LI static char get_ungot(lbool *p_end_command)
990*e433da38SAaron LI {
991*e433da38SAaron LI 	struct ungot *ug = ungot;
992*e433da38SAaron LI 	char c = ug->ug_char;
993*e433da38SAaron LI 	if (p_end_command != NULL)
994*e433da38SAaron LI 		*p_end_command = ug->ug_end_command;
995*e433da38SAaron LI 	ungot = ug->ug_next;
996*e433da38SAaron LI 	free(ug);
997*e433da38SAaron LI 	return c;
998*e433da38SAaron LI }
999*e433da38SAaron LI 
1000*e433da38SAaron LI /*
1001*e433da38SAaron LI  * Delete all ungotten characters.
1002*e433da38SAaron LI  */
getcc_clear(void)1003*e433da38SAaron LI public void getcc_clear(void)
1004*e433da38SAaron LI {
1005*e433da38SAaron LI 	while (ungot != NULL)
1006*e433da38SAaron LI 		(void) get_ungot(NULL);
1007*e433da38SAaron LI }
1008*e433da38SAaron LI 
1009*e433da38SAaron LI /*
10101133e27eSPeter Avalos  * Get command character.
10111133e27eSPeter Avalos  * The character normally comes from the keyboard,
10121133e27eSPeter Avalos  * but may come from ungotten characters
10131133e27eSPeter Avalos  * (characters previously given to ungetcc or ungetsc).
10141133e27eSPeter Avalos  */
getccu(void)1015*e433da38SAaron LI static char getccu(void)
10161133e27eSPeter Avalos {
1017*e433da38SAaron LI 	int c = 0;
10180c7ad07eSAntonio Huete Jimenez 	while (c == 0)
10190c7ad07eSAntonio Huete Jimenez 	{
1020fa0be7c5SJohn Marino 		if (ungot == NULL)
102125ce721eSPeter Avalos 		{
102202d62a0fSDaniel Fojt 			/* Normal case: no ungotten chars.
102302d62a0fSDaniel Fojt 			 * Get char from the user. */
102402d62a0fSDaniel Fojt 			c = getchr();
1025*e433da38SAaron LI 			if (c < 0) return ('\0');
102602d62a0fSDaniel Fojt 		} else
1027fa0be7c5SJohn Marino 		{
102802d62a0fSDaniel Fojt 			/* Ungotten chars available:
102902d62a0fSDaniel Fojt 			 * Take the top of stack (most recent). */
1030*e433da38SAaron LI 			lbool end_command;
1031*e433da38SAaron LI 			c = get_ungot(&end_command);
1032*e433da38SAaron LI 			if (end_command)
103302d62a0fSDaniel Fojt 				c = getcc_end_command();
10341133e27eSPeter Avalos 		}
10350c7ad07eSAntonio Huete Jimenez 	}
1036*e433da38SAaron LI 	return ((char) c);
103725ce721eSPeter Avalos }
103802d62a0fSDaniel Fojt 
103902d62a0fSDaniel Fojt /*
104002d62a0fSDaniel Fojt  * Get a command character, but if we receive the orig sequence,
104102d62a0fSDaniel Fojt  * convert it to the repl sequence.
104202d62a0fSDaniel Fojt  */
getcc_repl(char constant * orig,char constant * repl,char (* gr_getc)(void),void (* gr_ungetc)(char))1043*e433da38SAaron LI static char getcc_repl(char constant *orig, char constant *repl, char (*gr_getc)(void), void (*gr_ungetc)(char))
104402d62a0fSDaniel Fojt {
1045*e433da38SAaron LI 	char c;
1046*e433da38SAaron LI 	char keys[16];
1047*e433da38SAaron LI 	size_t ki = 0;
104802d62a0fSDaniel Fojt 
104902d62a0fSDaniel Fojt 	c = (*gr_getc)();
105002d62a0fSDaniel Fojt 	if (orig == NULL || orig[0] == '\0')
105102d62a0fSDaniel Fojt 		return c;
105202d62a0fSDaniel Fojt 	for (;;)
105302d62a0fSDaniel Fojt 	{
105402d62a0fSDaniel Fojt 		keys[ki] = c;
105502d62a0fSDaniel Fojt 		if (c != orig[ki] || ki >= sizeof(keys)-1)
105602d62a0fSDaniel Fojt 		{
105702d62a0fSDaniel Fojt 			/* This is not orig we have been receiving.
105802d62a0fSDaniel Fojt 			 * If we have stashed chars in keys[],
105902d62a0fSDaniel Fojt 			 * unget them and return the first one. */
106002d62a0fSDaniel Fojt 			while (ki > 0)
106102d62a0fSDaniel Fojt 				(*gr_ungetc)(keys[ki--]);
106202d62a0fSDaniel Fojt 			return keys[0];
106302d62a0fSDaniel Fojt 		}
106402d62a0fSDaniel Fojt 		if (orig[++ki] == '\0')
106502d62a0fSDaniel Fojt 		{
106602d62a0fSDaniel Fojt 			/* We've received the full orig sequence.
106702d62a0fSDaniel Fojt 			 * Return the repl sequence. */
106802d62a0fSDaniel Fojt 			ki = strlen(repl)-1;
106902d62a0fSDaniel Fojt 			while (ki > 0)
107002d62a0fSDaniel Fojt 				(*gr_ungetc)(repl[ki--]);
107102d62a0fSDaniel Fojt 			return repl[0];
107202d62a0fSDaniel Fojt 		}
107302d62a0fSDaniel Fojt 		/* We've received a partial orig sequence (ki chars of it).
107402d62a0fSDaniel Fojt 		 * Get next char and see if it continues to match orig. */
107502d62a0fSDaniel Fojt 		c = (*gr_getc)();
107602d62a0fSDaniel Fojt 	}
107702d62a0fSDaniel Fojt }
107802d62a0fSDaniel Fojt 
107902d62a0fSDaniel Fojt /*
108002d62a0fSDaniel Fojt  * Get command character.
108102d62a0fSDaniel Fojt  */
getcc(void)1082*e433da38SAaron LI public char getcc(void)
108302d62a0fSDaniel Fojt {
108402d62a0fSDaniel Fojt 	/* Replace kent (keypad Enter) with a newline. */
108502d62a0fSDaniel Fojt 	return getcc_repl(kent, "\n", getccu, ungetcc);
108625ce721eSPeter Avalos }
108725ce721eSPeter Avalos 
10881133e27eSPeter Avalos /*
10891133e27eSPeter Avalos  * "Unget" a command character.
10901133e27eSPeter Avalos  * The next getcc() will return this character.
10911133e27eSPeter Avalos  */
ungetcc(char c)1092*e433da38SAaron LI public void ungetcc(char c)
10931133e27eSPeter Avalos {
109425ce721eSPeter Avalos 	struct ungot *ug = (struct ungot *) ecalloc(1, sizeof(struct ungot));
109525ce721eSPeter Avalos 
109602d62a0fSDaniel Fojt 	ug->ug_char = c;
109725ce721eSPeter Avalos 	ug->ug_next = ungot;
109825ce721eSPeter Avalos 	ungot = ug;
10991133e27eSPeter Avalos }
11001133e27eSPeter Avalos 
11011133e27eSPeter Avalos /*
11020c7ad07eSAntonio Huete Jimenez  * "Unget" a command character.
11030c7ad07eSAntonio Huete Jimenez  * If any other chars are already ungotten, put this one after those.
11040c7ad07eSAntonio Huete Jimenez  */
ungetcc_back1(char c,lbool end_command)1105*e433da38SAaron LI static void ungetcc_back1(char c, lbool end_command)
11060c7ad07eSAntonio Huete Jimenez {
11070c7ad07eSAntonio Huete Jimenez 	struct ungot *ug = (struct ungot *) ecalloc(1, sizeof(struct ungot));
11080c7ad07eSAntonio Huete Jimenez 	ug->ug_char = c;
1109*e433da38SAaron LI 	ug->ug_end_command = end_command;
11100c7ad07eSAntonio Huete Jimenez 	ug->ug_next = NULL;
11110c7ad07eSAntonio Huete Jimenez 	if (ungot == NULL)
11120c7ad07eSAntonio Huete Jimenez 		ungot = ug;
11130c7ad07eSAntonio Huete Jimenez 	else
11140c7ad07eSAntonio Huete Jimenez 	{
11150c7ad07eSAntonio Huete Jimenez 		struct ungot *pu;
11160c7ad07eSAntonio Huete Jimenez 		for (pu = ungot; pu->ug_next != NULL; pu = pu->ug_next)
11170c7ad07eSAntonio Huete Jimenez 			continue;
11180c7ad07eSAntonio Huete Jimenez 		pu->ug_next = ug;
11190c7ad07eSAntonio Huete Jimenez 	}
11200c7ad07eSAntonio Huete Jimenez }
11210c7ad07eSAntonio Huete Jimenez 
ungetcc_back(char c)1122*e433da38SAaron LI public void ungetcc_back(char c)
1123*e433da38SAaron LI {
1124*e433da38SAaron LI 	ungetcc_back1(c, FALSE);
1125*e433da38SAaron LI }
1126*e433da38SAaron LI 
ungetcc_end_command(void)1127*e433da38SAaron LI public void ungetcc_end_command(void)
1128*e433da38SAaron LI {
1129*e433da38SAaron LI 	ungetcc_back1('\0', TRUE);
1130*e433da38SAaron LI }
1131*e433da38SAaron LI 
11320c7ad07eSAntonio Huete Jimenez /*
11331133e27eSPeter Avalos  * Unget a whole string of command characters.
11341133e27eSPeter Avalos  * The next sequence of getcc()'s will return this string.
11351133e27eSPeter Avalos  */
ungetsc(constant char * s)1136*e433da38SAaron LI public void ungetsc(constant char *s)
11371133e27eSPeter Avalos {
11380c7ad07eSAntonio Huete Jimenez 	while (*s != '\0')
11390c7ad07eSAntonio Huete Jimenez 		ungetcc_back(*s++);
11401133e27eSPeter Avalos }
11411133e27eSPeter Avalos 
11421133e27eSPeter Avalos /*
114302d62a0fSDaniel Fojt  * Peek the next command character, without consuming it.
114402d62a0fSDaniel Fojt  */
peekcc(void)1145*e433da38SAaron LI public char peekcc(void)
114602d62a0fSDaniel Fojt {
1147*e433da38SAaron LI 	char c = getcc();
114802d62a0fSDaniel Fojt 	ungetcc(c);
114902d62a0fSDaniel Fojt 	return c;
115002d62a0fSDaniel Fojt }
115102d62a0fSDaniel Fojt 
115202d62a0fSDaniel Fojt /*
11531133e27eSPeter Avalos  * Search for a pattern, possibly in multiple files.
11541133e27eSPeter Avalos  * If SRCH_FIRST_FILE is set, begin searching at the first file.
11551133e27eSPeter Avalos  * If SRCH_PAST_EOF is set, continue the search thru multiple files.
11561133e27eSPeter Avalos  */
multi_search(constant char * pattern,int n,int silent)1157*e433da38SAaron LI static void multi_search(constant char *pattern, int n, int silent)
11581133e27eSPeter Avalos {
115902d62a0fSDaniel Fojt 	int nomore;
11601133e27eSPeter Avalos 	IFILE save_ifile;
1161*e433da38SAaron LI 	lbool changed_file;
11621133e27eSPeter Avalos 
1163*e433da38SAaron LI 	changed_file = FALSE;
11641133e27eSPeter Avalos 	save_ifile = save_curr_ifile();
11651133e27eSPeter Avalos 
1166320d7c8aSAaron LI 	if ((search_type & (SRCH_FORW|SRCH_BACK)) == 0)
1167320d7c8aSAaron LI 		search_type |= SRCH_FORW;
11681133e27eSPeter Avalos 	if (search_type & SRCH_FIRST_FILE)
11691133e27eSPeter Avalos 	{
11701133e27eSPeter Avalos 		/*
11711133e27eSPeter Avalos 		 * Start at the first (or last) file
11721133e27eSPeter Avalos 		 * in the command line list.
11731133e27eSPeter Avalos 		 */
11741133e27eSPeter Avalos 		if (search_type & SRCH_FORW)
11751133e27eSPeter Avalos 			nomore = edit_first();
11761133e27eSPeter Avalos 		else
11771133e27eSPeter Avalos 			nomore = edit_last();
11781133e27eSPeter Avalos 		if (nomore)
11791133e27eSPeter Avalos 		{
11801133e27eSPeter Avalos 			unsave_ifile(save_ifile);
11811133e27eSPeter Avalos 			return;
11821133e27eSPeter Avalos 		}
1183*e433da38SAaron LI 		changed_file = TRUE;
11841133e27eSPeter Avalos 		search_type &= ~SRCH_FIRST_FILE;
11851133e27eSPeter Avalos 	}
11861133e27eSPeter Avalos 
11871133e27eSPeter Avalos 	for (;;)
11881133e27eSPeter Avalos 	{
11891133e27eSPeter Avalos 		n = search(search_type, pattern, n);
11901133e27eSPeter Avalos 		/*
11911133e27eSPeter Avalos 		 * The SRCH_NO_MOVE flag doesn't "stick": it gets cleared
11921133e27eSPeter Avalos 		 * after being used once.  This allows "n" to work after
11931133e27eSPeter Avalos 		 * using a /@@ search.
11941133e27eSPeter Avalos 		 */
11951133e27eSPeter Avalos 		search_type &= ~SRCH_NO_MOVE;
1196320d7c8aSAaron LI 		last_search_type = search_type;
11971133e27eSPeter Avalos 		if (n == 0)
11981133e27eSPeter Avalos 		{
11991133e27eSPeter Avalos 			/*
12001133e27eSPeter Avalos 			 * Found it.
12011133e27eSPeter Avalos 			 */
12021133e27eSPeter Avalos 			unsave_ifile(save_ifile);
12031133e27eSPeter Avalos 			return;
12041133e27eSPeter Avalos 		}
12051133e27eSPeter Avalos 
12061133e27eSPeter Avalos 		if (n < 0)
12071133e27eSPeter Avalos 			/*
12081133e27eSPeter Avalos 			 * Some kind of error in the search.
12091133e27eSPeter Avalos 			 * Error message has been printed by search().
12101133e27eSPeter Avalos 			 */
12111133e27eSPeter Avalos 			break;
12121133e27eSPeter Avalos 
12131133e27eSPeter Avalos 		if ((search_type & SRCH_PAST_EOF) == 0)
12141133e27eSPeter Avalos 			/*
12151133e27eSPeter Avalos 			 * We didn't find a match, but we're
12161133e27eSPeter Avalos 			 * supposed to search only one file.
12171133e27eSPeter Avalos 			 */
12181133e27eSPeter Avalos 			break;
12191133e27eSPeter Avalos 		/*
12201133e27eSPeter Avalos 		 * Move on to the next file.
12211133e27eSPeter Avalos 		 */
12221133e27eSPeter Avalos 		if (search_type & SRCH_FORW)
12231133e27eSPeter Avalos 			nomore = edit_next(1);
12241133e27eSPeter Avalos 		else
12251133e27eSPeter Avalos 			nomore = edit_prev(1);
12261133e27eSPeter Avalos 		if (nomore)
12271133e27eSPeter Avalos 			break;
1228*e433da38SAaron LI 		changed_file = TRUE;
12291133e27eSPeter Avalos 	}
12301133e27eSPeter Avalos 
12311133e27eSPeter Avalos 	/*
12321133e27eSPeter Avalos 	 * Didn't find it.
12331133e27eSPeter Avalos 	 * Print an error message if we haven't already.
12341133e27eSPeter Avalos 	 */
1235fa0be7c5SJohn Marino 	if (n > 0 && !silent)
12361133e27eSPeter Avalos 		error("Pattern not found", NULL_PARG);
12371133e27eSPeter Avalos 
12381133e27eSPeter Avalos 	if (changed_file)
12391133e27eSPeter Avalos 	{
12401133e27eSPeter Avalos 		/*
12411133e27eSPeter Avalos 		 * Restore the file we were originally viewing.
12421133e27eSPeter Avalos 		 */
12431133e27eSPeter Avalos 		reedit_ifile(save_ifile);
12441133e27eSPeter Avalos 	} else
12451133e27eSPeter Avalos 	{
12461133e27eSPeter Avalos 		unsave_ifile(save_ifile);
12471133e27eSPeter Avalos 	}
12481133e27eSPeter Avalos }
12491133e27eSPeter Avalos 
12501133e27eSPeter Avalos /*
1251e639dc31SJohn Marino  * Forward forever, or until a highlighted line appears.
1252e639dc31SJohn Marino  */
forw_loop(int until_hilite)1253320d7c8aSAaron LI static int forw_loop(int until_hilite)
1254e639dc31SJohn Marino {
1255e639dc31SJohn Marino 	POSITION curr_len;
1256e639dc31SJohn Marino 
1257e639dc31SJohn Marino 	if (ch_getflags() & CH_HELPFILE)
1258e639dc31SJohn Marino 		return (A_NOACTION);
1259e639dc31SJohn Marino 
1260e639dc31SJohn Marino 	cmd_exec();
1261fa0be7c5SJohn Marino 	jump_forw_buffered();
1262e639dc31SJohn Marino 	curr_len = ch_length();
1263e639dc31SJohn Marino 	highest_hilite = until_hilite ? curr_len : NULL_POSITION;
1264e639dc31SJohn Marino 	ignore_eoi = 1;
1265e639dc31SJohn Marino 	while (!sigs)
1266e639dc31SJohn Marino 	{
1267e639dc31SJohn Marino 		if (until_hilite && highest_hilite > curr_len)
1268e639dc31SJohn Marino 		{
1269e639dc31SJohn Marino 			bell();
1270e639dc31SJohn Marino 			break;
1271e639dc31SJohn Marino 		}
1272e639dc31SJohn Marino 		make_display();
1273e639dc31SJohn Marino 		forward(1, 0, 0);
1274e639dc31SJohn Marino 	}
1275e639dc31SJohn Marino 	ignore_eoi = 0;
1276e639dc31SJohn Marino 	ch_set_eof();
1277e639dc31SJohn Marino 
1278e639dc31SJohn Marino 	/*
1279e639dc31SJohn Marino 	 * This gets us back in "F mode" after processing
1280e639dc31SJohn Marino 	 * a non-abort signal (e.g. window-change).
1281e639dc31SJohn Marino 	 */
1282e639dc31SJohn Marino 	if (sigs && !ABORT_SIGS())
1283e639dc31SJohn Marino 		return (until_hilite ? A_F_UNTIL_HILITE : A_F_FOREVER);
1284e639dc31SJohn Marino 
1285e639dc31SJohn Marino 	return (A_NOACTION);
1286e639dc31SJohn Marino }
1287e639dc31SJohn Marino 
1288e639dc31SJohn Marino /*
12891133e27eSPeter Avalos  * Main command processor.
12901133e27eSPeter Avalos  * Accept and execute commands until a quit command.
12911133e27eSPeter Avalos  */
commands(void)1292320d7c8aSAaron LI public void commands(void)
12931133e27eSPeter Avalos {
1294*e433da38SAaron LI 	char c;
129502d62a0fSDaniel Fojt 	int action;
1296*e433da38SAaron LI 	constant char *cbuf;
1297*e433da38SAaron LI 	constant char *msg;
12981133e27eSPeter Avalos 	int newaction;
12990c7ad07eSAntonio Huete Jimenez 	int save_jump_sline;
13001133e27eSPeter Avalos 	int save_search_type;
1301*e433da38SAaron LI 	constant char *extra;
13021133e27eSPeter Avalos 	PARG parg;
13031133e27eSPeter Avalos 	IFILE old_ifile;
13041133e27eSPeter Avalos 	IFILE new_ifile;
1305*e433da38SAaron LI 	constant char *tagfile;
13061133e27eSPeter Avalos 
13071133e27eSPeter Avalos 	search_type = SRCH_FORW;
13081133e27eSPeter Avalos 	wscroll = (sc_height + 1) / 2;
13091133e27eSPeter Avalos 	newaction = A_NOACTION;
13101133e27eSPeter Avalos 
13111133e27eSPeter Avalos 	for (;;)
13121133e27eSPeter Avalos 	{
131302d62a0fSDaniel Fojt 		clear_mca();
13141133e27eSPeter Avalos 		cmd_accept();
13151133e27eSPeter Avalos 		number = 0;
131625ce721eSPeter Avalos 		curropt = NULL;
13171133e27eSPeter Avalos 
13181133e27eSPeter Avalos 		/*
13191133e27eSPeter Avalos 		 * See if any signals need processing.
13201133e27eSPeter Avalos 		 */
13211133e27eSPeter Avalos 		if (sigs)
13221133e27eSPeter Avalos 		{
13231133e27eSPeter Avalos 			psignals();
13241133e27eSPeter Avalos 			if (quitting)
13251133e27eSPeter Avalos 				quit(QUIT_SAVED_STATUS);
13261133e27eSPeter Avalos 		}
13271133e27eSPeter Avalos 
13281133e27eSPeter Avalos 		/*
13291133e27eSPeter Avalos 		 * See if window size changed, for systems that don't
13301133e27eSPeter Avalos 		 * generate SIGWINCH.
13311133e27eSPeter Avalos 		 */
13321133e27eSPeter Avalos 		check_winch();
13331133e27eSPeter Avalos 
13341133e27eSPeter Avalos 		/*
13351133e27eSPeter Avalos 		 * Display prompt and accept a character.
13361133e27eSPeter Avalos 		 */
13371133e27eSPeter Avalos 		cmd_reset();
13381133e27eSPeter Avalos 		prompt();
13391133e27eSPeter Avalos 		if (sigs)
13401133e27eSPeter Avalos 			continue;
13411133e27eSPeter Avalos 		if (newaction == A_NOACTION)
13421133e27eSPeter Avalos 			c = getcc();
13431133e27eSPeter Avalos 
13441133e27eSPeter Avalos 	again:
13451133e27eSPeter Avalos 		if (sigs)
13461133e27eSPeter Avalos 			continue;
13471133e27eSPeter Avalos 
13481133e27eSPeter Avalos 		if (newaction != A_NOACTION)
13491133e27eSPeter Avalos 		{
13501133e27eSPeter Avalos 			action = newaction;
13511133e27eSPeter Avalos 			newaction = A_NOACTION;
13521133e27eSPeter Avalos 		} else
13531133e27eSPeter Avalos 		{
13541133e27eSPeter Avalos 			/*
13551133e27eSPeter Avalos 			 * If we are in a multicharacter command, call mca_char.
13561133e27eSPeter Avalos 			 * Otherwise we call fcmd_decode to determine the
13571133e27eSPeter Avalos 			 * action to be performed.
13581133e27eSPeter Avalos 			 */
13591133e27eSPeter Avalos 			if (mca)
13601133e27eSPeter Avalos 				switch (mca_char(c))
13611133e27eSPeter Avalos 				{
13621133e27eSPeter Avalos 				case MCA_MORE:
13631133e27eSPeter Avalos 					/*
13641133e27eSPeter Avalos 					 * Need another character.
13651133e27eSPeter Avalos 					 */
13661133e27eSPeter Avalos 					c = getcc();
13671133e27eSPeter Avalos 					goto again;
13681133e27eSPeter Avalos 				case MCA_DONE:
13691133e27eSPeter Avalos 					/*
13701133e27eSPeter Avalos 					 * Command has been handled by mca_char.
13711133e27eSPeter Avalos 					 * Start clean with a prompt.
13721133e27eSPeter Avalos 					 */
13731133e27eSPeter Avalos 					continue;
13741133e27eSPeter Avalos 				case NO_MCA:
13751133e27eSPeter Avalos 					/*
13761133e27eSPeter Avalos 					 * Not a multi-char command
13771133e27eSPeter Avalos 					 * (at least, not anymore).
13781133e27eSPeter Avalos 					 */
13791133e27eSPeter Avalos 					break;
13801133e27eSPeter Avalos 				}
13811133e27eSPeter Avalos 
13821133e27eSPeter Avalos 			/*
13831133e27eSPeter Avalos 			 * Decode the command character and decide what to do.
13841133e27eSPeter Avalos 			 */
1385*e433da38SAaron LI 			extra = NULL;
13861133e27eSPeter Avalos 			if (mca)
13871133e27eSPeter Avalos 			{
13881133e27eSPeter Avalos 				/*
13891133e27eSPeter Avalos 				 * We're in a multichar command.
13901133e27eSPeter Avalos 				 * Add the character to the command buffer
13911133e27eSPeter Avalos 				 * and display it on the screen.
13921133e27eSPeter Avalos 				 * If the user backspaces past the start
13931133e27eSPeter Avalos 				 * of the line, abort the command.
13941133e27eSPeter Avalos 				 */
13951133e27eSPeter Avalos 				if (cmd_char(c) == CC_QUIT || len_cmdbuf() == 0)
13961133e27eSPeter Avalos 					continue;
13971133e27eSPeter Avalos 				cbuf = get_cmdbuf();
13980c7ad07eSAntonio Huete Jimenez 				if (cbuf == NULL)
13990c7ad07eSAntonio Huete Jimenez 					continue;
1400*e433da38SAaron LI 				action = fcmd_decode(cbuf, &extra);
14011133e27eSPeter Avalos 			} else
14021133e27eSPeter Avalos 			{
14031133e27eSPeter Avalos 				/*
14041133e27eSPeter Avalos 				 * Don't use cmd_char if we're starting fresh
14051133e27eSPeter Avalos 				 * at the beginning of a command, because we
14061133e27eSPeter Avalos 				 * don't want to echo the command until we know
14071133e27eSPeter Avalos 				 * it is a multichar command.  We also don't
14081133e27eSPeter Avalos 				 * want erase_char/kill_char to be treated
14091133e27eSPeter Avalos 				 * as line editing characters.
14101133e27eSPeter Avalos 				 */
1411*e433da38SAaron LI 				constant char tbuf[2] = { c, '\0' };
1412*e433da38SAaron LI 				action = fcmd_decode(tbuf, &extra);
14131133e27eSPeter Avalos 			}
14141133e27eSPeter Avalos 			/*
14151133e27eSPeter Avalos 			 * If an "extra" string was returned,
14161133e27eSPeter Avalos 			 * process it as a string of command characters.
14171133e27eSPeter Avalos 			 */
14181133e27eSPeter Avalos 			if (extra != NULL)
14191133e27eSPeter Avalos 				ungetsc(extra);
14201133e27eSPeter Avalos 		}
14211133e27eSPeter Avalos 		/*
14221133e27eSPeter Avalos 		 * Clear the cmdbuf string.
14231133e27eSPeter Avalos 		 * (But not if we're in the prefix of a command,
14241133e27eSPeter Avalos 		 * because the partial command string is kept there.)
14251133e27eSPeter Avalos 		 */
14261133e27eSPeter Avalos 		if (action != A_PREFIX)
14271133e27eSPeter Avalos 			cmd_reset();
14281133e27eSPeter Avalos 
14291133e27eSPeter Avalos 		switch (action)
14301133e27eSPeter Avalos 		{
14311133e27eSPeter Avalos 		case A_DIGIT:
14321133e27eSPeter Avalos 			/*
14331133e27eSPeter Avalos 			 * First digit of a number.
14341133e27eSPeter Avalos 			 */
1435*e433da38SAaron LI 			start_mca(A_DIGIT, ":", NULL, CF_QUIT_ON_ERASE);
14361133e27eSPeter Avalos 			goto again;
14371133e27eSPeter Avalos 
14381133e27eSPeter Avalos 		case A_F_WINDOW:
14391133e27eSPeter Avalos 			/*
14401133e27eSPeter Avalos 			 * Forward one window (and set the window size).
14411133e27eSPeter Avalos 			 */
14421133e27eSPeter Avalos 			if (number > 0)
14431133e27eSPeter Avalos 				swindow = (int) number;
14441133e27eSPeter Avalos 			/* FALLTHRU */
14451133e27eSPeter Avalos 		case A_F_SCREEN:
14461133e27eSPeter Avalos 			/*
14471133e27eSPeter Avalos 			 * Forward one screen.
14481133e27eSPeter Avalos 			 */
14491133e27eSPeter Avalos 			if (number <= 0)
14501133e27eSPeter Avalos 				number = get_swindow();
14511133e27eSPeter Avalos 			cmd_exec();
14521133e27eSPeter Avalos 			if (show_attn)
14531133e27eSPeter Avalos 				set_attnpos(bottompos);
14541133e27eSPeter Avalos 			forward((int) number, 0, 1);
14551133e27eSPeter Avalos 			break;
14561133e27eSPeter Avalos 
14571133e27eSPeter Avalos 		case A_B_WINDOW:
14581133e27eSPeter Avalos 			/*
14591133e27eSPeter Avalos 			 * Backward one window (and set the window size).
14601133e27eSPeter Avalos 			 */
14611133e27eSPeter Avalos 			if (number > 0)
14621133e27eSPeter Avalos 				swindow = (int) number;
14631133e27eSPeter Avalos 			/* FALLTHRU */
14641133e27eSPeter Avalos 		case A_B_SCREEN:
14651133e27eSPeter Avalos 			/*
14661133e27eSPeter Avalos 			 * Backward one screen.
14671133e27eSPeter Avalos 			 */
14681133e27eSPeter Avalos 			if (number <= 0)
14691133e27eSPeter Avalos 				number = get_swindow();
14701133e27eSPeter Avalos 			cmd_exec();
14711133e27eSPeter Avalos 			backward((int) number, 0, 1);
14721133e27eSPeter Avalos 			break;
14731133e27eSPeter Avalos 
14741133e27eSPeter Avalos 		case A_F_LINE:
14751133e27eSPeter Avalos 			/*
14761133e27eSPeter Avalos 			 * Forward N (default 1) line.
14771133e27eSPeter Avalos 			 */
14781133e27eSPeter Avalos 			if (number <= 0)
14791133e27eSPeter Avalos 				number = 1;
14801133e27eSPeter Avalos 			cmd_exec();
14811133e27eSPeter Avalos 			if (show_attn == OPT_ONPLUS && number > 1)
14821133e27eSPeter Avalos 				set_attnpos(bottompos);
14831133e27eSPeter Avalos 			forward((int) number, 0, 0);
14841133e27eSPeter Avalos 			break;
14851133e27eSPeter Avalos 
14861133e27eSPeter Avalos 		case A_B_LINE:
14871133e27eSPeter Avalos 			/*
14881133e27eSPeter Avalos 			 * Backward N (default 1) line.
14891133e27eSPeter Avalos 			 */
14901133e27eSPeter Avalos 			if (number <= 0)
14911133e27eSPeter Avalos 				number = 1;
14921133e27eSPeter Avalos 			cmd_exec();
14931133e27eSPeter Avalos 			backward((int) number, 0, 0);
14941133e27eSPeter Avalos 			break;
14951133e27eSPeter Avalos 
149602d62a0fSDaniel Fojt 		case A_F_MOUSE:
149702d62a0fSDaniel Fojt 			/*
149802d62a0fSDaniel Fojt 			 * Forward wheel_lines lines.
149902d62a0fSDaniel Fojt 			 */
150002d62a0fSDaniel Fojt 			cmd_exec();
150102d62a0fSDaniel Fojt 			forward(wheel_lines, 0, 0);
150202d62a0fSDaniel Fojt 			break;
150302d62a0fSDaniel Fojt 
150402d62a0fSDaniel Fojt 		case A_B_MOUSE:
150502d62a0fSDaniel Fojt 			/*
150602d62a0fSDaniel Fojt 			 * Backward wheel_lines lines.
150702d62a0fSDaniel Fojt 			 */
150802d62a0fSDaniel Fojt 			cmd_exec();
150902d62a0fSDaniel Fojt 			backward(wheel_lines, 0, 0);
151002d62a0fSDaniel Fojt 			break;
151102d62a0fSDaniel Fojt 
15121133e27eSPeter Avalos 		case A_FF_LINE:
15131133e27eSPeter Avalos 			/*
15141133e27eSPeter Avalos 			 * Force forward N (default 1) line.
15151133e27eSPeter Avalos 			 */
15161133e27eSPeter Avalos 			if (number <= 0)
15171133e27eSPeter Avalos 				number = 1;
15181133e27eSPeter Avalos 			cmd_exec();
15191133e27eSPeter Avalos 			if (show_attn == OPT_ONPLUS && number > 1)
15201133e27eSPeter Avalos 				set_attnpos(bottompos);
15211133e27eSPeter Avalos 			forward((int) number, 1, 0);
15221133e27eSPeter Avalos 			break;
15231133e27eSPeter Avalos 
15241133e27eSPeter Avalos 		case A_BF_LINE:
15251133e27eSPeter Avalos 			/*
15261133e27eSPeter Avalos 			 * Force backward N (default 1) line.
15271133e27eSPeter Avalos 			 */
15281133e27eSPeter Avalos 			if (number <= 0)
15291133e27eSPeter Avalos 				number = 1;
15301133e27eSPeter Avalos 			cmd_exec();
15311133e27eSPeter Avalos 			backward((int) number, 1, 0);
15321133e27eSPeter Avalos 			break;
15331133e27eSPeter Avalos 
15341133e27eSPeter Avalos 		case A_FF_SCREEN:
15351133e27eSPeter Avalos 			/*
15361133e27eSPeter Avalos 			 * Force forward one screen.
15371133e27eSPeter Avalos 			 */
15381133e27eSPeter Avalos 			if (number <= 0)
15391133e27eSPeter Avalos 				number = get_swindow();
15401133e27eSPeter Avalos 			cmd_exec();
15411133e27eSPeter Avalos 			if (show_attn == OPT_ONPLUS)
15421133e27eSPeter Avalos 				set_attnpos(bottompos);
15431133e27eSPeter Avalos 			forward((int) number, 1, 0);
15441133e27eSPeter Avalos 			break;
15451133e27eSPeter Avalos 
15461133e27eSPeter Avalos 		case A_F_FOREVER:
15471133e27eSPeter Avalos 			/*
15481133e27eSPeter Avalos 			 * Forward forever, ignoring EOF.
15491133e27eSPeter Avalos 			 */
1550fa0be7c5SJohn Marino 			if (show_attn)
1551fa0be7c5SJohn Marino 				set_attnpos(bottompos);
1552e639dc31SJohn Marino 			newaction = forw_loop(0);
15531133e27eSPeter Avalos 			break;
1554e639dc31SJohn Marino 
1555e639dc31SJohn Marino 		case A_F_UNTIL_HILITE:
1556e639dc31SJohn Marino 			newaction = forw_loop(1);
15571133e27eSPeter Avalos 			break;
15581133e27eSPeter Avalos 
15591133e27eSPeter Avalos 		case A_F_SCROLL:
15601133e27eSPeter Avalos 			/*
15611133e27eSPeter Avalos 			 * Forward N lines
15621133e27eSPeter Avalos 			 * (default same as last 'd' or 'u' command).
15631133e27eSPeter Avalos 			 */
15641133e27eSPeter Avalos 			if (number > 0)
15651133e27eSPeter Avalos 				wscroll = (int) number;
15661133e27eSPeter Avalos 			cmd_exec();
15671133e27eSPeter Avalos 			if (show_attn == OPT_ONPLUS)
15681133e27eSPeter Avalos 				set_attnpos(bottompos);
15691133e27eSPeter Avalos 			forward(wscroll, 0, 0);
15701133e27eSPeter Avalos 			break;
15711133e27eSPeter Avalos 
15721133e27eSPeter Avalos 		case A_B_SCROLL:
15731133e27eSPeter Avalos 			/*
15741133e27eSPeter Avalos 			 * Forward N lines
15751133e27eSPeter Avalos 			 * (default same as last 'd' or 'u' command).
15761133e27eSPeter Avalos 			 */
15771133e27eSPeter Avalos 			if (number > 0)
15781133e27eSPeter Avalos 				wscroll = (int) number;
15791133e27eSPeter Avalos 			cmd_exec();
15801133e27eSPeter Avalos 			backward(wscroll, 0, 0);
15811133e27eSPeter Avalos 			break;
15821133e27eSPeter Avalos 
15831133e27eSPeter Avalos 		case A_FREPAINT:
15841133e27eSPeter Avalos 			/*
15851133e27eSPeter Avalos 			 * Flush buffers, then repaint screen.
15861133e27eSPeter Avalos 			 * Don't flush the buffers on a pipe!
15871133e27eSPeter Avalos 			 */
15881133e27eSPeter Avalos 			clear_buffers();
15891133e27eSPeter Avalos 			/* FALLTHRU */
15901133e27eSPeter Avalos 		case A_REPAINT:
15911133e27eSPeter Avalos 			/*
15921133e27eSPeter Avalos 			 * Repaint screen.
15931133e27eSPeter Avalos 			 */
15941133e27eSPeter Avalos 			cmd_exec();
15951133e27eSPeter Avalos 			repaint();
15961133e27eSPeter Avalos 			break;
15971133e27eSPeter Avalos 
15981133e27eSPeter Avalos 		case A_GOLINE:
15991133e27eSPeter Avalos 			/*
16001133e27eSPeter Avalos 			 * Go to line N, default beginning of file.
16010c7ad07eSAntonio Huete Jimenez 			 * If N <= 0, ignore jump_sline in order to avoid
16020c7ad07eSAntonio Huete Jimenez 			 * empty lines before the beginning of the file.
16031133e27eSPeter Avalos 			 */
16040c7ad07eSAntonio Huete Jimenez 			save_jump_sline = jump_sline;
16051133e27eSPeter Avalos 			if (number <= 0)
16060c7ad07eSAntonio Huete Jimenez 			{
16071133e27eSPeter Avalos 				number = 1;
16080c7ad07eSAntonio Huete Jimenez 				jump_sline = 0;
16090c7ad07eSAntonio Huete Jimenez 			}
16101133e27eSPeter Avalos 			cmd_exec();
16111133e27eSPeter Avalos 			jump_back(number);
16120c7ad07eSAntonio Huete Jimenez 			jump_sline = save_jump_sline;
16131133e27eSPeter Avalos 			break;
16141133e27eSPeter Avalos 
16151133e27eSPeter Avalos 		case A_PERCENT:
16161133e27eSPeter Avalos 			/*
16171133e27eSPeter Avalos 			 * Go to a specified percentage into the file.
16181133e27eSPeter Avalos 			 */
16191133e27eSPeter Avalos 			if (number < 0)
16201133e27eSPeter Avalos 			{
16211133e27eSPeter Avalos 				number = 0;
16221133e27eSPeter Avalos 				fraction = 0;
16231133e27eSPeter Avalos 			}
162402d62a0fSDaniel Fojt 			if (number > 100 || (number == 100 && fraction != 0))
16251133e27eSPeter Avalos 			{
16261133e27eSPeter Avalos 				number = 100;
16271133e27eSPeter Avalos 				fraction = 0;
16281133e27eSPeter Avalos 			}
16291133e27eSPeter Avalos 			cmd_exec();
16301133e27eSPeter Avalos 			jump_percent((int) number, fraction);
16311133e27eSPeter Avalos 			break;
16321133e27eSPeter Avalos 
16331133e27eSPeter Avalos 		case A_GOEND:
16341133e27eSPeter Avalos 			/*
16351133e27eSPeter Avalos 			 * Go to line N, default end of file.
16361133e27eSPeter Avalos 			 */
16371133e27eSPeter Avalos 			cmd_exec();
16381133e27eSPeter Avalos 			if (number <= 0)
16391133e27eSPeter Avalos 				jump_forw();
16401133e27eSPeter Avalos 			else
16411133e27eSPeter Avalos 				jump_back(number);
16421133e27eSPeter Avalos 			break;
16431133e27eSPeter Avalos 
1644fa0be7c5SJohn Marino 		case A_GOEND_BUF:
1645fa0be7c5SJohn Marino 			/*
1646fa0be7c5SJohn Marino 			 * Go to line N, default last buffered byte.
1647fa0be7c5SJohn Marino 			 */
1648fa0be7c5SJohn Marino 			cmd_exec();
1649fa0be7c5SJohn Marino 			if (number <= 0)
1650fa0be7c5SJohn Marino 				jump_forw_buffered();
1651fa0be7c5SJohn Marino 			else
1652fa0be7c5SJohn Marino 				jump_back(number);
1653fa0be7c5SJohn Marino 			break;
1654fa0be7c5SJohn Marino 
16551133e27eSPeter Avalos 		case A_GOPOS:
16561133e27eSPeter Avalos 			/*
16571133e27eSPeter Avalos 			 * Go to a specified byte position in the file.
16581133e27eSPeter Avalos 			 */
16591133e27eSPeter Avalos 			cmd_exec();
16601133e27eSPeter Avalos 			if (number < 0)
16611133e27eSPeter Avalos 				number = 0;
16621133e27eSPeter Avalos 			jump_line_loc((POSITION) number, jump_sline);
16631133e27eSPeter Avalos 			break;
16641133e27eSPeter Avalos 
16651133e27eSPeter Avalos 		case A_STAT:
16661133e27eSPeter Avalos 			/*
16671133e27eSPeter Avalos 			 * Print file name, etc.
16681133e27eSPeter Avalos 			 */
16691133e27eSPeter Avalos 			if (ch_getflags() & CH_HELPFILE)
16701133e27eSPeter Avalos 				break;
16711133e27eSPeter Avalos 			cmd_exec();
16721133e27eSPeter Avalos 			parg.p_string = eq_message();
16731133e27eSPeter Avalos 			error("%s", &parg);
16741133e27eSPeter Avalos 			break;
16751133e27eSPeter Avalos 
16761133e27eSPeter Avalos 		case A_VERSION:
16771133e27eSPeter Avalos 			/*
16780c7ad07eSAntonio Huete Jimenez 			 * Print version number.
16791133e27eSPeter Avalos 			 */
16801133e27eSPeter Avalos 			cmd_exec();
16811133e27eSPeter Avalos 			dispversion();
16821133e27eSPeter Avalos 			break;
16831133e27eSPeter Avalos 
16841133e27eSPeter Avalos 		case A_QUIT:
16851133e27eSPeter Avalos 			/*
16861133e27eSPeter Avalos 			 * Exit.
16871133e27eSPeter Avalos 			 */
16881133e27eSPeter Avalos 			if (curr_ifile != NULL_IFILE &&
16891133e27eSPeter Avalos 			    ch_getflags() & CH_HELPFILE)
16901133e27eSPeter Avalos 			{
16911133e27eSPeter Avalos 				/*
16921133e27eSPeter Avalos 				 * Quit while viewing the help file
16931133e27eSPeter Avalos 				 * just means return to viewing the
16941133e27eSPeter Avalos 				 * previous file.
16951133e27eSPeter Avalos 				 */
16961133e27eSPeter Avalos 				hshift = save_hshift;
1697fa0be7c5SJohn Marino 				bs_mode = save_bs_mode;
1698320d7c8aSAaron LI 				proc_backspace = save_proc_backspace;
16991133e27eSPeter Avalos 				if (edit_prev(1) == 0)
17001133e27eSPeter Avalos 					break;
17011133e27eSPeter Avalos 			}
17021133e27eSPeter Avalos 			if (extra != NULL)
17031133e27eSPeter Avalos 				quit(*extra);
17041133e27eSPeter Avalos 			quit(QUIT_OK);
17051133e27eSPeter Avalos 			break;
17061133e27eSPeter Avalos 
17071133e27eSPeter Avalos /*
17081133e27eSPeter Avalos  * Define abbreviation for a commonly used sequence below.
17091133e27eSPeter Avalos  */
17101133e27eSPeter Avalos #define DO_SEARCH() \
17111133e27eSPeter Avalos 			if (number <= 0) number = 1;    \
17121133e27eSPeter Avalos 			mca_search();                   \
17131133e27eSPeter Avalos 			cmd_exec();                     \
1714*e433da38SAaron LI 			multi_search(NULL, (int) number, 0);
17151133e27eSPeter Avalos 
17161133e27eSPeter Avalos 		case A_F_SEARCH:
17171133e27eSPeter Avalos 			/*
17181133e27eSPeter Avalos 			 * Search forward for a pattern.
17191133e27eSPeter Avalos 			 * Get the first char of the pattern.
17201133e27eSPeter Avalos 			 */
17210c7ad07eSAntonio Huete Jimenez 			search_type = SRCH_FORW | def_search_type;
17221133e27eSPeter Avalos 			if (number <= 0)
17231133e27eSPeter Avalos 				number = 1;
1724*e433da38SAaron LI 			literal_char = FALSE;
17251133e27eSPeter Avalos 			mca_search();
17261133e27eSPeter Avalos 			c = getcc();
17271133e27eSPeter Avalos 			goto again;
17281133e27eSPeter Avalos 
17291133e27eSPeter Avalos 		case A_B_SEARCH:
17301133e27eSPeter Avalos 			/*
17311133e27eSPeter Avalos 			 * Search backward for a pattern.
17321133e27eSPeter Avalos 			 * Get the first char of the pattern.
17331133e27eSPeter Avalos 			 */
17340c7ad07eSAntonio Huete Jimenez 			search_type = SRCH_BACK | def_search_type;
17351133e27eSPeter Avalos 			if (number <= 0)
17361133e27eSPeter Avalos 				number = 1;
1737*e433da38SAaron LI 			literal_char = FALSE;
17381133e27eSPeter Avalos 			mca_search();
17391133e27eSPeter Avalos 			c = getcc();
17401133e27eSPeter Avalos 			goto again;
17411133e27eSPeter Avalos 
1742*e433da38SAaron LI 		case A_OSC8_F_SEARCH:
1743*e433da38SAaron LI #if OSC8_LINK
1744*e433da38SAaron LI 			cmd_exec();
1745*e433da38SAaron LI 			if (number <= 0)
1746*e433da38SAaron LI 				number = 1;
1747*e433da38SAaron LI 			osc8_search(SRCH_FORW, NULL, number);
1748*e433da38SAaron LI #else
1749*e433da38SAaron LI 			error("Command not available", NULL_PARG);
1750*e433da38SAaron LI #endif
1751*e433da38SAaron LI 			break;
1752*e433da38SAaron LI 
1753*e433da38SAaron LI 		case A_OSC8_B_SEARCH:
1754*e433da38SAaron LI #if OSC8_LINK
1755*e433da38SAaron LI 			cmd_exec();
1756*e433da38SAaron LI 			if (number <= 0)
1757*e433da38SAaron LI 				number = 1;
1758*e433da38SAaron LI 			osc8_search(SRCH_BACK, NULL, number);
1759*e433da38SAaron LI #else
1760*e433da38SAaron LI 			error("Command not available", NULL_PARG);
1761*e433da38SAaron LI #endif
1762*e433da38SAaron LI 			break;
1763*e433da38SAaron LI 
1764*e433da38SAaron LI 		case A_OSC8_OPEN:
1765*e433da38SAaron LI #if OSC8_LINK
1766*e433da38SAaron LI 			if (secure_allow(SF_OSC8_OPEN))
1767*e433da38SAaron LI 			{
1768*e433da38SAaron LI 				cmd_exec();
1769*e433da38SAaron LI 				osc8_open();
1770*e433da38SAaron LI 				break;
1771*e433da38SAaron LI 			}
1772*e433da38SAaron LI #endif
1773*e433da38SAaron LI 			error("Command not available", NULL_PARG);
1774*e433da38SAaron LI 			break;
1775*e433da38SAaron LI 
1776*e433da38SAaron LI 		case A_OSC8_JUMP:
1777*e433da38SAaron LI #if OSC8_LINK
1778*e433da38SAaron LI 			cmd_exec();
1779*e433da38SAaron LI 			osc8_jump();
1780*e433da38SAaron LI #else
1781*e433da38SAaron LI 			error("Command not available", NULL_PARG);
1782*e433da38SAaron LI #endif
1783*e433da38SAaron LI 			break;
1784*e433da38SAaron LI 
17858be36e5bSPeter Avalos 		case A_FILTER:
17868be36e5bSPeter Avalos #if HILITE_SEARCH
17878be36e5bSPeter Avalos 			search_type = SRCH_FORW | SRCH_FILTER;
1788*e433da38SAaron LI 			literal_char = FALSE;
17898be36e5bSPeter Avalos 			mca_search();
17908be36e5bSPeter Avalos 			c = getcc();
17918be36e5bSPeter Avalos 			goto again;
17928be36e5bSPeter Avalos #else
17938be36e5bSPeter Avalos 			error("Command not available", NULL_PARG);
17948be36e5bSPeter Avalos 			break;
17958be36e5bSPeter Avalos #endif
17968be36e5bSPeter Avalos 
17971133e27eSPeter Avalos 		case A_AGAIN_SEARCH:
17981133e27eSPeter Avalos 			/*
17991133e27eSPeter Avalos 			 * Repeat previous search.
18001133e27eSPeter Avalos 			 */
1801320d7c8aSAaron LI 			search_type = last_search_type;
18021133e27eSPeter Avalos 			DO_SEARCH();
18031133e27eSPeter Avalos 			break;
18041133e27eSPeter Avalos 
18051133e27eSPeter Avalos 		case A_T_AGAIN_SEARCH:
18061133e27eSPeter Avalos 			/*
18071133e27eSPeter Avalos 			 * Repeat previous search, multiple files.
18081133e27eSPeter Avalos 			 */
1809320d7c8aSAaron LI 			search_type = last_search_type | SRCH_PAST_EOF;
18101133e27eSPeter Avalos 			DO_SEARCH();
18111133e27eSPeter Avalos 			break;
18121133e27eSPeter Avalos 
18131133e27eSPeter Avalos 		case A_REVERSE_SEARCH:
18141133e27eSPeter Avalos 			/*
18151133e27eSPeter Avalos 			 * Repeat previous search, in reverse direction.
18161133e27eSPeter Avalos 			 */
1817320d7c8aSAaron LI 			save_search_type = search_type = last_search_type;
18181133e27eSPeter Avalos 			search_type = SRCH_REVERSE(search_type);
18191133e27eSPeter Avalos 			DO_SEARCH();
1820320d7c8aSAaron LI 			last_search_type = save_search_type;
18211133e27eSPeter Avalos 			break;
18221133e27eSPeter Avalos 
18231133e27eSPeter Avalos 		case A_T_REVERSE_SEARCH:
18241133e27eSPeter Avalos 			/*
18251133e27eSPeter Avalos 			 * Repeat previous search,
18261133e27eSPeter Avalos 			 * multiple files in reverse direction.
18271133e27eSPeter Avalos 			 */
1828320d7c8aSAaron LI 			save_search_type = search_type = last_search_type;
1829320d7c8aSAaron LI 			search_type = SRCH_REVERSE(search_type) | SRCH_PAST_EOF;
18301133e27eSPeter Avalos 			DO_SEARCH();
1831320d7c8aSAaron LI 			last_search_type = save_search_type;
18321133e27eSPeter Avalos 			break;
18331133e27eSPeter Avalos 
18341133e27eSPeter Avalos 		case A_UNDO_SEARCH:
18350c7ad07eSAntonio Huete Jimenez 		case A_CLR_SEARCH:
183602d62a0fSDaniel Fojt 			/*
183702d62a0fSDaniel Fojt 			 * Clear search string highlighting.
183802d62a0fSDaniel Fojt 			 */
18390c7ad07eSAntonio Huete Jimenez 			undo_search(action == A_CLR_SEARCH);
18401133e27eSPeter Avalos 			break;
18411133e27eSPeter Avalos 
18421133e27eSPeter Avalos 		case A_HELP:
18431133e27eSPeter Avalos 			/*
18441133e27eSPeter Avalos 			 * Help.
18451133e27eSPeter Avalos 			 */
18461133e27eSPeter Avalos 			if (ch_getflags() & CH_HELPFILE)
18471133e27eSPeter Avalos 				break;
18481133e27eSPeter Avalos 			cmd_exec();
18491133e27eSPeter Avalos 			save_hshift = hshift;
18501133e27eSPeter Avalos 			hshift = 0;
1851fa0be7c5SJohn Marino 			save_bs_mode = bs_mode;
1852fa0be7c5SJohn Marino 			bs_mode = BS_SPECIAL;
1853320d7c8aSAaron LI 			save_proc_backspace = proc_backspace;
1854320d7c8aSAaron LI 			proc_backspace = OPT_OFF;
18551133e27eSPeter Avalos 			(void) edit(FAKE_HELPFILE);
18561133e27eSPeter Avalos 			break;
18571133e27eSPeter Avalos 
18581133e27eSPeter Avalos 		case A_EXAMINE:
18591133e27eSPeter Avalos 			/*
18601133e27eSPeter Avalos 			 * Edit a new file.  Get the filename.
18611133e27eSPeter Avalos 			 */
186202d62a0fSDaniel Fojt #if EXAMINE
1863*e433da38SAaron LI 			if (secure_allow(SF_EXAMINE))
18641133e27eSPeter Avalos 			{
18651133e27eSPeter Avalos 				start_mca(A_EXAMINE, "Examine: ", ml_examine, 0);
18661133e27eSPeter Avalos 				c = getcc();
18671133e27eSPeter Avalos 				goto again;
186802d62a0fSDaniel Fojt 			}
186902d62a0fSDaniel Fojt #endif
18701133e27eSPeter Avalos 			error("Command not available", NULL_PARG);
18711133e27eSPeter Avalos 			break;
18721133e27eSPeter Avalos 
18731133e27eSPeter Avalos 		case A_VISUAL:
18741133e27eSPeter Avalos 			/*
18751133e27eSPeter Avalos 			 * Invoke an editor on the input file.
18761133e27eSPeter Avalos 			 */
18771133e27eSPeter Avalos #if EDITOR
1878*e433da38SAaron LI 			if (secure_allow(SF_EDIT))
18791133e27eSPeter Avalos 			{
18801133e27eSPeter Avalos 				if (ch_getflags() & CH_HELPFILE)
18811133e27eSPeter Avalos 					break;
18821133e27eSPeter Avalos 				if (strcmp(get_filename(curr_ifile), "-") == 0)
18831133e27eSPeter Avalos 				{
18841133e27eSPeter Avalos 					error("Cannot edit standard input", NULL_PARG);
18851133e27eSPeter Avalos 					break;
18861133e27eSPeter Avalos 				}
188702d62a0fSDaniel Fojt 				if (get_altfilename(curr_ifile) != NULL)
18881133e27eSPeter Avalos 				{
18891133e27eSPeter Avalos 					error("WARNING: This file was viewed via LESSOPEN",
18901133e27eSPeter Avalos 						NULL_PARG);
18911133e27eSPeter Avalos 				}
18921133e27eSPeter Avalos 				start_mca(A_SHELL, "!", ml_shell, 0);
18931133e27eSPeter Avalos 				/*
18941133e27eSPeter Avalos 				 * Expand the editor prototype string
18951133e27eSPeter Avalos 				 * and pass it to the system to execute.
18961133e27eSPeter Avalos 				 * (Make sure the screen is displayed so the
18971133e27eSPeter Avalos 				 * expansion of "+%lm" works.)
18981133e27eSPeter Avalos 				 */
18991133e27eSPeter Avalos 				make_display();
19001133e27eSPeter Avalos 				cmd_exec();
1901*e433da38SAaron LI 				lsystem(pr_expand(editproto), NULL);
19021133e27eSPeter Avalos 				break;
190302d62a0fSDaniel Fojt 			}
190402d62a0fSDaniel Fojt #endif
19051133e27eSPeter Avalos 			error("Command not available", NULL_PARG);
19061133e27eSPeter Avalos 			break;
19071133e27eSPeter Avalos 
19081133e27eSPeter Avalos 		case A_NEXT_FILE:
19091133e27eSPeter Avalos 			/*
19101133e27eSPeter Avalos 			 * Examine next file.
19111133e27eSPeter Avalos 			 */
19121133e27eSPeter Avalos #if TAGS
19131133e27eSPeter Avalos 			if (ntags())
19141133e27eSPeter Avalos 			{
19151133e27eSPeter Avalos 				error("No next file", NULL_PARG);
19161133e27eSPeter Avalos 				break;
19171133e27eSPeter Avalos 			}
19181133e27eSPeter Avalos #endif
19191133e27eSPeter Avalos 			if (number <= 0)
19201133e27eSPeter Avalos 				number = 1;
19211133e27eSPeter Avalos 			if (edit_next((int) number))
19221133e27eSPeter Avalos 			{
19238be36e5bSPeter Avalos 				if (get_quit_at_eof() && eof_displayed() &&
19241133e27eSPeter Avalos 				    !(ch_getflags() & CH_HELPFILE))
19251133e27eSPeter Avalos 					quit(QUIT_OK);
19261133e27eSPeter Avalos 				parg.p_string = (number > 1) ? "(N-th) " : "";
19271133e27eSPeter Avalos 				error("No %snext file", &parg);
19281133e27eSPeter Avalos 			}
19291133e27eSPeter Avalos 			break;
19301133e27eSPeter Avalos 
19311133e27eSPeter Avalos 		case A_PREV_FILE:
19321133e27eSPeter Avalos 			/*
19331133e27eSPeter Avalos 			 * Examine previous file.
19341133e27eSPeter Avalos 			 */
19351133e27eSPeter Avalos #if TAGS
19361133e27eSPeter Avalos 			if (ntags())
19371133e27eSPeter Avalos 			{
19381133e27eSPeter Avalos 				error("No previous file", NULL_PARG);
19391133e27eSPeter Avalos 				break;
19401133e27eSPeter Avalos 			}
19411133e27eSPeter Avalos #endif
19421133e27eSPeter Avalos 			if (number <= 0)
19431133e27eSPeter Avalos 				number = 1;
19441133e27eSPeter Avalos 			if (edit_prev((int) number))
19451133e27eSPeter Avalos 			{
19461133e27eSPeter Avalos 				parg.p_string = (number > 1) ? "(N-th) " : "";
19471133e27eSPeter Avalos 				error("No %sprevious file", &parg);
19481133e27eSPeter Avalos 			}
19491133e27eSPeter Avalos 			break;
19501133e27eSPeter Avalos 
19511133e27eSPeter Avalos 		case A_NEXT_TAG:
195202d62a0fSDaniel Fojt 			/*
195302d62a0fSDaniel Fojt 			 * Jump to the next tag in the current tag list.
195402d62a0fSDaniel Fojt 			 */
19551133e27eSPeter Avalos #if TAGS
19561133e27eSPeter Avalos 			if (number <= 0)
19571133e27eSPeter Avalos 				number = 1;
19581133e27eSPeter Avalos 			tagfile = nexttag((int) number);
19591133e27eSPeter Avalos 			if (tagfile == NULL)
19601133e27eSPeter Avalos 			{
19611133e27eSPeter Avalos 				error("No next tag", NULL_PARG);
19621133e27eSPeter Avalos 				break;
19631133e27eSPeter Avalos 			}
196402d62a0fSDaniel Fojt 			cmd_exec();
19651133e27eSPeter Avalos 			if (edit(tagfile) == 0)
19661133e27eSPeter Avalos 			{
19671133e27eSPeter Avalos 				POSITION pos = tagsearch();
19681133e27eSPeter Avalos 				if (pos != NULL_POSITION)
19691133e27eSPeter Avalos 					jump_loc(pos, jump_sline);
19701133e27eSPeter Avalos 			}
19711133e27eSPeter Avalos #else
19721133e27eSPeter Avalos 			error("Command not available", NULL_PARG);
19731133e27eSPeter Avalos #endif
19741133e27eSPeter Avalos 			break;
19751133e27eSPeter Avalos 
19761133e27eSPeter Avalos 		case A_PREV_TAG:
197702d62a0fSDaniel Fojt 			/*
197802d62a0fSDaniel Fojt 			 * Jump to the previous tag in the current tag list.
197902d62a0fSDaniel Fojt 			 */
19801133e27eSPeter Avalos #if TAGS
19811133e27eSPeter Avalos 			if (number <= 0)
19821133e27eSPeter Avalos 				number = 1;
19831133e27eSPeter Avalos 			tagfile = prevtag((int) number);
19841133e27eSPeter Avalos 			if (tagfile == NULL)
19851133e27eSPeter Avalos 			{
19861133e27eSPeter Avalos 				error("No previous tag", NULL_PARG);
19871133e27eSPeter Avalos 				break;
19881133e27eSPeter Avalos 			}
198902d62a0fSDaniel Fojt 			cmd_exec();
19901133e27eSPeter Avalos 			if (edit(tagfile) == 0)
19911133e27eSPeter Avalos 			{
19921133e27eSPeter Avalos 				POSITION pos = tagsearch();
19931133e27eSPeter Avalos 				if (pos != NULL_POSITION)
19941133e27eSPeter Avalos 					jump_loc(pos, jump_sline);
19951133e27eSPeter Avalos 			}
19961133e27eSPeter Avalos #else
19971133e27eSPeter Avalos 			error("Command not available", NULL_PARG);
19981133e27eSPeter Avalos #endif
19991133e27eSPeter Avalos 			break;
20001133e27eSPeter Avalos 
20011133e27eSPeter Avalos 		case A_INDEX_FILE:
20021133e27eSPeter Avalos 			/*
20031133e27eSPeter Avalos 			 * Examine a particular file.
20041133e27eSPeter Avalos 			 */
20051133e27eSPeter Avalos 			if (number <= 0)
20061133e27eSPeter Avalos 				number = 1;
20071133e27eSPeter Avalos 			if (edit_index((int) number))
20081133e27eSPeter Avalos 				error("No such file", NULL_PARG);
20091133e27eSPeter Avalos 			break;
20101133e27eSPeter Avalos 
20111133e27eSPeter Avalos 		case A_REMOVE_FILE:
201202d62a0fSDaniel Fojt 			/*
201302d62a0fSDaniel Fojt 			 * Remove a file from the input file list.
201402d62a0fSDaniel Fojt 			 */
20151133e27eSPeter Avalos 			if (ch_getflags() & CH_HELPFILE)
20161133e27eSPeter Avalos 				break;
20171133e27eSPeter Avalos 			old_ifile = curr_ifile;
20181133e27eSPeter Avalos 			new_ifile = getoff_ifile(curr_ifile);
20191133e27eSPeter Avalos 			if (new_ifile == NULL_IFILE)
20201133e27eSPeter Avalos 			{
20211133e27eSPeter Avalos 				bell();
20221133e27eSPeter Avalos 				break;
20231133e27eSPeter Avalos 			}
20241133e27eSPeter Avalos 			if (edit_ifile(new_ifile) != 0)
20251133e27eSPeter Avalos 			{
20261133e27eSPeter Avalos 				reedit_ifile(old_ifile);
20271133e27eSPeter Avalos 				break;
20281133e27eSPeter Avalos 			}
20291133e27eSPeter Avalos 			del_ifile(old_ifile);
20301133e27eSPeter Avalos 			break;
20311133e27eSPeter Avalos 
20321133e27eSPeter Avalos 		case A_OPT_TOGGLE:
203302d62a0fSDaniel Fojt 			/*
203402d62a0fSDaniel Fojt 			 * Change the setting of an  option.
203502d62a0fSDaniel Fojt 			 */
20361133e27eSPeter Avalos 			optflag = OPT_TOGGLE;
20371133e27eSPeter Avalos 			optgetname = FALSE;
20381133e27eSPeter Avalos 			mca_opt_toggle();
20391133e27eSPeter Avalos 			c = getcc();
2040*e433da38SAaron LI 			msg = opt_toggle_disallowed(c);
2041*e433da38SAaron LI 			if (msg != NULL)
20420c7ad07eSAntonio Huete Jimenez 			{
2043*e433da38SAaron LI 				error(msg, NULL_PARG);
20440c7ad07eSAntonio Huete Jimenez 				break;
20450c7ad07eSAntonio Huete Jimenez 			}
20461133e27eSPeter Avalos 			goto again;
20471133e27eSPeter Avalos 
20481133e27eSPeter Avalos 		case A_DISP_OPTION:
20491133e27eSPeter Avalos 			/*
205002d62a0fSDaniel Fojt 			 * Report the setting of an option.
20511133e27eSPeter Avalos 			 */
20521133e27eSPeter Avalos 			optflag = OPT_NO_TOGGLE;
20531133e27eSPeter Avalos 			optgetname = FALSE;
20541133e27eSPeter Avalos 			mca_opt_toggle();
20551133e27eSPeter Avalos 			c = getcc();
20561133e27eSPeter Avalos 			goto again;
20571133e27eSPeter Avalos 
20581133e27eSPeter Avalos 		case A_FIRSTCMD:
20591133e27eSPeter Avalos 			/*
20601133e27eSPeter Avalos 			 * Set an initial command for new files.
20611133e27eSPeter Avalos 			 */
2062*e433da38SAaron LI 			start_mca(A_FIRSTCMD, "+", NULL, 0);
20631133e27eSPeter Avalos 			c = getcc();
20641133e27eSPeter Avalos 			goto again;
20651133e27eSPeter Avalos 
20661133e27eSPeter Avalos 		case A_SHELL:
2067320d7c8aSAaron LI 		case A_PSHELL:
20681133e27eSPeter Avalos 			/*
20691133e27eSPeter Avalos 			 * Shell escape.
20701133e27eSPeter Avalos 			 */
20711133e27eSPeter Avalos #if SHELL_ESCAPE
2072*e433da38SAaron LI 			if (secure_allow(SF_SHELL))
20731133e27eSPeter Avalos 			{
2074320d7c8aSAaron LI 				start_mca(action, (action == A_SHELL) ? "!" : "#", ml_shell, 0);
20751133e27eSPeter Avalos 				c = getcc();
20761133e27eSPeter Avalos 				goto again;
207702d62a0fSDaniel Fojt 			}
207802d62a0fSDaniel Fojt #endif
20791133e27eSPeter Avalos 			error("Command not available", NULL_PARG);
20801133e27eSPeter Avalos 			break;
20811133e27eSPeter Avalos 
20821133e27eSPeter Avalos 		case A_SETMARK:
208302d62a0fSDaniel Fojt 		case A_SETMARKBOT:
20841133e27eSPeter Avalos 			/*
20851133e27eSPeter Avalos 			 * Set a mark.
20861133e27eSPeter Avalos 			 */
20871133e27eSPeter Avalos 			if (ch_getflags() & CH_HELPFILE)
20881133e27eSPeter Avalos 				break;
2089*e433da38SAaron LI 			start_mca(A_SETMARK, "set mark: ", NULL, 0);
20901133e27eSPeter Avalos 			c = getcc();
209102d62a0fSDaniel Fojt 			if (is_erase_char(c) || is_newline_char(c))
20921133e27eSPeter Avalos 				break;
209302d62a0fSDaniel Fojt 			setmark(c, action == A_SETMARKBOT ? BOTTOM : TOP);
209402d62a0fSDaniel Fojt 			repaint();
209502d62a0fSDaniel Fojt 			break;
209602d62a0fSDaniel Fojt 
209702d62a0fSDaniel Fojt 		case A_CLRMARK:
209802d62a0fSDaniel Fojt 			/*
209902d62a0fSDaniel Fojt 			 * Clear a mark.
210002d62a0fSDaniel Fojt 			 */
2101*e433da38SAaron LI 			start_mca(A_CLRMARK, "clear mark: ", NULL, 0);
210202d62a0fSDaniel Fojt 			c = getcc();
210302d62a0fSDaniel Fojt 			if (is_erase_char(c) || is_newline_char(c))
210402d62a0fSDaniel Fojt 				break;
210502d62a0fSDaniel Fojt 			clrmark(c);
210602d62a0fSDaniel Fojt 			repaint();
21071133e27eSPeter Avalos 			break;
21081133e27eSPeter Avalos 
21091133e27eSPeter Avalos 		case A_GOMARK:
21101133e27eSPeter Avalos 			/*
211102d62a0fSDaniel Fojt 			 * Jump to a marked position.
21121133e27eSPeter Avalos 			 */
2113*e433da38SAaron LI 			start_mca(A_GOMARK, "goto mark: ", NULL, 0);
21141133e27eSPeter Avalos 			c = getcc();
211502d62a0fSDaniel Fojt 			if (is_erase_char(c) || is_newline_char(c))
21161133e27eSPeter Avalos 				break;
21171133e27eSPeter Avalos 			cmd_exec();
21181133e27eSPeter Avalos 			gomark(c);
21191133e27eSPeter Avalos 			break;
21201133e27eSPeter Avalos 
21211133e27eSPeter Avalos 		case A_PIPE:
212202d62a0fSDaniel Fojt 			/*
212302d62a0fSDaniel Fojt 			 * Write part of the input to a pipe to a shell command.
212402d62a0fSDaniel Fojt 			 */
21251133e27eSPeter Avalos #if PIPEC
2126*e433da38SAaron LI 			if (secure_allow(SF_PIPE))
21271133e27eSPeter Avalos 			{
2128*e433da38SAaron LI 				start_mca(A_PIPE, "|mark: ", NULL, 0);
21291133e27eSPeter Avalos 				c = getcc();
213002d62a0fSDaniel Fojt 				if (is_erase_char(c))
21311133e27eSPeter Avalos 					break;
213202d62a0fSDaniel Fojt 				if (is_newline_char(c))
21331133e27eSPeter Avalos 					c = '.';
21341133e27eSPeter Avalos 				if (badmark(c))
21351133e27eSPeter Avalos 					break;
21361133e27eSPeter Avalos 				pipec = c;
21371133e27eSPeter Avalos 				start_mca(A_PIPE, "!", ml_shell, 0);
21381133e27eSPeter Avalos 				c = getcc();
21391133e27eSPeter Avalos 				goto again;
214002d62a0fSDaniel Fojt 			}
214102d62a0fSDaniel Fojt #endif
21421133e27eSPeter Avalos 			error("Command not available", NULL_PARG);
21431133e27eSPeter Avalos 			break;
21441133e27eSPeter Avalos 
21451133e27eSPeter Avalos 		case A_B_BRACKET:
21461133e27eSPeter Avalos 		case A_F_BRACKET:
2147*e433da38SAaron LI 			start_mca(action, "Brackets: ", NULL, 0);
21481133e27eSPeter Avalos 			c = getcc();
21491133e27eSPeter Avalos 			goto again;
21501133e27eSPeter Avalos 
21511133e27eSPeter Avalos 		case A_LSHIFT:
215202d62a0fSDaniel Fojt 			/*
215302d62a0fSDaniel Fojt 			 * Shift view left.
215402d62a0fSDaniel Fojt 			 */
21551133e27eSPeter Avalos 			if (number > 0)
2156*e433da38SAaron LI 				shift_count = (int) number;
21571133e27eSPeter Avalos 			else
2158*e433da38SAaron LI 				number = (shift_count > 0) ? shift_count : sc_width / 2;
21591133e27eSPeter Avalos 			if (number > hshift)
21601133e27eSPeter Avalos 				number = hshift;
2161*e433da38SAaron LI 			pos_rehead();
2162*e433da38SAaron LI 			hshift -= (int) number;
2163*e433da38SAaron LI 			screen_trashed();
21641133e27eSPeter Avalos 			break;
21651133e27eSPeter Avalos 
21661133e27eSPeter Avalos 		case A_RSHIFT:
216702d62a0fSDaniel Fojt 			/*
216802d62a0fSDaniel Fojt 			 * Shift view right.
216902d62a0fSDaniel Fojt 			 */
21701133e27eSPeter Avalos 			if (number > 0)
2171*e433da38SAaron LI 				shift_count = (int) number;
21721133e27eSPeter Avalos 			else
2173*e433da38SAaron LI 				number = (shift_count > 0) ? shift_count : sc_width / 2;
2174*e433da38SAaron LI 			pos_rehead();
2175*e433da38SAaron LI 			hshift += (int) number;
2176*e433da38SAaron LI 			screen_trashed();
21771133e27eSPeter Avalos 			break;
21781133e27eSPeter Avalos 
217902d62a0fSDaniel Fojt 		case A_LLSHIFT:
218002d62a0fSDaniel Fojt 			/*
218102d62a0fSDaniel Fojt 			 * Shift view left to margin.
218202d62a0fSDaniel Fojt 			 */
2183*e433da38SAaron LI 			pos_rehead();
218402d62a0fSDaniel Fojt 			hshift = 0;
2185*e433da38SAaron LI 			screen_trashed();
218602d62a0fSDaniel Fojt 			break;
218702d62a0fSDaniel Fojt 
218802d62a0fSDaniel Fojt 		case A_RRSHIFT:
218902d62a0fSDaniel Fojt 			/*
219002d62a0fSDaniel Fojt 			 * Shift view right to view rightmost char on screen.
219102d62a0fSDaniel Fojt 			 */
2192*e433da38SAaron LI 			pos_rehead();
219302d62a0fSDaniel Fojt 			hshift = rrshift();
2194*e433da38SAaron LI 			screen_trashed();
219502d62a0fSDaniel Fojt 			break;
219602d62a0fSDaniel Fojt 
21971133e27eSPeter Avalos 		case A_PREFIX:
21981133e27eSPeter Avalos 			/*
21991133e27eSPeter Avalos 			 * The command is incomplete (more chars are needed).
22001133e27eSPeter Avalos 			 * Display the current char, so the user knows
22011133e27eSPeter Avalos 			 * what's going on, and get another character.
22021133e27eSPeter Avalos 			 */
22031133e27eSPeter Avalos 			if (mca != A_PREFIX)
22041133e27eSPeter Avalos 			{
22051133e27eSPeter Avalos 				cmd_reset();
2206*e433da38SAaron LI 				start_mca(A_PREFIX, " ", NULL, CF_QUIT_ON_ERASE);
22071133e27eSPeter Avalos 				(void) cmd_char(c);
22081133e27eSPeter Avalos 			}
22091133e27eSPeter Avalos 			c = getcc();
22101133e27eSPeter Avalos 			goto again;
22111133e27eSPeter Avalos 
22121133e27eSPeter Avalos 		case A_NOACTION:
22131133e27eSPeter Avalos 			break;
22141133e27eSPeter Avalos 
22151133e27eSPeter Avalos 		default:
22161133e27eSPeter Avalos 			bell();
22171133e27eSPeter Avalos 			break;
22181133e27eSPeter Avalos 		}
22191133e27eSPeter Avalos 	}
22201133e27eSPeter Avalos }
2221