Imported Upstream version 551 upstream/551
authorJinWang An <jinwang.an@samsung.com>
Wed, 28 Dec 2022 07:13:18 +0000 (16:13 +0900)
committerJinWang An <jinwang.an@samsung.com>
Wed, 28 Dec 2022 07:13:18 +0000 (16:13 +0900)
69 files changed:
LICENSE
Makefile.aut
NEWS
README
brac.c
ch.c
charset.c
charset.h
cmd.h
cmdbuf.c
command.c
compose.uni
configure
configure.ac
cvt.c
decode.c
defines.ds
defines.h.in
defines.o2
defines.o9
defines.wn
edit.c
filename.c
fmt.uni
forwback.c
funcs.h
help.c
ifile.c
input.c
jump.c
less.h
less.hlp
less.man
less.nro
lessecho.c
lessecho.man
lessecho.nro
lesskey.c
lesskey.h
lesskey.man
lesskey.nro
lglob.h
line.c
linenum.c
lsystem.c
main.c
mark.c
mkutable
optfunc.c
option.c
option.h
opttbl.c
os.c
output.c
pattern.c
pattern.h
pckeys.h
position.c
position.h
prompt.c
screen.c
scrsize.c
search.c
signal.c
tags.c
ttyin.c
ubin.uni
version.c
wide.uni

diff --git a/LICENSE b/LICENSE
index 832ca1b..315d1d8 100644 (file)
--- 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
index 8816902..f16642c 100644 (file)
@@ -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 (file)
--- a/NEWS
+++ b/NEWS
 
 ======================================================================
 
+       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 (file)
--- 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 (file)
--- 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 (file)
--- 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);
index 8897891..5441952 100644 (file)
--- 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;
 
index 1e3f069..5003091 100644 (file)
--- 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 (file)
--- 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.
 #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
index db5b259..0648aec 100644 (file)
--- 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(&copy_hist, &ctx, skip_search, skip_shell);
+               save_marks(fout, HISTFILE_MARK_SECTION);
                fclose(fout);
 #if MSDOS_COMPILER==WIN32C
                /*
index 4338b3d..6c89ca3 100644 (file)
--- 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;
index 2a4b180..389814c 100644 (file)
@@ -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 */
        { 0x17c9, 0x17d3 }, /* Mn */
        { 0x17dd, 0x17dd }, /* Mn */
        { 0x180b, 0x180d }, /* Mn */
