xref: /netbsd-src/external/bsd/less/dist/ttyin.c (revision 838f5788460f0f133b15d706e644d692a9d4d6ec)
1*838f5788Ssimonb /*	$NetBSD: ttyin.c,v 1.4 2023/10/06 05:49:49 simonb Exp $	*/
220006a0bStron 
320006a0bStron /*
4*838f5788Ssimonb  * Copyright (C) 1984-2023  Mark Nudelman
520006a0bStron  *
620006a0bStron  * You may distribute under the terms of either the GNU General Public
720006a0bStron  * License or the Less License, as specified in the README file.
820006a0bStron  *
9ec18bca0Stron  * For more information, see the README file.
1020006a0bStron  */
1120006a0bStron 
1220006a0bStron 
1320006a0bStron /*
1420006a0bStron  * Routines dealing with getting input from the keyboard (i.e. from the user).
1520006a0bStron  */
1620006a0bStron 
1720006a0bStron #include "less.h"
1820006a0bStron #if OS2
1920006a0bStron #include "cmd.h"
2020006a0bStron #include "pckeys.h"
2120006a0bStron #endif
2220006a0bStron #if MSDOS_COMPILER==WIN32C
23*838f5788Ssimonb #define WIN32_LEAN_AND_MEAN
24*838f5788Ssimonb #ifndef _WIN32_WINNT
25*838f5788Ssimonb #define _WIN32_WINNT 0x400
2620006a0bStron #endif
27*838f5788Ssimonb #include <windows.h>
28*838f5788Ssimonb public DWORD console_mode;
29*838f5788Ssimonb public HANDLE tty;
30*838f5788Ssimonb #else
3120006a0bStron public int tty;
32*838f5788Ssimonb #endif
33*838f5788Ssimonb #if LESSTEST
34*838f5788Ssimonb public char *ttyin_name = NULL;
35*838f5788Ssimonb #endif /*LESSTEST*/
3620006a0bStron extern int sigs;
3720006a0bStron extern int utf_mode;
38*838f5788Ssimonb extern int wheel_lines;
39*838f5788Ssimonb 
40*838f5788Ssimonb #if !MSDOS_COMPILER
open_tty_device(constant char * dev)41*838f5788Ssimonb static int open_tty_device(constant char* dev)
42*838f5788Ssimonb {
43*838f5788Ssimonb #if OS2
44*838f5788Ssimonb 	/* The __open() system call translates "/dev/tty" to "con". */
45*838f5788Ssimonb 	return __open(dev, OPEN_READ);
46*838f5788Ssimonb #else
47*838f5788Ssimonb 	return open(dev, OPEN_READ);
48*838f5788Ssimonb #endif
49*838f5788Ssimonb }
50*838f5788Ssimonb 
51*838f5788Ssimonb /*
52*838f5788Ssimonb  * Open the tty device.
53*838f5788Ssimonb  * Try ttyname(), then try /dev/tty, then use file descriptor 2.
54*838f5788Ssimonb  * In Unix, file descriptor 2 is usually attached to the screen,
55*838f5788Ssimonb  * but also usually lets you read from the keyboard.
56*838f5788Ssimonb  */
open_tty(void)57*838f5788Ssimonb public int open_tty(void)
58*838f5788Ssimonb {
59*838f5788Ssimonb 	int fd = -1;
60*838f5788Ssimonb #if LESSTEST
61*838f5788Ssimonb 	if (ttyin_name != NULL)
62*838f5788Ssimonb 		fd = open_tty_device(ttyin_name);
63*838f5788Ssimonb #endif /*LESSTEST*/
64*838f5788Ssimonb #if HAVE_TTYNAME
65*838f5788Ssimonb 	if (fd < 0)
66*838f5788Ssimonb 	{
67*838f5788Ssimonb 		constant char *dev = ttyname(2);
68*838f5788Ssimonb 		if (dev != NULL)
69*838f5788Ssimonb 			fd = open_tty_device(dev);
70*838f5788Ssimonb 	}
71*838f5788Ssimonb #endif
72*838f5788Ssimonb 	if (fd < 0)
73*838f5788Ssimonb 		fd = open_tty_device("/dev/tty");
74*838f5788Ssimonb 	if (fd < 0)
75*838f5788Ssimonb 		fd = 2;
76*838f5788Ssimonb 	return fd;
77*838f5788Ssimonb }
78*838f5788Ssimonb #endif /* MSDOS_COMPILER */
7920006a0bStron 
8020006a0bStron /*
8120006a0bStron  * Open keyboard for input.
8220006a0bStron  */
open_getchr(void)83*838f5788Ssimonb public void open_getchr(void)
8420006a0bStron {
8520006a0bStron #if MSDOS_COMPILER==WIN32C
8620006a0bStron 	/* Need this to let child processes inherit our console handle */
8720006a0bStron 	SECURITY_ATTRIBUTES sa;
8820006a0bStron 	memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
8920006a0bStron 	sa.nLength = sizeof(SECURITY_ATTRIBUTES);
9020006a0bStron 	sa.bInheritHandle = TRUE;
91*838f5788Ssimonb 	tty = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
9220006a0bStron 			FILE_SHARE_READ, &sa,
9320006a0bStron 			OPEN_EXISTING, 0L, NULL);
94*838f5788Ssimonb 	GetConsoleMode(tty, &console_mode);
9520006a0bStron 	/* Make sure we get Ctrl+C events. */
96*838f5788Ssimonb 	SetConsoleMode(tty, ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT);
9720006a0bStron #else
9820006a0bStron #if MSDOS_COMPILER
9920006a0bStron 	extern int fd0;
10020006a0bStron 	/*
10120006a0bStron 	 * Open a new handle to CON: in binary mode
10220006a0bStron 	 * for unbuffered keyboard read.
10320006a0bStron 	 */
10420006a0bStron 	 fd0 = dup(0);
10520006a0bStron 	 close(0);
10620006a0bStron 	 tty = open("CON", OPEN_READ);
10720006a0bStron #if MSDOS_COMPILER==DJGPPC
10820006a0bStron 	/*
10920006a0bStron 	 * Setting stdin to binary causes Ctrl-C to not
11020006a0bStron 	 * raise SIGINT.  We must undo that side-effect.
11120006a0bStron 	 */
11220006a0bStron 	(void) __djgpp_set_ctrl_c(1);
11320006a0bStron #endif
11420006a0bStron #else
115*838f5788Ssimonb 	tty = open_tty();
11620006a0bStron #endif
11720006a0bStron #endif
11820006a0bStron }
11920006a0bStron 
12020006a0bStron /*
12120006a0bStron  * Close the keyboard.
12220006a0bStron  */
close_getchr(void)123*838f5788Ssimonb public void close_getchr(void)
12420006a0bStron {
12520006a0bStron #if MSDOS_COMPILER==WIN32C
126*838f5788Ssimonb 	SetConsoleMode(tty, console_mode);
127*838f5788Ssimonb 	CloseHandle(tty);
12820006a0bStron #endif
12920006a0bStron }
13020006a0bStron 
131*838f5788Ssimonb #if MSDOS_COMPILER==WIN32C
132*838f5788Ssimonb /*
133*838f5788Ssimonb  * Close the pipe, restoring the keyboard (CMD resets it, losing the mouse).
134*838f5788Ssimonb  */
pclose(FILE * f)135*838f5788Ssimonb public int pclose(FILE *f)
136*838f5788Ssimonb {
137*838f5788Ssimonb 	int result;
138*838f5788Ssimonb 
139*838f5788Ssimonb 	result = _pclose(f);
140*838f5788Ssimonb 	SetConsoleMode(tty, ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT);
141*838f5788Ssimonb 	return result;
142*838f5788Ssimonb }
143*838f5788Ssimonb #endif
144*838f5788Ssimonb 
145*838f5788Ssimonb /*
146*838f5788Ssimonb  * Get the number of lines to scroll when mouse wheel is moved.
147*838f5788Ssimonb  */
default_wheel_lines(void)148*838f5788Ssimonb public int default_wheel_lines(void)
149*838f5788Ssimonb {
150*838f5788Ssimonb 	int lines = 1;
151*838f5788Ssimonb #if MSDOS_COMPILER==WIN32C
152*838f5788Ssimonb 	if (SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &lines, 0))
153*838f5788Ssimonb 	{
154*838f5788Ssimonb 		if (lines == WHEEL_PAGESCROLL)
155*838f5788Ssimonb 			lines = 3;
156*838f5788Ssimonb 	}
157*838f5788Ssimonb #endif
158*838f5788Ssimonb 	return lines;
159*838f5788Ssimonb }
160*838f5788Ssimonb 
16120006a0bStron /*
16220006a0bStron  * Get a character from the keyboard.
16320006a0bStron  */
getchr(void)164*838f5788Ssimonb public int getchr(void)
16520006a0bStron {
16620006a0bStron 	char c;
16720006a0bStron 	int result;
16820006a0bStron 
16920006a0bStron 	do
17020006a0bStron 	{
171*838f5788Ssimonb 		flush();
17220006a0bStron #if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC
17320006a0bStron 		/*
17420006a0bStron 		 * In raw read, we don't see ^C so look here for it.
17520006a0bStron 		 */
17620006a0bStron #if MSDOS_COMPILER==WIN32C
17720006a0bStron 		if (ABORT_SIGS())
17820006a0bStron 			return (READ_INTR);
179*838f5788Ssimonb 		c = WIN32getch();
18020006a0bStron #else
18120006a0bStron 		c = getch();
18220006a0bStron #endif
18320006a0bStron 		result = 1;
18420006a0bStron 		if (c == '\003')
18520006a0bStron 			return (READ_INTR);
18620006a0bStron #else
187*838f5788Ssimonb 		{
188*838f5788Ssimonb 			unsigned char uc;
189*838f5788Ssimonb 			result = iread(tty, &uc, sizeof(char));
190*838f5788Ssimonb 			c = (char) uc;
191*838f5788Ssimonb 		}
19220006a0bStron 		if (result == READ_INTR)
19320006a0bStron 			return (READ_INTR);
19420006a0bStron 		if (result < 0)
19520006a0bStron 		{
19620006a0bStron 			/*
19720006a0bStron 			 * Don't call error() here,
19820006a0bStron 			 * because error calls getchr!
19920006a0bStron 			 */
20020006a0bStron 			quit(QUIT_ERROR);
20120006a0bStron 		}
20220006a0bStron #endif
203*838f5788Ssimonb #if LESSTEST
204*838f5788Ssimonb 		if (c == LESS_DUMP_CHAR)
205*838f5788Ssimonb 		{
206*838f5788Ssimonb 			dump_screen();
207*838f5788Ssimonb 			result = 0;
208*838f5788Ssimonb 			continue;
209*838f5788Ssimonb 		}
210*838f5788Ssimonb #endif
21120006a0bStron #if 0 /* allow entering arbitrary hex chars for testing */
21220006a0bStron 		/* ctrl-A followed by two hex chars makes a byte */
21320006a0bStron 	{
214*838f5788Ssimonb 		static int hex_in = 0;
215*838f5788Ssimonb 		static int hex_value = 0;
21620006a0bStron 		if (c == CONTROL('A'))
21720006a0bStron 		{
21820006a0bStron 			hex_in = 2;
21920006a0bStron 			result = 0;
22020006a0bStron 			continue;
22120006a0bStron 		}
22220006a0bStron 		if (hex_in > 0)
22320006a0bStron 		{
22420006a0bStron 			int v;
22520006a0bStron 			if (c >= '0' && c <= '9')
22620006a0bStron 				v = c - '0';
22720006a0bStron 			else if (c >= 'a' && c <= 'f')
22820006a0bStron 				v = c - 'a' + 10;
22920006a0bStron 			else if (c >= 'A' && c <= 'F')
23020006a0bStron 				v = c - 'A' + 10;
23120006a0bStron 			else
232*838f5788Ssimonb 				v = 0;
23320006a0bStron 			hex_value = (hex_value << 4) | v;
23420006a0bStron 			if (--hex_in > 0)
23520006a0bStron 			{
23620006a0bStron 				result = 0;
23720006a0bStron 				continue;
23820006a0bStron 			}
23920006a0bStron 			c = hex_value;
24020006a0bStron 		}
24120006a0bStron 	}
24220006a0bStron #endif
24320006a0bStron 		/*
24420006a0bStron 		 * Various parts of the program cannot handle
24520006a0bStron 		 * an input character of '\0'.
24620006a0bStron 		 * If a '\0' was actually typed, convert it to '\340' here.
24720006a0bStron 		 */
24820006a0bStron 		if (c == '\0')
24920006a0bStron 			c = '\340';
25020006a0bStron 	} while (result != 1);
25120006a0bStron 
25220006a0bStron 	return (c & 0xFF);
25320006a0bStron }
254