The branch main has been updated by delphij:

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

commit d5cb458b4b58b0f0b3c058a32439f232fd5455ca
Merge: dbb34d496708 a1320769a9f7
Author:     Xin LI <[email protected]>
AuthorDate: 2025-11-10 08:55:06 +0000
Commit:     Xin LI <[email protected]>
CommitDate: 2025-11-10 08:55:06 +0000

    MFV: less v685.
    
    MFC after:      3 days

 contrib/less/NEWS         |  39 ++++++++++++++++
 contrib/less/ch.c         |   4 --
 contrib/less/charset.c    |  48 +++++++++++++++++---
 contrib/less/command.c    |  40 +++++++++++++++++
 contrib/less/compose.uni  |   4 +-
 contrib/less/decode.c     |  11 +++--
 contrib/less/edit.c       |  10 +++--
 contrib/less/fmt.uni      |   6 +--
 contrib/less/forwback.c   |   2 +-
 contrib/less/funcs.h      |  12 ++++-
 contrib/less/help.c       |   2 +-
 contrib/less/input.c      |  72 +++++++++++++++++-------------
 contrib/less/less.h       |   5 ++-
 contrib/less/less.nro     | 110 ++++++++++++++++++++++++++++++++++++----------
 contrib/less/lessecho.nro |   6 +--
 contrib/less/lesskey.nro  |  18 +++++---
 contrib/less/lglob.h      |   2 +-
 contrib/less/line.c       | 106 +++++++++++++++++++++++++++++++++++++++-----
 contrib/less/lsystem.c    |   2 +-
 contrib/less/main.c       |  41 ++++++++++++-----
 contrib/less/mkutable     |  21 ++++++++-
 contrib/less/omit.uni     |   7 +++
 contrib/less/optfunc.c    |  18 ++++++++
 contrib/less/opttbl.c     |   6 +++
 contrib/less/os.c         |  51 ++++++++++++++++++---
 contrib/less/pattern.c    |   7 ++-
 contrib/less/screen.c     |  30 +++++++++++++
 contrib/less/search.c     |  12 +++--
 contrib/less/ubin.uni     |   2 +-
 contrib/less/version.c    |  14 +++++-
 contrib/less/wide.uni     |   8 ++--
 contrib/less/xbuf.c       |   2 +-
 usr.bin/less/defines.h    |  18 ++++++--
 33 files changed, 596 insertions(+), 140 deletions(-)

diff --cc contrib/less/command.c
index 3ec1f9b48358,000000000000..390385547385
mode 100644,000000..100644
--- a/contrib/less/command.c
+++ b/contrib/less/command.c
@@@ -1,2320 -1,0 +1,2360 @@@
 +/*
 + * Copyright (C) 1984-2025  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 sc_width;
 +extern int sc_height;
 +extern char *kent;
 +extern int swindow;
 +extern int jump_sline;
 +extern lbool quitting;
 +extern int wscroll;
 +extern int top_scroll;
 +extern int 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 lbool search_wrapped;
++extern lbool no_poll;
 +extern int no_paste;
 +extern lbool pasting;
 +extern int no_edit_warn;
 +extern POSITION soft_eof;
++extern POSITION search_incr_start;
++extern char *first_cmd_at_prompt;
 +#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 int incr_search;
 +extern int 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 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 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[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;
 +}
 +
 +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;
 +      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)
 +      {
 +              bell();
 +      }
 +      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)
 +      {
 +              literal_char = FALSE;
 +              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);
 +}
 +
 +/*
 + * Handle a character of a multi-character command.
 + */
 +static int mca_char(char 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))
 +      {
 +              if (pasting && no_paste)
 +              {
 +                      /* Ignore pasted input after (and including) the first 
newline */
 +                      start_ignoring_input();
 +                      return (MCA_MORE);
 +              }
 +              /* 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));
 +                      ssize_t save_updown;
 +                      constant char *pattern = get_cmdbuf();
 +                      if (pattern == NULL)
 +                              return (MCA_MORE);
++                      /* Defer searching if more chars of the pattern are 
available. */
++                      if (ttyin_ready())
++                              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. }}
 +                       */
 +                      save_updown = save_updown_match();
 +                      cmd_exec();
 +                      if (*pattern == '\0')
 +                      {
 +                              /* User has backspaced to an empty pattern. */
 +                              undo_search(1);
++                              hshift = search_incr_hshift;
++                              jump_loc(search_incr_pos.pos, 
search_incr_pos.ln);
 +                      } else
 +                      {
++                              /*
++                               * Suppress tty polling while searching.
++                               * This avoids a problem where tty input
++                               * can cause the search to be interrupted.
++                               */
++                              no_poll = TRUE;
 +                              if (search(st | SRCH_INCR, pattern, 1) != 0)
++                              {
 +                                      /* No match, invalid pattern, etc. */
 +                                      undo_search(1);
++                                      hshift = search_incr_hshift;
++                                      jump_loc(search_incr_pos.pos, 
search_incr_pos.ln);
++                              }
++                              no_poll = FALSE;
 +                      }
 +                      /* Redraw the search prompt and search string. */
 +                      if (is_screen_trashed() || !full_screen)
 +                      {
 +                              clear();
 +                              repaint();
 +                      }
 +                      mca_search1();
 +                      restore_updown_match(save_updown);
 +                      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
++      set_line_contig_pos(NULL_POSITION);
 +}
 +
 +public void screen_trashed_num(int trashed)
 +{
 +      screen_trashed_value = trashed;
 +}
 +
 +public void screen_trashed(void)
 +{
 +      screen_trashed_num(1);
 +}
 +
 +public int is_screen_trashed(void)
 +{
 +      return screen_trashed_value;
 +}
 +
 +/*
 + * 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 (is_screen_trashed() || !full_screen)
 +      {
 +              int save_top_scroll = top_scroll;
 +              int save_ignore_eoi = ignore_eoi;
 +              top_scroll = 1;
 +              ignore_eoi = 0;
 +              if (is_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_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(FALSE) && !(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 (first_cmd_at_prompt != NULL)
++      {
++              ungetsc(first_cmd_at_prompt);
++              first_cmd_at_prompt = NULL;
++              return;
++      }
 +
 +#if MSDOS_COMPILER==WIN32C
 +      /* 
 +       * In Win32, display the file name in the window title.
 +       */
*** 2619 LINES SKIPPED ***

Reply via email to