summaryrefslogtreecommitdiff
path: root/screen.c
diff options
context:
space:
mode:
Diffstat (limited to 'screen.c')
-rw-r--r--screen.c278
1 files changed, 175 insertions, 103 deletions
diff --git a/screen.c b/screen.c
index dfee5d217040a..cd25d744e8979 100644
--- a/screen.c
+++ b/screen.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1984-2017 Mark Nudelman
+ * Copyright (C) 1984-2019 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
@@ -120,7 +120,8 @@ struct keyRecord
static int keyCount = 0;
static WORD curr_attr;
static int pending_scancode = 0;
-static WORD *whitescreen;
+static char x11mousebuf[] = "[M???"; /* Mouse report, after ESC */
+static int x11mousePos, x11mouseCount;
static HANDLE con_out_save = INVALID_HANDLE_VALUE; /* previous console */
static HANDLE con_out_ours = INVALID_HANDLE_VALUE; /* our own */
@@ -187,6 +188,8 @@ static char
*sc_backspace, /* Backspace cursor */
*sc_s_keypad, /* Start keypad mode */
*sc_e_keypad, /* End keypad mode */
+ *sc_s_mousecap, /* Start mouse capture mode */
+ *sc_e_mousecap, /* End mouse capture mode */
*sc_init, /* Startup terminal initialization */
*sc_deinit; /* Exit terminal de-initialization */
#endif
@@ -211,8 +214,9 @@ public int missing_cap = 0; /* Some capability is missing */
public char *kent = NULL; /* Keypad ENTER sequence */
static int attrmode = AT_NORMAL;
+static int termcap_debug = -1;
extern int binattr;
-extern int line_count;
+extern int one_screen;
#if !MSDOS_COMPILER
static char *cheaper();
@@ -240,13 +244,18 @@ extern int no_keypad;
extern int sigs;
extern int wscroll;
extern int screen_trashed;
-extern int tty;
extern int top_scroll;
extern int quit_if_one_screen;
extern int oldbot;
+extern int mousecap;
#if HILITE_SEARCH
extern int hilite_search;
#endif
+#if MSDOS_COMPILER==WIN32C
+extern HANDLE tty;
+#else
+extern int tty;
+#endif
extern char *tgetstr();
extern char *tgoto();
@@ -632,11 +641,10 @@ static int hardcopy;
ltget_env(capname)
char *capname;
{
- char name[16];
+ char name[64];
char *s;
- s = lgetenv("LESS_TERMCAP_DEBUG");
- if (s != NULL && *s != '\0')
+ if (termcap_debug)
{
struct env { struct env *next; char *name; char *value; };
static struct env *envs = NULL;
@@ -652,8 +660,7 @@ ltget_env(capname)
envs = p;
return p->value;
}
- strcpy(name, "LESS_TERMCAP_");
- strcat(name, capname);
+ SNPRINTF1(name, sizeof(name), "LESS_TERMCAP_%s", capname);
return (lgetenv(name));
}
@@ -702,7 +709,7 @@ ltgetstr(capname, pp)
* Get size of the output screen.
*/
public void
-scrsize()
+scrsize(VOID_PARAM)
{
char *s;
int sys_height;
@@ -832,7 +839,7 @@ scrsize()
* Figure out how many empty loops it takes to delay a millisecond.
*/
static void
-get_clock()
+get_clock(VOID_PARAM)
{
clock_t start;
@@ -860,13 +867,6 @@ get_clock()
* Delay for a specified number of milliseconds.
*/
static void
-dummy_func()
-{
- static long delay_dummy = 0;
- delay_dummy++;
-}
-
- static void
delay(msec)
int msec;
{
@@ -875,13 +875,7 @@ delay(msec)
while (msec-- > 0)
{
for (i = 0; i < msec_loops; i++)
- {
- /*
- * Make it look like we're doing something here,
- * so the optimizer doesn't remove the whole loop.
- */
- dummy_func();
- }
+ (void) clock();
}
}
#endif
@@ -949,17 +943,13 @@ special_key_str(key)
s = windowid ? ltgetstr("@7", &sp) : k_end;
break;
case SK_DELETE:
- if (windowid)
+ s = windowid ? ltgetstr("kD", &sp) : k_delete;
+ if (s == NULL)
{
- s = ltgetstr("kD", &sp);
- if (s == NULL)
- {
- tbuf[0] = '\177';
- tbuf[1] = '\0';
- s = tbuf;
- }
- } else
- s = k_delete;
+ tbuf[0] = '\177';
+ tbuf[1] = '\0';
+ s = tbuf;
+ }
break;
#endif
#if MSDOS_COMPILER
@@ -1063,8 +1053,9 @@ special_key_str(key)
* Get terminal capabilities via termcap.
*/
public void
-get_term()
+get_term(VOID_PARAM)
{
+ termcap_debug = !isnullenv(lgetenv("LESS_TERMCAP_DEBUG"));
#if MSDOS_COMPILER
auto_wrap = 1;
ignaw = 0;
@@ -1127,7 +1118,7 @@ get_term()
#else /* !MSDOS_COMPILER */
-
+{
char *sp;
char *t1, *t2;
char *term;
@@ -1140,7 +1131,7 @@ get_term()
* Make sure the termcap database is available.
*/
sp = lgetenv("TERMCAP");
- if (sp == NULL || *sp == '\0')
+ if (isnullenv(sp))
{
char *termcap;
if ((sp = homefile("termcap.dat")) != NULL)
@@ -1220,6 +1211,13 @@ get_term()
sc_e_keypad = "";
kent = ltgetstr("@8", &sp);
+ sc_s_mousecap = ltgetstr("MOUSE_START", &sp);
+ if (sc_s_mousecap == NULL)
+ sc_s_mousecap = ESCS "[?1000h" ESCS "[?1006h";
+ sc_e_mousecap = ltgetstr("MOUSE_END", &sp);
+ if (sc_e_mousecap == NULL)
+ sc_e_mousecap = ESCS "[?1006l" ESCS "[?1000l";
+
sc_init = ltgetstr("ti", &sp);
if (sc_init == NULL)
sc_init = "";
@@ -1347,6 +1345,7 @@ get_term()
*/
no_back_scroll = 1;
}
+}
#endif /* MSDOS_COMPILER */
}
@@ -1459,7 +1458,7 @@ _settextposition(int row, int col)
* Initialize the screen to the correct color at startup.
*/
static void
-initcolor()
+initcolor(VOID_PARAM)
{
#if MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC
intensevideo();
@@ -1495,7 +1494,7 @@ initcolor()
* Termcap-like init with a private win32 console.
*/
static void
-win32_init_term()
+win32_init_term(VOID_PARAM)
{
CONSOLE_SCREEN_BUFFER_INFO scr;
COORD size;
@@ -1537,8 +1536,8 @@ win32_init_term()
/*
* Restore the startup console.
*/
-static void
-win32_deinit_term()
+ static void
+win32_deinit_term(VOID_PARAM)
{
if (con_out_save == INVALID_HANDLE_VALUE)
return;
@@ -1551,18 +1550,56 @@ win32_deinit_term()
#endif
/*
+ * Configure the termimal so mouse clicks and wheel moves
+ * produce input to less.
+ */
+ public void
+init_mouse(VOID_PARAM)
+{
+ if (!mousecap)
+ return;
+#if !MSDOS_COMPILER
+ tputs(sc_s_mousecap, sc_height, putchr);
+#else
+#if MSDOS_COMPILER==WIN32C
+ SetConsoleMode(tty, ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT);
+#endif
+#endif
+}
+
+/*
+ * Configure the terminal so mouse clicks and wheel moves
+ * are handled by the system (so text can be selected, etc).
+ */
+ public void
+deinit_mouse(VOID_PARAM)
+{
+ if (!mousecap)
+ return;
+#if !MSDOS_COMPILER
+ tputs(sc_e_mousecap, sc_height, putchr);
+#else
+#if MSDOS_COMPILER==WIN32C
+ SetConsoleMode(tty, ENABLE_PROCESSED_INPUT);
+#endif
+#endif
+}
+
+/*
* Initialize terminal
*/
public void
-init()
+init(VOID_PARAM)
{
#if !MSDOS_COMPILER
- if (quit_if_one_screen && line_count >= sc_height)
- quit_if_one_screen = FALSE;
- if (!no_init && !quit_if_one_screen)
- tputs(sc_init, sc_height, putchr);
- if (!no_keypad)
- tputs(sc_s_keypad, sc_height, putchr);
+ if (!(quit_if_one_screen && one_screen))
+ {
+ if (!no_init)
+ tputs(sc_init, sc_height, putchr);
+ if (!no_keypad)
+ tputs(sc_s_keypad, sc_height, putchr);
+ init_mouse();
+ }
if (top_scroll)
{
int i;
@@ -1592,15 +1629,19 @@ init()
* Deinitialize terminal
*/
public void
-deinit()
+deinit(VOID_PARAM)
{
if (!init_done)
return;
#if !MSDOS_COMPILER
- if (!no_keypad)
- tputs(sc_e_keypad, sc_height, putchr);
- if (!no_init && !quit_if_one_screen)
- tputs(sc_deinit, sc_height, putchr);
+ if (!(quit_if_one_screen && one_screen))
+ {
+ deinit_mouse();
+ if (!no_keypad)
+ tputs(sc_e_keypad, sc_height, putchr);
+ if (!no_init)
+ tputs(sc_deinit, sc_height, putchr);
+ }
#else
/* Restore system colors. */
SETCOLORS(sy_fg_color, sy_bg_color);
@@ -1619,7 +1660,7 @@ deinit()
* Home cursor (move to upper left corner of screen).
*/
public void
-home()
+home(VOID_PARAM)
{
#if !MSDOS_COMPILER
tputs(sc_home, 1, putchr);
@@ -1634,7 +1675,7 @@ home()
* Should scroll the display down.
*/
public void
-add_line()
+add_line(VOID_PARAM)
{
#if !MSDOS_COMPILER
tputs(sc_addline, sc_height, putchr);
@@ -1746,7 +1787,7 @@ remove_top(n)
* Clear the screen.
*/
static void
-win32_clear()
+win32_clear(VOID_PARAM)
{
/*
* This will clear only the currently visible rows of the NT
@@ -1843,7 +1884,7 @@ win32_scroll_up(n)
* Move cursor to lower left corner of screen.
*/
public void
-lower_left()
+lower_left(VOID_PARAM)
{
if (!init_done)
return;
@@ -1859,7 +1900,7 @@ lower_left()
* Move cursor to left position of current line.
*/
public void
-line_left()
+line_left(VOID_PARAM)
{
#if !MSDOS_COMPILER
tputs(sc_return, 1, putchr);
@@ -1891,7 +1932,7 @@ line_left()
* (in lieu of SIGWINCH for WIN32).
*/
public void
-check_winch()
+check_winch(VOID_PARAM)
{
#if MSDOS_COMPILER==WIN32C
CONSOLE_SCREEN_BUFFER_INFO scr;
@@ -1940,7 +1981,7 @@ goto_line(sindex)
* {{ Yuck! There must be a better way to get a visual bell. }}
*/
static void
-create_flash()
+create_flash(VOID_PARAM)
{
#if MSDOS_COMPILER==MSOFTC
struct videoconfig w;
@@ -1977,18 +2018,6 @@ create_flash()
return;
for (n = 0; n < sc_width * sc_height; n++)
whitescreen[n] = 0x7020;
-#else
-#if MSDOS_COMPILER==WIN32C
- int n;
-
- whitescreen = (WORD *)
- malloc(sc_height * sc_width * sizeof(WORD));
- if (whitescreen == NULL)
- return;
- /* Invert the standard colors. */
- for (n = 0; n < sc_width * sc_height; n++)
- whitescreen[n] = (WORD)((nm_fg_color << 4) | nm_bg_color);
-#endif
#endif
#endif
flash_created = 1;
@@ -1999,7 +2028,7 @@ create_flash()
* Output the "visual bell", if there is one.
*/
public void
-vbell()
+vbell(VOID_PARAM)
{
#if !MSDOS_COMPILER
if (*sc_visual_bell == '\0')
@@ -2063,7 +2092,7 @@ vbell()
* Make a noise.
*/
static void
-beep()
+beep(VOID_PARAM)
{
#if !MSDOS_COMPILER
putchr(CONTROL('G'));
@@ -2080,7 +2109,7 @@ beep()
* Ring the terminal bell.
*/
public void
-bell()
+bell(VOID_PARAM)
{
if (quiet == VERY_QUIET)
vbell();
@@ -2092,7 +2121,7 @@ bell()
* Clear the screen.
*/
public void
-clear()
+clear(VOID_PARAM)
{
#if !MSDOS_COMPILER
tputs(sc_clear, sc_height, putchr);
@@ -2111,7 +2140,7 @@ clear()
* {{ This must not move the cursor. }}
*/
public void
-clear_eol()
+clear_eol(VOID_PARAM)
{
#if !MSDOS_COMPILER
tputs(sc_eol_clear, 1, putchr);
@@ -2170,7 +2199,7 @@ clear_eol()
* Clear the screen if there's off-screen memory below the display.
*/
static void
-clear_eol_bot()
+clear_eol_bot(VOID_PARAM)
{
#if MSDOS_COMPILER
clear_eol();
@@ -2187,7 +2216,7 @@ clear_eol_bot()
* Leave the cursor at the beginning of the bottom line.
*/
public void
-clear_bot()
+clear_bot(VOID_PARAM)
{
/*
* If we're in a non-normal attribute mode, temporarily exit
@@ -2251,7 +2280,7 @@ at_enter(attr)
}
public void
-at_exit()
+at_exit(VOID_PARAM)
{
#if !MSDOS_COMPILER
/* Undo things in the reverse order we did them. */
@@ -2315,7 +2344,7 @@ apply_at_specials(attr)
* and move the cursor left.
*/
public void
-backspace()
+backspace(VOID_PARAM)
{
#if !MSDOS_COMPILER
/*
@@ -2364,8 +2393,12 @@ backspace()
* Output a plain backspace, without erasing the previous char.
*/
public void
-putbs()
+putbs(VOID_PARAM)
{
+ if (termcap_debug)
+ putstr("<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