From: JinWang An Date: Wed, 28 Dec 2022 07:13:18 +0000 (+0900) Subject: Imported Upstream version 551 X-Git-Tag: upstream/551^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c9e9cd2ae9c255dfad728f7578342bf6d3688d2b;p=platform%2Fupstream%2Fless.git Imported Upstream version 551 --- diff --git a/LICENSE b/LICENSE index 832ca1b..315d1d8 100644 --- a/LICENSE +++ b/LICENSE @@ -2,7 +2,7 @@ ------------ Less -Copyright (C) 1984-2016 Mark Nudelman +Copyright (C) 1984-2018 Mark Nudelman Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions diff --git a/Makefile.aut b/Makefile.aut index 8816902..f16642c 100644 --- a/Makefile.aut +++ b/Makefile.aut @@ -112,6 +112,13 @@ ubin.uni: unicode/UnicodeData.txt wide.uni: unicode/EastAsianWidth.txt ./mkutable -f1 W F -- unicode/EastAsianWidth.txt > $@ +unicode/UnicodeData.txt: + mkdir -p unicode + curl -s -o $@ ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt +unicode/EastAsianWidth.txt: + mkdir -p unicode + curl -s -o $@ ftp://ftp.unicode.org/Public/UNIDATA/EastAsianWidth.txt + distfiles: ${DISTFILES} dist: ${DISTFILES} @@ -137,4 +144,4 @@ dist: ${DISTFILES} tagall: @REL=`sed -e '/char version/!d' -e 's/[^0-9.]*\([0-9.]*\).*/v\1/' -e q ${srcdir}/version.c`; \ echo "tagging $$REL"; \ - $(GIT) tag -f "$$REL" + $(GIT) tag -a -f -m "$$REL" "$$REL" diff --git a/NEWS b/NEWS index 14997c2..24d74af 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,38 @@ ====================================================================== + Major changes between "less" versions 530 and 551 + +* Add --mouse option. + +* Add --wheel-lines option. + +* Add --no-histdups option. + +* Add --save-marks option. + +* Support PCRE2 regular expression library. + +* Redraw screen on SIGWINCH even if screen size doesn't change. + +* Shell-escape filenames in history so they can be used again. + +* Ring bell if user enters invalid long option name. + +* Use PCRE_UTF8 flag for pcre regular expressions when in UTF-8 mode. + +* Windows: use wide-char string to set console title. + +* Don't count lines in initial screen if using -X with -F. + +* Support mingw build system. + +* Fix bug in v command on empty file. + +* Fix bug in v command when filename contains shell metacharacters. + +====================================================================== + Major changes between "less" versions 487 and 530 * Don't output terminal init sequence if using -F and file fits on one screen. diff --git a/README b/README index 9103598..682cdc5 100644 --- a/README +++ b/README @@ -1,7 +1,7 @@ - Less, version 530 + Less, version 551 - This is the distribution of less, version 530, released 05 Dec 2017. + This is the distribution of less, version 551, released 11 Jun 2019. This program is part of the GNU project (http://www.gnu.org). This program is free software. You may redistribute it and/or @@ -48,6 +48,7 @@ INSTALLATION (Unix systems only): 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. @@ -55,6 +56,7 @@ INSTALLATION (Unix systems only): 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 diff --git a/brac.c b/brac.c index 44f2403..cea4a2b 100644 --- a/brac.c +++ b/brac.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. diff --git a/ch.c b/ch.c index 47c1a32..636f68f 100644 --- a/ch.c +++ b/ch.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -144,7 +144,7 @@ static int ch_addbuf(); * Get the character pointed to by the read pointer. */ int -ch_get() +ch_get(VOID_PARAM) { struct buf *bp; struct bufnode *bn; @@ -392,7 +392,7 @@ ch_ungetchar(c) * If we haven't read all of standard input into it, do that now. */ public void -end_logfile() +end_logfile(VOID_PARAM) { static int tried = FALSE; @@ -417,7 +417,7 @@ end_logfile() * Write all the existing buffered data to the log file. */ public void -sync_logfile() +sync_logfile(VOID_PARAM) { struct buf *bp; struct bufnode *bn; @@ -515,7 +515,7 @@ ch_seek(pos) * Seek to the end of the file. */ public int -ch_end_seek() +ch_end_seek(VOID_PARAM) { POSITION len; @@ -542,7 +542,7 @@ ch_end_seek() * Seek to the last position in the file that is currently buffered. */ public int -ch_end_buffer_seek() +ch_end_buffer_seek(VOID_PARAM) { struct buf *bp; struct bufnode *bn; @@ -570,7 +570,7 @@ ch_end_buffer_seek() * beginning of the pipe is no longer buffered. */ public int -ch_beg_seek() +ch_beg_seek(VOID_PARAM) { struct bufnode *bn; struct bufnode *firstbn; @@ -602,7 +602,7 @@ ch_beg_seek() * Return the length of the file, if known. */ public POSITION -ch_length() +ch_length(VOID_PARAM) { if (thisfile == NULL) return (NULL_POSITION); @@ -619,7 +619,7 @@ ch_length() * Return the current position in the file. */ public POSITION -ch_tell() +ch_tell(VOID_PARAM) { if (thisfile == NULL) return (NULL_POSITION); @@ -630,7 +630,7 @@ ch_tell() * Get the current char and post-increment the read pointer. */ public int -ch_forw_get() +ch_forw_get(VOID_PARAM) { int c; @@ -653,7 +653,7 @@ ch_forw_get() * Pre-decrement the read pointer and get the new current char. */ public int -ch_back_get() +ch_back_get(VOID_PARAM) { if (thisfile == NULL) return (EOI); @@ -693,7 +693,7 @@ ch_setbufspace(bufspace) * Flush (discard) any saved file state, including buffer contents. */ public void -ch_flush() +ch_flush(VOID_PARAM) { struct bufnode *bn; @@ -760,7 +760,7 @@ ch_flush() * The buffer is added to the tail of the buffer chain. */ static int -ch_addbuf() +ch_addbuf(VOID_PARAM) { struct buf *bp; struct bufnode *bn; @@ -785,7 +785,7 @@ ch_addbuf() * */ static void -init_hashtbl() +init_hashtbl(VOID_PARAM) { int h; @@ -800,7 +800,7 @@ init_hashtbl() * Delete all buffers for this file. */ static void -ch_delbufs() +ch_delbufs(VOID_PARAM) { struct bufnode *bn; @@ -840,7 +840,7 @@ seekable(f) * This is used after an ignore_eof read, during which the EOF may change. */ public void -ch_set_eof() +ch_set_eof(VOID_PARAM) { ch_fsize = ch_fpos; } @@ -890,7 +890,7 @@ ch_init(f, flags) * Close a filestate. */ public void -ch_close() +ch_close(VOID_PARAM) { int keepstate = FALSE; @@ -933,7 +933,7 @@ ch_close() * Return ch_flags for the current file. */ public int -ch_getflags() +ch_getflags(VOID_PARAM) { if (thisfile == NULL) return (0); diff --git a/charset.c b/charset.c index 8897891..5441952 100644 --- a/charset.c +++ b/charset.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -245,7 +245,7 @@ icharset(name, no_error) * Define a charset, given a locale name. */ static void -ilocale() +ilocale(VOID_PARAM) { int c; @@ -315,7 +315,7 @@ setfmt(s, fmtvarptr, attrptr, default_fmt) * */ static void -set_charset() +set_charset(VOID_PARAM) { char *s; @@ -338,7 +338,7 @@ set_charset() * LESSCHARSET is not defined: try LESSCHARDEF. */ s = lgetenv("LESSCHARDEF"); - if (s != NULL && *s != '\0') + if (!isnullenv(s)) { ichardef(s); return; @@ -395,7 +395,7 @@ set_charset() * Initialize charset data structures. */ public void -init_charset() +init_charset(VOID_PARAM) { char *s; diff --git a/charset.h b/charset.h index 1e3f069..5003091 100644 --- a/charset.h +++ b/charset.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. diff --git a/cmd.h b/cmd.h index 632b65e..8ea1783 100644 --- a/cmd.h +++ b/cmd.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -71,6 +71,13 @@ #define A_RRSHIFT 59 #define A_CLRMARK 62 #define A_SETMARKBOT 63 +#define A_X11MOUSE_IN 64 +#define A_X11MOUSE_IGNORE 65 +#define A_F_MOUSE 66 +#define A_B_MOUSE 67 +/* Note "X116" refers to extended (1006) X11 mouse reporting. */ +#define A_X116MOUSE_IN 68 +#define A_X116MOUSE_IGNORE 69 #define A_INVALID 100 #define A_NOACTION 101 diff --git a/cmdbuf.c b/cmdbuf.c index db5b259..0648aec 100644 --- a/cmdbuf.c +++ b/cmdbuf.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -22,6 +22,8 @@ extern int sc_width; extern int utf_mode; +extern int no_hist_dups; +extern int marks_modified; static char cmdbuf[CMDBUF_SIZE]; /* Buffer for holding a multi-char command */ static int cmd_col; /* Current column of the cursor */ @@ -58,6 +60,7 @@ public char closequote = '"'; #define HISTFILE_FIRST_LINE ".less-history-file:" #define HISTFILE_SEARCH_SECTION ".search" #define HISTFILE_SHELL_SECTION ".shell" +#define HISTFILE_MARK_SECTION ".mark" /* * A mlist structure represents a command history. @@ -114,7 +117,7 @@ static int cmd_mbc_buf_index; * Reset command buffer (to empty). */ public void -cmd_reset() +cmd_reset(VOID_PARAM) { cp = cmdbuf; *cp = '\0'; @@ -129,7 +132,7 @@ cmd_reset() * Clear command line. */ public void -clear_cmd() +clear_cmd(VOID_PARAM) { cmd_col = prompt_col = 0; cmd_mbc_buf_len = 0; @@ -169,7 +172,7 @@ cmd_putstr(s) * How many characters are in the command buffer? */ public int -len_cmdbuf() +len_cmdbuf(VOID_PARAM) { char *s = cmdbuf; char *endline = s + strlen(s); @@ -302,7 +305,7 @@ cmd_repaint(old_cp) * and set cp to the corresponding char in cmdbuf. */ static void -cmd_home() +cmd_home(VOID_PARAM) { while (cmd_col > prompt_col) { @@ -321,7 +324,7 @@ cmd_home() * Shift the cmdbuf display left a half-screen. */ static void -cmd_lshift() +cmd_lshift(VOID_PARAM) { char *s; char *save_cp; @@ -359,7 +362,7 @@ cmd_lshift() * Shift the cmdbuf display right a half-screen. */ static void -cmd_rshift() +cmd_rshift(VOID_PARAM) { char *s; char *save_cp; @@ -389,7 +392,7 @@ cmd_rshift() * Move cursor right one character. */ static int -cmd_right() +cmd_right(VOID_PARAM) { char *pr; char *ncp; @@ -424,7 +427,7 @@ cmd_right() * Move cursor left one character. */ static int -cmd_left() +cmd_left(VOID_PARAM) { char *ncp; int width = 0; @@ -492,7 +495,7 @@ cmd_ichar(cs, clen) * Delete the char to the left of the cursor. */ static int -cmd_erase() +cmd_erase(VOID_PARAM) { char *s; int clen; @@ -541,7 +544,7 @@ cmd_erase() * Delete the char under the cursor. */ static int -cmd_delete() +cmd_delete(VOID_PARAM) { if (*cp == '\0') { @@ -560,7 +563,7 @@ cmd_delete() * Delete the "word" to the left of the cursor. */ static int -cmd_werase() +cmd_werase(VOID_PARAM) { if (cp > cmdbuf && cp[-1] == ' ') { @@ -586,7 +589,7 @@ cmd_werase() * Delete the "word" under the cursor. */ static int -cmd_wdelete() +cmd_wdelete(VOID_PARAM) { if (*cp == ' ') { @@ -612,7 +615,7 @@ cmd_wdelete() * Delete all chars in the command buffer. */ static int -cmd_kill() +cmd_kill(VOID_PARAM) { if (cmdbuf[0] == '\0') { @@ -702,6 +705,7 @@ cmd_updown(action) s = ml->string; if (s == NULL) s = ""; + cmd_offset = 0; cmd_home(); clear_eol(); strcpy(cmdbuf, s); @@ -719,6 +723,31 @@ cmd_updown(action) #endif /* + * + */ + static void +ml_link(mlist, ml) + struct mlist *mlist; + struct mlist *ml; +{ + ml->next = mlist; + ml->prev = mlist->prev; + mlist->prev->next = ml; + mlist->prev = ml; +} + +/* + * + */ + static void +ml_unlink(ml) + struct mlist *ml; +{ + ml->prev->next = ml->next; + ml->next->prev = ml->prev; +} + +/* * Add a string to an mlist. */ public void @@ -736,6 +765,21 @@ cmd_addhist(mlist, cmd, modified) if (strlen(cmd) == 0) return; + if (no_hist_dups) + { + struct mlist *next = NULL; + for (ml = mlist->next; ml->string != NULL; ml = next) + { + next = ml->next; + if (strcmp(ml->string, cmd) == 0) + { + ml_unlink(ml); + free(ml->string); + free(ml); + } + } + } + /* * Save the command unless it's a duplicate of the * last command in the history. @@ -750,10 +794,7 @@ cmd_addhist(mlist, cmd, modified) ml = (struct mlist *) ecalloc(1, sizeof(struct mlist)); ml->string = save(cmd); ml->modified = modified; - ml->next = mlist; - ml->prev = mlist->prev; - mlist->prev->next = ml; - mlist->prev = ml; + ml_link(mlist, ml); } /* * Point to the cmd just after the just-accepted command. @@ -768,13 +809,13 @@ cmd_addhist(mlist, cmd, modified) * Add it to the currently selected history list. */ public void -cmd_accept() +cmd_accept(VOID_PARAM) { #if CMD_HISTORY /* * Nothing to do if there is no currently selected history list. */ - if (curr_mlist == NULL) + if (curr_mlist == NULL || curr_mlist == ml_examine) return; cmd_addhist(curr_mlist, cmdbuf, 1); curr_mlist->modified = 1; @@ -799,7 +840,7 @@ cmd_edit(c) #if TAB_COMPLETE_FILENAME #define not_in_completion() in_completion = 0 #else -#define not_in_completion() +#define not_in_completion(VOID_PARAM) #endif /* @@ -934,7 +975,7 @@ cmd_istr(str) * cursor at the end of the word. */ static char * -delimit_word() +delimit_word(VOID_PARAM) { char *word; #if SPACES_IN_FILENAMES @@ -1021,7 +1062,7 @@ delimit_word() * which start with that word, and set tk_text to that list. */ static void -init_compl() +init_compl(VOID_PARAM) { char *word; char c; @@ -1148,9 +1189,9 @@ cmd_complete(action) tk_trial = next_compl(action, tk_trial); } - /* - * Remove the original word, or the previous trial completion. - */ + /* + * Remove the original word, or the previous trial completion. + */ while (cp > tk_ipoint) (void) cmd_erase(); @@ -1323,7 +1364,7 @@ cmd_int(frac) * Return a pointer to the command buffer. */ public char * -get_cmdbuf() +get_cmdbuf(VOID_PARAM) { return (cmdbuf); } @@ -1333,7 +1374,7 @@ get_cmdbuf() * Return the last (most recent) string in the current command history. */ public char * -cmd_lastpattern() +cmd_lastpattern(VOID_PARAM) { if (curr_mlist == NULL) return (NULL); @@ -1358,7 +1399,7 @@ mlist_size(ml) * Get the name of the history file. */ static char * -histfile_name() +histfile_name(VOID_PARAM) { char *home; char *name; @@ -1366,7 +1407,7 @@ histfile_name() /* See if filename is explicitly specified by $LESSHISTFILE. */ name = lgetenv("LESSHISTFILE"); - if (name != NULL && *name != '\0') + if (!isnullenv(name)) { if (strcmp(name, "-") == 0 || strcmp(name, "/dev/null") == 0) /* $LESSHISTFILE == "-" means don't use a history file. */ @@ -1380,11 +1421,11 @@ histfile_name() /* Otherwise, file is in $HOME. */ home = lgetenv("HOME"); - if (home == NULL || *home == '\0') + if (isnullenv(home)) { #if OS2 home = lgetenv("INIT"); - if (home == NULL || *home == '\0') + if (isnullenv(home)) #endif return (NULL); } @@ -1447,6 +1488,9 @@ read_cmdhist2(action, uparam, skip_search, skip_shell) ml = NULL; skip = NULL; #endif + } else if (strcmp(line, HISTFILE_MARK_SECTION) == 0) + { + ml = NULL; } else if (*line == '"') { if (ml != NULL) @@ -1456,6 +1500,9 @@ read_cmdhist2(action, uparam, skip_search, skip_shell) else (*action)(uparam, ml, line+1); } + } else if (*line == 'm') + { + (*action)(uparam, NULL, line); } } fclose(f); @@ -1475,9 +1522,10 @@ read_cmdhist(action, uparam, skip_search, skip_shell) static void addhist_init(void *uparam, struct mlist *ml, char *string) { - if (ml == NULL || string == NULL) - return; - cmd_addhist(ml, string, 0); + if (ml != NULL) + cmd_addhist(ml, string, 0); + else if (string != NULL) + restore_mark(string); } #endif /* CMD_HISTORY */ @@ -1485,7 +1533,7 @@ addhist_init(void *uparam, struct mlist *ml, char *string) * Initialize history from a .lesshist file. */ public void -init_cmdhist() +init_cmdhist(VOID_PARAM) { #if CMD_HISTORY read_cmdhist(&addhist_init, NULL, 0, 0); @@ -1558,7 +1606,7 @@ copy_hist(void *uparam, struct mlist *ml, char *string) { struct save_ctx *ctx = (struct save_ctx *) uparam; - if (ml != ctx->mlist) { + if (ml != NULL && ml != ctx->mlist) { /* We're changing mlists. */ if (ctx->mlist) /* Append any new entries to the end of the current mlist. */ @@ -1567,12 +1615,8 @@ copy_hist(void *uparam, struct mlist *ml, char *string) ctx->mlist = ml; write_mlist_header(ctx->mlist, ctx->fout); } - if (string != NULL) - { - /* Copy the entry. */ - fprintf(ctx->fout, "\"%s\n", string); - } - if (ml == NULL) /* End of file */ + + if (string == NULL) /* End of file */ { /* Write any sections that were not in the original file. */ if (mlist_search.modified) @@ -1587,7 +1631,12 @@ copy_hist(void *uparam, struct mlist *ml, char *string) write_mlist(&mlist_shell, ctx->fout); } #endif + } else if (ml != NULL) + { + /* Copy mlist entry. */ + fprintf(ctx->fout, "\"%s\n", string); } + /* Skip marks */ } #endif /* CMD_HISTORY */ @@ -1616,7 +1665,7 @@ make_file_private(f) * Does the history file need to be updated? */ static int -histfile_modified() +histfile_modified(VOID_PARAM) { if (mlist_search.modified) return 1; @@ -1624,6 +1673,10 @@ histfile_modified() if (mlist_shell.modified) return 1; #endif +#if CMD_HISTORY + if (marks_modified) + return 1; +#endif return 0; } @@ -1631,7 +1684,7 @@ histfile_modified() * Update the .lesshst file. */ public void -save_cmdhist() +save_cmdhist(VOID_PARAM) { #if CMD_HISTORY char *histname; @@ -1665,7 +1718,8 @@ save_cmdhist() fprintf(fout, "%s\n", HISTFILE_FIRST_LINE); ctx.fout = fout; ctx.mlist = NULL; - read_cmdhist(copy_hist, &ctx, skip_search, skip_shell); + read_cmdhist(©_hist, &ctx, skip_search, skip_shell); + save_marks(fout, HISTFILE_MARK_SECTION); fclose(fout); #if MSDOS_COMPILER==WIN32C /* diff --git a/command.c b/command.c index 4338b3d..6c89ca3 100644 --- a/command.c +++ b/command.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -47,6 +47,7 @@ extern struct scrpos initial_scrpos; extern IFILE curr_ifile; extern void *ml_search; extern void *ml_examine; +extern int wheel_lines; #if SHELL_ESCAPE || PIPEC extern void *ml_shell; #endif @@ -58,6 +59,9 @@ extern int screen_trashed; /* The screen has been overwritten */ extern int shift_count; extern int oldbot; extern int forw_prompt; +#if MSDOS_COMPILER==WIN32C +extern int utf_mode; +#endif #if SHELL_ESCAPE static char *shellcmd = NULL; /* For holding last shell command for "!!" */ @@ -92,14 +96,39 @@ static void multi_search(); * updating the screen. */ static void -cmd_exec() +cmd_exec(VOID_PARAM) { - clear_attn(); + clear_attn(); clear_bot(); flush(); } /* + * Indicate we are reading a multi-character command. + */ + static void +set_mca(action) + int action; +{ + mca = action; + deinit_mouse(); /* we don't want mouse events while entering a cmd */ + clear_bot(); + clear_cmd(); +} + +/* + * Indicate we are not reading a multi-character command. + */ + static void +clear_mca(VOID_PARAM) +{ + if (mca == 0) + return; + mca = 0; + init_mouse(); +} + +/* * Set up the display to start a new multi-character command. */ static void @@ -109,15 +138,13 @@ start_mca(action, prompt, mlist, cmdflags) void *mlist; int cmdflags; { - mca = action; - clear_bot(); - clear_cmd(); + set_mca(action); cmd_putstr(prompt); set_mlist(mlist, cmdflags); } public int -in_mca() +in_mca(VOID_PARAM) { return (mca != 0 && mca != A_PREFIX); } @@ -126,20 +153,17 @@ in_mca() * Set up the display to start a new search command. */ static void -mca_search() +mca_search(VOID_PARAM) { #if HILITE_SEARCH if (search_type & SRCH_FILTER) - mca = A_FILTER; + set_mca(A_FILTER); else #endif if (search_type & SRCH_FORW) - mca = A_F_SEARCH; + set_mca(A_F_SEARCH); else - mca = A_B_SEARCH; - - clear_bot(); - clear_cmd(); + set_mca(A_B_SEARCH); if (search_type & SRCH_NO_MATCH) cmd_putstr("Non-match "); @@ -169,7 +193,7 @@ mca_search() * Set up the display to start a new toggle-option command. */ static void -mca_opt_toggle() +mca_opt_toggle(VOID_PARAM) { int no_prompt; int flag; @@ -179,9 +203,7 @@ mca_opt_toggle() flag = (optflag & ~OPT_NO_PROMPT); dash = (flag == OPT_NO_TOGGLE) ? "_" : "-"; - mca = A_OPT_TOGGLE; - clear_bot(); - clear_cmd(); + set_mca(A_OPT_TOGGLE); cmd_putstr(dash); if (optgetname) cmd_putstr(dash); @@ -204,7 +226,7 @@ mca_opt_toggle() * Execute a multicharacter command. */ static void -exec_mca() +exec_mca(VOID_PARAM) { char *cbuf; @@ -371,6 +393,7 @@ mca_opt_nonfirst_char(c) { char *p; char *oname; + int err; if (curropt != NULL) { @@ -390,7 +413,8 @@ mca_opt_nonfirst_char(c) return (MCA_DONE); p = get_cmdbuf(); opt_lower = ASCII_IS_LOWER(p[0]); - curropt = findopt_name(&p, &oname, NULL); + err = 0; + curropt = findopt_name(&p, &oname, &err); if (curropt != NULL) { /* @@ -408,6 +432,9 @@ mca_opt_nonfirst_char(c) if (cmd_char(c) != CC_OK) return (MCA_DONE); } + } else if (err != OPT_AMBIG) + { + bell(); } return (MCA_MORE); } @@ -459,6 +486,7 @@ mca_opt_char(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 @@ -468,7 +496,7 @@ mca_opt_char(c) if ((optflag & ~OPT_NO_PROMPT) != OPT_TOGGLE || !opt_has_param(curropt)) { - toggle_option(curropt, ASCII_IS_LOWER(c), "", optflag); + toggle_option(curropt, opt_lower, "", optflag); return (MCA_DONE); } /* @@ -571,7 +599,7 @@ mca_char(c) * as a normal command character. */ number = cmd_int(&fraction); - mca = 0; + clear_mca(); cmd_accept(); return (NO_MCA); } @@ -638,7 +666,7 @@ mca_char(c) * Discard any buffered file data. */ static void -clear_buffers() +clear_buffers(VOID_PARAM) { if (!(ch_getflags() & CH_CANSEEK)) return; @@ -653,7 +681,7 @@ clear_buffers() * Make sure the screen is displayed. */ static void -make_display() +make_display(VOID_PARAM) { /* * If nothing is displayed yet, display starting from initial_scrpos. @@ -693,7 +721,7 @@ make_display() * Display the appropriate prompt. */ static void -prompt() +prompt(VOID_PARAM) { constant char *p; @@ -733,8 +761,14 @@ prompt() * In Win32, display the file name in the window title. */ if (!(ch_getflags() & CH_HELPFILE)) - SetConsoleTitle(pr_expand("Less?f - %f.", 0)); + { + WCHAR w[MAX_PATH+16]; + p = pr_expand("Less?f - %f.", 0); + MultiByteToWideChar(CP_ACP, 0, p, -1, w, sizeof(w)/sizeof(*w)); + SetConsoleTitleW(w); + } #endif + /* * Select the proper prompt and display it. */ @@ -759,6 +793,14 @@ prompt() putchr(':'); else { +#if MSDOS_COMPILER==WIN32C + WCHAR w[MAX_PATH*2]; + char a[MAX_PATH*2]; + MultiByteToWideChar(CP_ACP, 0, p, -1, w, sizeof(w)/sizeof(*w)); + WideCharToMultiByte(utf_mode ? CP_UTF8 : GetConsoleOutputCP(), + 0, w, -1, a, sizeof(a), NULL, NULL); + p = a; +#endif at_enter(AT_STANDOUT); putstr(p); at_exit(); @@ -770,7 +812,7 @@ prompt() * Display the less version message. */ public void -dispversion() +dispversion(VOID_PARAM) { PARG parg; @@ -782,7 +824,7 @@ dispversion() * Return a character to complete a partial command, if possible. */ static LWCHAR -getcc_end_command() +getcc_end_command(VOID_PARAM) { switch (mca) { @@ -878,10 +920,10 @@ getcc_repl(orig, repl, gr_getc, gr_ungetc) * Get command character. */ public int -getcc() +getcc(VOID_PARAM) { - /* Replace kent (keypad Enter) with a newline. */ - return getcc_repl(kent, "\n", getccu, ungetcc); + /* Replace kent (keypad Enter) with a newline. */ + return getcc_repl(kent, "\n", getccu, ungetcc); } /* @@ -917,7 +959,7 @@ ungetsc(s) * Peek the next command character, without consuming it. */ public LWCHAR -peekcc() +peekcc(VOID_PARAM) { LWCHAR c = getcc(); ungetcc(c); @@ -1068,7 +1110,7 @@ forw_loop(until_hilite) * Accept and execute commands until a quit command. */ public void -commands() +commands(VOID_PARAM) { int c; int action; @@ -1088,7 +1130,7 @@ commands() for (;;) { - mca = 0; + clear_mca(); cmd_accept(); number = 0; curropt = NULL; @@ -1270,6 +1312,22 @@ commands() backward((int) number, 0, 0); break; + case A_F_MOUSE: + /* + * Forward wheel_lines lines. + */ + cmd_exec(); + forward(wheel_lines, 0, 0); + break; + + case A_B_MOUSE: + /* + * Backward wheel_lines lines. + */ + cmd_exec(); + backward(wheel_lines, 0, 0); + break; + case A_FF_LINE: /* * Force forward N (default 1) line. @@ -1375,7 +1433,7 @@ commands() number = 0; fraction = 0; } - if (number > 100) + if (number > 100 || (number == 100 && fraction != 0)) { number = 100; fraction = 0; diff --git a/compose.uni b/compose.uni index 2a4b180..389814c 100644 --- a/compose.uni +++ b/compose.uni @@ -1,5 +1,4 @@ -/* Generated by "./mkutable -f2 Mn Me Cf -- unicode/UnicodeData.txt" on Tue Jul 25 09:04:35 PDT 2017 */ - { 0x00ad, 0x00ad }, /* Cf */ +/* Generated by "./mkutable -f2 Mn Me -- unicode/UnicodeData.txt" on Wed Feb 13 17:57:05 PST 2019 */ { 0x0300, 0x036f }, /* Mn */ { 0x0483, 0x0487 }, /* Mn */ { 0x0488, 0x0489 }, /* Me */ @@ -8,28 +7,24 @@ { 0x05c1, 0x05c2 }, /* Mn */ { 0x05c4, 0x05c5 }, /* Mn */ { 0x05c7, 0x05c7 }, /* Mn */ - { 0x0600, 0x0605 }, /* Cf */ { 0x0610, 0x061a }, /* Mn */ - { 0x061c, 0x061c }, /* Cf */ { 0x064b, 0x065f }, /* Mn */ { 0x0670, 0x0670 }, /* Mn */ { 0x06d6, 0x06dc }, /* Mn */ - { 0x06dd, 0x06dd }, /* Cf */ { 0x06df, 0x06e4 }, /* Mn */ { 0x06e7, 0x06e8 }, /* Mn */ { 0x06ea, 0x06ed }, /* Mn */ - { 0x070f, 0x070f }, /* Cf */ { 0x0711, 0x0711 }, /* Mn */ { 0x0730, 0x074a }, /* Mn */ { 0x07a6, 0x07b0 }, /* Mn */ { 0x07eb, 0x07f3 }, /* Mn */ + { 0x07fd, 0x07fd }, /* Mn */ { 0x0816, 0x0819 }, /* Mn */ { 0x081b, 0x0823 }, /* Mn */ { 0x0825, 0x0827 }, /* Mn */ { 0x0829, 0x082d }, /* Mn */ { 0x0859, 0x085b }, /* Mn */ - { 0x08d4, 0x08e1 }, /* Mn */ - { 0x08e2, 0x08e2 }, /* Cf */ + { 0x08d3, 0x08e1 }, /* Mn */ { 0x08e3, 0x0902 }, /* Mn */ { 0x093a, 0x093a }, /* Mn */ { 0x093c, 0x093c }, /* Mn */ @@ -42,6 +37,7 @@ { 0x09c1, 0x09c4 }, /* Mn */ { 0x09cd, 0x09cd }, /* Mn */ { 0x09e2, 0x09e3 }, /* Mn */ + { 0x09fe, 0x09fe }, /* Mn */ { 0x0a01, 0x0a02 }, /* Mn */ { 0x0a3c, 0x0a3c }, /* Mn */ { 0x0a41, 0x0a42 }, /* Mn */ @@ -68,6 +64,7 @@ { 0x0bc0, 0x0bc0 }, /* Mn */ { 0x0bcd, 0x0bcd }, /* Mn */ { 0x0c00, 0x0c00 }, /* Mn */ + { 0x0c04, 0x0c04 }, /* Mn */ { 0x0c3e, 0x0c40 }, /* Mn */ { 0x0c46, 0x0c48 }, /* Mn */ { 0x0c4a, 0x0c4d }, /* Mn */ @@ -126,7 +123,6 @@ { 0x17c9, 0x17d3 }, /* Mn */ { 0x17dd, 0x17dd }, /* Mn */ { 0x180b, 0x180d }, /* Mn */ - { 0x180e, 0x180e }, /* Cf */ { 0x1885, 0x1886 }, /* Mn */ { 0x18a9, 0x18a9 }, /* Mn */ { 0x1920, 0x1922 }, /* Mn */ @@ -168,10 +164,6 @@ { 0x1cf8, 0x1cf9 }, /* Mn */ { 0x1dc0, 0x1df9 }, /* Mn */ { 0x1dfb, 0x1dff }, /* Mn */ - { 0x200b, 0x200f }, /* Cf */ - { 0x202a, 0x202e }, /* Cf */ - { 0x2060, 0x2064 }, /* Cf */ - { 0x2066, 0x206f }, /* Cf */ { 0x20d0, 0x20dc }, /* Mn */ { 0x20dd, 0x20e0 }, /* Me */ { 0x20e1, 0x20e1 }, /* Mn */ @@ -193,6 +185,7 @@ { 0xa825, 0xa826 }, /* Mn */ { 0xa8c4, 0xa8c5 }, /* Mn */ { 0xa8e0, 0xa8f1 }, /* Mn */ + { 0xa8ff, 0xa8ff }, /* Mn */ { 0xa926, 0xa92d }, /* Mn */ { 0xa947, 0xa951 }, /* Mn */ { 0xa980, 0xa982 }, /* Mn */ @@ -219,8 +212,6 @@ { 0xfb1e, 0xfb1e }, /* Mn */ { 0xfe00, 0xfe0f }, /* Mn */ { 0xfe20, 0xfe2f }, /* Mn */ - { 0xfeff, 0xfeff }, /* Cf */ - { 0xfff9, 0xfffb }, /* Cf */ { 0x101fd, 0x101fd }, /* Mn */ { 0x102e0, 0x102e0 }, /* Mn */ { 0x10376, 0x1037a }, /* Mn */ @@ -230,19 +221,20 @@ { 0x10a38, 0x10a3a }, /* Mn */ { 0x10a3f, 0x10a3f }, /* Mn */ { 0x10ae5, 0x10ae6 }, /* Mn */ + { 0x10d24, 0x10d27 }, /* Mn */ + { 0x10f46, 0x10f50 }, /* Mn */ { 0x11001, 0x11001 }, /* Mn */ { 0x11038, 0x11046 }, /* Mn */ { 0x1107f, 0x11081 }, /* Mn */ { 0x110b3, 0x110b6 }, /* Mn */ { 0x110b9, 0x110ba }, /* Mn */ - { 0x110bd, 0x110bd }, /* Cf */ { 0x11100, 0x11102 }, /* Mn */ { 0x11127, 0x1112b }, /* Mn */ { 0x1112d, 0x11134 }, /* Mn */ { 0x11173, 0x11173 }, /* Mn */ { 0x11180, 0x11181 }, /* Mn */ { 0x111b6, 0x111be }, /* Mn */ - { 0x111ca, 0x111cc }, /* Mn */ + { 0x111c9, 0x111cc }, /* Mn */ { 0x1122f, 0x11231 }, /* Mn */ { 0x11234, 0x11234 }, /* Mn */ { 0x11236, 0x11237 }, /* Mn */ @@ -250,13 +242,14 @@ { 0x112df, 0x112df }, /* Mn */ { 0x112e3, 0x112ea }, /* Mn */ { 0x11300, 0x11301 }, /* Mn */ - { 0x1133c, 0x1133c }, /* Mn */ + { 0x1133b, 0x1133c }, /* Mn */ { 0x11340, 0x11340 }, /* Mn */ { 0x11366, 0x1136c }, /* Mn */ { 0x11370, 0x11374 }, /* Mn */ { 0x11438, 0x1143f }, /* Mn */ { 0x11442, 0x11444 }, /* Mn */ { 0x11446, 0x11446 }, /* Mn */ + { 0x1145e, 0x1145e }, /* Mn */ { 0x114b3, 0x114b8 }, /* Mn */ { 0x114ba, 0x114ba }, /* Mn */ { 0x114bf, 0x114c0 }, /* Mn */ @@ -275,8 +268,9 @@ { 0x1171d, 0x1171f }, /* Mn */ { 0x11722, 0x11725 }, /* Mn */ { 0x11727, 0x1172b }, /* Mn */ - { 0x11a01, 0x11a06 }, /* Mn */ - { 0x11a09, 0x11a0a }, /* Mn */ + { 0x1182f, 0x11837 }, /* Mn */ + { 0x11839, 0x1183a }, /* Mn */ + { 0x11a01, 0x11a0a }, /* Mn */ { 0x11a33, 0x11a38 }, /* Mn */ { 0x11a3b, 0x11a3e }, /* Mn */ { 0x11a47, 0x11a47 }, /* Mn */ @@ -296,13 +290,15 @@ { 0x11d3c, 0x11d3d }, /* Mn */ { 0x11d3f, 0x11d45 }, /* Mn */ { 0x11d47, 0x11d47 }, /* Mn */ + { 0x11d90, 0x11d91 }, /* Mn */ + { 0x11d95, 0x11d95 }, /* Mn */ + { 0x11d97, 0x11d97 }, /* Mn */ + { 0x11ef3, 0x11ef4 }, /* Mn */ { 0x16af0, 0x16af4 }, /* Mn */ { 0x16b30, 0x16b36 }, /* Mn */ { 0x16f8f, 0x16f92 }, /* Mn */ { 0x1bc9d, 0x1bc9e }, /* Mn */ - { 0x1bca0, 0x1bca3 }, /* Cf */ { 0x1d167, 0x1d169 }, /* Mn */ - { 0x1d173, 0x1d17a }, /* Cf */ { 0x1d17b, 0x1d182 }, /* Mn */ { 0x1d185, 0x1d18b }, /* Mn */ { 0x1d1aa, 0x1d1ad }, /* Mn */ @@ -320,6 +316,4 @@ { 0x1e026, 0x1e02a }, /* Mn */ { 0x1e8d0, 0x1e8d6 }, /* Mn */ { 0x1e944, 0x1e94a }, /* Mn */ - { 0xe0001, 0xe0001 }, /* Cf */ - { 0xe0020, 0xe007f }, /* Cf */ { 0xe0100, 0xe01ef }, /* Mn */ diff --git a/configure b/configure index 10a0305..0ce6db1 100755 --- a/configure +++ b/configure @@ -1307,7 +1307,7 @@ Optional Packages: --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-secure Compile in secure mode --with-no-float Do not use floating point - --with-regex=LIB select regular expression library (LIB is one of auto,none,gnu,pcre,posix,regcmp,re_comp,regcomp,regcomp-local) [auto] + --with-regex=LIB select regular expression library (LIB is one of auto,none,gnu,pcre,pcre2,posix,regcmp,re_comp,regcomp,regcomp-local) [auto] --with-editor=PROGRAM use PROGRAM as the default editor [vi] Some influential environment variables: @@ -4611,6 +4611,7 @@ fi + # Checks for identifiers. ac_fn_c_check_type "$LINENO" "off_t" "ac_cv_type_off_t" "$ac_includes_default" if test "x$ac_cv_type_off_t" = xyes; then : @@ -4771,7 +4772,7 @@ cat >>confdefs.h <<_ACEOF _ACEOF -for ac_func in fsync popen _setjmp sigprocmask sigsetmask snprintf stat system fchmod +for ac_func in fsync popen _setjmp sigprocmask sigsetmask snprintf stat system fchmod realpath do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" @@ -5312,6 +5313,52 @@ fi fi if test $have_regex = no; then +if test $WANT_REGEX = auto -o $WANT_REGEX = pcre2; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pcre2_compile_8 in -lpcre2-8" >&5 +$as_echo_n "checking for pcre2_compile_8 in -lpcre2-8... " >&6; } +if ${ac_cv_lib_pcre2_8_pcre2_compile_8+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpcre2-8 $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pcre2_compile_8 (); +int +main () +{ +return pcre2_compile_8 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_pcre2_8_pcre2_compile_8=yes +else + ac_cv_lib_pcre2_8_pcre2_compile_8=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pcre2_8_pcre2_compile_8" >&5 +$as_echo "$ac_cv_lib_pcre2_8_pcre2_compile_8" >&6; } +if test "x$ac_cv_lib_pcre2_8_pcre2_compile_8" = xyes; then : + $as_echo "#define HAVE_PCRE2 1" >>confdefs.h + LIBS="$LIBS -lpcre2-8" have_regex=yes; supported_regex="$supported_regex pcre2" +fi + +fi +fi + +if test $have_regex = no; then if test $WANT_REGEX = auto -o $WANT_REGEX = pcre; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pcre_compile in -lpcre" >&5 $as_echo_n "checking for pcre_compile in -lpcre... " >&6; } diff --git a/configure.ac b/configure.ac index 3616ef0..7a69398 100644 --- a/configure.ac +++ b/configure.ac @@ -183,6 +183,8 @@ AH_TEMPLATE([HAVE_POSIX_REGCOMP], [POSIX regcomp() and regex.h]) AH_TEMPLATE([HAVE_PCRE], [PCRE (Perl-compatible regular expression) library]) +AH_TEMPLATE([HAVE_PCRE2], + [PCRE2 (Perl-compatible regular expression) library]) AH_TEMPLATE([HAVE_RE_COMP], [BSD re_comp()]) AH_TEMPLATE([HAVE_REGCMP], @@ -258,7 +260,7 @@ AC_TRY_COMPILE([], [int f(int a) { return a; }], # Checks for library functions. AC_TYPE_SIGNAL -AC_CHECK_FUNCS([fsync popen _setjmp sigprocmask sigsetmask snprintf stat system fchmod]) +AC_CHECK_FUNCS([fsync popen _setjmp sigprocmask sigsetmask snprintf stat system fchmod realpath]) # AC_CHECK_FUNCS may not work for inline functions, so test these separately. AC_MSG_CHECKING(for memcpy) @@ -393,7 +395,7 @@ supported_regex="" # Select a regular expression library. WANT_REGEX=auto AC_ARG_WITH(regex, - [ --with-regex=LIB select regular expression library (LIB is one of auto,none,gnu,pcre,posix,regcmp,re_comp,regcomp,regcomp-local) [[auto]]], + [ --with-regex=LIB select regular expression library (LIB is one of auto,none,gnu,pcre,pcre2,posix,regcmp,re_comp,regcomp,regcomp-local) [[auto]]], WANT_REGEX="$withval") if test $have_regex = no; then @@ -432,6 +434,13 @@ fi fi if test $have_regex = no; then +if test $WANT_REGEX = auto -o $WANT_REGEX = pcre2; then +AC_CHECK_LIB(pcre2-8, pcre2_compile_8, +[AC_DEFINE(HAVE_PCRE2) LIBS="$LIBS -lpcre2-8" have_regex=yes; supported_regex="$supported_regex pcre2"], []) +fi +fi + +if test $have_regex = no; then if test $WANT_REGEX = auto -o $WANT_REGEX = pcre; then AC_CHECK_LIB(pcre, pcre_compile, [AC_DEFINE(HAVE_PCRE) LIBS="$LIBS -lpcre" have_regex=yes; supported_regex="$supported_regex pcre"], []) @@ -575,7 +584,7 @@ AH_TOP([ #define PIPEC (!SECURE) /* - * LOGFILE is 1 if you wish to allow the -l option (to create log files). + * LOGFILE is 1 if you wish to allow the -o option (to create log files). */ #define LOGFILE (!SECURE) diff --git a/cvt.c b/cvt.c index 3a77949..e635655 100644 --- a/cvt.c +++ b/cvt.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. diff --git a/decode.c b/decode.c index 80f47f9..74bbc4f 100644 --- a/decode.c +++ b/decode.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -35,6 +35,9 @@ extern int erase_char, erase2_char, kill_char; extern int secure; +extern int mousecap; +extern int screen_trashed; +extern int sc_height; #define SK(k) \ SK_SPECIAL_KEY, (k), 6, 1, 1, 1 @@ -65,6 +68,8 @@ static unsigned char cmdtable[] = CONTROL('D'),0, A_F_SCROLL, 'u',0, A_B_SCROLL, CONTROL('U'),0, A_B_SCROLL, + ESC,'[','M',0, A_X11MOUSE_IN, + ESC,'[','<',0, A_X116MOUSE_IN, ' ',0, A_F_SCREEN, 'f',0, A_F_SCREEN, CONTROL('F'),0, A_F_SCREEN, @@ -310,7 +315,7 @@ expand_cmd_table(tlist) * Expand special key abbreviations in all command tables. */ public void -expand_cmd_tables() +expand_cmd_tables(VOID_PARAM) { expand_cmd_table(list_fcmd_tables); expand_cmd_table(list_ecmd_tables); @@ -323,7 +328,7 @@ expand_cmd_tables() * Initialize the command lists. */ public void -init_cmds() +init_cmds(VOID_PARAM) { /* * Add the default command tables. @@ -416,6 +421,116 @@ add_var_table(tlist, buf, len) } /* + * Return action for a mouse wheel down event. + */ + static int +mouse_wheel_down(VOID_PARAM) +{ + return ((mousecap == OPT_ONPLUS) ? A_B_MOUSE : A_F_MOUSE); +} + +/* + * Return action for a mouse wheel up event. + */ + static int +mouse_wheel_up(VOID_PARAM) +{ + return ((mousecap == OPT_ONPLUS) ? A_F_MOUSE : A_B_MOUSE); +} + +/* + * Return action for a mouse button release event. + */ + static int +mouse_button_rel(x, y) + int x; + int y; +{ + /* + * {{ It would be better to return an action and then do this + * in commands() but it's nontrivial to pass y to it. }} + */ + if (y < sc_height-1) + { + setmark('#', y); + screen_trashed = 1; + } + return (A_NOACTION); +} + +/* + * Read a decimal integer. Return the integer and set *pterm to the terminating char. + */ + static int +getcc_int(pterm) + char* pterm; +{ + int num = 0; + int digits = 0; + for (;;) + { + char ch = getcc(); + if (ch < '0' || ch > '9') + { + if (pterm != NULL) *pterm = ch; + if (digits == 0) + return (-1); + return (num); + } + num = (10 * num) + (ch - '0'); + ++digits; + } +} + +/* + * Read suffix of mouse input and return the action to take. + * The prefix ("\e[M") has already been read. + */ + static int +x11mouse_action(VOID_PARAM) +{ + int b = getcc() - X11MOUSE_OFFSET; + int x = getcc() - X11MOUSE_OFFSET-1; + int y = getcc() - X11MOUSE_OFFSET-1; + switch (b) { + default: + return (A_NOACTION); + case X11MOUSE_WHEEL_DOWN: + return mouse_wheel_down(); + case X11MOUSE_WHEEL_UP: + return mouse_wheel_up(); + case X11MOUSE_BUTTON_REL: + return mouse_button_rel(x, y); + } +} + +/* + * Read suffix of mouse input and return the action to take. + * The prefix ("\e[<") has already been read. + */ + static int +x116mouse_action(VOID_PARAM) +{ + char ch; + int x, y; + int b = getcc_int(&ch); + if (b < 0 || ch != ';') return (A_NOACTION); + x = getcc_int(&ch) - 1; + if (x < 0 || ch != ';') return (A_NOACTION); + y = getcc_int(&ch) - 1; + if (y < 0) return (A_NOACTION); + switch (b) { + case X11MOUSE_WHEEL_DOWN: + return mouse_wheel_down(); + case X11MOUSE_WHEEL_UP: + return mouse_wheel_up(); + default: + if (ch != 'm') return (A_NOACTION); + return mouse_button_rel(x, y); + } +} + +/* * Search a single command table for the command string in cmd. */ static int @@ -464,6 +579,10 @@ cmd_search(cmd, table, endtable, sp) *sp = ++p; a &= ~A_EXTRA; } + if (a == A_X11MOUSE_IN) + a = x11mouse_action(); + else if (a == A_X116MOUSE_IN) + a = x116mouse_action(); return (a); } } else if (*q == '\0') @@ -579,6 +698,16 @@ lgetenv(var) return (NULL); } +/* + * Is a string null or empty? + */ + public int +isnullenv(s) + char* s; +{ + return (s == NULL || *s == '\0'); +} + #if USERFILE /* * Get an "integer" from a lesskey file. @@ -791,7 +920,13 @@ editchar(c, flags) if (c == erase_char || c == erase2_char) return (EC_BACKSPACE); if (c == kill_char) + { +#if MSDOS_COMPILER==WIN32C + if (!win32_kbhit()) +#endif + return (EC_LINEKILL); + } /* * Collect characters in a buffer. diff --git a/defines.ds b/defines.ds index 80a2d7b..b952232 100644 --- a/defines.ds +++ b/defines.ds @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -93,7 +93,7 @@ #endif /* - * LOGFILE is 1 if you wish to allow the -l option (to create log files). + * LOGFILE is 1 if you wish to allow the -o option (to create log files). */ #define LOGFILE (!SECURE) diff --git a/defines.h.in b/defines.h.in index 874c150..36822bc 100644 --- a/defines.h.in +++ b/defines.h.in @@ -83,7 +83,7 @@ #define PIPEC (!SECURE) /* - * LOGFILE is 1 if you wish to allow the -l option (to create log files). + * LOGFILE is 1 if you wish to allow the -o option (to create log files). */ #define LOGFILE (!SECURE) @@ -263,12 +263,18 @@ /* PCRE (Perl-compatible regular expression) library */ #undef HAVE_PCRE +/* PCRE2 (Perl-compatible regular expression) library */ +#undef HAVE_PCRE2 + /* Define to 1 if you have the `popen' function. */ #undef HAVE_POPEN /* POSIX regcomp() and regex.h */ #undef HAVE_POSIX_REGCOMP +/* Define to 1 if you have the `realpath' function. */ +#undef HAVE_REALPATH + /* System V regcmp() */ #undef HAVE_REGCMP diff --git a/defines.o2 b/defines.o2 index 4dba142..1490cdc 100644 --- a/defines.o2 +++ b/defines.o2 @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -86,7 +86,7 @@ #define PIPEC (!SECURE) /* - * LOGFILE is 1 if you wish to allow the -l option (to create log files). + * LOGFILE is 1 if you wish to allow the -o option (to create log files). */ #define LOGFILE (!SECURE) diff --git a/defines.o9 b/defines.o9 index 99983d7..fb980ac 100644 --- a/defines.o9 +++ b/defines.o9 @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -85,7 +85,7 @@ #define PIPEC (!SECURE) /* - * LOGFILE is 1 if you wish to allow the -l option (to create log files). + * LOGFILE is 1 if you wish to allow the -o option (to create log files). */ #define LOGFILE (!SECURE) diff --git a/defines.wn b/defines.wn index 98ca990..4235402 100644 --- a/defines.wn +++ b/defines.wn @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -86,7 +86,7 @@ #define PIPEC 1 /* - * LOGFILE is 1 if you wish to allow the -l option (to create log files). + * LOGFILE is 1 if you wish to allow the -o option (to create log files). */ #define LOGFILE (!SECURE) @@ -172,7 +172,7 @@ /* * Sizes of various buffers. */ -#if 0 /* old sizes for small memory machines +#if 0 /* old sizes for small memory machines */ #define CMDBUF_SIZE 512 /* Buffer for multichar commands */ #define UNGOT_SIZE 100 /* Max chars to unget() */ #define LINEBUF_SIZE 1024 /* Max size of line in input file */ @@ -216,9 +216,26 @@ /* #undef HAVE_POSIX_REGCOMP */ /* #undef HAVE_RE_COMP */ /* #undef HAVE_REGCMP */ +#ifdef MINGW + #ifdef USE_POSIX_REGCOMP + #define HAVE_POSIX_REGCOMP 1 + #else + #ifdef USE_GNU_REGEX + #define HAVE_GNU_REGEX 1 + #else + #ifdef USE_REGEXP_C + #define HAVE_V8_REGCOMP 1 + #define HAVE_REGEXEC2 1 + #else + #define NO_REGEX 1 + #endif + #endif + #endif +#else #define HAVE_V8_REGCOMP 1 /* #undef NO_REGEX */ #define HAVE_REGEXEC2 1 +#endif /* Define HAVE_VOID if your compiler supports the "void" type. */ #define HAVE_VOID 1 @@ -239,7 +256,11 @@ /* Define MUST_DEFINE_ERRNO if you have errno but it is not define * in errno.h */ #define HAVE_ERRNO 1 +#ifdef MINGW +#define MUST_DEFINE_ERRNO 0 +#else #define MUST_DEFINE_ERRNO 1 +#endif /* Define HAVE_SYS_ERRLIST if you have the sys_errlist[] variable */ #define HAVE_SYS_ERRLIST 1 @@ -339,19 +360,28 @@ #define HAVE_TIME_H 1 /* Define if you have the header file. */ +#ifdef MINGW +#define HAVE_UNISTD_H 1 +#else #define HAVE_UNISTD_H 0 +#endif /* Define if you have the header file. */ #ifdef _MSC_VER #define HAVE_VALUES_H 0 #else +#ifdef MINGW +#define HAVE_VALUES_H 0 +#else #define HAVE_VALUES_H 1 #endif +#endif #define popen _popen -#define pclose _pclose #if !defined(_MSC_VER) || (_MSC_VER < 1900) #define snprintf _snprintf #endif +#ifndef MINGW #pragma warning(disable:4996) +#endif diff --git a/edit.c b/edit.c index 7dc80bb..82a79b1 100644 --- a/edit.c +++ b/edit.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -171,7 +171,7 @@ close_pipe(FILE *pipefd) * Close the current input file. */ static void -close_file() +close_file(VOID_PARAM) { struct scrpos scrpos; int chflags; @@ -486,7 +486,12 @@ edit_ifile(ifile) clr_hilite(); #endif if (strcmp(filename, FAKE_HELPFILE) && strcmp(filename, FAKE_EMPTYFILE)) - cmd_addhist(ml_examine, filename, 1); + { + char *qfilename = shell_quote(filename); + cmd_addhist(ml_examine, qfilename, 1); + free(qfilename); + } + if (no_display && errmsgs > 0) { /* @@ -570,8 +575,10 @@ edit_list(filelist) * Edit the first file in the command line (ifile) list. */ public int -edit_first() +edit_first(VOID_PARAM) { + if (nifile() == 0) + return (edit_stdin()); curr_ifile = NULL_IFILE; return (edit_next(1)); } @@ -580,7 +587,7 @@ edit_first() * Edit the last file in the command line (ifile) list. */ public int -edit_last() +edit_last(VOID_PARAM) { curr_ifile = NULL_IFILE; return (edit_prev(1)); @@ -687,7 +694,7 @@ edit_index(n) } public IFILE -save_curr_ifile() +save_curr_ifile(VOID_PARAM) { if (curr_ifile != NULL_IFILE) hold_ifile(curr_ifile, 1); @@ -740,7 +747,7 @@ reedit_ifile(save_ifile) } public void -reopen_curr_ifile() +reopen_curr_ifile(VOID_PARAM) { IFILE save_ifile = save_curr_ifile(); close_file(); @@ -751,7 +758,7 @@ reopen_curr_ifile() * Edit standard input. */ public int -edit_stdin() +edit_stdin(VOID_PARAM) { if (isatty(fd0)) { @@ -766,7 +773,7 @@ edit_stdin() * Used if standard output is not a tty. */ public void -cat_file() +cat_file(VOID_PARAM) { int c; diff --git a/filename.c b/filename.c index 983a02b..7c3ccd2 100644 --- a/filename.c +++ b/filename.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -98,7 +98,7 @@ shell_unquote(str) * Get the shell's escape character. */ public char * -get_meta_escape() +get_meta_escape(VOID_PARAM) { char *s; @@ -112,7 +112,7 @@ get_meta_escape() * Get the characters which the shell considers to be "metacharacters". */ static char * -metachars() +metachars(VOID_PARAM) { static char *mchars = NULL; @@ -561,8 +561,6 @@ readfd(fd) #if HAVE_POPEN -FILE *popen(); - /* * Execute a shell command. * Return a pointer to a pipe connected to the shell command's standard output. @@ -577,7 +575,7 @@ shellcmd(cmd) char *shell; shell = lgetenv("SHELL"); - if (shell != NULL && *shell != '\0') + if (!isnullenv(shell)) { char *scmd; char *esccmd; @@ -754,7 +752,7 @@ lglob(filename) return (filename); } lessecho = lgetenv("LESSECHO"); - if (lessecho == NULL || *lessecho == '\0') + if (isnullenv(lessecho)) lessecho = "lessecho"; /* * Invoke lessecho, and read its output (a globbed list of filenames). @@ -781,7 +779,7 @@ lglob(filename) if (*gfilename == '\0') { free(gfilename); - return (save(filename)); + return (filename); } } #else @@ -797,6 +795,21 @@ lglob(filename) } /* + * @@@ + */ + public char * +lrealpath(path) + char *path; +{ +#if HAVE_REALPATH + char rpath[PATH_MAX]; + if (realpath(path, rpath) != NULL) + return (save(rpath)); +#endif + return (save(path)); +} + +/* * Return number of %s escapes in a string. * Return a large number if there are any other % escapes besides %s. */ @@ -1080,7 +1093,7 @@ filesize(f) * */ public char * -shell_coption() +shell_coption(VOID_PARAM) { return ("-c"); } diff --git a/fmt.uni b/fmt.uni index a0bad77..ff71d29 100644 --- a/fmt.uni +++ b/fmt.uni @@ -1,4 +1,4 @@ -/* Generated by "./mkutable -f2 Cf -- unicode/UnicodeData.txt" on Sun Nov 12 16:13:49 PST 2017 */ +/* Generated by "./mkutable -f2 Cf -- unicode/UnicodeData.txt" on Wed Feb 13 17:57:05 PST 2019 */ { 0x00ad, 0x00ad }, /* Cf */ { 0x0600, 0x0605 }, /* Cf */ { 0x061c, 0x061c }, /* Cf */ @@ -13,6 +13,7 @@ { 0xfeff, 0xfeff }, /* Cf */ { 0xfff9, 0xfffb }, /* Cf */ { 0x110bd, 0x110bd }, /* Cf */ + { 0x110cd, 0x110cd }, /* Cf */ { 0x1bca0, 0x1bca3 }, /* Cf */ { 0x1d173, 0x1d17a }, /* Cf */ { 0xe0001, 0xe0001 }, /* Cf */ diff --git a/forwback.c b/forwback.c index 680fa25..1e0397c 100644 --- a/forwback.c +++ b/forwback.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -46,7 +46,7 @@ extern char *tagoption; * Sound the bell to indicate user is trying to move past end of file. */ static void -eof_bell() +eof_bell(VOID_PARAM) { if (quiet == NOT_QUIET) bell(); @@ -58,7 +58,7 @@ eof_bell() * Check to see if the end of file is currently displayed. */ public int -eof_displayed() +eof_displayed(VOID_PARAM) { POSITION pos; @@ -85,7 +85,7 @@ eof_displayed() * Check to see if the entire file is currently displayed. */ public int -entire_file_displayed() +entire_file_displayed(VOID_PARAM) { POSITION pos; @@ -105,7 +105,7 @@ entire_file_displayed() * for the first time. */ public void -squish_check() +squish_check(VOID_PARAM) { if (!squished) return; @@ -434,7 +434,7 @@ backward(n, force, only_last) * top_scroll, as well as back_scroll. */ public int -get_back_scroll() +get_back_scroll(VOID_PARAM) { if (no_back_scroll) return (0); @@ -446,19 +446,18 @@ get_back_scroll() } /* - * Return number of displayable lines in the file. - * Stop counting at screen height + 1. + * Will the entire file fit on one screen? */ public int -get_line_count() +get_one_screen(VOID_PARAM) { int nlines; POSITION pos = ch_zero(); - for (nlines = 0; nlines <= sc_height; nlines++) + for (nlines = 0; nlines < sc_height; nlines++) { pos = forw_line(pos); if (pos == NULL_POSITION) break; } - return nlines; + return (nlines < sc_height); } diff --git a/funcs.h b/funcs.h index d70c359..9686df1 100644 --- a/funcs.h +++ b/funcs.h @@ -7,6 +7,8 @@ public void raw_mode LESSPARAMS ((int on)); public void scrsize LESSPARAMS ((VOID_PARAM)); public char * special_key_str LESSPARAMS ((int key)); public void get_term LESSPARAMS ((VOID_PARAM)); +public void init_mouse LESSPARAMS ((VOID_PARAM)); +public void deinit_mouse LESSPARAMS ((VOID_PARAM)); public void init LESSPARAMS ((VOID_PARAM)); public void deinit LESSPARAMS ((VOID_PARAM)); public void home LESSPARAMS ((VOID_PARAM)); @@ -29,7 +31,8 @@ public int is_at_equiv LESSPARAMS ((int attr1, int attr2)); public int apply_at_specials LESSPARAMS ((int attr)); public void backspace LESSPARAMS ((VOID_PARAM)); public void putbs LESSPARAMS ((VOID_PARAM)); -public char WIN32getch LESSPARAMS ((int tty)); +public int win32_kbhit LESSPARAMS ((VOID_PARAM)); +public char WIN32getch LESSPARAMS ((VOID_PARAM)); public void WIN32setcolors LESSPARAMS ((int fg, int bg)); public void WIN32textout LESSPARAMS ((char *text, int len)); public void match_brac LESSPARAMS ((int obrac, int cbrac, int forwdir, int n)); @@ -98,6 +101,7 @@ public void add_ecmd_table LESSPARAMS ((char *buf, int len)); public int fcmd_decode LESSPARAMS ((char *cmd, char **sp)); public int ecmd_decode LESSPARAMS ((char *cmd, char **sp)); public char * lgetenv LESSPARAMS ((char *var)); +public int isnullenv LESSPARAMS ((char* s)); public int lesskey LESSPARAMS ((char *filename, int sysvar)); public void add_hometable LESSPARAMS ((char *envname, char *def_filename, int sysvar)); public int editchar LESSPARAMS ((int c, int flags)); @@ -127,6 +131,7 @@ public char * fexpand LESSPARAMS ((char *s)); public char * fcomplete LESSPARAMS ((char *s)); public int bin_file LESSPARAMS ((int f)); public char * lglob LESSPARAMS ((char *filename)); +public char * lrealpath LESSPARAMS ((char *path)); public char * open_altfile LESSPARAMS ((char *filename, int *pf, void **pfd)); public void close_altfile LESSPARAMS ((char *altfilename, char *filename)); public int is_dir LESSPARAMS ((char *filename)); @@ -142,7 +147,7 @@ public void back LESSPARAMS ((int n, POSITION pos, int force, int only_last)); public void forward LESSPARAMS ((int n, int force, int only_last)); public void backward LESSPARAMS ((int n, int force, int only_last)); public int get_back_scroll LESSPARAMS ((VOID_PARAM)); -public int get_line_count LESSPARAMS ((VOID_PARAM)); +public int get_one_screen LESSPARAMS ((VOID_PARAM)); public void del_ifile LESSPARAMS ((IFILE h)); public IFILE next_ifile LESSPARAMS ((IFILE h)); public IFILE prev_ifile LESSPARAMS ((IFILE h)); @@ -208,6 +213,9 @@ public void gomark LESSPARAMS ((int c)); public POSITION markpos LESSPARAMS ((int c)); public char posmark LESSPARAMS ((POSITION pos)); public void unmark LESSPARAMS ((IFILE ifile)); +public void mark_check_ifile LESSPARAMS ((IFILE ifile)); +public void save_marks LESSPARAMS ((FILE *fout, char *hdr)); +public void restore_mark LESSPARAMS ((char *line)); public void opt_o LESSPARAMS ((int type, char *s)); public void opt__O LESSPARAMS ((int type, char *s)); public void opt_j LESSPARAMS ((int type, char *s)); @@ -227,6 +235,8 @@ public void opt_x LESSPARAMS ((int type, char *s)); public void opt_quote LESSPARAMS ((int type, char *s)); public void opt_rscroll LESSPARAMS ((int type, char *s)); public void opt_query LESSPARAMS ((int type, char *s)); +public void opt_mousecap LESSPARAMS ((int type, char *s)); +public void opt_wheel_lines LESSPARAMS ((int type, char *s)); public int get_swindow LESSPARAMS ((VOID_PARAM)); public char * propt LESSPARAMS ((int c)); public void scan_option LESSPARAMS ((char *s)); @@ -261,6 +271,7 @@ public void uncompile_pattern LESSPARAMS ((PATTERN_TYPE *pattern)); public int valid_pattern LESSPARAMS ((char *pattern)); public int is_null_pattern LESSPARAMS ((PATTERN_TYPE pattern)); public int match_pattern LESSPARAMS ((PATTERN_TYPE pattern, char *tpattern, char *line, int line_len, char **sp, char **ep, int notbol, int search_type)); +public char * pattern_lib_name LESSPARAMS ((VOID_PARAM)); public POSITION position LESSPARAMS ((int sindex)); public void add_forw_pos LESSPARAMS ((POSITION pos)); public void add_back_pos LESSPARAMS ((POSITION pos)); @@ -307,4 +318,5 @@ public int curr_tag LESSPARAMS ((VOID_PARAM)); public int edit_tagfile LESSPARAMS ((VOID_PARAM)); public void open_getchr LESSPARAMS ((VOID_PARAM)); public void close_getchr LESSPARAMS ((VOID_PARAM)); +public int default_wheel_lines LESSPARAMS ((VOID_PARAM)); public int getchr LESSPARAMS ((VOID_PARAM)); diff --git a/help.c b/help.c index efa236a..f9c2dd9 100644 --- a/help.c +++ b/help.c @@ -1,4 +1,4 @@ -/* This file was generated by mkhelp.pl from less.hlp at 22:56 on 2017/12/5 */ +/* This file was generated by mkhelp.pl from less.hlp at 18:12 on 2019/6/11 */ #include "less.h" constant char helpdata[] = { '\n', @@ -47,7 +47,7 @@ constant char helpdata[] = { ' ',' ','E','S','C','-','u',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','U','n','d','o',' ','(','t','o','g','g','l','e',')',' ','s','e','a','r','c','h',' ','h','i','g','h','l','i','g','h','t','i','n','g','.','\n', ' ',' ','&','_','\b','p','_','\b','a','_','\b','t','_','\b','t','_','\b','e','_','\b','r','_','\b','n',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','D','i','s','p','l','a','y',' ','o','n','l','y',' ','m','a','t','c','h','i','n','g',' ','l','i','n','e','s','\n', ' ',' ',' ',' ',' ',' ',' ',' ','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\n', -' ',' ',' ',' ',' ',' ',' ',' ','A',' ','s','e','a','r','c','h',' ','p','a','t','t','e','r','n',' ','m','a','y',' ','b','e',' ','p','r','e','c','e','d','e','d',' ','b','y',' ','o','n','e',' ','o','r',' ','m','o','r','e',' ','o','f',':','\n', +' ',' ',' ',' ',' ',' ',' ',' ','A',' ','s','e','a','r','c','h',' ','p','a','t','t','e','r','n',' ','m','a','y',' ','b','e','g','i','n',' ','w','i','t','h',' ','o','n','e',' ','o','r',' ','m','o','r','e',' ','o','f',':','\n', ' ',' ',' ',' ',' ',' ',' ',' ','^','N',' ','o','r',' ','!',' ',' ','S','e','a','r','c','h',' ','f','o','r',' ','N','O','N','-','m','a','t','c','h','i','n','g',' ','l','i','n','e','s','.','\n', ' ',' ',' ',' ',' ',' ',' ',' ','^','E',' ','o','r',' ','*',' ',' ','S','e','a','r','c','h',' ','m','u','l','t','i','p','l','e',' ','f','i','l','e','s',' ','(','p','a','s','s',' ','t','h','r','u',' ','E','N','D',' ','O','F',' ','F','I','L','E',')','.','\n', ' ',' ',' ',' ',' ',' ',' ',' ','^','F',' ','o','r',' ','@',' ',' ','S','t','a','r','t',' ','s','e','a','r','c','h',' ','a','t',' ','F','I','R','S','T',' ','f','i','l','e',' ','(','f','o','r',' ','/',')',' ','o','r',' ','l','a','s','t',' ','f','i','l','e',' ','(','f','o','r',' ','?',')','.','\n', @@ -156,7 +156,7 @@ constant char helpdata[] = { ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','i','s','p','l','a','y',' ','a',' ','s','t','a','t','u','s',' ','c','o','l','u','m','n',' ','a','t',' ','l','e','f','t',' ','e','d','g','e',' ','o','f',' ','s','c','r','e','e','n','.','\n', ' ',' ','-','k',' ','[','_','\b','f','_','\b','i','_','\b','l','_','\b','e',']',' ',' ','.',' ',' ','-','-','l','e','s','s','k','e','y','-','f','i','l','e','=','[','_','\b','f','_','\b','i','_','\b','l','_','\b','e',']','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','U','s','e',' ','a',' ','l','e','s','s','k','e','y',' ','f','i','l','e','.','\n', -' ',' ','-','K',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','q','u','i','t','-','o','n','-','i','n','t','r','\n', +' ',' ','-','K',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','q','u','i','t','-','o','n','-','i','n','t','r','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','E','x','i','t',' ','l','e','s','s',' ','i','n',' ','r','e','s','p','o','n','s','e',' ','t','o',' ','c','t','r','l','-','C','.','\n', ' ',' ','-','L',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','n','o','-','l','e','s','s','o','p','e','n','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','I','g','n','o','r','e',' ','t','h','e',' ','L','E','S','S','O','P','E','N',' ','e','n','v','i','r','o','n','m','e','n','t',' ','v','a','r','i','a','b','l','e','.','\n', @@ -206,12 +206,22 @@ constant char helpdata[] = { ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','o','n','\'','t',' ','d','i','s','p','l','a','y',' ','t','i','l','d','e','s',' ','a','f','t','e','r',' ','e','n','d',' ','o','f',' ','f','i','l','e','.','\n', ' ',' ','-','#',' ','[','_','\b','N',']',' ',' ','.','.','.','.',' ',' ','-','-','s','h','i','f','t','=','[','_','\b','N',']','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','H','o','r','i','z','o','n','t','a','l',' ','s','c','r','o','l','l',' ','a','m','o','u','n','t',' ','(','0',' ','=',' ','o','n','e',' ','h','a','l','f',' ','s','c','r','e','e','n',' ','w','i','d','t','h',')','\n', -' ',' ',' ',' ',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','n','o','-','k','e','y','p','a','d','\n', -' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','o','n','\'','t',' ','s','e','n','d',' ','t','e','r','m','c','a','p',' ','k','e','y','p','a','d',' ','i','n','i','t','/','d','e','i','n','i','t',' ','s','t','r','i','n','g','s','.','\n', -' ',' ',' ',' ',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','f','o','l','l','o','w','-','n','a','m','e','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','f','o','l','l','o','w','-','n','a','m','e','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','T','h','e',' ','F',' ','c','o','m','m','a','n','d',' ','c','h','a','n','g','e','s',' ','f','i','l','e','s',' ','i','f',' ','t','h','e',' ','i','n','p','u','t',' ','f','i','l','e',' ','i','s',' ','r','e','n','a','m','e','d','.','\n', -' ',' ',' ',' ',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','u','s','e','-','b','a','c','k','s','l','a','s','h','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','m','o','u','s','e','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','E','n','a','b','l','e',' ','m','o','u','s','e',' ','i','n','p','u','t','.','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','n','o','-','k','e','y','p','a','d','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','o','n','\'','t',' ','s','e','n','d',' ','t','e','r','m','c','a','p',' ','k','e','y','p','a','d',' ','i','n','i','t','/','d','e','i','n','i','t',' ','s','t','r','i','n','g','s','.','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','n','o','-','h','i','s','t','d','u','p','s','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','R','e','m','o','v','e',' ','d','u','p','l','i','c','a','t','e','s',' ','f','r','o','m',' ','c','o','m','m','a','n','d',' ','h','i','s','t','o','r','y','.','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','r','s','c','r','o','l','l','=','C','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','e','t',' ','t','h','e',' ','c','h','a','r','a','c','t','e','r',' ','u','s','e','d',' ','t','o',' ','m','a','r','k',' ','t','r','u','n','c','a','t','e','d',' ','l','i','n','e','s','.','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','s','a','v','e','-','m','a','r','k','s','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','R','e','t','a','i','n',' ','m','a','r','k','s',' ','a','c','r','o','s','s',' ','i','n','v','o','c','a','t','i','o','n','s',' ','o','f',' ','l','e','s','s','.','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','u','s','e','-','b','a','c','k','s','l','a','s','h','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','u','b','s','e','q','u','e','n','t',' ','o','p','t','i','o','n','s',' ','u','s','e',' ','b','a','c','k','s','l','a','s','h',' ','a','s',' ','e','s','c','a','p','e',' ','c','h','a','r','.','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','w','h','e','e','l','-','l','i','n','e','s','=','N','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','E','a','c','h',' ','c','l','i','c','k',' ','o','f',' ','t','h','e',' ','m','o','u','s','e',' ','w','h','e','e','l',' ','m','o','v','e','s',' ','N',' ','l','i','n','e','s','.','\n', '\n', '\n', ' ','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\n', diff --git a/ifile.c b/ifile.c index 613312b..ceb59b7 100644 --- a/ifile.c +++ b/ifile.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -121,6 +121,12 @@ new_ifile(filename, prev) p->h_hold = 0; p->h_filestate = NULL; link_ifile(p, prev); + /* + * {{ It's dodgy to call mark.c functions from here; + * there is potentially dangerous recursion. + * Probably need to revisit this design. }} + */ + mark_check_ifile(ext_ifile(p)); return (p); } @@ -198,7 +204,7 @@ getoff_ifile(ifile) * Return the number of ifiles. */ public int -nifile() +nifile(VOID_PARAM) { return (ifiles); } @@ -211,11 +217,26 @@ find_ifile(filename) char *filename; { struct ifile *p; + char *rfilename = lrealpath(filename); for (p = anchor.h_next; p != &anchor; p = p->h_next) - if (strcmp(filename, p->h_filename) == 0) - return (p); - return (NULL); + { + if (strcmp(filename, p->h_filename) == 0 || + strcmp(rfilename, p->h_filename) == 0) + { + /* + * If given name is shorter than the name we were + * previously using for this file, adopt shorter name. + */ + if (strlen(filename) < strlen(p->h_filename)) + strcpy(p->h_filename, filename); + break; + } + } + free(rfilename); + if (p == &anchor) + p = NULL; + return (p); } /* @@ -365,7 +386,7 @@ get_altfilename(ifile) #if 0 public void -if_dump() +if_dump(VOID_PARAM) { struct ifile *p; diff --git a/input.c b/input.c index 27be124..8d0ebb1 100644 --- a/input.c +++ b/input.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. diff --git a/jump.c b/jump.c index 2c7d28b..0e1d35d 100644 --- a/jump.c +++ b/jump.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -26,7 +26,7 @@ extern int top_scroll; * Jump to the end of the file. */ public void -jump_forw() +jump_forw(VOID_PARAM) { POSITION pos; POSITION end_pos; @@ -64,7 +64,7 @@ jump_forw() * Jump to the last buffered line in the file. */ public void -jump_forw_buffered() +jump_forw_buffered(VOID_PARAM) { POSITION end; @@ -115,7 +115,7 @@ jump_back(linenum) * Repaint the screen. */ public void -repaint() +repaint(VOID_PARAM) { struct scrpos scrpos; /* diff --git a/less.h b/less.h index 39ca65e..7ec58c3 100644 --- a/less.h +++ b/less.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -302,15 +302,6 @@ struct scrpos int ln; }; -/* - * A mark is an ifile (input file) plus a position within the file. - */ -struct mark -{ - IFILE m_ifile; - struct scrpos m_scrpos; -}; - typedef union parg { char *p_string; @@ -471,6 +462,7 @@ struct wchar_range_table #endif /* IS_EBCDIC_HOST */ #define ESC CONTROL('[') +#define ESCS "\33" #define CSI ((unsigned char)'\233') #define CHAR_END_COMMAND 0x40000000 @@ -531,6 +523,15 @@ struct wchar_range_table #define time_type long #endif +/* X11 mouse reporting definitions */ +#define X11MOUSE_BUTTON1 0 /* Left button press */ +#define X11MOUSE_BUTTON2 1 /* Middle button press */ +#define X11MOUSE_BUTTON3 2 /* Right button press */ +#define X11MOUSE_BUTTON_REL 3 /* Button release */ +#define X11MOUSE_WHEEL_UP 0x40 /* Wheel scroll up */ +#define X11MOUSE_WHEEL_DOWN 0x41 /* Wheel scroll down */ +#define X11MOUSE_OFFSET 0x20 /* Added to button & pos bytes to create a char */ + struct mlist; struct loption; struct hilite_tree; @@ -541,3 +542,8 @@ struct hilite_tree; void postoa LESSPARAMS ((POSITION, char*)); void linenumtoa LESSPARAMS ((LINENUM, char*)); void inttoa LESSPARAMS ((int, char*)); +int lstrtoi LESSPARAMS ((char*, char**)); +POSITION lstrtopos LESSPARAMS ((char*, char**)); +#if MSDOS_COMPILER==WIN32C +int pclose LESSPARAMS ((FILE*)); +#endif diff --git a/less.hlp b/less.hlp index 0bbada9..a8f78ad 100644 --- a/less.hlp +++ b/less.hlp @@ -44,7 +44,7 @@ ESC-u Undo (toggle) search highlighting. &_p_a_t_t_e_r_n * Display only matching lines --------------------------------------------------- - A search pattern may be preceded by one or more of: + A search pattern may begin with one or more of: ^N or ! Search for NON-matching lines. ^E or * Search multiple files (pass thru END OF FILE). ^F or @ Start search at FIRST file (for /) or last file (for ?). @@ -153,7 +153,7 @@ Display a status column at left edge of screen. -k [_f_i_l_e] . --lesskey-file=[_f_i_l_e] Use a lesskey file. - -K --quit-on-intr + -K ........ --quit-on-intr Exit less in response to ctrl-C. -L ........ --no-lessopen Ignore the LESSOPEN environment variable. @@ -203,12 +203,22 @@ Don't display tildes after end of file. -# [_N] .... --shift=[_N] Horizontal scroll amount (0 = one half screen width) - ........ --no-keypad - Don't send termcap keypad init/deinit strings. - ........ --follow-name + --follow-name The F command changes files if the input file is renamed. - ........ --use-backslash + --mouse + Enable mouse input. + --no-keypad + Don't send termcap keypad init/deinit strings. + --no-histdups + Remove duplicates from command history. + --rscroll=C + Set the character used to mark truncated lines. + --save-marks + Retain marks across invocations of less. + --use-backslash Subsequent options use backslash as escape char. + --wheel-lines=N + Each click of the mouse wheel moves N lines. --------------------------------------------------------------------------- diff --git a/less.man b/less.man index 84420a4..f0e178c 100644 --- a/less.man +++ b/less.man @@ -718,96 +718,97 @@ LESS(1) General Commands Manual LESS(1) -Q or --QUIET or --SILENT Causes totally "quiet" operation: the terminal bell is never - rung. + rung. If the terminal has a "visual bell", it is used in all + cases where the terminal bell would have been rung. -r or --raw-control-chars Causes "raw" control characters to be displayed. The default is - to display control characters using the caret notation; for + to display control characters using the caret notation; for example, a control-A (octal 001) is displayed as "^A". Warning: when the -r option is used, less cannot keep track of the actual - appearance of the screen (since this depends on how the screen + appearance of the screen (since this depends on how the screen responds to each type of control character). Thus, various dis- - play problems may result, such as long lines being split in the + play problems may result, such as long lines being split in the wrong place. -R or --RAW-CONTROL-CHARS - Like -r, but only ANSI "color" escape sequences are output in + Like -r, but only ANSI "color" escape sequences are output in "raw" form. Unlike -r, the screen appearance is maintained cor- rectly in most cases. ANSI "color" escape sequences are sequences of the form: ESC [ ... m - where the "..." is zero or more color specification characters - For the purpose of keeping track of screen appearance, ANSI - color escape sequences are assumed to not move the cursor. You - can make less think that characters other than "m" can end ANSI - color escape sequences by setting the environment variable + where the "..." is zero or more color specification characters + For the purpose of keeping track of screen appearance, ANSI + color escape sequences are assumed to not move the cursor. You + can make less think that characters other than "m" can end ANSI + color escape sequences by setting the environment variable LESSANSIENDCHARS to the list of characters which can end a color - escape sequence. And you can make less think that characters - other than the standard ones may appear between the ESC and the - m by setting the environment variable LESSANSIMIDCHARS to the + escape sequence. And you can make less think that characters + other than the standard ones may appear between the ESC and the + m by setting the environment variable LESSANSIMIDCHARS to the list of characters which can appear. -s or --squeeze-blank-lines - Causes consecutive blank lines to be squeezed into a single + Causes consecutive blank lines to be squeezed into a single blank line. This is useful when viewing nroff output. -S or --chop-long-lines - Causes lines longer than the screen width to be chopped (trun- + Causes lines longer than the screen width to be chopped (trun- cated) rather than wrapped. That is, the portion of a long line that does not fit in the screen width is not shown. The default - is to wrap long lines; that is, display the remainder on the + is to wrap long lines; that is, display the remainder on the next line. -ttag or --tag=tag The -t option, followed immediately by a TAG, will edit the file - containing that tag. For this to work, tag information must be - available; for example, there may be a file in the current + containing that tag. For this to work, tag information must be + available; for example, there may be a file in the current directory called "tags", which was previously built by ctags (1) or an equivalent command. If the environment variable LESSGLOB- - ALTAGS is set, it is taken to be the name of a command compati- - ble with global (1), and that command is executed to find the + ALTAGS is set, it is taken to be the name of a command compati- + ble with global (1), and that command is executed to find the tag. (See http://www.gnu.org/software/global/global.html). The - -t option may also be specified from within less (using the - - command) as a way of examining a new file. The command ":t" is + -t option may also be specified from within less (using the - + command) as a way of examining a new file. The command ":t" is equivalent to specifying -t from within less. -Ttagsfile or --tag-file=tagsfile Specifies a tags file to be used instead of "tags". -u or --underline-special - Causes backspaces and carriage returns to be treated as print- - able characters; that is, they are sent to the terminal when + Causes backspaces and carriage returns to be treated as print- + able characters; that is, they are sent to the terminal when they appear in the input. -U or --UNDERLINE-SPECIAL - Causes backspaces, tabs, carriage returns and "formatting char- + Causes backspaces, tabs, carriage returns and "formatting char- acters" (as defined by Unicode) to be treated as control charac- ters; that is, they are handled as specified by the -r option. - By default, if neither -u nor -U is given, backspaces which - appear adjacent to an underscore character are treated spe- - cially: the underlined text is displayed using the terminal's - hardware underlining capability. Also, backspaces which appear - between two identical characters are treated specially: the - overstruck text is printed using the terminal's hardware bold- - face capability. Other backspaces are deleted, along with the + By default, if neither -u nor -U is given, backspaces which + appear adjacent to an underscore character are treated spe- + cially: the underlined text is displayed using the terminal's + hardware underlining capability. Also, backspaces which appear + between two identical characters are treated specially: the + overstruck text is printed using the terminal's hardware bold- + face capability. Other backspaces are deleted, along with the preceding character. Carriage returns immediately followed by a - newline are deleted. Other carriage returns are handled as - specified by the -r option. Text which is overstruck or under- + newline are deleted. Other carriage returns are handled as + specified by the -r option. Text which is overstruck or under- lined can be searched for if neither -u nor -U is in effect. -V or --version Displays the version number of less. -w or --hilite-unread - Temporarily highlights the first "new" line after a forward + Temporarily highlights the first "new" line after a forward movement of a full page. The first "new" line is the line imme- - diately following the line previously at the bottom of the + diately following the line previously at the bottom of the screen. Also highlights the target line after a g or p command. - The highlight is removed at the next command which causes move- - ment. The entire line is highlighted, unless the -J option is + The highlight is removed at the next command which causes move- + ment. The entire line is highlighted, unless the -J option is in effect, in which case only the status column is highlighted. -W or --HILITE-UNREAD @@ -815,48 +816,48 @@ LESS(1) General Commands Manual LESS(1) forward movement command larger than one line. -xn,... or --tabs=n,... - Sets tab stops. If only one n is specified, tab stops are set - at multiples of n. If multiple values separated by commas are - specified, tab stops are set at those positions, and then con- - tinue with the same spacing as the last two. For example, - -x9,17 will set tabs at positions 9, 17, 25, 33, etc. The + Sets tab stops. If only one n is specified, tab stops are set + at multiples of n. If multiple values separated by commas are + specified, tab stops are set at those positions, and then con- + tinue with the same spacing as the last two. For example, + -x9,17 will set tabs at positions 9, 17, 25, 33, etc. The default for n is 8. -X or --no-init Disables sending the termcap initialization and deinitialization - strings to the terminal. This is sometimes desirable if the - deinitialization string does something unnecessary, like clear- + strings to the terminal. This is sometimes desirable if the + deinitialization string does something unnecessary, like clear- ing the screen. -yn or --max-forw-scroll=n Specifies a maximum number of lines to scroll forward. If it is - necessary to scroll forward more than n lines, the screen is - repainted instead. The -c or -C option may be used to repaint - from the top of the screen if desired. By default, any forward + necessary to scroll forward more than n lines, the screen is + repainted instead. The -c or -C option may be used to repaint + from the top of the screen if desired. By default, any forward movement causes scrolling. -zn or --window=n or -n - Changes the default scrolling window size to n lines. The + Changes the default scrolling window size to n lines. The default is one screenful. The z and w commands can also be used - to change the window size. The "z" may be omitted for compati- + to change the window size. The "z" may be omitted for compati- bility with some versions of more. If the number n is negative, - it indicates n lines less than the current screen size. For + it indicates n lines less than the current screen size. For example, if the screen is 24 lines, -z-4 sets the scrolling win- - dow to 20 lines. If the screen is resized to 40 lines, the + dow to 20 lines. If the screen is resized to 40 lines, the scrolling window automatically changes to 36 lines. -"cc or --quotes=cc - Changes the filename quoting character. This may be necessary - if you are trying to name a file which contains both spaces and - quote characters. Followed by a single character, this changes - the quote character to that character. Filenames containing a + Changes the filename quoting character. This may be necessary + if you are trying to name a file which contains both spaces and + quote characters. Followed by a single character, this changes + the quote character to that character. Filenames containing a space should then be surrounded by that character rather than by - double quotes. Followed by two characters, changes the open - quote to the first character, and the close quote to the second + double quotes. Followed by two characters, changes the open + quote to the first character, and the close quote to the second character. Filenames containing a space should then be preceded - by the open quote character and followed by the close quote - character. Note that even after the quote characters are - changed, this option remains -" (a dash followed by a double + by the open quote character and followed by the close quote + character. Note that even after the quote characters are + changed, this option remains -" (a dash followed by a double quote). -~ or --tilde @@ -866,45 +867,75 @@ LESS(1) General Commands Manual LESS(1) -# or --shift Specifies the default number of positions to scroll horizontally - in the RIGHTARROW and LEFTARROW commands. If the number speci- - fied is zero, it sets the default number of positions to one + in the RIGHTARROW and LEFTARROW commands. If the number speci- + fied is zero, it sets the default number of positions to one half of the screen width. Alternately, the number may be speci- - fied as a fraction of the width of the screen, starting with a - decimal point: .5 is half of the screen width, .3 is three - tenths of the screen width, and so on. If the number is speci- - fied as a fraction, the actual number of scroll positions is - recalculated if the terminal window is resized, so that the - actual scroll remains at the specified fraction of the screen + fied as a fraction of the width of the screen, starting with a + decimal point: .5 is half of the screen width, .3 is three + tenths of the screen width, and so on. If the number is speci- + fied as a fraction, the actual number of scroll positions is + recalculated if the terminal window is resized, so that the + actual scroll remains at the specified fraction of the screen width. --follow-name - Normally, if the input file is renamed while an F command is - executing, less will continue to display the contents of the - original file despite its name change. If --follow-name is + Normally, if the input file is renamed while an F command is + executing, less will continue to display the contents of the + original file despite its name change. If --follow-name is specified, during an F command less will periodically attempt to reopen the file by name. If the reopen succeeds and the file is - a different file from the original (which means that a new file - has been created with the same name as the original (now + a different file from the original (which means that a new file + has been created with the same name as the original (now renamed) file), less will display the contents of that new file. + --mouse + Enables mouse input: scrolling the mouse wheel down moves for- + ward in the file, scrolling the mouse wheel up moves backwards + in the file, and clicking the mouse sets the "#" mark to the + line where the mouse is clicked. The number of lines to scroll + when the wheel is moved can be set by the --wheel-lines option. + Mouse input works only on terminals which support X11 mouse + reporting, and on the Windows version of less. + + --MOUSE + Like --mouse, except the direction scrolled on mouse wheel move- + ment is reversed. + --no-keypad Disables sending the keypad initialization and deinitialization strings to the terminal. This is sometimes useful if the keypad strings make the numeric keypad behave in an undesirable manner. - --use-backslash - This option changes the interpretations of options which follow - this one. After the --use-backslash option, any backslash in an - option string is removed and the following character is taken - literally. This allows a dollar sign to be included in option - strings. + --no-histdups + This option changes the behavior so that if a search string or + file name is typed in, and the same string is already in the + history list, the existing copy is removed from the history list + before the new one is added. Thus, a given string will appear + only once in the history list. Normally, a string may appear + multiple times. --rscroll - This option changes the character used to mark truncated lines. + This option changes the character used to mark truncated lines. It may begin with a two-character attribute indicator like LESS- - BINFMT does. If there is no attribute indicator, standout is + BINFMT does. If there is no attribute indicator, standout is used. If set to "-", truncated lines are not marked. + --save-marks + Save marks in the history file, so marks are retained across + different invocations of less. + + --use-backslash + This option changes the interpretations of options which follow + this one. After the --use-backslash option, any backslash in an + option string is removed and the following character is taken + literally. This allows a dollar sign to be included in option + strings. + + --wheel-lines=n + Set the number of lines to scroll when the mouse wheel is + scrolled and the --mouse or --MOUSE option is in effect. The + default is 1 line. + -- A command line argument of "--" marks the end of option argu- ments. Any arguments following this are interpreted as file- names. This can be useful when viewing a file whose name begins @@ -1077,11 +1108,12 @@ LESS(1) General Commands Manual LESS(1) lessopen.sh: #! /bin/sh case "$1" in - *.Z) uncompress -c $1 >/tmp/less.$$ 2>/dev/null - if [ -s /tmp/less.$$ ]; then - echo /tmp/less.$$ + *.Z) TEMPFILE=$(mktemp) + uncompress -c $1 >$TEMPFILE 2>/dev/null + if [ -s $TEMPFILE ]; then + echo $TEMPFILE else - rm -f /tmp/less.$$ + rm -f $TEMPFILE fi ;; esac @@ -1117,6 +1149,7 @@ LESS(1) General Commands Manual LESS(1) #! /bin/sh case "$1" in *.Z) uncompress -c $1 2>/dev/null + ;; *) exit 1 ;; esac @@ -1317,6 +1350,10 @@ LESS(1) General Commands Manual LESS(1) %F Replaced by the last component of the name of the current input file. + %g Replaced by the shell-escaped name of the current input file. + This is useful when the expanded string will be used in a shell + command, such as in LESSEDIT. + %i Replaced by the index of the current file in the list of input files. @@ -1442,16 +1479,17 @@ LESS(1) General Commands Manual LESS(1) expanded in the same way as the prompt strings. The default value for LESSEDIT is: - %E ?lm+%lm. %f + %E ?lm+%lm. %g Note that this expands to the editor name, followed by a + and the line - number, followed by the file name. If your editor does not accept the - "+linenumber" syntax, or has other differences in invocation syntax, - the LESSEDIT variable can be changed to modify this default. + number, followed by the shell-escaped file name. If your editor does + not accept the "+linenumber" syntax, or has other differences in invo- + cation syntax, the LESSEDIT variable can be changed to modify this + default. SECURITY - When the environment variable LESSSECURE is set to 1, less runs in a + When the environment variable LESSSECURE is set to 1, less runs in a "secure" mode. This means these features are disabled: ! the shell command @@ -1477,54 +1515,54 @@ LESS(1) General Commands Manual LESS(1) COMPATIBILITY WITH MORE If the environment variable LESS_IS_MORE is set to 1, or if the program - is invoked via a file link named "more", less behaves (mostly) in con- - formance with the POSIX "more" command specification. In this mode, + is invoked via a file link named "more", less behaves (mostly) in con- + formance with the POSIX "more" command specification. In this mode, less behaves differently in these ways: - The -e option works differently. If the -e option is not set, less - behaves as if the -e option were set. If the -e option is set, less + The -e option works differently. If the -e option is not set, less + behaves as if the -e option were set. If the -e option is set, less behaves as if the -E option were set. - The -m option works differently. If the -m option is not set, the - medium prompt is used, and it is prefixed with the string "--More--". + The -m option works differently. If the -m option is not set, the + medium prompt is used, and it is prefixed with the string "--More--". If the -m option is set, the short prompt is used. - The -n option acts like the -z option. The normal behavior of the -n + The -n option acts like the -z option. The normal behavior of the -n option is unavailable in this mode. - The parameter to the -p option is taken to be a less command rather + The parameter to the -p option is taken to be a less command rather than a search pattern. - The LESS environment variable is ignored, and the MORE environment + The LESS environment variable is ignored, and the MORE environment variable is used in its place. ENVIRONMENT VARIABLES Environment variables may be specified either in the system environment - as usual, or in a lesskey (1) file. If environment variables are - defined in more than one place, variables defined in a local lesskey - file take precedence over variables defined in the system environment, + as usual, or in a lesskey (1) file. If environment variables are + defined in more than one place, variables defined in a local lesskey + file take precedence over variables defined in the system environment, which take precedence over variables defined in the system-wide lesskey file. COLUMNS Sets the number of columns on the screen. Takes precedence over - the number of columns specified by the TERM variable. (But if + the number of columns specified by the TERM variable. (But if you have a windowing system which supports TIOCGWINSZ or - WIOCGETD, the window system's idea of the screen size takes + WIOCGETD, the window system's idea of the screen size takes precedence over the LINES and COLUMNS environment variables.) EDITOR The name of the editor (used for the v command). - HOME Name of the user's home directory (used to find a lesskey file + HOME Name of the user's home directory (used to find a lesskey file on Unix and OS/2 systems). HOMEDRIVE, HOMEPATH - Concatenation of the HOMEDRIVE and HOMEPATH environment vari- + Concatenation of the HOMEDRIVE and HOMEPATH environment vari- ables is the name of the user's home directory if the HOME vari- able is not set (only in the Windows version). - INIT Name of the user's init directory (used to find a lesskey file + INIT Name of the user's init directory (used to find a lesskey file on OS/2 systems). LANG Language for determining the character set. @@ -1535,12 +1573,12 @@ LESS(1) General Commands Manual LESS(1) LESS Options which are passed to less automatically. LESSANSIENDCHARS - Characters which may end an ANSI color escape sequence (default + Characters which may end an ANSI color escape sequence (default "m"). LESSANSIMIDCHARS - Characters which may appear between the ESC character and the - end character in an ANSI color escape sequence (default + Characters which may appear between the ESC character and the + end character in an ANSI color escape sequence (default "0123456789:;[?!"'#%()*+ ". LESSBINFMT @@ -1557,24 +1595,24 @@ LESS(1) General Commands Manual LESS(1) LESSECHO Name of the lessecho program (default "lessecho"). The lessecho - program is needed to expand metacharacters, such as * and ?, in + program is needed to expand metacharacters, such as * and ?, in filenames on Unix systems. LESSEDIT - Editor prototype string (used for the v command). See discus- + Editor prototype string (used for the v command). See discus- sion under PROMPTS. LESSGLOBALTAGS - Name of the command used by the -t option to find global tags. + Name of the command used by the -t option to find global tags. Normally should be set to "global" if your system has the global (1) command. If not set, global tags are not used. LESSHISTFILE - Name of the history file used to remember search commands and - shell commands between invocations of less. If set to "-" or - "/dev/null", a history file is not used. The default is - "$HOME/.lesshst" on Unix systems, "$HOME/_lesshst" on DOS and - Windows systems, or "$HOME/lesshst.ini" or "$INIT/lesshst.ini" + Name of the history file used to remember search commands and + shell commands between invocations of less. If set to "-" or + "/dev/null", a history file is not used. The default is + "$HOME/.lesshst" on Unix systems, "$HOME/_lesshst" on DOS and + Windows systems, or "$HOME/lesshst.ini" or "$INIT/lesshst.ini" on OS/2 systems. LESSHISTSIZE @@ -1588,13 +1626,13 @@ LESS(1) General Commands Manual LESS(1) Name of the default system-wide lesskey(1) file. LESSMETACHARS - List of characters which are considered "metacharacters" by the + List of characters which are considered "metacharacters" by the shell. LESSMETAESCAPE - Prefix which less will add before each metacharacter in a com- - mand sent to the shell. If LESSMETAESCAPE is an empty string, - commands containing metacharacters will not be passed to the + Prefix which less will add before each metacharacter in a com- + mand sent to the shell. If LESSMETAESCAPE is an empty string, + commands containing metacharacters will not be passed to the shell. LESSOPEN @@ -1604,7 +1642,7 @@ LESS(1) General Commands Manual LESS(1) Runs less in "secure" mode. See discussion under SECURITY. LESSSEPARATOR - String to be appended to a directory name in filename comple- + String to be appended to a directory name in filename comple- tion. LESSUTFBINFMT @@ -1613,19 +1651,19 @@ LESS(1) General Commands Manual LESS(1) LESS_IS_MORE Emulate the more (1) command. - LINES Sets the number of lines on the screen. Takes precedence over + LINES Sets the number of lines on the screen. Takes precedence over the number of lines specified by the TERM variable. (But if you - have a windowing system which supports TIOCGWINSZ or WIOCGETD, - the window system's idea of the screen size takes precedence + have a windowing system which supports TIOCGWINSZ or WIOCGETD, + the window system's idea of the screen size takes precedence over the LINES and COLUMNS environment variables.) - MORE Options which are passed to less automatically when running in + MORE Options which are passed to less automatically when running in more compatible mode. - PATH User's search path (used to find a lesskey file on MS-DOS and + PATH User's search path (used to find a lesskey file on MS-DOS and OS/2 systems). - SHELL The shell used to execute the ! command, as well as to expand + SHELL The shell used to execute the ! command, as well as to expand filenames. TERM The type of terminal on which less is being run. @@ -1638,32 +1676,30 @@ LESS(1) General Commands Manual LESS(1) COPYRIGHT - Copyright (C) 1984-2017 Mark Nudelman + Copyright (C) 1984-2019 Mark Nudelman - less is part of the GNU project and is free software. You can redis- - tribute it and/or modify it under the terms of either (1) the GNU Gen- - eral Public License as published by the Free Software Foundation; or + less is part of the GNU project and is free software. You can redis- + tribute it and/or modify it under the terms of either (1) the GNU Gen- + eral Public License as published by the Free Software Foundation; or (2) the Less License. See the file README in the less distribution for more details regarding redistribution. You should have received a copy - of the GNU General Public License along with the source for less; see - the file COPYING. If not, write to the Free Software Foundation, 59 - Temple Place, Suite 330, Boston, MA 02111-1307, USA. You should also + of the GNU General Public License along with the source for less; see + the file COPYING. If not, write to the Free Software Foundation, 59 + Temple Place, Suite 330, Boston, MA 02111-1307, USA. You should also have received a copy of the Less License; see the file LICENSE. less is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FIT- - NESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + WARRANTY; without even the implied warranty of MERCHANTABILITY or FIT- + NESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. AUTHOR Mark Nudelman - Send bug reports or comments to - See http://www.greenwoodsoftware.com/less/bugs.html for the latest list - of known bugs in less. + Report bugs at https://github.com/gwsw/less/issues. For more information, see the less homepage at http://www.greenwoodsoftware.com/less. - Version 530: 05 Dec 2017 LESS(1) + Version 551: 11 Jun 2019 LESS(1) diff --git a/less.nro b/less.nro index fa0b4ff..0aa8b78 100644 --- a/less.nro +++ b/less.nro @@ -1,4 +1,4 @@ -.TH LESS 1 "Version 530: 05 Dec 2017" +.TH LESS 1 "Version 551: 11 Jun 2019" .SH NAME less \- opposite of more .SH SYNOPSIS @@ -762,6 +762,8 @@ The default is to ring the terminal bell in all such cases. .IP "\-Q or \-\-QUIET or \-\-SILENT" Causes totally "quiet" operation: the terminal bell is never rung. +If the terminal has a "visual bell", it is used in all cases +where the terminal bell would have been rung. .IP "\-r or \-\-raw-control-chars" Causes "raw" control characters to be displayed. The default is to display control characters using the caret notation; @@ -938,21 +940,48 @@ If the reopen succeeds and the file is a different file from the original with the same name as the original (now renamed) file), .I less will display the contents of that new file. +.IP "\-\-mouse" +Enables mouse input: +scrolling the mouse wheel down moves forward in the file, +scrolling the mouse wheel up moves backwards in the file, +and clicking the mouse sets the "#" mark to the line +where the mouse is clicked. +The number of lines to scroll when the wheel is moved +can be set by the \-\-wheel-lines option. +Mouse input works only on terminals which support X11 mouse reporting, +and on the Windows version of +.IR less . +.IP "\-\-MOUSE" +Like \-\-mouse, except the direction scrolled +on mouse wheel movement is reversed. .IP "\-\-no-keypad" Disables sending the keypad initialization and deinitialization strings to the terminal. This is sometimes useful if the keypad strings make the numeric keypad behave in an undesirable manner. -.IP "\-\-use-backslash" -This option changes the interpretations of options which follow this one. -After the \-\-use-backslash option, any backslash in an option string is -removed and the following character is taken literally. -This allows a dollar sign to be included in option strings. +.IP "\-\-no-histdups" +This option changes the behavior so that if a search string or +file name is typed in, and the same string is already in the history list, +the existing copy is removed from the history list before the new one is added. +Thus, a given string will appear only once in the history list. +Normally, a string may appear multiple times. .IP "\-\-rscroll" This option changes the character used to mark truncated lines. It may begin with a two-character attribute indicator like LESSBINFMT does. If there is no attribute indicator, standout is used. If set to "-", truncated lines are not marked. +.IP "\-\-save-marks" +Save marks in the history file, so marks are retained +across different invocations of \fIless\fP. +.IP "\-\-use-backslash" +This option changes the interpretations of options which follow this one. +After the \-\-use-backslash option, any backslash in an option string is +removed and the following character is taken literally. +This allows a dollar sign to be included in option strings. +.IP "\-\-wheel-lines=\fIn\fP" +Set the number of lines to scroll when the mouse wheel is scrolled +and the \-\-mouse or \-\-MOUSE option is in effect. +The default is 1 line. .IP \-\- A command line argument of "\-\-" marks the end of option arguments. Any arguments following this are interpreted as filenames. @@ -1154,15 +1183,17 @@ lessopen.sh: .br case "$1" in .br - *.Z) uncompress \-c $1 >/tmp/less.$$ 2>/dev/null + *.Z) TEMPFILE=$(mktemp) +.br + uncompress \-c $1 >$TEMPFILE 2>/dev/null .br - if [ \-s /tmp/less.$$ ]; then + if [ \-s $TEMPFILE ]; then .br - echo /tmp/less.$$ + echo $TEMPFILE .br else .br - rm \-f /tmp/less.$$ + rm \-f $TEMPFILE .br fi .br @@ -1213,6 +1244,8 @@ lesspipe.sh: .br *.Z) uncompress \-c $1 2>/dev/null .br + ;; +.br *) exit 1 .br ;; @@ -1440,6 +1473,10 @@ See the discussion of the LESSEDIT feature below. Replaced by the name of the current input file. .IP "%F" Replaced by the last component of the name of the current input file. +.IP "%g" +Replaced by the shell-escaped name of the current input file. +This is useful when the expanded string will be used in a shell command, +such as in LESSEDIT. .IP "%i" Replaced by the index of the current file in the list of input files. @@ -1575,11 +1612,11 @@ The LESSEDIT string is expanded in the same way as the prompt strings. The default value for LESSEDIT is: .nf .sp - %E\ ?lm+%lm.\ %f + %E\ ?lm+%lm.\ %g .sp .fi Note that this expands to the editor name, followed by a + and the -line number, followed by the file name. +line number, followed by the shell-escaped file name. If your editor does not accept the "+linenumber" syntax, or has other differences in invocation syntax, the LESSEDIT variable can be changed to modify this default. @@ -1766,7 +1803,7 @@ The name of the editor (used for the v command). lesskey(1) .SH COPYRIGHT -Copyright (C) 1984-2017 Mark Nudelman +Copyright (C) 1984-2019 Mark Nudelman .PP less is part of the GNU project and is free software. You can redistribute it and/or modify it @@ -1791,9 +1828,7 @@ See the GNU General Public License for more details. .PP Mark Nudelman .br -Send bug reports or comments to -.br -See http://www.greenwoodsoftware.com/less/bugs.html for the latest list of known bugs in less. +Report bugs at https://github.com/gwsw/less/issues. .br For more information, see the less homepage at .br diff --git a/lessecho.c b/lessecho.c index 4ed4830..2f4a10e 100644 --- a/lessecho.c +++ b/lessecho.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -38,14 +38,14 @@ static char metachars[64] = ""; static int num_metachars = 0; static void -pr_usage() +pr_usage(VOID_PARAM) { fprintf(stderr, "usage: lessecho [-ox] [-cx] [-pn] [-dn] [-mx] [-nn] [-ex] [-fn] [-a] file ...\n"); } static void -pr_version() +pr_version(VOID_PARAM) { char *p; char buf[10]; diff --git a/lessecho.man b/lessecho.man index de4200c..6a26991 100644 --- a/lessecho.man +++ b/lessecho.man @@ -51,4 +51,4 @@ LESSECHO(1) General Commands Manual LESSECHO(1) - Version 530: 05 Dec 2017 LESSECHO(1) + Version 551: 11 Jun 2019 LESSECHO(1) diff --git a/lessecho.nro b/lessecho.nro index 49a97ff..4fe997e 100644 --- a/lessecho.nro +++ b/lessecho.nro @@ -1,4 +1,4 @@ -.TH LESSECHO 1 "Version 530: 05 Dec 2017" +.TH LESSECHO 1 "Version 551: 11 Jun 2019" .SH NAME lessecho \- expand metacharacters .SH SYNOPSIS diff --git a/lesskey.c b/lesskey.c index fa1ab6d..96a4462 100644 --- a/lesskey.c +++ b/lesskey.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -220,7 +220,7 @@ int errors; extern char version[]; void -usage() +usage(VOID_PARAM) { fprintf(stderr, "usage: lesskey [-o output] [input]\n"); exit(1); @@ -343,7 +343,7 @@ parse_args(argc, argv) * Initialize data structures. */ void -init_tables() +init_tables(VOID_PARAM) { cmdtable.names = cmdnames; cmdtable.pbuffer = cmdtable.buffer; diff --git a/lesskey.h b/lesskey.h index 92d4d93..299bf45 100644 --- a/lesskey.h +++ b/lesskey.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. diff --git a/lesskey.man b/lesskey.man index 99e5f16..68af6c4 100644 --- a/lesskey.man +++ b/lesskey.man @@ -337,7 +337,7 @@ LESSKEY(1) General Commands Manual LESSKEY(1) COPYRIGHT - Copyright (C) 1984-2017 Mark Nudelman + Copyright (C) 1984-2019 Mark Nudelman less is part of the GNU project and is free software. You can redis- tribute it and/or modify it under the terms of either (1) the GNU Gen- @@ -361,4 +361,4 @@ LESSKEY(1) General Commands Manual LESSKEY(1) - Version 530: 05 Dec 2017 LESSKEY(1) + Version 551: 11 Jun 2019 LESSKEY(1) diff --git a/lesskey.nro b/lesskey.nro index ffe520b..48aec7f 100644 --- a/lesskey.nro +++ b/lesskey.nro @@ -1,4 +1,4 @@ -.TH LESSKEY 1 "Version 530: 05 Dec 2017" +.TH LESSKEY 1 "Version 551: 11 Jun 2019" .SH NAME lesskey \- specify key bindings for less .SH SYNOPSIS @@ -363,7 +363,7 @@ which start with a NUL character (0). This NUL character should be represented as \e340 in a lesskey file. .SH COPYRIGHT -Copyright (C) 1984-2017 Mark Nudelman +Copyright (C) 1984-2019 Mark Nudelman .PP less is part of the GNU project and is free software. You can redistribute it and/or modify it diff --git a/lglob.h b/lglob.h index 0d9fb5b..ed44fcc 100644 --- a/lglob.h +++ b/lglob.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -56,7 +56,7 @@ char ext[_MAX_EXT]; \ int handle; #else -#if MSDOS_COMPILER==WIN32C && defined(_MSC_VER) +#if MSDOS_COMPILER==WIN32C && (defined(_MSC_VER) || defined(MINGW)) #define GLOB_FIRST_NAME(filename,fndp,h) h = _findfirst(filename, fndp) #define GLOB_FIRST_FAILED(handle) ((handle) == -1) diff --git a/line.c b/line.c index dd890f3..02a2d86 100644 --- a/line.c +++ b/line.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -67,7 +67,7 @@ extern int sc_width, sc_height; extern int utf_mode; extern POSITION start_attnpos; extern POSITION end_attnpos; -extern LWCHAR rscroll_char; +extern char rscroll_char; extern int rscroll_attr; static char mbc_buf[MAX_UTF_CHAR_LEN]; @@ -79,14 +79,14 @@ static POSITION mbc_pos; * Initialize from environment variables. */ public void -init_line() +init_line(VOID_PARAM) { end_ansi_chars = lgetenv("LESSANSIENDCHARS"); - if (end_ansi_chars == NULL || *end_ansi_chars == '\0') + if (isnullenv(end_ansi_chars)) end_ansi_chars = "m"; mid_ansi_chars = lgetenv("LESSANSIMIDCHARS"); - if (mid_ansi_chars == NULL || *mid_ansi_chars == '\0') + if (isnullenv(mid_ansi_chars)) mid_ansi_chars = "0123456789:;[?!\"'#%()*+ "; linebuf = (char *) ecalloc(LINEBUF_SIZE, sizeof(char)); @@ -98,7 +98,7 @@ init_line() * Expand the line buffer. */ static int -expand_linebuf() +expand_linebuf(VOID_PARAM) { /* Double the size of the line buffer. */ int new_size = size_linebuf * 2; @@ -119,15 +119,7 @@ expand_linebuf() free(new_buf); return 1; } -#if HAVE_REALLOC - /* - * We realloc'd the buffers; they already have the old contents. - */ - #if 0 - memset(new_buf + size_linebuf, 0, new_size - size_linebuf); - memset(new_attr + size_linebuf, 0, new_size - size_linebuf); - #endif -#else +#if !HAVE_REALLOC /* * We just calloc'd the buffers; copy the old contents. */ @@ -156,7 +148,7 @@ is_ascii_char(ch) * Rewind the line buffer. */ public void -prewind() +prewind(VOID_PARAM) { curr = 0; column = 0; @@ -179,7 +171,7 @@ prewind() static void set_linebuf(n, ch, a) int n; - LWCHAR ch; + char ch; char a; { linebuf[n] = ch; @@ -191,7 +183,7 @@ set_linebuf(n, ch, a) */ static void add_linebuf(ch, a, w) - LWCHAR ch; + char ch; char a; int w; { @@ -395,7 +387,7 @@ pshift(shift) * */ public void -pshift_all() +pshift_all(VOID_PARAM) { pshift(column); } @@ -519,7 +511,7 @@ pwidth(ch, a, prev_ch) * Return 1 if one is found. */ static int -backc() +backc(VOID_PARAM) { LWCHAR prev_ch; char *p = linebuf + curr; @@ -547,7 +539,7 @@ backc() * Are we currently within a recognized ANSI escape sequence? */ static int -in_ansi_esc_seq() +in_ansi_esc_seq(VOID_PARAM) { char *p; @@ -1046,7 +1038,7 @@ do_append(ch, rep, pos) * */ public int -pflushmbc() +pflushmbc(VOID_PARAM) { int r = 0; @@ -1063,7 +1055,7 @@ pflushmbc() * Switch to normal attribute at end of line. */ static void -add_attr_normal() +add_attr_normal(VOID_PARAM) { char *p = "\033[m"; @@ -1215,7 +1207,7 @@ gline(i, ap) * Indicate that there is no current line. */ public void -null_line() +null_line(VOID_PARAM) { is_null_line = 1; cshift = 0; @@ -1349,7 +1341,7 @@ back_raw_line(curr_pos, linep, line_lenp) * Find the shift necessary to show the end of the longest displayed line. */ public int -rrshift() +rrshift(VOID_PARAM) { POSITION pos; int save_width; diff --git a/linenum.c b/linenum.c index 4e72637..6a5560b 100644 --- a/linenum.c +++ b/linenum.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -73,7 +73,7 @@ extern int screen_trashed; * Initialize the line number structures. */ public void -clr_linenum() +clr_linenum(VOID_PARAM) { struct linenum_info *p; @@ -209,7 +209,7 @@ add_lnum(linenum, pos) * line number, print a message to tell the user what we're doing. */ static void -longloopmessage() +longloopmessage(VOID_PARAM) { ierror("Calculating line numbers", NULL_PARG); } @@ -220,7 +220,7 @@ static time_type startime; #endif static void -longish() +longish(VOID_PARAM) { #if HAVE_TIME if (loopcount >= 0 && ++loopcount > 100) @@ -246,7 +246,7 @@ longish() * a lengthy line number calculation. */ static void -abort_long() +abort_long(VOID_PARAM) { if (linenums == OPT_ONPLUS) /* diff --git a/lsystem.c b/lsystem.c index 10911eb..d4f1e77 100644 --- a/lsystem.c +++ b/lsystem.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -19,6 +19,10 @@ #if MSDOS_COMPILER #include +#if MSDOS_COMPILER==WIN32C && defined(MINGW) +#include +#define setdisk(n) _chdrive((n)+1) +#else #ifdef _MSC_VER #include #define setdisk(n) _chdrive((n)+1) @@ -26,6 +30,7 @@ #include #endif #endif +#endif extern int screen_trashed; extern IFILE curr_ifile; @@ -291,7 +296,6 @@ pipe_data(cmd, spos, epos) { FILE *f; int c; - extern FILE *popen(); /* * This is structured much like lsystem(). diff --git a/main.c b/main.c index 179bd78..c527e61 100644 --- a/main.c +++ b/main.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -14,6 +14,7 @@ #include "less.h" #if MSDOS_COMPILER==WIN32C +#define WIN32_LEAN_AND_MEAN #include #endif @@ -53,12 +54,13 @@ extern int jump_sline; static char consoleTitle[256]; #endif -public int line_count; +public int one_screen; extern int less_is_more; extern int missing_cap; extern int know_dumb; extern int pr_type; extern int quit_if_one_screen; +extern int no_init; /* @@ -82,7 +84,7 @@ main(argc, argv) secure = 0; s = lgetenv("LESSSECURE"); - if (s != NULL && *s != '\0') + if (!isnullenv(s)) secure = 1; #ifdef WIN32 @@ -112,6 +114,7 @@ main(argc, argv) * Command line arguments override environment arguments. */ is_tty = isatty(1); + init_mark(); init_cmds(); get_term(); expand_cmd_tables(); @@ -125,11 +128,7 @@ main(argc, argv) * If the name of the executable program is "more", * act like LESS_IS_MORE is set. */ - for (s = progname + strlen(progname); s > progname; s--) - { - if (s[-1] == PATHNAME_SEP[0]) - break; - } + s = last_component(progname); if (strcmp(s, "more") == 0) less_is_more = 1; @@ -165,12 +164,12 @@ main(argc, argv) if (editor == NULL || *editor == '\0') { editor = lgetenv("EDITOR"); - if (editor == NULL || *editor == '\0') + if (isnullenv(editor)) editor = EDIT_PGM; } editproto = lgetenv("LESSEDIT"); - if (editproto == NULL || *editproto == '\0') - editproto = "%E ?lm+%lm. %f"; + if (isnullenv(editproto)) + editproto = "%E ?lm+%lm. %g"; #endif /* @@ -220,11 +219,7 @@ main(argc, argv) * Just copy the input file(s) to output. */ SET_BINARY(1); - if (nifile() == 0) - { - if (edit_stdin() == 0) - cat_file(); - } else if (edit_first() == 0) + if (edit_first() == 0) { do { cat_file(); @@ -235,7 +230,6 @@ main(argc, argv) if (missing_cap && !know_dumb) error("WARNING: terminal is not fully functional", NULL_PARG); - init_mark(); open_getchr(); raw_mode(1); init_signals(1); @@ -270,22 +264,20 @@ main(argc, argv) initial_scrpos.ln = jump_sline; } else #endif - if (nifile() == 0) - { - if (edit_stdin()) /* Edit standard input */ - quit(QUIT_ERROR); - if (quit_if_one_screen) - line_count = get_line_count(); - } else { - if (edit_first()) /* Edit first valid file in cmd line */ + if (edit_first()) quit(QUIT_ERROR); + /* + * See if file fits on one screen to decide whether + * to send terminal init. But don't need this + * if -X (no_init) overrides this (see init()). + */ if (quit_if_one_screen) { - if (nifile() == 1) - line_count = get_line_count(); - else /* If more than one file, -F can not be used */ + if (nifile() > 1) /* If more than one file, -F cannot be used */ quit_if_one_screen = FALSE; + else if (!no_init) + one_screen = get_one_screen(); } } diff --git a/mark.c b/mark.c index fbdac6e..92cb8ce 100644 --- a/mark.c +++ b/mark.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -14,30 +14,103 @@ extern IFILE curr_ifile; extern int sc_height; extern int jump_sline; +extern int perma_marks; + +/* + * A mark is an ifile (input file) plus a position within the file. + */ +struct mark +{ + /* + * Normally m_ifile != IFILE_NULL and m_filename == NULL. + * For restored marks we set m_filename instead of m_ifile + * because we don't want to create an ifile until the + * user explicitly requests the file (by name or mark). + */ + char m_letter; /* Associated character */ + IFILE m_ifile; /* Input file being marked */ + char *m_filename; /* Name of the input file */ + struct scrpos m_scrpos; /* Position of the mark */ +}; /* * The table of marks. * Each mark is identified by a lowercase or uppercase letter. * The final one is lmark, for the "last mark"; addressed by the apostrophe. */ -#define NMARKS ((2*26)+1) /* a-z, A-Z, lastmark */ +#define NMARKS ((2*26)+2) /* a-z, A-Z, mousemark, lastmark */ +#define NUMARKS ((2*26)+1) /* user marks (not lastmark) */ +#define MOUSEMARK (NMARKS-2) #define LASTMARK (NMARKS-1) static struct mark marks[NMARKS]; +public int marks_modified = 0; + + +/* + * Initialize a mark struct. + */ + static void +cmark(m, ifile, pos, ln) + struct mark *m; + IFILE ifile; + POSITION pos; + int ln; +{ + m->m_ifile = ifile; + m->m_scrpos.pos = pos; + m->m_scrpos.ln = ln; + m->m_filename = NULL; +} /* * Initialize the mark table to show no marks are set. */ public void -init_mark() +init_mark(VOID_PARAM) { int i; for (i = 0; i < NMARKS; i++) - marks[i].m_scrpos.pos = NULL_POSITION; + { + char letter; + switch (i) { + case MOUSEMARK: letter = '#'; break; + case LASTMARK: letter = '\''; break; + default: letter = (i < 26) ? 'a'+i : 'A'+i-26; break; + } + marks[i].m_letter = letter; + cmark(&marks[i], NULL_IFILE, NULL_POSITION, -1); + } } /* - * See if a mark letter is valid (between a and z). + * Set m_ifile and clear m_filename. + */ + static void +mark_set_ifile(m, ifile) + struct mark *m; + IFILE ifile; +{ + m->m_ifile = ifile; + /* With m_ifile set, m_filename is no longer needed. */ + free(m->m_filename); + m->m_filename = NULL; +} + +/* + * Populate the m_ifile member of a mark struct from m_filename. + */ + static void +mark_get_ifile(m) + struct mark *m; +{ + if (m->m_ifile != NULL_IFILE) + return; /* m_ifile is already set */ + mark_set_ifile(m, get_ifile(m->m_filename, prev_ifile(NULL_IFILE))); +} + +/* + * Return the user mark struct identified by a character. */ static struct mark * getumark(c) @@ -45,17 +118,17 @@ getumark(c) { if (c >= 'a' && c <= 'z') return (&marks[c-'a']); - if (c >= 'A' && c <= 'Z') return (&marks[c-'A'+26]); - + if (c == '#') + return (&marks[MOUSEMARK]); error("Invalid mark letter", NULL_PARG); return (NULL); } /* * Get the mark structure identified by a character. - * The mark struct may come either from the mark table + * The mark struct may either be in the mark table (user mark) * or may be constructed on the fly for certain characters like ^, $. */ static struct mark * @@ -72,9 +145,7 @@ getmark(c) * Beginning of the current file. */ m = &sm; - m->m_scrpos.pos = ch_zero(); - m->m_scrpos.ln = 0; - m->m_ifile = curr_ifile; + cmark(m, curr_ifile, ch_zero(), 0); break; case '$': /* @@ -86,9 +157,7 @@ getmark(c) return (NULL); } m = &sm; - m->m_scrpos.pos = ch_tell(); - m->m_scrpos.ln = sc_height; - m->m_ifile = curr_ifile; + cmark(m, curr_ifile, ch_tell(), sc_height); break; case '.': /* @@ -96,7 +165,7 @@ getmark(c) */ m = &sm; get_scrpos(&m->m_scrpos, TOP); - m->m_ifile = curr_ifile; + cmark(m, curr_ifile, m->m_scrpos.pos, m->m_scrpos.ln); break; case '\'': /* @@ -122,7 +191,7 @@ getmark(c) } /* - * Is a mark letter is invalid? + * Is a mark letter invalid? */ public int badmark(c) @@ -146,8 +215,13 @@ setmark(c, where) if (m == NULL) return; get_scrpos(&scrpos, where); - m->m_scrpos = scrpos; - m->m_ifile = curr_ifile; + if (scrpos.pos == NULL_POSITION) + { + bell(); + return; + } + cmark(m, curr_ifile, scrpos.pos, scrpos.ln); + marks_modified = 1; } /* @@ -162,14 +236,20 @@ clrmark(c) m = getumark(c); if (m == NULL) return; + if (m->m_scrpos.pos == NULL_POSITION) + { + bell(); + return; + } m->m_scrpos.pos = NULL_POSITION; + marks_modified = 1; } /* * Set lmark (the mark named by the apostrophe). */ public void -lastmark() +lastmark(VOID_PARAM) { struct scrpos scrpos; @@ -178,8 +258,7 @@ lastmark() get_scrpos(&scrpos, TOP); if (scrpos.pos == NULL_POSITION) return; - marks[LASTMARK].m_scrpos = scrpos; - marks[LASTMARK].m_ifile = curr_ifile; + cmark(&marks[LASTMARK], curr_ifile, scrpos.pos, scrpos.ln); } /* @@ -200,19 +279,14 @@ gomark(c) * If we're trying to go to the lastmark and * it has not been set to anything yet, * set it to the beginning of the current file. + * {{ Couldn't we instead set marks[LASTMARK] in edit()? }} */ if (m == &marks[LASTMARK] && m->m_scrpos.pos == NULL_POSITION) - { - m->m_ifile = curr_ifile; - m->m_scrpos.pos = ch_zero(); - m->m_scrpos.ln = jump_sline; - } + cmark(m, curr_ifile, ch_zero(), jump_sline); - /* - * If we're using lmark, we must save the screen position now, - * because if we call edit_ifile() below, lmark will change. - * (We save the screen position even if we're not using lmark.) - */ + mark_get_ifile(m); + + /* Save scrpos; if it's LASTMARK it could change in edit_ifile. */ scrpos = m->m_scrpos; if (m->m_ifile != curr_ifile) { @@ -260,13 +334,14 @@ posmark(pos) { int i; - /* Only lower case and upper case letters */ - for (i = 0; i < 26*2; i++) + /* Only user marks */ + for (i = 0; i < NUMARKS; i++) { if (marks[i].m_ifile == curr_ifile && marks[i].m_scrpos.pos == pos) { if (i < 26) return 'a' + i; - return 'A' + i - 26; + if (i < 26*2) return 'A' + (i - 26); + return '#'; } } return 0; @@ -285,3 +360,97 @@ unmark(ifile) if (marks[i].m_ifile == ifile) marks[i].m_scrpos.pos = NULL_POSITION; } + +/* + * Check if any marks refer to a specified ifile vi m_filename + * rather than m_ifile. + */ + public void +mark_check_ifile(ifile) + IFILE ifile; +{ + int i; + char *filename = lrealpath(get_filename(ifile)); + + for (i = 0; i < NMARKS; i++) + { + struct mark *m = &marks[i]; + char *mark_filename = m->m_filename; + if (mark_filename != NULL) + { + mark_filename = lrealpath(mark_filename); + if (strcmp(filename, mark_filename) == 0) + mark_set_ifile(m, ifile); + free(mark_filename); + } + } + free(filename); +} + +#if CMD_HISTORY + +/* + * Save marks to history file. + */ + public void +save_marks(fout, hdr) + FILE *fout; + char *hdr; +{ + int i; + + if (!perma_marks) + return; + + fprintf(fout, "%s\n", hdr); + for (i = 0; i < NUMARKS; i++) + { + char *filename; + struct mark *m = &marks[i]; + char pos_str[INT_STRLEN_BOUND(m->m_scrpos.pos) + 2]; + if (m->m_scrpos.pos == NULL_POSITION) + continue; + postoa(m->m_scrpos.pos, pos_str); + filename = m->m_filename; + if (filename == NULL) + filename = get_filename(m->m_ifile); + filename = lrealpath(filename); + if (strcmp(filename, "-") != 0) + fprintf(fout, "m %c %d %s %s\n", + m->m_letter, m->m_scrpos.ln, pos_str, filename); + free(filename); + } +} + +/* + * Restore one mark from the history file. + */ + public void +restore_mark(line) + char *line; +{ + struct mark *m; + int ln; + POSITION pos; + +#define skip_whitespace while (*line == ' ') line++ + if (*line++ != 'm') + return; + skip_whitespace; + m = getumark(*line++); + if (m == NULL) + return; + skip_whitespace; + ln = lstrtoi(line, &line); + if (ln < 1) + ln = 1; + if (ln > sc_height) + ln = sc_height; + skip_whitespace; + pos = lstrtopos(line, &line); + skip_whitespace; + cmark(m, NULL_IFILE, pos, ln); + m->m_filename = save(line); +} + +#endif /* CMD_HISTORY */ diff --git a/mkutable b/mkutable index 2760628..b7c3e68 100755 --- a/mkutable +++ b/mkutable @@ -4,7 +4,7 @@ use strict; my $USAGE = <<__EOF__; usage: mkutable [-n] [-f#] type... [--] [<] UnicodeData.txt -n = take non-matching types - -f = zero-based type field (default 2) + -f = zero-based type field (default 2) __EOF__ use vars qw( $opt_f $opt_n ); diff --git a/optfunc.c b/optfunc.c index 9185c01..7fe947e 100644 --- a/optfunc.c +++ b/optfunc.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -50,8 +50,10 @@ extern int jump_sline; extern long jump_sline_fraction; extern int shift_count; extern long shift_count_fraction; -extern LWCHAR rscroll_char; +extern char rscroll_char; extern int rscroll_attr; +extern int mousecap; +extern int wheel_lines; extern int less_is_more; #if LOGFILE extern char *namelogfile; @@ -203,7 +205,7 @@ opt_j(type, s) } public void -calc_jump_sline() +calc_jump_sline(VOID_PARAM) { if (jump_sline_fraction < 0) return; @@ -267,7 +269,7 @@ opt_shift(type, s) } } public void -calc_shift_count() +calc_shift_count(VOID_PARAM) { if (shift_count_fraction < 0) return; @@ -509,33 +511,13 @@ opt__V(type, s) putstr("less "); putstr(version); putstr(" ("); -#if HAVE_GNU_REGEX - putstr("GNU "); -#endif -#if HAVE_POSIX_REGCOMP - putstr("POSIX "); -#endif -#if HAVE_PCRE - putstr("PCRE "); -#endif -#if HAVE_RE_COMP - putstr("BSD "); -#endif -#if HAVE_REGCMP - putstr("V8 "); -#endif -#if HAVE_V8_REGCOMP - putstr("Spencer V8 "); -#endif -#if !HAVE_GNU_REGEX && !HAVE_POSIX_REGCOMP && !HAVE_PCRE && !HAVE_RE_COMP && !HAVE_REGCMP && !HAVE_V8_REGCOMP - putstr("no "); -#endif - putstr("regular expressions)\n"); - putstr("Copyright (C) 1984-2017 Mark Nudelman\n\n"); + putstr(pattern_lib_name()); + putstr(" regular expressions)\n"); + putstr("Copyright (C) 1984-2019 Mark Nudelman\n\n"); putstr("less comes with NO WARRANTY, to the extent permitted by law.\n"); putstr("For information about the terms of redistribution,\n"); putstr("see the file named README in the less distribution.\n"); - putstr("Homepage: http://www.greenwoodsoftware.com/less\n"); + putstr("Home page: http://www.greenwoodsoftware.com/less\n"); quit(QUIT_OK); break; } @@ -809,10 +791,54 @@ opt_query(type, s) } /* + * Handler for the --mouse option. + */ + /*ARGSUSED*/ + public void +opt_mousecap(type, s) + int type; + char *s; +{ + switch (type) + { + case TOGGLE: + if (mousecap == OPT_OFF) + deinit_mouse(); + else + init_mouse(); + break; + case INIT: + case QUERY: + break; + } +} + +/* + * Handler for the --wheel-lines option. + */ + /*ARGSUSED*/ + public void +opt_wheel_lines(type, s) + int type; + char *s; +{ + switch (type) + { + case INIT: + case TOGGLE: + if (wheel_lines <= 0) + wheel_lines = default_wheel_lines(); + break; + case QUERY: + break; + } +} + +/* * Get the "screen window" size. */ public int -get_swindow() +get_swindow(VOID_PARAM) { if (swindow > 0) return (swindow); diff --git a/option.c b/option.c index 8ba67bc..d402e11 100644 --- a/option.c +++ b/option.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -150,8 +150,11 @@ scan_option(s) if (s == NULL) return; if (*str == '+') + { + if (every_first_cmd != NULL) + free(every_first_cmd); every_first_cmd = save(str+1); - else + } else { ungetcc(CHAR_END_COMMAND); ungetsc(str); @@ -530,7 +533,7 @@ opt_prompt(o) * the previous option. */ public int -isoptpending() +isoptpending(VOID_PARAM) { return (pendopt != NULL); } @@ -551,7 +554,7 @@ nostring(printopt) * Print error message if a STRING type option is not followed by a string. */ public void -nopendopt() +nopendopt(VOID_PARAM) { nostring(opt_desc(pendopt)); } @@ -699,7 +702,7 @@ getfraction(sp, printopt, errp) * Get the value of the -e flag. */ public int -get_quit_at_eof() +get_quit_at_eof(VOID_PARAM) { if (!less_is_more) return quit_at_eof; diff --git a/option.h b/option.h index b253da8..fb73416 100644 --- a/option.h +++ b/option.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. diff --git a/opttbl.c b/opttbl.c index 0c68ccc..967761c 100644 --- a/opttbl.c +++ b/opttbl.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -53,8 +53,12 @@ public int quit_on_intr; /* Quit on interrupt */ public int follow_mode; /* F cmd Follows file desc or file name? */ public int oldbot; /* Old bottom of screen behavior {{REMOVE}} */ public int opt_use_backslash; /* Use backslash escaping in option parsing */ -public LWCHAR rscroll_char; /* Char which marks chopped lines with -S */ +public char rscroll_char; /* Char which marks chopped lines with -S */ public int rscroll_attr; /* Attribute of rscroll_char */ +public int no_hist_dups; /* Remove dups from history list */ +public int mousecap; /* Allow mouse for scrolling */ +public int wheel_lines; /* Number of lines to scroll on mouse wheel scroll */ +public int perma_marks; /* Save marks in history file */ #if HILITE_SEARCH public int hilite_search; /* Highlight matched search patterns? */ #endif @@ -120,6 +124,10 @@ static struct optname oldbot_optname = { "old-bot", NULL }; static struct optname follow_optname = { "follow-name", NULL }; static struct optname use_backslash_optname = { "use-backslash", NULL }; static struct optname rscroll_optname = { "rscroll", NULL }; +static struct optname nohistdups_optname = { "no-histdups", NULL }; +static struct optname mousecap_optname = { "mouse", NULL }; +static struct optname wheel_lines_optname = { "wheel-lines", NULL }; +static struct optname perma_marks_optname = { "save-marks", NULL }; /* @@ -463,6 +471,38 @@ static struct loption option[] = STRING|REPAINT|INIT_HANDLER, 0, NULL, opt_rscroll, { "right scroll character: ", NULL, NULL } }, + { OLETTER_NONE, &nohistdups_optname, + BOOL, OPT_OFF, &no_hist_dups, NULL, + { + "Allow duplicates in history list", + "Remove duplicates from history list", + NULL + } + }, + { OLETTER_NONE, &mousecap_optname, + TRIPLE, OPT_OFF, &mousecap, opt_mousecap, + { + "Ignore mouse input", + "Use the mouse for scrolling", + "Use the mouse for scrolling (reverse)" + } + }, + { OLETTER_NONE, &wheel_lines_optname, + NUMBER|INIT_HANDLER, 0, &wheel_lines, opt_wheel_lines, + { + "Lines to scroll on mouse wheel: ", + "Scroll %d line(s) on mouse wheel", + NULL + } + }, + { OLETTER_NONE, &perma_marks_optname, + BOOL, OPT_OFF, &perma_marks, NULL, + { + "Don't save marks in history file", + "Save marks in history file", + NULL + } + }, { '\0', NULL, NOVAR, 0, NULL, NULL, { NULL, NULL, NULL } } }; @@ -471,13 +511,13 @@ static struct loption option[] = * Initialize each option to its default value. */ public void -init_option() +init_option(VOID_PARAM) { struct loption *o; char *p; p = lgetenv("LESS_IS_MORE"); - if (p != NULL && *p != '\0') + if (!isnullenv(p)) less_is_more = 1; for (o = option; o->oletter != '\0'; o++) diff --git a/os.c b/os.c index df11761..53c82e4 100644 --- a/os.c +++ b/os.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -176,7 +176,7 @@ start: * Interrupt a pending iread(). */ public void -intread() +intread(VOID_PARAM) { LONG_JUMP(read_label, 1); } @@ -186,7 +186,7 @@ intread() */ #if HAVE_TIME public time_type -get_time() +get_time(VOID_PARAM) { time_type t; diff --git a/output.c b/output.c index c6a9981..0563cf0 100644 --- a/output.c +++ b/output.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -50,7 +50,7 @@ extern int have_ul; * Display the line which is in the line buffer. */ public void -put_line() +put_line(VOID_PARAM) { int c; int i; @@ -100,7 +100,7 @@ static char *ob = obuf; * overwritten or scrolled away. */ public void -flush() +flush(VOID_PARAM) { int n; int fd; @@ -483,6 +483,27 @@ TYPE_TO_A_FUNC(linenumtoa, LINENUM) TYPE_TO_A_FUNC(inttoa, int) /* + * Convert an string to an integral type. + */ +#define STR_TO_TYPE_FUNC(funcname, type) \ +type funcname(buf, ebuf) \ + char *buf; \ + char **ebuf; \ +{ \ + type val = 0; \ + for (;;) { \ + char c = *buf++; \ + if (c < '0' || c > '9') break; \ + val = 10 * val + c - '0'; \ + } \ + if (ebuf != NULL) *ebuf = buf; \ + return val; \ +} + +STR_TO_TYPE_FUNC(lstrtopos, POSITION); +STR_TO_TYPE_FUNC(lstrtoi, int); + +/* * Output an integer in a given radix. */ static int @@ -566,7 +587,7 @@ less_printf(fmt, parg) * become the next command. */ public void -get_return() +get_return(VOID_PARAM) { int c; diff --git a/pattern.c b/pattern.c index 563bde0..da27dc6 100644 --- a/pattern.c +++ b/pattern.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -14,6 +14,7 @@ #include "less.h" extern int caseless; +extern int utf_mode; /* * Compile a search pattern, for future use by match_pattern. @@ -63,11 +64,11 @@ compile_pattern2(pattern, search_type, comp_pattern, show_error) *comp_pattern = comp; #endif #if HAVE_PCRE - pcre *comp; constant char *errstring; int erroffset; PARG parg; - comp = pcre_compile(pattern, 0, + pcre *comp = pcre_compile(pattern, + (utf_mode) ? PCRE_UTF8 | PCRE_NO_UTF8_CHECK : 0, &errstring, &erroffset, NULL); if (comp == NULL) { @@ -78,6 +79,25 @@ compile_pattern2(pattern, search_type, comp_pattern, show_error) } *comp_pattern = comp; #endif +#if HAVE_PCRE2 + int errcode; + PCRE2_SIZE erroffset; + PARG parg; + pcre2_code *comp = pcre2_compile((PCRE2_SPTR)pattern, strlen(pattern), + 0, &errcode, &erroffset, NULL); + if (comp == NULL) + { + if (show_error) + { + char msg[160]; + pcre2_get_error_message(errcode, (PCRE2_UCHAR*)msg, sizeof(msg)); + parg.p_string = msg; + error("%s", &parg); + } + return (-1); + } + *comp_pattern = comp; +#endif #if HAVE_RE_COMP PARG parg; if ((parg.p_string = re_comp(pattern)) != NULL) @@ -174,6 +194,11 @@ uncompile_pattern(pattern) pcre_free(*pattern); *pattern = NULL; #endif +#if HAVE_PCRE2 + if (*pattern != NULL) + pcre2_code_free(*pattern); + *pattern = NULL; +#endif #if HAVE_RE_COMP *pattern = 0; #endif @@ -223,6 +248,9 @@ is_null_pattern(pattern) #if HAVE_PCRE return (pattern == NULL); #endif +#if HAVE_PCRE2 + return (pattern == NULL); +#endif #if HAVE_RE_COMP return (pattern == 0); #endif @@ -351,6 +379,21 @@ match_pattern(pattern, tpattern, line, line_len, sp, ep, notbol, search_type) } } #endif +#if HAVE_PCRE2 + { + int flags = (notbol) ? PCRE2_NOTBOL : 0; + pcre2_match_data *md = pcre2_match_data_create(3, NULL); + matched = pcre2_match(pattern, (PCRE2_SPTR)line, line_len, + 0, flags, md, NULL) >= 0; + if (matched) + { + PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(md); + *sp = line + ovector[0]; + *ep = line + ovector[1]; + } + pcre2_match_data_free(md); + } +#endif #if HAVE_RE_COMP matched = (re_exec(line) == 1); /* @@ -382,3 +425,39 @@ match_pattern(pattern, tpattern, line, line_len, sp, ep, notbol, search_type) return (matched); } +/* + * Return the name of the pattern matching library. + */ + public char * +pattern_lib_name(VOID_PARAM) +{ +#if HAVE_GNU_REGEX + return ("GNU"); +#else +#if HAVE_POSIX_REGCOMP + return ("POSIX"); +#else +#if HAVE_PCRE2 + return ("PCRE2"); +#else +#if HAVE_PCRE + return ("PCRE"); +#else +#if HAVE_RE_COMP + return ("BSD"); +#else +#if HAVE_REGCMP + return ("V8"); +#else +#if HAVE_V8_REGCOMP + return ("Spencer V8"); +#else + return ("no"); +#endif +#endif +#endif +#endif +#endif +#endif +#endif +} diff --git a/pattern.h b/pattern.h index 7bde5c7..19ce5b9 100644 --- a/pattern.h +++ b/pattern.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -31,6 +31,13 @@ #define CLEAR_PATTERN(name) name = NULL #endif +#if HAVE_PCRE2 +#define PCRE2_CODE_UNIT_WIDTH 8 +#include +#define PATTERN_TYPE pcre2_code * +#define CLEAR_PATTERN(name) name = NULL +#endif + #if HAVE_RE_COMP char *re_comp LESSPARAMS ((char*)); int re_exec LESSPARAMS ((char*)); diff --git a/pckeys.h b/pckeys.h index e0d86e7..fb345f2 100644 --- a/pckeys.h +++ b/pckeys.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. diff --git a/position.c b/position.c index ae3899c..8a65ed4 100644 --- a/position.c +++ b/position.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -22,7 +22,7 @@ #include "position.h" static POSITION *table = NULL; /* The position table */ -static int table_size; +static int table_size = 0; extern int sc_width, sc_height; @@ -92,7 +92,7 @@ add_back_pos(pos) * Initialize the position table, done whenever we clear the screen. */ public void -pos_clear() +pos_clear(VOID_PARAM) { int i; @@ -104,7 +104,7 @@ pos_clear() * Allocate or reallocate the position table. */ public void -pos_init() +pos_init(VOID_PARAM) { struct scrpos scrpos; @@ -150,7 +150,7 @@ onscreen(pos) * See if the entire screen is empty. */ public int -empty_screen() +empty_screen(VOID_PARAM) { return (empty_lines(0, sc_height-1)); } @@ -187,8 +187,20 @@ get_scrpos(scrpos, where) switch (where) { - case TOP: i = 0; dir = +1; last = sc_height-2; break; - default: i = sc_height-2; dir = -1; last = 0; break; + case TOP: + i = 0; dir = +1; last = sc_height-2; + break; + case BOTTOM: case BOTTOM_PLUS_ONE: + i = sc_height-2; dir = -1; last = 0; + break; + default: + i = where; + if (table[i] == NULL_POSITION) { + scrpos->pos = NULL_POSITION; + return; + } + /* Values of dir and last don't matter after this. */ + break; } /* diff --git a/position.h b/position.h index 3067896..77216da 100644 --- a/position.h +++ b/position.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. diff --git a/prompt.c b/prompt.c index 3067d2b..12413fb 100644 --- a/prompt.c +++ b/prompt.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -66,7 +66,7 @@ static char *mp; * Initialize the prompt prototype strings. */ public void -init_prompt() +init_prompt(VOID_PARAM) { prproto[0] = save(s_proto); prproto[1] = save(less_is_more ? more_proto : m_proto); @@ -150,7 +150,7 @@ ap_int(num) * Append a question mark to the end of the message. */ static void -ap_quest() +ap_quest(VOID_PARAM) { ap_str("?"); } @@ -196,10 +196,13 @@ cond(c, where) case 'e': /* At end of file? */ return (eof_displayed()); case 'f': /* Filename known? */ + case 'g': return (strcmp(get_filename(curr_ifile), "-") != 0); case 'l': /* Line number known? */ case 'd': /* Same as l */ - return (linenums); + if (!linenums) + return 0; + return (currline(where) != 0); case 'L': /* Final line number known? */ case 'D': /* Final page number known? */ return (linenums && ch_length() != NULL_POSITION); @@ -254,6 +257,7 @@ protochar(c, where, iseditproto) LINENUM linenum; LINENUM last_linenum; IFILE h; + char *s; #undef PAGE_NUM #define PAGE_NUM(linenum) ((((linenum) - 1) / (sc_height - 1)) + 1) @@ -305,6 +309,11 @@ protochar(c, where, iseditproto) case 'F': /* Last component of file name */ ap_str(last_component(get_filename(curr_ifile))); break; + case 'g': /* Shell-escaped file name */ + s = shell_quote(get_filename(curr_ifile)); + ap_str(s); + free(s); + break; case 'i': /* Index into list of files */ #if TAGS if (ntags()) @@ -551,7 +560,7 @@ pr_expand(proto, maxwidth) * Return a message suitable for printing by the "=" command. */ public char * -eq_message() +eq_message(VOID_PARAM) { return (pr_expand(eqproto, 0)); } @@ -563,7 +572,7 @@ eq_message() * and the caller will prompt with a colon. */ public char * -pr_string() +pr_string(VOID_PARAM) { char *prompt; int type; @@ -580,7 +589,7 @@ pr_string() * Return a message suitable for printing while waiting in the F command. */ public char * -wait_message() +wait_message(VOID_PARAM) { return (pr_expand(wproto, sc_width-so_s_width-so_e_width-2)); } diff --git a/screen.c b/screen.c index dfee5d2..cd25d74 100644 --- a/screen.c +++ b/screen.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -120,7 +120,8 @@ struct keyRecord static int keyCount = 0; static WORD curr_attr; static int pending_scancode = 0; -static WORD *whitescreen; +static char x11mousebuf[] = "[M???"; /* Mouse report, after ESC */ +static int x11mousePos, x11mouseCount; static HANDLE con_out_save = INVALID_HANDLE_VALUE; /* previous console */ static HANDLE con_out_ours = INVALID_HANDLE_VALUE; /* our own */ @@ -187,6 +188,8 @@ static char *sc_backspace, /* Backspace cursor */ *sc_s_keypad, /* Start keypad mode */ *sc_e_keypad, /* End keypad mode */ + *sc_s_mousecap, /* Start mouse capture mode */ + *sc_e_mousecap, /* End mouse capture mode */ *sc_init, /* Startup terminal initialization */ *sc_deinit; /* Exit terminal de-initialization */ #endif @@ -211,8 +214,9 @@ public int missing_cap = 0; /* Some capability is missing */ public char *kent = NULL; /* Keypad ENTER sequence */ static int attrmode = AT_NORMAL; +static int termcap_debug = -1; extern int binattr; -extern int line_count; +extern int one_screen; #if !MSDOS_COMPILER static char *cheaper(); @@ -240,13 +244,18 @@ extern int no_keypad; extern int sigs; extern int wscroll; extern int screen_trashed; -extern int tty; extern int top_scroll; extern int quit_if_one_screen; extern int oldbot; +extern int mousecap; #if HILITE_SEARCH extern int hilite_search; #endif +#if MSDOS_COMPILER==WIN32C +extern HANDLE tty; +#else +extern int tty; +#endif extern char *tgetstr(); extern char *tgoto(); @@ -632,11 +641,10 @@ static int hardcopy; ltget_env(capname) char *capname; { - char name[16]; + char name[64]; char *s; - s = lgetenv("LESS_TERMCAP_DEBUG"); - if (s != NULL && *s != '\0') + if (termcap_debug) { struct env { struct env *next; char *name; char *value; }; static struct env *envs = NULL; @@ -652,8 +660,7 @@ ltget_env(capname) envs = p; return p->value; } - strcpy(name, "LESS_TERMCAP_"); - strcat(name, capname); + SNPRINTF1(name, sizeof(name), "LESS_TERMCAP_%s", capname); return (lgetenv(name)); } @@ -702,7 +709,7 @@ ltgetstr(capname, pp) * Get size of the output screen. */ public void -scrsize() +scrsize(VOID_PARAM) { char *s; int sys_height; @@ -832,7 +839,7 @@ scrsize() * Figure out how many empty loops it takes to delay a millisecond. */ static void -get_clock() +get_clock(VOID_PARAM) { clock_t start; @@ -860,13 +867,6 @@ get_clock() * Delay for a specified number of milliseconds. */ static void -dummy_func() -{ - static long delay_dummy = 0; - delay_dummy++; -} - - static void delay(msec) int msec; { @@ -875,13 +875,7 @@ delay(msec) while (msec-- > 0) { for (i = 0; i < msec_loops; i++) - { - /* - * Make it look like we're doing something here, - * so the optimizer doesn't remove the whole loop. - */ - dummy_func(); - } + (void) clock(); } } #endif @@ -949,17 +943,13 @@ special_key_str(key) s = windowid ? ltgetstr("@7", &sp) : k_end; break; case SK_DELETE: - if (windowid) + s = windowid ? ltgetstr("kD", &sp) : k_delete; + if (s == NULL) { - s = ltgetstr("kD", &sp); - if (s == NULL) - { - tbuf[0] = '\177'; - tbuf[1] = '\0'; - s = tbuf; - } - } else - s = k_delete; + tbuf[0] = '\177'; + tbuf[1] = '\0'; + s = tbuf; + } break; #endif #if MSDOS_COMPILER @@ -1063,8 +1053,9 @@ special_key_str(key) * Get terminal capabilities via termcap. */ public void -get_term() +get_term(VOID_PARAM) { + termcap_debug = !isnullenv(lgetenv("LESS_TERMCAP_DEBUG")); #if MSDOS_COMPILER auto_wrap = 1; ignaw = 0; @@ -1127,7 +1118,7 @@ get_term() #else /* !MSDOS_COMPILER */ - +{ char *sp; char *t1, *t2; char *term; @@ -1140,7 +1131,7 @@ get_term() * Make sure the termcap database is available. */ sp = lgetenv("TERMCAP"); - if (sp == NULL || *sp == '\0') + if (isnullenv(sp)) { char *termcap; if ((sp = homefile("termcap.dat")) != NULL) @@ -1220,6 +1211,13 @@ get_term() sc_e_keypad = ""; kent = ltgetstr("@8", &sp); + sc_s_mousecap = ltgetstr("MOUSE_START", &sp); + if (sc_s_mousecap == NULL) + sc_s_mousecap = ESCS "[?1000h" ESCS "[?1006h"; + sc_e_mousecap = ltgetstr("MOUSE_END", &sp); + if (sc_e_mousecap == NULL) + sc_e_mousecap = ESCS "[?1006l" ESCS "[?1000l"; + sc_init = ltgetstr("ti", &sp); if (sc_init == NULL) sc_init = ""; @@ -1347,6 +1345,7 @@ get_term() */ no_back_scroll = 1; } +} #endif /* MSDOS_COMPILER */ } @@ -1459,7 +1458,7 @@ _settextposition(int row, int col) * Initialize the screen to the correct color at startup. */ static void -initcolor() +initcolor(VOID_PARAM) { #if MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC intensevideo(); @@ -1495,7 +1494,7 @@ initcolor() * Termcap-like init with a private win32 console. */ static void -win32_init_term() +win32_init_term(VOID_PARAM) { CONSOLE_SCREEN_BUFFER_INFO scr; COORD size; @@ -1537,8 +1536,8 @@ win32_init_term() /* * Restore the startup console. */ -static void -win32_deinit_term() + static void +win32_deinit_term(VOID_PARAM) { if (con_out_save == INVALID_HANDLE_VALUE) return; @@ -1551,18 +1550,56 @@ win32_deinit_term() #endif /* + * Configure the termimal so mouse clicks and wheel moves + * produce input to less. + */ + public void +init_mouse(VOID_PARAM) +{ + if (!mousecap) + return; +#if !MSDOS_COMPILER + tputs(sc_s_mousecap, sc_height, putchr); +#else +#if MSDOS_COMPILER==WIN32C + SetConsoleMode(tty, ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT); +#endif +#endif +} + +/* + * Configure the terminal so mouse clicks and wheel moves + * are handled by the system (so text can be selected, etc). + */ + public void +deinit_mouse(VOID_PARAM) +{ + if (!mousecap) + return; +#if !MSDOS_COMPILER + tputs(sc_e_mousecap, sc_height, putchr); +#else +#if MSDOS_COMPILER==WIN32C + SetConsoleMode(tty, ENABLE_PROCESSED_INPUT); +#endif +#endif +} + +/* * Initialize terminal */ public void -init() +init(VOID_PARAM) { #if !MSDOS_COMPILER - if (quit_if_one_screen && line_count >= sc_height) - quit_if_one_screen = FALSE; - if (!no_init && !quit_if_one_screen) - tputs(sc_init, sc_height, putchr); - if (!no_keypad) - tputs(sc_s_keypad, sc_height, putchr); + if (!(quit_if_one_screen && one_screen)) + { + if (!no_init) + tputs(sc_init, sc_height, putchr); + if (!no_keypad) + tputs(sc_s_keypad, sc_height, putchr); + init_mouse(); + } if (top_scroll) { int i; @@ -1592,15 +1629,19 @@ init() * Deinitialize terminal */ public void -deinit() +deinit(VOID_PARAM) { if (!init_done) return; #if !MSDOS_COMPILER - if (!no_keypad) - tputs(sc_e_keypad, sc_height, putchr); - if (!no_init && !quit_if_one_screen) - tputs(sc_deinit, sc_height, putchr); + if (!(quit_if_one_screen && one_screen)) + { + deinit_mouse(); + if (!no_keypad) + tputs(sc_e_keypad, sc_height, putchr); + if (!no_init) + tputs(sc_deinit, sc_height, putchr); + } #else /* Restore system colors. */ SETCOLORS(sy_fg_color, sy_bg_color); @@ -1619,7 +1660,7 @@ deinit() * Home cursor (move to upper left corner of screen). */ public void -home() +home(VOID_PARAM) { #if !MSDOS_COMPILER tputs(sc_home, 1, putchr); @@ -1634,7 +1675,7 @@ home() * Should scroll the display down. */ public void -add_line() +add_line(VOID_PARAM) { #if !MSDOS_COMPILER tputs(sc_addline, sc_height, putchr); @@ -1746,7 +1787,7 @@ remove_top(n) * Clear the screen. */ static void -win32_clear() +win32_clear(VOID_PARAM) { /* * This will clear only the currently visible rows of the NT @@ -1843,7 +1884,7 @@ win32_scroll_up(n) * Move cursor to lower left corner of screen. */ public void -lower_left() +lower_left(VOID_PARAM) { if (!init_done) return; @@ -1859,7 +1900,7 @@ lower_left() * Move cursor to left position of current line. */ public void -line_left() +line_left(VOID_PARAM) { #if !MSDOS_COMPILER tputs(sc_return, 1, putchr); @@ -1891,7 +1932,7 @@ line_left() * (in lieu of SIGWINCH for WIN32). */ public void -check_winch() +check_winch(VOID_PARAM) { #if MSDOS_COMPILER==WIN32C CONSOLE_SCREEN_BUFFER_INFO scr; @@ -1940,7 +1981,7 @@ goto_line(sindex) * {{ Yuck! There must be a better way to get a visual bell. }} */ static void -create_flash() +create_flash(VOID_PARAM) { #if MSDOS_COMPILER==MSOFTC struct videoconfig w; @@ -1977,18 +2018,6 @@ create_flash() return; for (n = 0; n < sc_width * sc_height; n++) whitescreen[n] = 0x7020; -#else -#if MSDOS_COMPILER==WIN32C - int n; - - whitescreen = (WORD *) - malloc(sc_height * sc_width * sizeof(WORD)); - if (whitescreen == NULL) - return; - /* Invert the standard colors. */ - for (n = 0; n < sc_width * sc_height; n++) - whitescreen[n] = (WORD)((nm_fg_color << 4) | nm_bg_color); -#endif #endif #endif flash_created = 1; @@ -1999,7 +2028,7 @@ create_flash() * Output the "visual bell", if there is one. */ public void -vbell() +vbell(VOID_PARAM) { #if !MSDOS_COMPILER if (*sc_visual_bell == '\0') @@ -2063,7 +2092,7 @@ vbell() * Make a noise. */ static void -beep() +beep(VOID_PARAM) { #if !MSDOS_COMPILER putchr(CONTROL('G')); @@ -2080,7 +2109,7 @@ beep() * Ring the terminal bell. */ public void -bell() +bell(VOID_PARAM) { if (quiet == VERY_QUIET) vbell(); @@ -2092,7 +2121,7 @@ bell() * Clear the screen. */ public void -clear() +clear(VOID_PARAM) { #if !MSDOS_COMPILER tputs(sc_clear, sc_height, putchr); @@ -2111,7 +2140,7 @@ clear() * {{ This must not move the cursor. }} */ public void -clear_eol() +clear_eol(VOID_PARAM) { #if !MSDOS_COMPILER tputs(sc_eol_clear, 1, putchr); @@ -2170,7 +2199,7 @@ clear_eol() * Clear the screen if there's off-screen memory below the display. */ static void -clear_eol_bot() +clear_eol_bot(VOID_PARAM) { #if MSDOS_COMPILER clear_eol(); @@ -2187,7 +2216,7 @@ clear_eol_bot() * Leave the cursor at the beginning of the bottom line. */ public void -clear_bot() +clear_bot(VOID_PARAM) { /* * If we're in a non-normal attribute mode, temporarily exit @@ -2251,7 +2280,7 @@ at_enter(attr) } public void -at_exit() +at_exit(VOID_PARAM) { #if !MSDOS_COMPILER /* Undo things in the reverse order we did them. */ @@ -2315,7 +2344,7 @@ apply_at_specials(attr) * and move the cursor left. */ public void -backspace() +backspace(VOID_PARAM) { #if !MSDOS_COMPILER /* @@ -2364,8 +2393,12 @@ backspace() * Output a plain backspace, without erasing the previous char. */ public void -putbs() +putbs(VOID_PARAM) { + if (termcap_debug) + putstr(""); + else + { #if !MSDOS_COMPILER tputs(sc_backspace, 1, putchr); #else @@ -2396,15 +2429,15 @@ putbs() return; _settextposition(row, col-1); #endif /* MSDOS_COMPILER */ + } } #if MSDOS_COMPILER==WIN32C /* * Determine whether an input character is waiting to be read. */ - static int -win32_kbhit(tty) - HANDLE tty; + public int +win32_kbhit(VOID_PARAM) { INPUT_RECORD ip; DWORD read; @@ -2415,6 +2448,14 @@ win32_kbhit(tty) currentKey.ascii = 0; currentKey.scan = 0; + if (x11mouseCount > 0) + { + currentKey.ascii = x11mousebuf[x11mousePos++]; + --x11mouseCount; + keyCount = 1; + return (TRUE); + } + /* * Wait for a real key-down event, but * ignore SHIFT and CONTROL key events. @@ -2425,6 +2466,34 @@ win32_kbhit(tty) if (read == 0) return (FALSE); ReadConsoleInput(tty, &ip, 1, &read); + /* generate an X11 mouse sequence from the mouse event */ + if (mousecap && ip.EventType == MOUSE_EVENT && + ip.Event.MouseEvent.dwEventFlags != MOUSE_MOVED) + { + x11mousebuf[3] = X11MOUSE_OFFSET + ip.Event.MouseEvent.dwMousePosition.X + 1; + x11mousebuf[4] = X11MOUSE_OFFSET + ip.Event.MouseEvent.dwMousePosition.Y + 1; + switch (ip.Event.MouseEvent.dwEventFlags) + { + case 0: /* press or release */ + if (ip.Event.MouseEvent.dwButtonState == 0) + x11mousebuf[2] = X11MOUSE_OFFSET + X11MOUSE_BUTTON_REL; + else if (ip.Event.MouseEvent.dwButtonState & (FROM_LEFT_3RD_BUTTON_PRESSED | FROM_LEFT_4TH_BUTTON_PRESSED)) + continue; + else + x11mousebuf[2] = X11MOUSE_OFFSET + X11MOUSE_BUTTON1 + ((int)ip.Event.MouseEvent.dwButtonState << 1); + break; + case MOUSE_WHEELED: + x11mousebuf[2] = X11MOUSE_OFFSET + (((int)ip.Event.MouseEvent.dwButtonState < 0) ? X11MOUSE_WHEEL_DOWN : X11MOUSE_WHEEL_UP); + break; + default: + continue; + } + x11mousePos = 0; + x11mouseCount = 5; + currentKey.ascii = ESC; + keyCount = 1; + return (TRUE); + } } while (ip.EventType != KEY_EVENT || ip.Event.KeyEvent.bKeyDown != TRUE || ip.Event.KeyEvent.wVirtualScanCode == 0 || @@ -2477,8 +2546,7 @@ win32_kbhit(tty) * Read a character from the keyboard. */ public char -WIN32getch(tty) - int tty; +WIN32getch(VOID_PARAM) { int ascii; @@ -2488,21 +2556,25 @@ WIN32getch(tty) return ((char)(currentKey.scan & 0x00FF)); } - while (win32_kbhit((HANDLE)tty) == FALSE) - { - Sleep(20); - if (ABORT_SIGS()) - return ('\003'); - continue; - } - keyCount --; - ascii = currentKey.ascii; - /* - * On PC's, the extended keys return a 2 byte sequence beginning - * with '00', so if the ascii code is 00, the next byte will be - * the lsb of the scan code. - */ - pending_scancode = (ascii == 0x00); + do { + while (win32_kbhit() == FALSE) + { + Sleep(20); + if (ABORT_SIGS()) + return ('\003'); + continue; + } + keyCount --; + ascii = currentKey.ascii; + /* + * On PC's, the extended keys return a 2 byte sequence beginning + * with '00', so if the ascii code is 00, the next byte will be + * the lsb of the scan code. + */ + pending_scancode = (ascii == 0x00); + } while (pending_scancode && + (currentKey.scan == PCK_CAPS_LOCK || currentKey.scan == PCK_NUM_LOCK)); + return ((char)ascii); } #endif diff --git a/scrsize.c b/scrsize.c index 001c55a..1e3be1f 100644 --- a/scrsize.c +++ b/scrsize.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. diff --git a/search.c b/search.c index 7219188..e1d0073 100644 --- a/search.c +++ b/search.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -204,7 +204,7 @@ init_pattern(info) * Initialize search variables. */ public void -init_search() +init_search(VOID_PARAM) { init_pattern(&search_info); init_pattern(&filter_info); @@ -214,7 +214,7 @@ init_search() * Determine which text conversions to perform before pattern matching. */ static int -get_cvt_ops() +get_cvt_ops(VOID_PARAM) { int ops = 0; if (is_caseless || bs_mode == BS_SPECIAL) @@ -297,7 +297,7 @@ repaint_hilite(on) * Clear the attn hilite. */ public void -clear_attn() +clear_attn(VOID_PARAM) { int sindex; POSITION old_start_attnpos; @@ -344,7 +344,7 @@ clear_attn() * Hide search string highlighting. */ public void -undo_search() +undo_search(VOID_PARAM) { if (!prev_pattern(&search_info)) { @@ -389,13 +389,13 @@ clr_hlist(anchor) } public void -clr_hilite() +clr_hilite(VOID_PARAM) { clr_hlist(&hilite_anchor); } public void -clr_filter() +clr_filter(VOID_PARAM) { clr_hlist(&filter_anchor); } @@ -1031,7 +1031,7 @@ hilite_line(linepos, line, line_len, chpos, sp, ep, cvt_ops) * Find matching text which is currently on screen and highlight it. */ static void -hilite_screen() +hilite_screen(VOID_PARAM) { struct scrpos scrpos; @@ -1046,7 +1046,7 @@ hilite_screen() * Change highlighting parameters. */ public void -chg_hilite() +chg_hilite(VOID_PARAM) { /* * Erase any highlights currently on screen. @@ -1377,7 +1377,7 @@ hist_pattern(search_type) * Updates the internal search state to reflect a change in the -i flag. */ public void -chg_caseless() +chg_caseless(VOID_PARAM) { if (!is_ucase_pattern) /* @@ -1730,7 +1730,7 @@ set_filter_pattern(pattern, search_type) * Is there a line filter in effect? */ public int -is_filtering() +is_filtering(VOID_PARAM) { if (ch_getflags() & CH_HELPFILE) return (0); diff --git a/signal.c b/signal.c index f53b2f9..4f7444c 100644 --- a/signal.c +++ b/signal.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -38,6 +38,7 @@ extern long jump_sline_fraction; /* * Interrupt signal handler. */ +#if MSDOS_COMPILER!=WIN32C /* ARGSUSED*/ static RETSIGTYPE u_interrupt(type) @@ -61,6 +62,7 @@ u_interrupt(type) if (reading) intread(); /* May longjmp */ } +#endif #ifdef SIGTSTP /* @@ -107,7 +109,8 @@ winch(type) /* * Handle CTRL-C and CTRL-BREAK keys. */ -#include "windows.h" +#define WIN32_LEAN_AND_MEAN +#include static BOOL WINAPI wbreak_handler(dwCtrlType) @@ -145,9 +148,10 @@ init_signals(on) /* * Set signal handlers. */ - (void) LSIGNAL(SIGINT, u_interrupt); #if MSDOS_COMPILER==WIN32C SetConsoleCtrlHandler(wbreak_handler, TRUE); +#else + (void) LSIGNAL(SIGINT, u_interrupt); #endif #ifdef SIGTSTP (void) LSIGNAL(SIGTSTP, stop); @@ -169,9 +173,10 @@ init_signals(on) /* * Restore signals to defaults. */ - (void) LSIGNAL(SIGINT, SIG_DFL); #if MSDOS_COMPILER==WIN32C SetConsoleCtrlHandler(wbreak_handler, FALSE); +#else + (void) LSIGNAL(SIGINT, SIG_DFL); #endif #ifdef SIGTSTP (void) LSIGNAL(SIGTSTP, SIG_DFL); @@ -196,7 +201,7 @@ init_signals(on) * A received signal cause a bit to be set in "sigs". */ public void -psignals() +psignals(VOID_PARAM) { int tsignals; @@ -250,8 +255,8 @@ psignals() wscroll = (sc_height + 1) / 2; calc_jump_sline(); calc_shift_count(); - screen_trashed = 1; } + screen_trashed = 1; } #endif if (tsignals & S_INTERRUPT) diff --git a/tags.c b/tags.c index ebb3048..9a413b7 100644 --- a/tags.c +++ b/tags.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -38,7 +38,7 @@ enum tag_result { enum { T_CTAGS, /* 'tags': standard and extended format (ctags) */ T_CTAGS_X, /* stdin: cross reference format (ctags) */ - T_GTAGS, /* 'GTAGS': function defenition (global) */ + T_GTAGS, /* 'GTAGS': function definition (global) */ T_GRTAGS, /* 'GRTAGS': function reference (global) */ T_GSYMS, /* 'GSYMS': other symbols (global) */ T_GPATH /* 'GPATH': path name (global) */ @@ -89,7 +89,7 @@ static struct tag *curtag; * Delete tag structures. */ public void -cleantags() +cleantags(VOID_PARAM) { struct tag *tp; @@ -141,7 +141,7 @@ maketagent(name, file, linenum, pattern, endline) * Get tag mode. */ public int -gettagtype() +gettagtype(VOID_PARAM) { int f; @@ -203,7 +203,7 @@ findtag(tag) * Search for a tag. */ public POSITION -tagsearch() +tagsearch(VOID_PARAM) { if (curtag == NULL) return (NULL_POSITION); /* No gtags loaded! */ @@ -245,7 +245,7 @@ prevtag(n) * Return the total number of tags. */ public int -ntags() +ntags(VOID_PARAM) { return total; } @@ -254,7 +254,7 @@ ntags() * Return the sequence number of current tag. */ public int -curr_tag() +curr_tag(VOID_PARAM) { return curseq; } @@ -380,7 +380,7 @@ findctag(tag) * Edit current tagged file. */ public int -edit_tagfile() +edit_tagfile(VOID_PARAM) { if (curtag == NULL) return (1); @@ -417,7 +417,7 @@ curtag_match(char const *line, POSITION linepos) * parentheses (which are almost always found in a tag). */ static POSITION -ctagsearch() +ctagsearch(VOID_PARAM) { POSITION pos, linepos; LINENUM linenum; @@ -529,7 +529,7 @@ findgtag(tag, type) char *qtag; char *cmd = lgetenv("LESSGLOBALTAGS"); - if (cmd == NULL || *cmd == '\0') + if (isnullenv(cmd)) return TAG_NOFILE; /* Get suitable flag value for global(1). */ switch (type) @@ -631,7 +631,7 @@ static int circular = 0; /* 1: circular tag structure */ * appropriate tag. */ static char * -nextgtag() +nextgtag(VOID_PARAM) { struct tag *tp; @@ -661,7 +661,7 @@ nextgtag() * at the appropriate tag. */ static char * -prevgtag() +prevgtag(VOID_PARAM) { struct tag *tp; @@ -691,7 +691,7 @@ prevgtag() * if it was unable to position at the tag, 0 if successful. */ static POSITION -gtagsearch() +gtagsearch(VOID_PARAM) { if (curtag == NULL) return (NULL_POSITION); /* No gtags loaded! */ diff --git a/ttyin.c b/ttyin.c index 87cffc2..8ef11ef 100644 --- a/ttyin.c +++ b/ttyin.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -18,20 +18,25 @@ #include "pckeys.h" #endif #if MSDOS_COMPILER==WIN32C -#include "windows.h" -extern char WIN32getch(); -static DWORD console_mode; +#define WIN32_LEAN_AND_MEAN +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x400 #endif - +#include +static DWORD console_mode; +public HANDLE tty; +#else public int tty; +#endif extern int sigs; extern int utf_mode; +extern int wheel_lines; /* * Open keyboard for input. */ public void -open_getchr() +open_getchr(VOID_PARAM) { #if MSDOS_COMPILER==WIN32C /* Need this to let child processes inherit our console handle */ @@ -39,12 +44,12 @@ open_getchr() memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES)); sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.bInheritHandle = TRUE; - tty = (int) CreateFile("CONIN$", GENERIC_READ, + tty = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, &sa, OPEN_EXISTING, 0L, NULL); - GetConsoleMode((HANDLE)tty, &console_mode); + GetConsoleMode(tty, &console_mode); /* Make sure we get Ctrl+C events. */ - SetConsoleMode((HANDLE)tty, ENABLE_PROCESSED_INPUT); + SetConsoleMode(tty, ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT); #else #if MSDOS_COMPILER extern int fd0; @@ -85,19 +90,52 @@ open_getchr() * Close the keyboard. */ public void -close_getchr() +close_getchr(VOID_PARAM) +{ +#if MSDOS_COMPILER==WIN32C + SetConsoleMode(tty, console_mode); + CloseHandle(tty); +#endif +} + +#if MSDOS_COMPILER==WIN32C +/* + * Close the pipe, restoring the keyboard (CMD resets it, losing the mouse). + */ + int +pclose(f) + FILE *f; +{ + int result; + + result = _pclose(f); + SetConsoleMode(tty, ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT); + return result; +} +#endif + +/* + * Get the number of lines to scroll when mouse wheel is moved. + */ + public int +default_wheel_lines(VOID_PARAM) { + int lines = 1; #if MSDOS_COMPILER==WIN32C - SetConsoleMode((HANDLE)tty, console_mode); - CloseHandle((HANDLE)tty); + if (SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &lines, 0)) + { + if (lines == WHEEL_PAGESCROLL) + lines = 3; + } #endif + return lines; } /* * Get a character from the keyboard. */ public int -getchr() +getchr(VOID_PARAM) { char c; int result; @@ -112,7 +150,7 @@ getchr() #if MSDOS_COMPILER==WIN32C if (ABORT_SIGS()) return (READ_INTR); - c = WIN32getch(tty); + c = WIN32getch(); #else c = getch(); #endif @@ -157,7 +195,7 @@ getchr() else if (c >= 'A' && c <= 'F') v = c - 'A' + 10; else - hex_in = 0; + v = 0; hex_value = (hex_value << 4) | v; if (--hex_in > 0) { diff --git a/ubin.uni b/ubin.uni index 888fe75..a8d4b54 100644 --- a/ubin.uni +++ b/ubin.uni @@ -1,4 +1,4 @@ -/* Generated by "./mkutable -f2 Cc Cs Co Zl Zp -- unicode/UnicodeData.txt" on Tue Jul 25 09:04:35 PDT 2017 */ +/* Generated by "./mkutable -f2 Cc Cs Co Zl Zp -- unicode/UnicodeData.txt" on Wed Feb 13 17:57:06 PST 2019 */ { 0x0000, 0x0007 }, /* Cc */ { 0x000b, 0x000b }, /* Cc */ { 0x000e, 0x001f }, /* Cc */ diff --git a/version.c b/version.c index 1432b37..7aca8d6 100644 --- a/version.c +++ b/version.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2017 Mark Nudelman + * Copyright (C) 1984-2019 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. @@ -853,6 +853,33 @@ v527 10/30/17 Fix search hilite bug on last page with -a. v528 11/3/17 Make second ESC-u clear status column. v529 11/12/17 Display Unicode formatting chars in hex if -U is set. v530 12/2/17 Minor doc change and add missing VOID_PARAM. +----------------------------------------------------------------- +v531 5/13/18 Fix bug with v on empty file; fix bug with v on file with + metachars in name; add --nohistdups option. +v532 7/27/18 Redraw screen on SIGWINCH even if screen size doesn't change. +v533 8/1/18 Shell escape filenames in history; use PCRE_UTF8 flag; + use wide-chars for Windows console title (thanks to Jason Hood). +v534 8/9/18 Support PCRE2. +v535 8/16/18 Don't count lines of initial screen if using -X with -F + (thanks to Linus Torvalds). +v536 8/31/18 Use descriptive error messages for PCRE2. +v537 8/31/18 Support mingw build system (thanks to Mike Soyka). +v538 9/3/18 Clean up some WIN32 code. +v539 9/13/18 Fix spurious input on Windows with CAPSLOCK. +v540 10/29/18 Add --mouse option. +v541 10/30/18 Add --MOUSE option. +v542 11/6/18 Add mouse support for WIN32; add --wheel-lines option. + (thanks to Jason Hood). +v543 11/12/18 Code cleanup. +v544 11/16/18 Don't init/deinit keyboard/mouse if quit due to -F. +v545 11/22/18 Fix Windows build, memory leaks. +v546 11/29/18 Add --save-marks option. +v547 11/30/18 Fix some bugs with saved marks. +v548 12/14/18 Ignore mouse input when line editing. +v549 2/10/19 Support X11 mouse extension 1006; + Win32 fixes (thanks to Jason Hood). +v550 2/16/19 Fix Win32 build; don't enable mouse unless --mouse is set. +v551 6/10/19 Doc changes. */ -char version[] = "530"; +char version[] = "551"; diff --git a/wide.uni b/wide.uni index 801a352..e23ba73 100644 --- a/wide.uni +++ b/wide.uni @@ -1,4 +1,4 @@ -/* Generated by "./mkutable -f1 W F -- unicode/EastAsianWidth.txt" on Tue Jul 25 09:04:35 PDT 2017 */ +/* Generated by "./mkutable -f1 W F -- unicode/EastAsianWidth.txt" on Thu Feb 14 08:30:47 PST 2019 */ { 0x1100, 0x115f }, /* W */ { 0x231a, 0x231b }, /* W */ { 0x2329, 0x232a }, /* W */ @@ -42,7 +42,7 @@ { 0x3001, 0x303e }, /* W */ { 0x3041, 0x3096 }, /* W */ { 0x3099, 0x30ff }, /* W */ - { 0x3105, 0x312e }, /* W */ + { 0x3105, 0x312f }, /* W */ { 0x3131, 0x318e }, /* W */ { 0x3190, 0x31ba }, /* W */ { 0x31c0, 0x31e3 }, /* W */ @@ -62,7 +62,7 @@ { 0xff01, 0xff60 }, /* F */ { 0xffe0, 0xffe6 }, /* F */ { 0x16fe0, 0x16fe1 }, /* W */ - { 0x17000, 0x187ec }, /* W */ + { 0x17000, 0x187f1 }, /* W */ { 0x18800, 0x18af2 }, /* W */ { 0x1b000, 0x1b11e }, /* W */ { 0x1b170, 0x1b2fb }, /* W */ @@ -97,12 +97,14 @@ { 0x1f6cc, 0x1f6cc }, /* W */ { 0x1f6d0, 0x1f6d2 }, /* W */ { 0x1f6eb, 0x1f6ec }, /* W */ - { 0x1f6f4, 0x1f6f8 }, /* W */ + { 0x1f6f4, 0x1f6f9 }, /* W */ { 0x1f910, 0x1f93e }, /* W */ - { 0x1f940, 0x1f94c }, /* W */ - { 0x1f950, 0x1f96b }, /* W */ - { 0x1f980, 0x1f997 }, /* W */ - { 0x1f9c0, 0x1f9c0 }, /* W */ - { 0x1f9d0, 0x1f9e6 }, /* W */ + { 0x1f940, 0x1f970 }, /* W */ + { 0x1f973, 0x1f976 }, /* W */ + { 0x1f97a, 0x1f97a }, /* W */ + { 0x1f97c, 0x1f9a2 }, /* W */ + { 0x1f9b0, 0x1f9b9 }, /* W */ + { 0x1f9c0, 0x1f9c2 }, /* W */ + { 0x1f9d0, 0x1f9ff }, /* W */ { 0x20000, 0x2fffd }, /* W */ { 0x30000, 0x3fffd }, /* W */