Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 13 Aug 2023 07:15:20 GMT
From:      Xin LI <delphij@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: f80a33ea416e - main - MFV: less v643.
Message-ID:  <202308130715.37D7FKY8002435@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by delphij:

URL: https://cgit.FreeBSD.org/src/commit/?id=f80a33ea416e408c490a1f1f031a6abbccbae085

commit f80a33ea416e408c490a1f1f031a6abbccbae085
Merge: 09078445fb94 448d114b2515
Author:     Xin LI <delphij@FreeBSD.org>
AuthorDate: 2023-08-13 07:13:31 +0000
Commit:     Xin LI <delphij@FreeBSD.org>
CommitDate: 2023-08-13 07:13:31 +0000

    MFV: less v643.
    
    MFC after:      2 weeks

 contrib/less/NEWS         | 38 +++++++++++++++++++++++++++++++++
 contrib/less/ch.c         |  2 ++
 contrib/less/command.c    |  5 +++--
 contrib/less/edit.c       |  2 +-
 contrib/less/forwback.c   |  8 +++----
 contrib/less/funcs.h      |  1 +
 contrib/less/help.c       |  2 +-
 contrib/less/less.h       |  9 ++++++++
 contrib/less/less.nro     | 15 ++++++++++----
 contrib/less/lessecho.nro |  2 +-
 contrib/less/lesskey.nro  | 15 ++++++++++----
 contrib/less/optfunc.c    |  8 +++----
 contrib/less/os.c         | 44 +++++++++++++++++++++++++++++++--------
 contrib/less/screen.c     | 53 +++++++++++++++++++++++++++++++++++++----------
 contrib/less/search.c     |  2 ++
 contrib/less/version.c    | 14 ++++++++++++-
 contrib/less/xbuf.c       |  8 +++----
 usr.bin/less/defines.h    | 18 ++++++++--------
 18 files changed, 191 insertions(+), 55 deletions(-)

