git: fa0dc4f0f96a - main - MFV: less v704.

Xin LI <[email protected]>
Newsgroups gmane.os.freebsd.devel.cvs.src,gmane.os.freebsd.current.scm
Message-ID <[email protected]>
The branch main has been updated by delphij:

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

commit fa0dc4f0f96a1b77d4be7bcdbf965897cda14521
Merge: 06aaca43fe05 156348af10ce
Author:     Xin LI <[email protected]>
AuthorDate: 2026-08-15 05:55:38 +0000
Commit:     Xin LI <[email protected]>
CommitDate: 2026-08-15 06:21:18 +0000

    MFV: less v704.
    
    MFC after:      3 days

 contrib/less/NEWS              | 126 ++++++++++++++++
 contrib/less/README            |   8 -
 contrib/less/ch.c              |  10 +-
 contrib/less/charset.c         |  25 +--
 contrib/less/charset.h         |   2 +
 contrib/less/cmd.h             |   3 +
 contrib/less/cmdbuf.c          |   6 +-
 contrib/less/command.c         | 186 ++++++++++++++++-------
 contrib/less/decode.c          | 334 ++++++++++++++++++++++++++++++-----------
 contrib/less/edit.c            |  42 ++++--
 contrib/less/filename.c        |  20 +--
 contrib/less/forwback.c        |  53 +++++--
 contrib/less/funcs.h           |  41 +++--
 contrib/less/help.c            |  28 ++--
 contrib/less/input.c           |  12 +-
 contrib/less/jump.c            |  31 ++--
 contrib/less/less-osc8-open.sh |  64 ++++++++
 contrib/less/less.h            |  44 ++++--
 contrib/less/less.hlp          |  26 ++--
 contrib/less/less.nro          | 331 ++++++++++++++++++++++++++--------------
 contrib/less/lessecho.nro      |   2 +-
 contrib/less/lesskey.nro       |   3 +-
 contrib/less/lesskey_parse.c   |   2 +
 contrib/less/line.c            |  62 ++++----
 contrib/less/lsystem.c         |   2 +-
 contrib/less/main.c            |  73 ++-------
 contrib/less/mark.c            |  50 ++++--
 contrib/less/optfunc.c         | 200 ++++++++++++++++++++----
 contrib/less/opttbl.c          |  60 ++++++--
 contrib/less/os.c              |  45 +++---
 contrib/less/output.c          |  68 +++++----
 contrib/less/pattern.c         |   8 +-
 contrib/less/pattern.h         |  10 +-
 contrib/less/position.c        |  82 ++++++----
 contrib/less/prompt.c          |  33 ++--
 contrib/less/regexp.c          | 206 +++++++++++++++++--------
 contrib/less/regexp.h          |   5 +-
 contrib/less/screen.c          | 105 +++++++++----
 contrib/less/search.c          | 140 ++++++++++-------
 contrib/less/tags.c            |   8 +-
 contrib/less/ttyin.c           |   2 +-
 contrib/less/version.c         |  37 ++++-
 usr.bin/less/Makefile          |   2 +-
 usr.bin/less/defines.h         |  12 ++
 44 files changed, 1845 insertions(+), 764 deletions(-)

