git: 252d6dde57d5 - main - MFV: less v678.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 20 May 2025 03:47:40 UTC
The branch main has been updated by delphij: URL: https://cgit.FreeBSD.org/src/commit/?id=252d6dde57d5dd0184929d1f8fb65e7713f51c6d commit 252d6dde57d5dd0184929d1f8fb65e7713f51c6d Merge: 9b5ddb2accfc 48b0a08b8724 Author: Xin LI <delphij@FreeBSD.org> AuthorDate: 2025-05-20 03:44:02 +0000 Commit: Xin LI <delphij@FreeBSD.org> CommitDate: 2025-05-20 03:44:02 +0000 MFV: less v678. MFC after: 2 weeks contrib/less/LICENSE | 2 +- contrib/less/NEWS | 73 ++++++++++ contrib/less/brac.c | 2 +- contrib/less/ch.c | 55 ++++++-- contrib/less/charset.c | 36 +++-- contrib/less/charset.h | 2 +- contrib/less/cmd.h | 9 +- contrib/less/cmdbuf.c | 189 +++++++++++++++++++------- contrib/less/command.c | 206 ++++++++++++++++++++-------- contrib/less/compose.uni | 19 ++- contrib/less/cvt.c | 2 +- contrib/less/decode.c | 315 ++++++++++++++++++++++++------------------- contrib/less/edit.c | 7 +- contrib/less/evar.c | 6 +- contrib/less/filename.c | 6 +- contrib/less/fmt.uni | 2 +- contrib/less/forwback.c | 163 +++++++++++----------- contrib/less/funcs.h | 51 ++++--- contrib/less/help.c | 12 +- contrib/less/ifile.c | 2 +- contrib/less/input.c | 48 ++++--- contrib/less/jump.c | 27 ++-- contrib/less/lang.h | 2 +- contrib/less/less.h | 41 +++--- contrib/less/less.hlp | 10 ++ contrib/less/less.nro | 212 +++++++++++++++++++---------- contrib/less/lessecho.c | 2 +- contrib/less/lessecho.nro | 6 +- contrib/less/lesskey.c | 2 +- contrib/less/lesskey.h | 2 +- contrib/less/lesskey.nro | 23 +++- contrib/less/lesskey_parse.c | 9 +- contrib/less/lglob.h | 2 +- contrib/less/line.c | 279 +++++++++++++++++++++++++++++--------- contrib/less/linenum.c | 24 ++-- contrib/less/lsystem.c | 2 +- contrib/less/main.c | 33 +++-- contrib/less/mark.c | 2 +- contrib/less/mkutable | 7 +- contrib/less/optfunc.c | 25 +++- contrib/less/option.c | 80 +++++------ contrib/less/option.h | 26 ++-- contrib/less/opttbl.c | 231 ++++++++++++++++++++----------- contrib/less/os.c | 115 ++++++++++++---- contrib/less/output.c | 19 +-- contrib/less/pattern.c | 52 ++++--- contrib/less/pattern.h | 2 +- contrib/less/pckeys.h | 2 +- contrib/less/position.c | 15 ++- contrib/less/position.h | 3 +- contrib/less/prompt.c | 11 +- contrib/less/screen.c | 120 +++++++++++------ contrib/less/scrsize.c | 2 +- contrib/less/search.c | 184 ++++++++++--------------- contrib/less/signal.c | 55 ++++++-- contrib/less/tags.c | 2 +- contrib/less/ttyin.c | 8 +- contrib/less/ubin.uni | 2 +- contrib/less/version.c | 19 ++- contrib/less/wide.uni | 22 +-- usr.bin/less/defines.h | 15 ++- 61 files changed, 1903 insertions(+), 999 deletions(-) diff --cc contrib/less/command.c index 27eba082e520,000000000000..3ec1f9b48358 mode 100644,000000..100644 --- a/contrib/less/command.c +++ b/contrib/less/command.c @@@ -1,2226 -1,0 +1,2320 @@@ - /* $FreeBSD$ */ +/* - * Copyright (C) 1984-2024 Mark Nudelman ++ * 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 int quitting; ++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 int no_paste; ++extern lbool pasting; ++extern int no_edit_warn; ++extern POSITION soft_eof; +#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 int opt_lower; ++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; ++#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. + */ - static void cmd_exec(void) ++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) +{ + 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, 0); ++ set_mlist(NULL, CF_OPTION); +} + +/* + * Execute a multicharacter command. + */ +static void exec_mca(void) +{ + constant char *cbuf; - char *p; + + 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: ++ 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; ++ 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. - * Don't accept anything but erase/kill. - */ ++ /* Already have a match for the name. */ + if (is_erase_char(c)) + return (MCA_DONE); - return (MCA_MORE); ++ /* {{ 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) ++ 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) + { - /* - * Got a match. - * Remember the option and - * display the full option name. - */ - cmd_reset(); - mca_opt_toggle(); - for (p = oname; *p != '\0'; p++) ++ if (was_curropt == NULL) + { - c = *p; - if (!opt_lower && ASCII_IS_LOWER(c)) - c = ASCII_TO_UPPER(c); - if (cmd_char(c) != CC_OK) - return (MCA_DONE); ++ /* ++ * 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 && len_cmdbuf() == 0) ++ 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, 0); ++ 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 (len_cmdbuf() > 0 || literal_char) ++ 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)) + { - /* - * Execute the command. - */ ++ 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); + /* + * 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); + } 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 (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 +} + +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; + } + *** 2968 LINES SKIPPED ***