-       { 0x180e, 0x180e }, /* Cf */
        { 0x1885, 0x1886 }, /* Mn */
        { 0x18a9, 0x18a9 }, /* Mn */
        { 0x1920, 0x1922 }, /* Mn */
        { 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 */
        { 0xa825, 0xa826 }, /* Mn */
        { 0xa8c4, 0xa8c5 }, /* Mn */
        { 0xa8e0, 0xa8f1 }, /* Mn */
+       { 0xa8ff, 0xa8ff }, /* Mn */
        { 0xa926, 0xa92d }, /* Mn */
        { 0xa947, 0xa951 }, /* Mn */
        { 0xa980, 0xa982 }, /* Mn */
        { 0xfb1e, 0xfb1e }, /* Mn */
        { 0xfe00, 0xfe0f }, /* Mn */
        { 0xfe20, 0xfe2f }, /* Mn */
-       { 0xfeff, 0xfeff }, /* Cf */
-       { 0xfff9, 0xfffb }, /* Cf */
        { 0x101fd, 0x101fd }, /* Mn */
        { 0x102e0, 0x102e0 }, /* Mn */
        { 0x10376, 0x1037a }, /* Mn */
        { 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 */
        { 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 */
        { 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 */
        { 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 */
        { 0x1e026, 0x1e02a }, /* Mn */
        { 0x1e8d0, 0x1e8d6 }, /* Mn */
        { 0x1e944, 0x1e94a }, /* Mn */
-       { 0xe0001, 0xe0001 }, /* Cf */
-       { 0xe0020, 0xe007f }, /* Cf */
        { 0xe0100, 0xe01ef }, /* Mn */
index 10a0305..0ce6db1 100755 (executable)
--- 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; }
index 3616ef0..7a69398 100644 (file)
@@ -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 (file)
--- 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.
index 80f47f9..74bbc4f 100644 (file)
--- 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.
index 80a2d7b..b952232 100644 (file)
@@ -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)
 
index 874c150..36822bc 100644 (file)
@@ -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)
 
 /* 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
 
index 4dba142..1490cdc 100644 (file)
@@ -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)
 
index 99983d7..fb980ac 100644 (file)
@@ -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)
 
index 98ca990..4235402 100644 (file)
@@ -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)
 
 /*
  * 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 */
 /* #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
 /* 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
 #define HAVE_TIME_H 1
 
 /* Define if you have the <unistd.h> header file.  */
+#ifdef MINGW
+#define HAVE_UNISTD_H 1
+#else
 #define HAVE_UNISTD_H 0
+#endif
 
 /* Define if you have the <values.h> 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 (file)
--- 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;
 
index 983a02b..7c3ccd2 100644 (file)
@@ -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 (file)
--- 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 */
index 680fa25..1e0397c 100644 (file)
@@ -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 (file)
--- 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 (file)
--- 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 (file)
--- 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 (file)
--- 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 (file)
--- 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 (file)
--- 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
index 0bbada9..a8f78ad 100644 (file)
--- a/less.hlp
+++ b/less.hlp
@@ -44,7 +44,7 @@
   ESC-u                Undo (toggle) search highlighting.
   &_\bp_\ba_\bt_\bt_\be_\br_\bn          *  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 ?).
                   Display a status column at left edge of screen.
   -k [_\bf_\bi_\bl_\be]  .  --lesskey-file=[_\bf_\bi_\bl_\be]
                   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.
                   Don't display tildes after end of file.
   -# [_\bN]  ....  --shift=[_\bN]
                   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.
 
 
  ---------------------------------------------------------------------------
index 84420a4..f0e178c 100644 (file)
--- 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, \e[4mless\e[24m 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 \e[4mless\e[24m 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 \e[4mless\e[24m 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 \e[4mless\e[24m  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 \e[4mless\e[24m 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 \e[4mnroff\e[24m 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.
 
        -t\e[4mtag\e[24m or --tag=\e[4mtag\e[0m
               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 \e[4mctags\e[24m (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 \e[4mglobal\e[24m (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  \e[4mglobal\e[24m  (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 \e[4mless\e[24m  (using  the  -
-              command)  as a way of examining a new file.  The command ":t" is
+              -t  option  may  also be specified from within \e[4mless\e[24m (using the -
+              command) as a way of examining a new file.  The command ":t"  is
               equivalent to specifying -t from within \e[4mless\e[24m.
 
        -T\e[4mtagsfile\e[24m or --tag-file=\e[4mtagsfile\e[0m
               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 \e[4mless\e[24m.
 
        -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.
 
        -x\e[4mn\e[24m,... or --tabs=\e[4mn\e[24m,...
-              Sets  tab  stops.  If only one \e[4mn\e[24m is specified, tab stops are set
-              at multiples of \e[4mn\e[24m.  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,
-              \e[4m-x9,17\e[24m  will  set  tabs  at  positions  9, 17, 25, 33, etc.  The
+              Sets tab stops.  If only one \e[4mn\e[24m is specified, tab stops  are  set
+              at  multiples  of \e[4mn\e[24m.  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,
+              \e[4m-x9,17\e[24m will set tabs at positions  9,  17,  25,  33,  etc.   The
               default for \e[4mn\e[24m 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.
 
        -y\e[4mn\e[24m or --max-forw-scroll=\e[4mn\e[0m
               Specifies a maximum number of lines to scroll forward.  If it is
-              necessary to scroll forward more than \e[4mn\e[24m  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 \e[4mn\e[24m 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.
 
        -z\e[4mn\e[24m or --window=\e[4mn\e[24m or -\e[4mn\e[0m
-              Changes  the  default  scrolling  window  size  to \e[4mn\e[24m lines.  The
+              Changes the default scrolling  window  size  to  \e[4mn\e[24m  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 \e[4mmore\e[24m.  If the number \e[4mn\e[24m is negative,
-              it  indicates  \e[4mn\e[24m  lines  less than the current screen size.  For
+              it indicates \e[4mn\e[24m lines less than the  current  screen  size.   For
               example, if the screen is 24 lines, \e[4m-z-4\e[24m 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.
 
        -"\e[4mcc\e[24m or --quotes=\e[4mcc\e[0m
-              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, \e[4mless\e[24m 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,  \e[4mless\e[24m  will  continue  to display the contents of the
+              original file despite its  name  change.   If  --follow-name  is
               specified, during an F command \e[4mless\e[24m 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), \e[4mless\e[24m 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 \e[4mless\e[24m.
+
+       --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 \e[4mless\e[24m.
+
+       --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=\e[4mn\e[0m
+              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.
 
 
 \e[1mSECURITY\e[0m
-       When the environment variable LESSSECURE is set to 1, \e[4mless\e[24m  runs  in  a
+       When  the  environment  variable LESSSECURE is set to 1, \e[4mless\e[24m 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)
 
 \e[1mCOMPATIBILITY WITH MORE\e[0m
        If the environment variable LESS_IS_MORE is set to 1, or if the program
-       is invoked via a file link named "more", \e[4mless\e[24m behaves (mostly) in  con-
-       formance  with  the  POSIX "more" command specification.  In this mode,
+       is  invoked via a file link named "more", \e[4mless\e[24m 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,  \e[4mless\e[0m
-       behaves  as  if  the -e option were set.  If the -e option is set, \e[4mless\e[0m
+       The  -e  option  works  differently.  If the -e option is not set, \e[4mless\e[0m
+       behaves as if the -e option were set.  If the -e option  is  set,  \e[4mless\e[0m
        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 \e[4mless\e[24m command rather
+       The parameter to the -p option is taken to be  a  \e[4mless\e[24m  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.
 
 
 \e[1mENVIRONMENT VARIABLES\e[0m
        Environment variables may be specified either in the system environment
-       as usual, or in a \e[4mlesskey\e[24m  (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  \e[4mlesskey\e[24m  (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 \e[4mless\e[24m 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 \e[4mglobal\e[0m
               (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 \e[4mless\e[24m.  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 \e[4mless\e[24m.  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 \e[4mmore\e[24m (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 \e[4mless\e[24m automatically when running in
+       MORE   Options which are passed to \e[4mless\e[24m automatically when  running  in
               \e[4mmore\e[24m 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 \e[4mless\e[24m is being run.
@@ -1638,32 +1676,30 @@ LESS(1)                     General Commands Manual                    LESS(1)
 
 
 \e[1mCOPYRIGHT\e[0m
-       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.
 
 
 \e[1mAUTHOR\e[0m
        Mark Nudelman
-       Send bug reports or comments to <bug-less@gnu.org>
-       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)
index fa0b4ff..0aa8b78 100644 (file)
--- 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 <bug-less@gnu.org>
-.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
index 4ed4830..2f4a10e 100644 (file)
@@ -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];
index de4200c..6a26991 100644 (file)
@@ -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)
index 49a97ff..4fe997e 100644 (file)
@@ -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
index fa1ab6d..96a4462 100644 (file)
--- 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;
index 92d4d93..299bf45 100644 (file)
--- 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.
index 99e5f16..68af6c4 100644 (file)
@@ -337,7 +337,7 @@ LESSKEY(1)                  General Commands Manual                 LESSKEY(1)
 
 
 \e[1mCOPYRIGHT\e[0m
-       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)
index ffe520b..48aec7f 100644 (file)
@@ -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 (file)
--- 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 (file)
--- 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;
index 4e72637..6a5560b 100644 (file)
--- 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)
                /*
index 10911eb..d4f1e77 100644 (file)
--- 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.
 
 #if MSDOS_COMPILER
 #include <dos.h>
+#if MSDOS_COMPILER==WIN32C && defined(MINGW)
+#include <direct.h>
+#define setdisk(n) _chdrive((n)+1)
+#else
 #ifdef _MSC_VER
 #include <direct.h>
 #define setdisk(n) _chdrive((n)+1)
@@ -26,6 +30,7 @@
 #include <dir.h>
 #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 (file)
--- 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 <windows.h>
 #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 (file)
--- 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.
 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 */
index 2760628..b7c3e68 100755 (executable)
--- 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 );
index 9185c01..7fe947e 100644 (file)
--- 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);
index 8ba67bc..d402e11 100644 (file)
--- 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;
index b253da8..fb73416 100644 (file)
--- 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.
index 0c68ccc..967761c 100644 (file)
--- 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 (file)
--- 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;
 
index c6a9981..0563cf0 100644 (file)
--- 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;
 
index 563bde0..da27dc6 100644 (file)
--- 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
+}
index 7bde5c7..19ce5b9 100644 (file)
--- 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.
 #define CLEAR_PATTERN(name)   name = NULL
 #endif
 
+#if HAVE_PCRE2
+#define PCRE2_CODE_UNIT_WIDTH 8
+#include <pcre2.h>
+#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*));
index e0d86e7..fb345f2 100644 (file)
--- 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.
index ae3899c..8a65ed4 100644 (file)
@@ -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;
        }
 
        /*
index 3067896..77216da 100644 (file)
@@ -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.
index 3067d2b..12413fb 100644 (file)
--- 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));
 }
index dfee5d2..cd25d74 100644 (file)
--- 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("<bs>");
+       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
index 001c55a..1e3be1f 100644 (file)
--- 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.
index 7219188..e1d0073 100644 (file)
--- 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);
index f53b2f9..4f7444c 100644 (file)
--- 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 <windows.h>
 
        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 (file)
--- 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 (file)
--- 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.
 #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 <windows.h>
+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)
                        {
index 888fe75..a8d4b54 100644 (file)
--- 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 */
index 1432b37..7aca8d6 100644 (file)
--- 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";
index 801a352..e23ba73 100644 (file)
--- 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 */
        { 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 */