diff --cc contrib/less/command.c
index 88c0cb49ee77,000000000000..c1003d55fada
mode 100644,000000..100644
--- a/contrib/less/command.c
+++ b/contrib/less/command.c
@@@ -1,2095 -1,0 +1,2096 @@@
 +/* $FreeBSD$ */
 +/*
 + * Copyright (C) 1984-2023  Mark Nudelman
 + *
 + * You may distribute under the terms of either the GNU General Public
 + * License or the Less License, as specified in the README file.
 + *
 + * For more information, see the README file.
 + */
 +
 +
 +/*
 + * User-level command processor.
 + */
 +
 +#include "less.h"
 +#if MSDOS_COMPILER==WIN32C
 +#include <windows.h>
 +#endif
 +#include "position.h"
 +#include "option.h"
 +#include "cmd.h"
 +
 +extern int erase_char, erase2_char, kill_char;
 +extern int sigs;
 +extern int quit_if_one_screen;
 +extern int one_screen;
 +extern int squished;
 +extern int sc_width;
 +extern int sc_height;
 +extern char *kent;
 +extern int swindow;
 +extern int jump_sline;
 +extern int quitting;
 +extern int wscroll;
 +extern int top_scroll;
 +extern int ignore_eoi;
 +extern int secure;
 +extern int hshift;
 +extern int bs_mode;
 +extern int proc_backspace;
 +extern int show_attn;
 +extern int less_is_more;
 +extern int status_col;
 +extern POSITION highest_hilite;
 +extern POSITION start_attnpos;
 +extern POSITION end_attnpos;
 +extern char *every_first_cmd;
 +extern char version[];
 +extern struct scrpos initial_scrpos;
 +extern IFILE curr_ifile;
 +extern void *ml_search;
 +extern void *ml_examine;
 +extern int wheel_lines;
 +extern int header_lines;
 +extern int def_search_type;
 +extern int updown_match;
 +#if SHELL_ESCAPE || PIPEC
 +extern void *ml_shell;
 +#endif
 +#if EDITOR
 +extern char *editor;
 +extern char *editproto;
 +#endif
 +extern int screen_trashed;      /* The screen has been overwritten */
 +extern int shift_count;
 +extern int oldbot;
 +extern int forw_prompt;
 +extern int incr_search;
 +extern int full_screen;
 +#if MSDOS_COMPILER==WIN32C
 +extern int utf_mode;
 +#endif
 +
 +#if SHELL_ESCAPE
 +static char *shellcmd = NULL;   /* For holding last shell command for "!!" */
 +#endif
 +static int mca;                 /* The multicharacter command (action) */
 +static int search_type;         /* The previous type of search */
 +static int last_search_type;    /* Type of last executed search */
 +static LINENUM number;          /* The number typed by the user */
 +static long fraction;           /* The fractional part of the number */
 +static struct loption *curropt;
 +static int opt_lower;
 +static int optflag;
 +static int optgetname;
 +static POSITION bottompos;
 +static int save_hshift;
 +static int save_bs_mode;
 +static int save_proc_backspace;
 +#if PIPEC
 +static char pipec;
 +#endif
 +
 +/* Stack of ungotten chars (via ungetcc) */
 +struct ungot {
 +	struct ungot *ug_next;
 +	LWCHAR ug_char;
 +};
 +static struct ungot* ungot = NULL;
 +
 +static void multi_search (char *pattern, int n, int silent);
 +
 +/*
 + * Move the cursor to start of prompt line before executing a command.
 + * This looks nicer if the command takes a long time before
 + * updating the screen.
 + */
 +static void cmd_exec(void)
 +{
 +	clear_attn();
 +	clear_bot();
 +	flush();
 +}
 +
 +/*
 + * Indicate we are reading a multi-character command.
 + */
 +static void set_mca(int action)
 +{
 +	mca = action;
 +	clear_bot();
 +	clear_cmd();
 +}
 +
 +/*
 + * Indicate we are not reading a multi-character command.
 + */
 +static void clear_mca(void)
 +{
 +	if (mca == 0)
 +		return;
 +	mca = 0;
 +}
 +
 +/*
 + * Set up the display to start a new multi-character command.
 + */
 +static void start_mca(int action, constant char *prompt, void *mlist, int cmdflags)
 +{
 +	set_mca(action);
 +	cmd_putstr(prompt);
 +	set_mlist(mlist, cmdflags);
 +}
 +
 +public int in_mca(void)
 +{
 +	return (mca != 0 && mca != A_PREFIX);
 +}
 +
 +/*
 + * Set up the display to start a new search command.
 + */
 +static void mca_search1(void)
 +{
 +	int i;
 +
 +#if HILITE_SEARCH
 +	if (search_type & SRCH_FILTER)
 +		set_mca(A_FILTER);
 +	else 
 +#endif
 +	if (search_type & SRCH_FORW)
 +		set_mca(A_F_SEARCH);
 +	else
 +		set_mca(A_B_SEARCH);
 +
 +	if (search_type & SRCH_NO_MATCH)
 +		cmd_putstr("Non-match ");
 +	if (search_type & SRCH_FIRST_FILE)
 +		cmd_putstr("First-file ");
 +	if (search_type & SRCH_PAST_EOF)
 +		cmd_putstr("EOF-ignore ");
 +	if (search_type & SRCH_NO_MOVE)
 +		cmd_putstr("Keep-pos ");
 +	if (search_type & SRCH_NO_REGEX)
 +		cmd_putstr("Regex-off ");
 +	if (search_type & SRCH_WRAP)
 +		cmd_putstr("Wrap ");
 +	for (i = 1; i <= NUM_SEARCH_COLORS; i++)
 +	{
 +		if (search_type & SRCH_SUBSEARCH(i))
 +		{
- 			char buf[8];
++			char buf[INT_STRLEN_BOUND(int)+8];
 +			SNPRINTF1(buf, sizeof(buf), "Sub-%d ", i);
 +			cmd_putstr(buf);
 +		}
 +	}
 +
 +#if HILITE_SEARCH
 +	if (search_type & SRCH_FILTER)
 +		cmd_putstr("&/");
 +	else 
 +#endif
 +	if (search_type & SRCH_FORW)
 +		cmd_putstr("/");
 +	else
 +		cmd_putstr("?");
 +	forw_prompt = 0;
 +}
 +
 +static void mca_search(void)
 +{
 +	mca_search1();
 +	set_mlist(ml_search, 0);
 +}
 +
 +/*
 + * Set up the display to start a new toggle-option command.
 + */
 +static void mca_opt_toggle(void)
 +{
 +	int no_prompt;
 +	int flag;
 +	char *dash;
 +	
 +	no_prompt = (optflag & OPT_NO_PROMPT);
 +	flag = (optflag & ~OPT_NO_PROMPT);
 +	dash = (flag == OPT_NO_TOGGLE) ? "_" : "-";
 +
 +	set_mca(A_OPT_TOGGLE);
 +	cmd_putstr(dash);
 +	if (optgetname)
 +		cmd_putstr(dash);
 +	if (no_prompt)
 +		cmd_putstr("(P)");
 +	switch (flag)
 +	{
 +	case OPT_UNSET:
 +		cmd_putstr("+");
 +		break;
 +	case OPT_SET:
 +		cmd_putstr("!");
 +		break;
 +	}
 +	forw_prompt = 0;
 +	set_mlist(NULL, 0);
 +}
 +
 +/*
 + * Execute a multicharacter command.
 + */
 +static void exec_mca(void)
 +{
 +	char *cbuf;
 +
 +	cmd_exec();
 +	cbuf = get_cmdbuf();
 +	if (cbuf == NULL)
 +		return;
 +
 +	switch (mca)
 +	{
 +	case A_F_SEARCH:
 +	case A_B_SEARCH:
 +		multi_search(cbuf, (int) number, 0);
 +		break;
 +#if HILITE_SEARCH
 +	case A_FILTER:
 +		search_type ^= SRCH_NO_MATCH;
 +		set_filter_pattern(cbuf, search_type);
 +		break;
 +#endif
 +	case A_FIRSTCMD:
 +		/*
 +		 * Skip leading spaces or + signs in the string.
 +		 */
 +		while (*cbuf == '+' || *cbuf == ' ')
 +			cbuf++;
 +		if (every_first_cmd != NULL)
 +			free(every_first_cmd);
 +		if (*cbuf == '\0')
 +			every_first_cmd = NULL;
 +		else
 +			every_first_cmd = save(cbuf);
 +		break;
 +	case A_OPT_TOGGLE:
 +		toggle_option(curropt, opt_lower, cbuf, optflag);
 +		curropt = NULL;
 +		break;
 +	case A_F_BRACKET:
 +		match_brac(cbuf[0], cbuf[1], 1, (int) number);
 +		break;
 +	case A_B_BRACKET:
 +		match_brac(cbuf[1], cbuf[0], 0, (int) number);
 +		break;
 +#if EXAMINE
 +	case A_EXAMINE:
 +		if (secure)
 +			break;
 +		edit_list(cbuf);
 +#if TAGS
 +		/* If tag structure is loaded then clean it up. */
 +		cleantags();
 +#endif
 +		break;
 +#endif
 +#if SHELL_ESCAPE
 +	case A_SHELL:
 +		/*
 +		 * !! just uses whatever is in shellcmd.
 +		 * Otherwise, copy cmdbuf to shellcmd,
 +		 * expanding any special characters ("%" or "#").
 +		 */
 +		if (*cbuf != '!')
 +		{
 +			if (shellcmd != NULL)
 +				free(shellcmd);
 +			shellcmd = fexpand(cbuf);
 +		}
 +
 +		if (secure)
 +			break;
 +		if (shellcmd == NULL)
 +			lsystem("", "!done");
 +		else
 +			lsystem(shellcmd, "!done");
 +		break;
 +	case A_PSHELL:
 +		if (secure)
 +			break;
 +		lsystem(pr_expand(cbuf), "#done");
 +		break;
 +#endif
 +#if PIPEC
 +	case A_PIPE:
 +		if (secure)
 +			break;
 +		(void) pipe_mark(pipec, cbuf);
 +		error("|done", NULL_PARG);
 +		break;
 +#endif
 +	}
 +}
 +
 +/*
 + * Is a character an erase or kill char?
 + */
 +static int is_erase_char(int c)
 +{
 +	return (c == erase_char || c == erase2_char || c == kill_char);
 +}
 +
 +/*
 + * Is a character a carriage return or newline?
 + */
 +static int is_newline_char(int c)
 +{
 +	return (c == '\n' || c == '\r');
 +}
 +
 +/*
 + * Handle the first char of an option (after the initial dash).
 + */
 +static int mca_opt_first_char(int c)
 +{
 +	int no_prompt = (optflag & OPT_NO_PROMPT);
 +	int flag = (optflag & ~OPT_NO_PROMPT);
 +	if (flag == OPT_NO_TOGGLE)
 +	{
 +		switch (c)
 +		{
 +		case '_':
 +			/* "__" = long option name. */
 +			optgetname = TRUE;
 +			mca_opt_toggle();
 +			return (MCA_MORE);
 +		}
 +	} else
 +	{
 +		switch (c)
 +		{
 +		case '+':
 +			/* "-+" = UNSET. */
 +			optflag = no_prompt | ((flag == OPT_UNSET) ?
 +				OPT_TOGGLE : OPT_UNSET);
 +			mca_opt_toggle();
 +			return (MCA_MORE);
 +		case '!':
 +			/* "-!" = SET */
 +			optflag = no_prompt | ((flag == OPT_SET) ?
 +				OPT_TOGGLE : OPT_SET);
 +			mca_opt_toggle();
 +			return (MCA_MORE);
 +		case CONTROL('P'):
 +			optflag ^= OPT_NO_PROMPT;
 +			mca_opt_toggle();
 +			return (MCA_MORE);
 +		case '-':
 +			/* "--" = long option name. */
 +			optgetname = TRUE;
 +			mca_opt_toggle();
 +			return (MCA_MORE);
 +		}
 +	}
 +	/* Char was not handled here. */
 +	return (NO_MCA);
 +}
 +
 +/*
 + * Add a char to a long option name.
 + * See if we've got a match for an option name yet.
 + * If so, display the complete name and stop 
 + * accepting chars until user hits RETURN.
 + */
 +static int mca_opt_nonfirst_char(int c)
 +{
 +	char *p;
 +	char *oname;
 +	int err;
 +
 +	if (curropt != NULL)
 +	{
 +		/*
 +		 * Already have a match for the name.
 +		 * Don't accept anything but erase/kill.
 +		 */
 +		if (is_erase_char(c))
 +			return (MCA_DONE);
 +		return (MCA_MORE);
 +	}
 +	/*
 +	 * Add char to cmd buffer and try to match
 +	 * the option name.
 +	 */
 +	if (cmd_char(c) == CC_QUIT)
 +		return (MCA_DONE);
 +	p = get_cmdbuf();
 +	if (p == NULL)
 +		return (MCA_MORE);
 +	opt_lower = ASCII_IS_LOWER(p[0]);
 +	err = 0;
 +	curropt = findopt_name(&p, &oname, &err);
 +	if (curropt != NULL)
 +	{
 +		/*
 +		 * Got a match.
 +		 * Remember the option and
 +		 * display the full option name.
 +		 */
 +		cmd_reset();
 +		mca_opt_toggle();
 +		for (p = oname;  *p != '\0';  p++)
 +		{
 +			c = *p;
 +			if (!opt_lower && ASCII_IS_LOWER(c))
 +				c = ASCII_TO_UPPER(c);
 +			if (cmd_char(c) != CC_OK)
 +				return (MCA_DONE);
 +		}
 +	} else if (err != OPT_AMBIG)
 +	{
 +		bell();
 +	}
 +	return (MCA_MORE);
 +}
 +
 +/*
 + * Handle a char of an option toggle command.
 + */
 +static int mca_opt_char(int c)
 +{
 +	PARG parg;
 +
 +	/*
 +	 * This may be a short option (single char),
 +	 * or one char of a long option name,
 +	 * or one char of the option parameter.
 +	 */
 +	if (curropt == NULL && len_cmdbuf() == 0)
 +	{
 +		int ret = mca_opt_first_char(c);
 +		if (ret != NO_MCA)
 +			return (ret);
 +	}
 +	if (optgetname)
 +	{
 +		/* We're getting a long option name.  */
 +		if (!is_newline_char(c) && c != '=')
 +			return (mca_opt_nonfirst_char(c));
 +		if (curropt == NULL)
 +		{
 +			parg.p_string = get_cmdbuf();
 +			if (parg.p_string == NULL)
 +				return (MCA_MORE);
 +			error("There is no --%s option", &parg);
 +			return (MCA_DONE);
 +		}
 +		optgetname = FALSE;
 +		cmd_reset();
 +	} else
 +	{
 +		if (is_erase_char(c))
 +			return (NO_MCA);
 +		if (curropt != NULL)
 +			/* We're getting the option parameter. */
 +			return (NO_MCA);
 +		curropt = findopt(c);
 +		if (curropt == NULL)
 +		{
 +			parg.p_string = propt(c);
 +			error("There is no %s option", &parg);
 +			return (MCA_DONE);
 +		}
 +		opt_lower = ASCII_IS_LOWER(c);
 +	}
 +	/*
 +	 * If the option which was entered does not take a 
 +	 * parameter, toggle the option immediately,
 +	 * so user doesn't have to hit RETURN.
 +	 */
 +	if ((optflag & ~OPT_NO_PROMPT) != OPT_TOGGLE ||
 +	    !opt_has_param(curropt))
 +	{
 +		toggle_option(curropt, opt_lower, "", optflag);
 +		return (MCA_DONE);
 +	}
 +	/*
 +	 * Display a prompt appropriate for the option parameter.
 +	 */
 +	start_mca(A_OPT_TOGGLE, opt_prompt(curropt), (void*)NULL, 0);
 +	return (MCA_MORE);
 +}
 +
 +/*
 + * Normalize search type.
 + */
 +public int norm_search_type(int st)
 +{
 +	/* WRAP and PAST_EOF are mutually exclusive. */
 +	if ((st & (SRCH_PAST_EOF|SRCH_WRAP)) == (SRCH_PAST_EOF|SRCH_WRAP))
 +		st ^= SRCH_PAST_EOF;
 +	return st;
 +}
 +
 +/*
 + * Handle a char of a search command.
 + */
 +static int mca_search_char(int c)
 +{
 +	int flag = 0;
 +
 +	/*
 +	 * Certain characters as the first char of 
 +	 * the pattern have special meaning:
 +	 *      !  Toggle the NO_MATCH flag
 +	 *      *  Toggle the PAST_EOF flag
 +	 *      @  Toggle the FIRST_FILE flag
 +	 */
 +	if (len_cmdbuf() > 0)
 +		return (NO_MCA);
 +
 +	switch (c)
 +	{
 +	case '*':
 +		if (less_is_more)
 +			break;
 +	case CONTROL('E'): /* ignore END of file */
 +		if (mca != A_FILTER)
 +			flag = SRCH_PAST_EOF;
++		search_type &= ~SRCH_WRAP;
 +		break;
 +	case '@':
 +		if (less_is_more)
 +			break;
 +	case CONTROL('F'): /* FIRST file */
 +		if (mca != A_FILTER)
 +			flag = SRCH_FIRST_FILE;
 +		break;
 +	case CONTROL('K'): /* KEEP position */
 +		if (mca != A_FILTER)
 +			flag = SRCH_NO_MOVE;
 +		break;
 +	case CONTROL('S'): { /* SUBSEARCH */
- 		char buf[32];
++		char buf[INT_STRLEN_BOUND(int)+24];
 +		SNPRINTF1(buf, sizeof(buf), "Sub-pattern (1-%d):", NUM_SEARCH_COLORS);
 +		clear_bot();
 +		cmd_putstr(buf);
 +		flush();
 +		c = getcc();
 +		if (c >= '1' && c <= '0'+NUM_SEARCH_COLORS)
 +			flag = SRCH_SUBSEARCH(c-'0');
 +		else
 +			flag = -1; /* calls mca_search() below to repaint */
 +		break; }
 +	case CONTROL('W'): /* WRAP around */
 +		if (mca != A_FILTER)
 +			flag = SRCH_WRAP;
 +		break;
 +	case CONTROL('R'): /* Don't use REGULAR EXPRESSIONS */
 +		flag = SRCH_NO_REGEX;
 +		break;
 +	case CONTROL('N'): /* NOT match */
 +	case '!':
 +		flag = SRCH_NO_MATCH;
 +		break;
 +	}
 +
 +	if (flag != 0)
 +	{
 +		if (flag != -1)
 +			search_type = norm_search_type(search_type ^ flag);
 +		mca_search();
 +		return (MCA_MORE);
 +	}
 +	return (NO_MCA);
 +}
 +
 +/*
 + * Handle a character of a multi-character command.
 + */
 +static int mca_char(int c)
 +{
 +	int ret;
 +
 +	switch (mca)
 +	{
 +	case 0:
 +		/*
 +		 * We're not in a multicharacter command.
 +		 */
 +		return (NO_MCA);
 +
 +	case A_PREFIX:
 +		/*
 +		 * In the prefix of a command.
 +		 * This not considered a multichar command
 +		 * (even tho it uses cmdbuf, etc.).
 +		 * It is handled in the commands() switch.
 +		 */
 +		return (NO_MCA);
 +
 +	case A_DIGIT:
 +		/*
 +		 * Entering digits of a number.
 +		 * Terminated by a non-digit.
 +		 */
 +		if ((c >= '0' && c <= '9') || c == '.')
 +			break;
 +		switch (editchar(c, ECF_PEEK|ECF_NOHISTORY|ECF_NOCOMPLETE|ECF_NORIGHTLEFT))
 +		{
 +		case A_NOACTION:
 +			/*
 +			 * Ignore this char and get another one.
 +			 */
 +			return (MCA_MORE);
 +		case A_INVALID:
 +			/*
 +			 * Not part of the number.
 +			 * End the number and treat this char 
 +			 * as a normal command character.
 +			 */
 +			number = cmd_int(&fraction);
 +			clear_mca();
 +			cmd_accept();
 +			return (NO_MCA);
 +		}
 +		break;
 +
 +	case A_OPT_TOGGLE:
 +		ret = mca_opt_char(c);
 +		if (ret != NO_MCA)
 +			return (ret);
 +		break;
 +
 +	case A_F_SEARCH:
 +	case A_B_SEARCH:
 +	case A_FILTER:
 +		ret = mca_search_char(c);
 +		if (ret != NO_MCA)
 +			return (ret);
 +		break;
 +
 +	default:
 +		/* Other multicharacter command. */
 +		break;
 +	}
 +
 +	/*
 +	 * The multichar command is terminated by a newline.
 +	 */
 +	if (is_newline_char(c))
 +	{
 +		/*
 +		 * Execute the command.
 +		 */
 +		exec_mca();
 +		return (MCA_DONE);
 +	}
 +
 +	/*
 +	 * Append the char to the command buffer.
 +	 */
 +	if (cmd_char(c) == CC_QUIT)
 +		/*
 +		 * Abort the multi-char command.
 +		 */
 +		return (MCA_DONE);
 +
 +	switch (mca)
 +	{
 +	case A_F_BRACKET:
 +	case A_B_BRACKET:
 +		if (len_cmdbuf() >= 2)
 +		{
 +			/*
 +			 * Special case for the bracket-matching commands.
 +			 * Execute the command after getting exactly two
 +			 * characters from the user.
 +			 */
 +			exec_mca();
 +			return (MCA_DONE);
 +		}
 +		break;
 +	case A_F_SEARCH:
 +	case A_B_SEARCH:
 +		if (incr_search)
 +		{
 +			/* Incremental search: do a search after every input char. */
 +			int st = (search_type & (SRCH_FORW|SRCH_BACK|SRCH_NO_MATCH|SRCH_NO_REGEX|SRCH_NO_MOVE|SRCH_WRAP|SRCH_SUBSEARCH_ALL));
 +			char *pattern = get_cmdbuf();
 +			if (pattern == NULL)
 +				return (MCA_MORE);
 +			/*
 +			 * Must save updown_match because mca_search
 +			 * reinits it. That breaks history scrolling.
 +			 * {{ This is ugly. mca_search probably shouldn't call set_mlist. }}
 +			 */
 +			int save_updown_match = updown_match;
 +			cmd_exec();
 +			if (*pattern == '\0')
 +			{
 +				/* User has backspaced to an empty pattern. */
 +				undo_search(1);
 +			} else
 +			{
 +				if (search(st | SRCH_INCR, pattern, 1) != 0)
 +					/* No match, invalid pattern, etc. */
 +					undo_search(1);
 +			}
 +			/* Redraw the search prompt and search string. */
 +			if (!full_screen)
 +			{
 +				clear();
 +				repaint();
 +			}
 +			mca_search1();
 +			updown_match = save_updown_match;
 +			cmd_repaint(NULL);
 +		}
 +		break;
 +	}
 +
 +	/*
 +	 * Need another character.
 +	 */
 +	return (MCA_MORE);
 +}
 +
 +/*
 + * Discard any buffered file data.
 + */
 +static void clear_buffers(void)
 +{
 +	if (!(ch_getflags() & CH_CANSEEK))
 +		return;
 +	ch_flush();
 +	clr_linenum();
 +#if HILITE_SEARCH
 +	clr_hilite();
 +#endif
 +}
 +
 +/*
 + * Make sure the screen is displayed.
 + */
 +static void make_display(void)
 +{
 +	/*
 +	 * If not full_screen, we can't rely on scrolling to fill the screen.
 +	 * We need to clear and repaint screen before any change.
 +	 */
 +	if (!full_screen && !(quit_if_one_screen && one_screen))
 +		clear();
 +	/*
 +	 * If nothing is displayed yet, display starting from initial_scrpos.
 +	 */
 +	if (empty_screen())
 +	{
 +		if (initial_scrpos.pos == NULL_POSITION)
 +			jump_loc(ch_zero(), 1);
 +		else
 +			jump_loc(initial_scrpos.pos, initial_scrpos.ln);
 +	} else if (screen_trashed || !full_screen)
 +	{
 +		int save_top_scroll = top_scroll;
 +		int save_ignore_eoi = ignore_eoi;
 +		top_scroll = 1;
 +		ignore_eoi = 0;
 +		if (screen_trashed == 2)
 +		{
 +			/* Special case used by ignore_eoi: re-open the input file
 +			 * and jump to the end of the file. */
 +			reopen_curr_ifile();
 +			jump_forw();
 +		}
 +		repaint();
 +		top_scroll = save_top_scroll;
 +		ignore_eoi = save_ignore_eoi;
 +	}
 +}
 +
 +/*
 + * Display the appropriate prompt.
 + */
 +static void prompt(void)
 +{
 +	constant char *p;
 +
 +	if (ungot != NULL && ungot->ug_char != CHAR_END_COMMAND)
 +	{
 +		/*
 +		 * No prompt necessary if commands are from 
 +		 * ungotten chars rather than from the user.
 +		 */
 +		return;
 +	}
 +
 +	/*
 +	 * Make sure the screen is displayed.
 +	 */
 +	make_display();
 +	bottompos = position(BOTTOM_PLUS_ONE);
 +
 +	/*
 +	 * If we've hit EOF on the last file and the -E flag is set, quit.
 +	 */
 +	if (get_quit_at_eof() == OPT_ONPLUS &&
 +	    eof_displayed() && !(ch_getflags() & CH_HELPFILE) && 
 +	    next_ifile(curr_ifile) == NULL_IFILE)
 +		quit(QUIT_OK);
 +
 +	/*
 +	 * If the entire file is displayed and the -F flag is set, quit.
 +	 */
 +	if (quit_if_one_screen &&
 +	    entire_file_displayed() && !(ch_getflags() & CH_HELPFILE) && 
 +	    next_ifile(curr_ifile) == NULL_IFILE)
 +		quit(QUIT_OK);
 +	quit_if_one_screen = FALSE; /* only get one chance at this */
 +
 +#if MSDOS_COMPILER==WIN32C
 +	/* 
 +	 * In Win32, display the file name in the window title.
 +	 */
 +	if (!(ch_getflags() & CH_HELPFILE))
 +	{
 +		WCHAR w[MAX_PATH+16];
 +		p = pr_expand("Less?f - %f.");
 +		MultiByteToWideChar(CP_ACP, 0, p, -1, w, sizeof(w)/sizeof(*w));
 +		SetConsoleTitleW(w);
 +	}
 +#endif
 +
 +	/*
 +	 * Select the proper prompt and display it.
 +	 */
 +	/*
 +	 * If the previous action was a forward movement, 
 +	 * don't clear the bottom line of the display;
 +	 * just print the prompt since the forward movement guarantees 
 +	 * that we're in the right position to display the prompt.
 +	 * Clearing the line could cause a problem: for example, if the last
 +	 * line displayed ended at the right screen edge without a newline,
 +	 * then clearing would clear the last displayed line rather than
 +	 * the prompt line.
 +	 */
 +	if (!forw_prompt)
 +		clear_bot();
 +	clear_cmd();
 +	forw_prompt = 0;
 +	p = pr_string();
 +#if HILITE_SEARCH
 +	if (is_filtering())
 +		putstr("& ");
 +#endif
 +	if (p == NULL || *p == '\0')
 +	{
 +		at_enter(AT_NORMAL|AT_COLOR_PROMPT);
 +		putchr(':');
 +		at_exit();
 +	} else
 +	{
 +#if MSDOS_COMPILER==WIN32C
 +		WCHAR w[MAX_PATH*2];
 +		char  a[MAX_PATH*2];
 +		MultiByteToWideChar(CP_ACP, 0, p, -1, w, sizeof(w)/sizeof(*w));
 +		WideCharToMultiByte(utf_mode ? CP_UTF8 : GetConsoleOutputCP(),
 +		                    0, w, -1, a, sizeof(a), NULL, NULL);
 +		p = a;
 +#endif
 +		load_line(p);
 +		put_line();
 +	}
 +	clear_eol();
 +}
 +
 +/*
 + * Display the less version message.
 + */
 +public void dispversion(void)
 +{
 +	PARG parg;
 +
 +	parg.p_string = version;
 +	error("less %s", &parg);
 +}
 +
 +/*
 + * Return a character to complete a partial command, if possible.
 + */
 +static LWCHAR getcc_end_command(void)
 +{
 +	switch (mca)
 +	{
 +	case A_DIGIT:
 +		/* We have a number but no command.  Treat as #g. */
 +		return ('g');
 +	case A_F_SEARCH:
 +	case A_B_SEARCH:
 +	case A_FILTER:
 +		/* We have "/string" but no newline.  Add the \n. */
 +		return ('\n'); 
 +	default:
 +		/* Some other incomplete command.  Let user complete it. */
 +		return ((ungot == NULL) ? getchr() : 0);
 +	}
 +}
 +
 +/*
 + * Get command character.
 + * The character normally comes from the keyboard,
 + * but may come from ungotten characters
 + * (characters previously given to ungetcc or ungetsc).
*** 2666 LINES SKIPPED ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202308130715.37D7FKY8002435>