diff --cc contrib/less/README
index a6954eb67c1e,000000000000..384d99155616
mode 100644,000000..100644
--- a/contrib/less/README
+++ b/contrib/less/README
@@@ -1,242 -1,0 +1,234 @@@
 +**************************************************************************
 +**************************************************************************
 +**                                                                      **
 +** The FreeBSD Project has chosen to redistribute and modify Less under **
 +** the 'Less License' (as described in the 'LICENSE' file).             **
 +**                                                                      **
 +**************************************************************************
 +**************************************************************************
 +
 +    This is the source code distribution of "less".
 +    This program is part of the GNU project (https://www.gnu.org).
 +
 +    This program is free software.  You may redistribute it and/or
 +    modify it under the terms of either:
 +
 +    1. The GNU General Public License, as published by the Free
 +       Software Foundation; either version 3, or (at your option) any
 +       later version.  A copy of this license is in the file COPYING.
 +    or
 +    2. The Less License, in the file LICENSE.
 +
 +    Please report any problems at https://github.com/gwsw/less/issues.
 +    See https://greenwoodsoftware.com/less for the latest info.
 +    Source repository is at https://github.com/gwsw/less.git.
 +
 +=========================================================================
 +
 +You should build from a clone of a git repository 
 +ONLY IF you are doing development on the less source itself.
 +If you are merely using less as a tool, you should download a release
 +from https://greenwoodsoftware.com and NOT from github.
 +
 +The formatted manual page is in less.man.
 +The manual page nroff source is in less.nro.
 +Major changes made since the last posted version are in NEWS.
 +
 +=======================================================================
 +INSTALLATION (Unix & Linux systems only):
 +
 +1. Move the distributed source to its own directory and unpack it,
 +   if you have not already done so.  
 +
 +2. If you are building from a clone of a git repository,
 +   type "make -f Makefile.aut distfiles".
 +   If you are building from a numbered release package (a tar or 
 +   zip file with a name like less-999.tar.gz or less-999.zip downloaded 
 +   from greenwoodsoftware.com, not from github), you should skip this step. 
 +
 +3. Type "sh configure".
 +   This will generate a Makefile and a defines.h.
 +   Warning: if you have a GNU sed, make sure it is version 2.05 or later.
 +
 +   The file INSTALL describes the usage of the configure program in
 +   general.  In addition, these options to configure are supported:
 +
 +   --with-editor=program
 +     Specifies the default editor program used by the "v" command.
 +     The default is "vi".
 +
 +   --with-regex=lib
 +     Specifies the regular expression library used by less for pattern
 +     matching.  The default is "auto", which means the configure program 
 +     finds a regular expression library automatically.  Other values are:
 +        gnu            Use the GNU regex library.
 +        pcre           Use the PCRE library.
 +        pcre2          Use the PCRE2 library.
 +        posix          Use the POSIX-compatible regcomp.
 +        regcmp         Use the regcmp library.
 +        re_comp        Use the re_comp library.
 +        regcomp        Use the V8-compatible regcomp.
 +        regcomp-local  Use Henry Spencer's V8-compatible regcomp
 +                       (source is supplied with less).
 +        none           No regular expressions, only simple string matching.
 +
 +   --with-secure
 +     Builds a "secure" version of less, with some features disabled
 +     to prevent users from viewing other files, accessing shell
 +     commands, etc.
 +
 +
 +4. It is a good idea to look over the generated Makefile and defines.h
 +   and make sure they look ok.  If you know of any peculiarities of
 +   your system that configure might not have detected, you may fix the
 +   Makefile now.  Take particular notice of the list of "terminal" 
 +   libraries in the LIBS definition in the Makefile; these may need 
 +   to be edited.  The terminal libraries will be some subset of
 +    -ltinfo -ltinfow -lxcurses -lncursesw -lncurses -lcurses -ltermcap -ltermlib
 +
 +   If you wish, you may edit defines.h to remove some optional features.
 +   If you choose not to include some features in your version, you may
 +   wish to edit the manual page "less.nro" and the help page "less.hlp" 
 +   to remove the descriptions of the features which you are removing.
 +   If you edit less.hlp, you should run "make -f Makefile.aut help.c".
 +
 +5. Type "make" and watch the fun.
 +
 +6. If the make succeeds, it will generate the programs "less",
 +   "lesskey" and "lessecho" in your current directory.  Test the 
 +   generated programs.
 +
 +7. When satisfied that it works, if you wish to install it
 +   in a public place, type "make install".
 +
 +   The default install destinations are:
 +        Executables (less, lesskey, lessecho) in /usr/local/bin
 +        Documentation (less.nro, lesskey.nro) in /usr/local/man/man1
 +   If you want to install any of these files elsewhere, define
 +   bindir and/or mandir to the appropriate directories.
 +
 +
- Note to hackers: comments noting possible improvements are enclosed
- in double curly brackets {{ like this }}.
- 
- (Note that the above note was originally written at a time when 
- "hackers" most commonly meant "enthusiastic and dedicated computer 
- programmers", not "persons who attempt to circumvent computer security".)
- 
- 
 +
 +=======================================================================
 +INSTALLATION (Windows-95, Windows-98 and Windows-NT systems only,
 +              with Microsoft Visual C++, mingw, or Borland C)
 +
 +1. Move the distributed source to its own directory.
 +
 +2. If you wish, you may edit defines.wn to remove some optional features.
 +   If you choose not to include some features in your version, you may
 +   wish to edit the manual page less.man and the help page help.c
 +   to remove the descriptions of the features which you are removing.
 +
 +3. If you are using Microsoft Visual C++, run "nmake -f Makefile.wnm".
 +   If you are using mingw, run "make -f Makefile.wng".
 +   If you are using Borland C, run "make -f Makefile.wnb".
 +
 +   If the environment variable SECURE_COMPILE is to 1 during the make,
 +   a "secure" version of less is built, with some features disabled.
 +
 +4. If the make succeeds, it will generate the programs "less.exe" and
 +   "lesskey.exe" in your current directory.  Test the generated programs.
 +
 +
 +
 +=======================================================================
 +INSTALLATION (MS-DOS systems only,
 +              with Microsoft C, Borland C, or DJGPP)
 +
 +1. Move the distributed source to its own directory.
 +   Depending on your compiler, you may need to convert the source 
 +   to have CR-LF rather than LF as line terminators.
 +
 +2. If you are using Microsoft C, rename MAKEFILE.DSU to MAKEFILE.
 +   If you are using Borland C, rename MAKEFILE.DSB to MAKEFILE.
 +   If you are using DJGPP, rename MAKEFILE.DSG to MAKEFILE.
 +
 +3. Look at MAKEFILE to make sure that the definitions for CC and LIBDIR
 +   are correct.  CC should be the name of your C compiler and
 +   LIBDIR should be the directory where the C libraries reside (for
 +   Microsoft C only).  If these definitions need to be changed, you can
 +   either modify the definitions directly in MAKEFILE, or set your
 +   environment variables CC and/or LIBDIR to override the definitions
 +   in MAKEFILE.
 +
 +4. If you wish, you may edit DEFINES.DS to remove some optional features.
 +   If you choose not to include some features in your version, you may
 +   wish to edit the manual page LESS.MAN and the help page HELP.C
 +   to remove the descriptions of the features which you are removing.
 +
 +5. Run your "make" program and watch the fun.
 +   If your "make" requires a flag to import environment variables,
 +   you should use that flag.
 +   If your compiler runs out of memory, try running "make -n >cmds.bat" 
 +   and then run cmds.bat.
 +
 +6. If the make succeeds, it will generate the programs "LESS.EXE" and
 +   "LESSKEY.EXE" in your current directory.  Test the generated programs.
 +
 +7. When satisfied that it works, you may wish to install LESS.EXE and
 +   LESSKEY.EXE in a directory which is included in your PATH.
 +
 +
 +
 +=======================================================================
 +INSTALLATION (OS/2 systems only,
 +              with EMX C)
 +
 +1. Move the distributed source to its own directory.
 +
 +2. Rename Makefile.o2e to Makefile.
 +
 +3. Check the Makefile to make sure the definitions look ok.
 +
 +4. If you wish, you may edit defines.o2 to remove some optional features.
 +   If you choose not to include some features in your version, you may
 +   wish to edit the manual page less.man and the help page help.c
 +   to remove the descriptions of the features which you are removing.
 +
 +5. Type "make" and watch the fun.
 +
 +6. If the make succeeds, it will generate the programs "less.exe" and
 +   "lesskey.exe" in your current directory.  Test the generated programs.
 +
 +7. Make sure you have the emx runtime installed. You need the emx DLLs
 +   emx.dll and emxlibcs.dll and also the termcap database, termcap.dat.
 +   Make sure you have termcap.dat either in the default location or
 +   somewhere in a directory listed in the PATH or INIT environment 
 +   variables.
 +
 +8. When satisfied that it works, you may wish to install less.exe,
 +   lesskey.exe and scrsize.exe in a directory which is included in 
 +   your PATH.  scrsize.exe is required only if you use a terminal
 +   emulator such as xterm or rxvt.
 +
 +
 +
 +=======================================================================
 +INSTALLATION (OS-9 systems only,
 +              with Microware C or Ultra C)
 +
 +1. Move the distributed source to its own directory.
 +
 +2. If you are using Microware C, rename Makefile.o9c to Makefile.
 +   If you are using Ultra C, rename Makefile.o9u to Makefile.
 +
 +3. Check the Makefile to make sure the definitions look ok.
 +
 +4. If you wish, you may edit defines.o9 to remove some optional features.
 +   If you choose not to include some features in your version, you may
 +   wish to edit the manual page less.man and the help page help.c
 +   to remove the descriptions of the features which you are removing.
 +
 +5. Type "dmake" and watch the fun.
 +   The standard OS-9 "make" will probably not work.  If you don't
 +   have dmake, you can get a copy from os9archive.rtsi.com.
 +
 +6. If the make succeeds, it will generate the programs "less" and
 +   "lesskey" in your current directory.  Test the generated programs.
 +
 +7. When satisfied that it works, if you wish to install it
 +   in a public place, type "dmake install".
 +   See step 6 of the Unix installation instructions for details
 +   on how to change the default installation directories.
 +
diff --cc contrib/less/command.c
index 1bb8d006f8ec,000000000000..09eb1614c76d
mode 100644,000000..100644
--- a/contrib/less/command.c
+++ b/contrib/less/command.c
@@@ -1,2365 -1,0 +1,2443 @@@
 +/*
 + * Copyright (C) 1984-2026  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 lbool one_screen;
 +extern int sc_width;
 +extern int sc_height;
 +extern char *kent;
++extern lbool kent_mapped;
 +extern int swindow;
 +extern int jump_sline;
 +extern lbool quitting;
 +extern int wscroll;
 +extern int top_scroll;
 +extern lbool ignore_eoi;
 +extern int hshift;
 +extern int bs_mode;
 +extern int proc_backspace;
 +extern int show_attn;
 +extern int less_is_more;
 +extern int chopline;
 +extern POSITION highest_hilite;
 +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 def_search_type;
++extern int hilite_target;
 +extern lbool search_wrapped;
 +extern int no_paste;
 +extern lbool pasting;
 +extern int no_edit_warn;
++extern lbool read_error;
 +extern POSITION soft_eof;
 +extern POSITION search_incr_start;
 +extern char *first_cmd_at_prompt;
++extern lbool prompting;
 +#if SHELL_ESCAPE || PIPEC
 +extern void *ml_shell;
 +#endif
 +#if EDITOR
 +extern constant char *editproto;
 +#endif
 +#if OSC8_LINK
 +extern char *osc8_uri;
 +#endif
 +extern int shift_count;
- extern int forw_prompt;
++extern lbool forw_prompt;
 +extern int incr_search;
- extern int full_screen;
++extern lbool full_screen;
 +#if MSDOS_COMPILER==WIN32C
 +extern int utf_mode;
 +extern unsigned less_acp;
 +#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 lbool opt_lower;
 +static int optflag;
 +static lbool optgetname;
++static POSITION toppos;
 +static POSITION bottompos;
 +static int save_hshift;
 +static int save_bs_mode;
 +static int save_proc_backspace;
 +static int screen_trashed_value = 0;
 +static lbool literal_char = FALSE;
 +static lbool ignoring_input = FALSE;
 +static struct scrpos search_incr_pos = { NULL_POSITION, 0 };
 +static int search_incr_hshift;
 +#if HAVE_TIME
 +static time_type ignoring_input_time;
 +#endif
 +#if PIPEC
 +static char pipec;
 +#endif
 +
 +/* Stack of ungotten chars (via ungetcc) */
 +struct ungot {
 +	struct ungot *ug_next;
 +	char ug_char;
 +	lbool ug_end_command;
 +};
 +static struct ungot* ungot = NULL;
 +
 +static void multi_search(constant 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.
 + */
 +public 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 lbool 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[INT_STRLEN_BOUND(int)+8];
 +			SNPRINTF1(buf, sizeof(buf), "Sub-%d ", i);
 +			cmd_putstr(buf);
 +		}
 +	}
 +	if (literal_char)
 +		cmd_putstr("Lit ");
 +
 +#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;
++	forw_prompt = FALSE;
 +}
 +
 +static void mca_search(void)
 +{
 +	if (incr_search)
 +	{
 +		/* Remember where the incremental search started. */
 +		get_scrpos(&search_incr_pos, TOP);
 +		search_incr_start = search_pos(search_type);
 +		search_incr_hshift = hshift;
 +	}
 +	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 = (optflag & OPT_NO_PROMPT);
 +	int flag = (optflag & ~OPT_NO_PROMPT);
 +	constant char *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;
++	forw_prompt = FALSE;
 +	set_mlist(NULL, CF_OPTION);
 +}
 +
 +/*
 + * Execute a multicharacter command.
 + */
 +static void exec_mca(void)
 +{
 +	constant 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);
 +		soft_eof = NULL_POSITION;
 +		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: {
 +		char *p;
 +		if (!secure_allow(SF_EXAMINE))
 +			break;
 +		p = save(cbuf);
 +		edit_list(p);
 +		free(p);
 +#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 "#").
 +		 */
 +		constant char *done_msg = (*cbuf == CONTROL('P')) ? NULL : "!done";
 +		if (done_msg == NULL)
 +			++cbuf;
 +		if (*cbuf != '!')
 +		{
 +			if (shellcmd != NULL)
 +				free(shellcmd);
 +			shellcmd = fexpand(cbuf);
 +		}
 +		if (!secure_allow(SF_SHELL))
 +			break;
 +		if (shellcmd == NULL)
 +			shellcmd = "";
 +		lsystem(shellcmd, done_msg);
 +		break; }
 +	case A_PSHELL: {
 +		constant char *done_msg = (*cbuf == CONTROL('P')) ? NULL : "#done";
 +		if (done_msg == NULL)
 +			++cbuf;
 +		if (!secure_allow(SF_SHELL))
 +			break;
 +		lsystem(pr_expand(cbuf), done_msg);
 +		break; }
 +#endif
 +#if PIPEC
 +	case A_PIPE: {
 +		constant char *done_msg = (*cbuf == CONTROL('P')) ? NULL : "|done";
 +		if (done_msg == NULL)
 +			++cbuf;
 +		if (!secure_allow(SF_PIPE))
 +			break;
 +		(void) pipe_mark(pipec, cbuf);
 +		if (done_msg != NULL)
 +			error(done_msg, NULL_PARG);
 +		break; }
 +#endif
 +	}
 +}
 +
 +/*
 + * Is a character an erase or kill char?
 + */
 +static lbool is_erase_char(char c)
 +{
 +	return (c == erase_char || c == erase2_char || c == kill_char);
 +}
 +
 +/*
 + * Is a character a carriage return or newline?
 + */
 +static lbool is_newline_char(char c)
 +{
 +	return (c == '\n' || c == '\r');
 +}
 +
 +/*
 + * Handle the first char of an option (after the initial dash).
 + */
 +static int mca_opt_first_char(char 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(char c)
 +{
 +	constant char *p;
 +	constant char *oname;
 +	lbool ambig;
 +	struct loption *was_curropt;
 +
 +	if (curropt != NULL)
 +	{
 +		/* Already have a match for the name. */
 +		if (is_erase_char(c))
 +			return (MCA_DONE);
 +		/* {{ Checking for TAB here is ugly.
 +		 *    Also doesn't extend well -- can't do BACKTAB this way
 +		 *    because it's a multichar sequence. }} */
 +		if (c != '\t') 
 +			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 || p[0] == '\0')
 +		return (MCA_MORE);
 +	opt_lower = ASCII_IS_LOWER(p[0]);
 +	was_curropt = curropt;
 +	curropt = findopt_name(&p, &oname, &ambig);
 +	if (curropt != NULL)
 +	{
 +		if (was_curropt == NULL)
 +		{
 +			/*
 +			 * Got a match.
 +			 * Remember the option and
 +			 * display the full option name.
 +			 */
 +			cmd_reset();
 +			mca_opt_toggle();
 +			cmd_setstring(oname, !opt_lower);
 +		}
 +	} else if (!ambig)
 +	{
 +		lbell();
 +	}
 +	return (MCA_MORE);
 +}
 +
 +/*
 + * Handle a char of an option toggle command.
 + */
 +static int mca_opt_char(char 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 && cmdbuf_empty())
 +	{
 +		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), NULL, CF_OPTION);
 +	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(char 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 (!cmdbuf_empty() || literal_char)
 +	{
 +		lbool was_literal_char = literal_char;
 +		literal_char = FALSE;
 +		if (was_literal_char)
 +			mca_search1();
 +		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[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;
 +	case CONTROL('L'):
 +		literal_char = TRUE;
 +		flag = -1;
 +		break;
 +	}
 +
 +	if (flag != 0)
 +	{
 +		if (flag != -1)
 +			search_type = norm_search_type(search_type ^ flag);
 +		mca_search();
 +		return (MCA_MORE);
 +	}
 +	return (NO_MCA);
 +}
 +
 +/*
 + * Jump back to the starting position of an incremental search.
 + */
 +static void jump_search_incr_pos(void)
 +{
 +	if (search_incr_pos.pos == NULL_POSITION)
 +		return;
 +	hshift = search_incr_hshift;
 +	jump_loc(search_incr_pos.pos, search_incr_pos.ln);
 +}
 +
 +/*
 + * Handle a character of a multi-character command.
 + */
 +static int mca_char(char c)
 +{
 +	int ret;
 +
 +	switch (mca)
*** 3075 LINES SKIPPED ***
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.