From nobody Tue May 2 03:45:11 2023 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4Q9QvW3hJxz48NmW; Tue, 2 May 2023 03:45:11 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4Q9QvW3Sl6z4FBS; Tue, 2 May 2023 03:45:11 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1682999111; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=j2rFI/sga0nvdF+37PNYrAiwkV3CgpZN6HImBnh2kws=; b=SmKEDpgr3pNeFkqIIhClCwiHDnwDdc+a1fZCLnekGv0cTA6WanRNRfc4bcYsGBxDzMpiE9 f/Kv5Fz3cu0S0FIYvekNqU3qQMQ0mF5QcVAOh1wrG/8Vazmo4CgNLHEV+9nHWPptoFQM5J a80puL5vTf5MAtQ3+xFa55tfwLP9lUi4ptKL/7rubcMt2hh9Lh0IjYq6vOorImMqnmudou K5BT5lrjN32E+7C6hTggg3m2PQzGHodx9fXsLrDhbGT4aFB5XfWfOhXTDbdfbY8YdFxunC 4X8AzneGKufbWzKyggASnIzma9eQebkoBBO3oxtDdbxP6QlxHnN3H4cPY7sZQg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1682999111; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=j2rFI/sga0nvdF+37PNYrAiwkV3CgpZN6HImBnh2kws=; b=dXmLMyHDDqavcUz6xT9u6bP5KnjSi3ToIEp31eoRxtKCvQ/5xT3kcz6lCCzRVdRx6fklaf PHVPg5TPO/+bKCGe45U1QLLlNQfwjtybZBEFyj0l/AjK4AynO0G+aJYoUANdq1IpJNJq2C 52TvYRRBoNvD9nla/PZ/8n/OM2XAh8lgGm/5AirrboLnLAdFUBokL61wOXvRZQiS1VDoB0 E7R3BNGkdYwFMS3FjTJ4uVndyCKUkLl2P8KGJdufhT0yN61uuDc3s0KFPuYp2OJ/1C+qWx dxwiEO6YiHDmU4mJtBrk2ybu8Ws3MyGh653fg1MIjYxLGhgk6mae5FNOU+JhHw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1682999111; a=rsa-sha256; cv=none; b=mNWncH4mJF0wH7x++yfvPnKkVOVM2tONWARGpyLXHEvFazOywrEuScRnyhYZujaQsdoWXY GfXnYWe48K3q50q2BrKALeC3W8eE8/K7uXkjoOlMtQUjnW94RLpHyhgYSq+0GrCg2gurRs Npph9wOmcdrciSu8X4KXgPWsXKBWrkHkkJB4uxnJ7YWI6AwPY5GMExHRuK/0wy7UBjrfxp h9PInnThWPL7V2I31dvcLEKlnT7m6DPs/jahiWaFn35GIpU9sU/0vXA+gr8cby7T4D7RKI 8AuLwk7doWaF9ir3KU1ApZHIC3Ido3hRq9pZZE8qMkAhNvgW3dE21P65mYACjQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4Q9QvW2WcczY0B; Tue, 2 May 2023 03:45:11 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 3423jBh8014058; Tue, 2 May 2023 03:45:11 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 3423jB5J014057; Tue, 2 May 2023 03:45:11 GMT (envelope-from git) Date: Tue, 2 May 2023 03:45:11 GMT Message-Id: <202305020345.3423jB5J014057@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Xin LI Subject: git: d713e0891ff9 - main - MFV: less v632. List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-main@freebsd.org X-BeenThere: dev-commits-src-main@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: delphij X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: d713e0891ff9ab8246245c3206851d486ecfdd37 Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by delphij: URL: https://cgit.FreeBSD.org/src/commit/?id=d713e0891ff9ab8246245c3206851d486ecfdd37 commit d713e0891ff9ab8246245c3206851d486ecfdd37 Merge: 83d5725005c5 159d764c1668 Author: Xin LI AuthorDate: 2023-05-02 03:43:57 +0000 Commit: Xin LI CommitDate: 2023-05-02 03:43:57 +0000 MFV: less v632. MFC after: 2 weeks contrib/less/LICENSE | 2 +- contrib/less/NEWS | 79 ++++- contrib/less/brac.c | 9 +- contrib/less/ch.c | 321 ++++++++----------- contrib/less/charset.c | 234 +++++++++----- contrib/less/charset.h | 2 +- contrib/less/cmd.h | 3 +- contrib/less/cmdbuf.c | 211 +++--------- contrib/less/command.c | 200 ++++++------ contrib/less/compose.uni | 14 +- contrib/less/cvt.c | 19 +- contrib/less/decode.c | 144 ++------- contrib/less/edit.c | 357 +++++++++++++++------ contrib/less/filename.c | 137 ++++---- contrib/less/fmt.uni | 4 +- contrib/less/forwback.c | 64 +--- contrib/less/funcs.h | 748 ++++++++++++++++++++++--------------------- contrib/less/help.c | 46 ++- contrib/less/ifile.c | 118 ++----- contrib/less/input.c | 203 +++++++++--- contrib/less/jump.c | 37 +-- contrib/less/less.h | 89 +++-- contrib/less/less.hlp | 44 ++- contrib/less/less.nro | 677 ++++++++++++++++++++++++++------------- contrib/less/lessecho.c | 44 +-- contrib/less/lessecho.nro | 38 +-- contrib/less/lesskey.c | 66 ++-- contrib/less/lesskey.h | 2 +- contrib/less/lesskey.nro | 62 ++-- contrib/less/lesskey_parse.c | 111 ++----- contrib/less/lglob.h | 2 +- contrib/less/line.c | 467 ++++++++++++--------------- contrib/less/linenum.c | 53 ++- contrib/less/lsystem.c | 18 +- contrib/less/main.c | 54 ++-- contrib/less/mark.c | 84 ++--- contrib/less/mkutable | 15 +- contrib/less/optfunc.c | 314 ++++++++---------- contrib/less/option.c | 105 ++---- contrib/less/option.h | 4 +- contrib/less/opttbl.c | 116 +++++-- contrib/less/os.c | 231 +++++++------ contrib/less/output.c | 135 ++++---- contrib/less/pattern.c | 176 +++++----- contrib/less/pattern.h | 10 +- contrib/less/pckeys.h | 2 +- contrib/less/position.c | 41 +-- contrib/less/position.h | 2 +- contrib/less/prompt.c | 78 ++--- contrib/less/screen.c | 562 +++++++++++++++----------------- contrib/less/scrsize.c | 2 +- contrib/less/search.c | 370 ++++++++------------- contrib/less/signal.c | 29 +- contrib/less/tags.c | 87 ++--- contrib/less/ttyin.c | 52 +-- contrib/less/ubin.uni | 16 +- contrib/less/version.c | 31 +- contrib/less/wide.uni | 22 +- contrib/less/xbuf.c | 150 +++++++-- contrib/less/xbuf.h | 7 +- usr.bin/less/defines.h | 24 +- 61 files changed, 3721 insertions(+), 3623 deletions(-) diff --cc contrib/less/command.c index 8bd999e9f7a3,000000000000..88c0cb49ee77 mode 100644,000000..100644 --- a/contrib/less/command.c +++ b/contrib/less/command.c @@@ -1,2099 -1,0 +1,2095 @@@ +/* $FreeBSD$ */ +/* - * Copyright (C) 1984-2022 Mark Nudelman ++ * 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 +#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 LESSPARAMS((char *pattern, int n, int silent)); ++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_PARAM) ++static void cmd_exec(void) +{ + clear_attn(); + clear_bot(); + flush(); +} + +/* + * Indicate we are reading a multi-character command. + */ - static void - set_mca(action) - int action; ++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_PARAM) ++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(action, prompt, mlist, cmdflags) - int action; - constant char *prompt; - void *mlist; - int cmdflags; ++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_PARAM) ++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_PARAM) ++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]; ++ 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_PARAM) ++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_PARAM) ++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_PARAM) ++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(c) - int c; ++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(c) - int c; ++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(c) - int c; ++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(c) - int c; ++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(c) - int c; ++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(st) - int st; ++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(c) - int c; ++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; + 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]; ++ 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) + { - search_type = norm_search_type(search_type ^ flag); ++ 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(c) - int c; ++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)); ++ 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_PARAM) ++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_PARAM) ++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) ++ } 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_PARAM) ++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 && *** 3700 LINES SKIPPED ***