diff options
| author | Xin LI <delphij@FreeBSD.org> | 2019-06-29 04:39:01 +0000 | 
|---|---|---|
| committer | Xin LI <delphij@FreeBSD.org> | 2019-06-29 04:39:01 +0000 | 
| commit | 6aa86b45318b321ba7e9cc3c221ab9062ddac4a0 (patch) | |
| tree | ed38a1d35ad0e927ec1b5282deedc86014f9181d /screen.c | |
| parent | b04073e3aef4b6c7e7d2755a7bbc098e5f2a03f8 (diff) | |
Diffstat (limited to 'screen.c')
| -rw-r--r-- | screen.c | 278 | 
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 | 
