xref: /freebsd/contrib/less/ttyin.c (revision d713e0891ff9ab8246245c3206851d486ecfdd37)
1a5f0fb15SPaul Saab /*
2*d713e089SXin LI  * Copyright (C) 1984-2023  Mark Nudelman
3a5f0fb15SPaul Saab  *
4a5f0fb15SPaul Saab  * You may distribute under the terms of either the GNU General Public
5a5f0fb15SPaul Saab  * License or the Less License, as specified in the README file.
6a5f0fb15SPaul Saab  *
796e55cc7SXin LI  * For more information, see the README file.
8a5f0fb15SPaul Saab  */
9a5f0fb15SPaul Saab 
10a5f0fb15SPaul Saab 
11a5f0fb15SPaul Saab /*
12a5f0fb15SPaul Saab  * Routines dealing with getting input from the keyboard (i.e. from the user).
13a5f0fb15SPaul Saab  */
14a5f0fb15SPaul Saab 
15a5f0fb15SPaul Saab #include "less.h"
16c9346414SPaul Saab #if OS2
17c9346414SPaul Saab #include "cmd.h"
18c9346414SPaul Saab #include "pckeys.h"
19c9346414SPaul Saab #endif
20a5f0fb15SPaul Saab #if MSDOS_COMPILER==WIN32C
21b7780dbeSXin LI #define WIN32_LEAN_AND_MEAN
22b7780dbeSXin LI #ifndef _WIN32_WINNT
23b7780dbeSXin LI #define _WIN32_WINNT 0x400
24a5f0fb15SPaul Saab #endif
25b7780dbeSXin LI #include <windows.h>
266f26c71dSXin LI public DWORD console_mode;
27b7780dbeSXin LI public HANDLE tty;
28b7780dbeSXin LI #else
29000ba3e8STim J. Robbins public int tty;
30b7780dbeSXin LI #endif
312235c7feSXin LI #if LESSTEST
322235c7feSXin LI public char *ttyin_name = NULL;
332235c7feSXin LI #endif /*LESSTEST*/
34a5f0fb15SPaul Saab extern int sigs;
356dcb072bSXin LI extern int utf_mode;
36b7780dbeSXin LI extern int wheel_lines;
37a5f0fb15SPaul Saab 
382235c7feSXin LI #if !MSDOS_COMPILER
39*d713e089SXin LI static int open_tty_device(constant char* dev)
402235c7feSXin LI {
4195270f73SXin LI #if OS2
4295270f73SXin LI 	/* The __open() system call translates "/dev/tty" to "con". */
4395270f73SXin LI 	return __open(dev, OPEN_READ);
4495270f73SXin LI #else
4595270f73SXin LI 	return open(dev, OPEN_READ);
462235c7feSXin LI #endif
4795270f73SXin LI }
4895270f73SXin LI 
4995270f73SXin LI /*
5095270f73SXin LI  * Open the tty device.
5195270f73SXin LI  * Try ttyname(), then try /dev/tty, then use file descriptor 2.
5295270f73SXin LI  * In Unix, file descriptor 2 is usually attached to the screen,
5395270f73SXin LI  * but also usually lets you read from the keyboard.
5495270f73SXin LI  */
55*d713e089SXin LI public int open_tty(void)
5695270f73SXin LI {
5795270f73SXin LI 	int fd = -1;
582235c7feSXin LI #if LESSTEST
592235c7feSXin LI 	if (ttyin_name != NULL)
6095270f73SXin LI 		fd = open_tty_device(ttyin_name);
612235c7feSXin LI #endif /*LESSTEST*/
6295270f73SXin LI #if HAVE_TTYNAME
6395270f73SXin LI 	if (fd < 0)
6495270f73SXin LI 	{
6595270f73SXin LI 		constant char *dev = ttyname(2);
6695270f73SXin LI 		if (dev != NULL)
6795270f73SXin LI 			fd = open_tty_device(dev);
6895270f73SXin LI 	}
6995270f73SXin LI #endif
7095270f73SXin LI 	if (fd < 0)
7195270f73SXin LI 		fd = open_tty_device("/dev/tty");
7295270f73SXin LI 	if (fd < 0)
7395270f73SXin LI 		fd = 2;
7495270f73SXin LI 	return fd;
752235c7feSXin LI }
762235c7feSXin LI #endif /* MSDOS_COMPILER */
772235c7feSXin LI 
782235c7feSXin LI /*
79a5f0fb15SPaul Saab  * Open keyboard for input.
80a5f0fb15SPaul Saab  */
81*d713e089SXin LI public void open_getchr(void)
82a5f0fb15SPaul Saab {
83a5f0fb15SPaul Saab #if MSDOS_COMPILER==WIN32C
84a5f0fb15SPaul Saab 	/* Need this to let child processes inherit our console handle */
85a5f0fb15SPaul Saab 	SECURITY_ATTRIBUTES sa;
86a5f0fb15SPaul Saab 	memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
87a5f0fb15SPaul Saab 	sa.nLength = sizeof(SECURITY_ATTRIBUTES);
88a5f0fb15SPaul Saab 	sa.bInheritHandle = TRUE;
89b7780dbeSXin LI 	tty = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
90a5f0fb15SPaul Saab 			FILE_SHARE_READ, &sa,
91a5f0fb15SPaul Saab 			OPEN_EXISTING, 0L, NULL);
92b7780dbeSXin LI 	GetConsoleMode(tty, &console_mode);
93a5f0fb15SPaul Saab 	/* Make sure we get Ctrl+C events. */
94b7780dbeSXin LI 	SetConsoleMode(tty, ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT);
95a5f0fb15SPaul Saab #else
96c9346414SPaul Saab #if MSDOS_COMPILER
97a5f0fb15SPaul Saab 	extern int fd0;
98a5f0fb15SPaul Saab 	/*
99a5f0fb15SPaul Saab 	 * Open a new handle to CON: in binary mode
100a5f0fb15SPaul Saab 	 * for unbuffered keyboard read.
101a5f0fb15SPaul Saab 	 */
102a5f0fb15SPaul Saab 	 fd0 = dup(0);
103a5f0fb15SPaul Saab 	 close(0);
104a5f0fb15SPaul Saab 	 tty = open("CON", OPEN_READ);
105a5f0fb15SPaul Saab #if MSDOS_COMPILER==DJGPPC
106a5f0fb15SPaul Saab 	/*
107a5f0fb15SPaul Saab 	 * Setting stdin to binary causes Ctrl-C to not
108a5f0fb15SPaul Saab 	 * raise SIGINT.  We must undo that side-effect.
109a5f0fb15SPaul Saab 	 */
110a5f0fb15SPaul Saab 	(void) __djgpp_set_ctrl_c(1);
111a5f0fb15SPaul Saab #endif
112a5f0fb15SPaul Saab #else
11395270f73SXin LI 	tty = open_tty();
114a5f0fb15SPaul Saab #endif
115a5f0fb15SPaul Saab #endif
116a5f0fb15SPaul Saab }
117a5f0fb15SPaul Saab 
118a5f0fb15SPaul Saab /*
119a5f0fb15SPaul Saab  * Close the keyboard.
120a5f0fb15SPaul Saab  */
121*d713e089SXin LI public void close_getchr(void)
122a5f0fb15SPaul Saab {
123a5f0fb15SPaul Saab #if MSDOS_COMPILER==WIN32C
124b7780dbeSXin LI 	SetConsoleMode(tty, console_mode);
125b7780dbeSXin LI 	CloseHandle(tty);
126a5f0fb15SPaul Saab #endif
127a5f0fb15SPaul Saab }
128a5f0fb15SPaul Saab 
129b7780dbeSXin LI #if MSDOS_COMPILER==WIN32C
130b7780dbeSXin LI /*
131b7780dbeSXin LI  * Close the pipe, restoring the keyboard (CMD resets it, losing the mouse).
132b7780dbeSXin LI  */
133*d713e089SXin LI public int pclose(FILE *f)
134b7780dbeSXin LI {
135b7780dbeSXin LI 	int result;
136b7780dbeSXin LI 
137b7780dbeSXin LI 	result = _pclose(f);
138b7780dbeSXin LI 	SetConsoleMode(tty, ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT);
139b7780dbeSXin LI 	return result;
140b7780dbeSXin LI }
141b7780dbeSXin LI #endif
142b7780dbeSXin LI 
143b7780dbeSXin LI /*
144b7780dbeSXin LI  * Get the number of lines to scroll when mouse wheel is moved.
145b7780dbeSXin LI  */
146*d713e089SXin LI public int default_wheel_lines(void)
147b7780dbeSXin LI {
148b7780dbeSXin LI 	int lines = 1;
149b7780dbeSXin LI #if MSDOS_COMPILER==WIN32C
150b7780dbeSXin LI 	if (SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &lines, 0))
151b7780dbeSXin LI 	{
152b7780dbeSXin LI 		if (lines == WHEEL_PAGESCROLL)
153b7780dbeSXin LI 			lines = 3;
154b7780dbeSXin LI 	}
155b7780dbeSXin LI #endif
156b7780dbeSXin LI 	return lines;
157b7780dbeSXin LI }
158b7780dbeSXin LI 
159a5f0fb15SPaul Saab /*
160a5f0fb15SPaul Saab  * Get a character from the keyboard.
161a5f0fb15SPaul Saab  */
162*d713e089SXin LI public int getchr(void)
163a5f0fb15SPaul Saab {
164a5f0fb15SPaul Saab 	char c;
165a5f0fb15SPaul Saab 	int result;
166a5f0fb15SPaul Saab 
167a5f0fb15SPaul Saab 	do
168a5f0fb15SPaul Saab 	{
1692235c7feSXin LI 		flush();
170a5f0fb15SPaul Saab #if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC
171a5f0fb15SPaul Saab 		/*
172a5f0fb15SPaul Saab 		 * In raw read, we don't see ^C so look here for it.
173a5f0fb15SPaul Saab 		 */
174a5f0fb15SPaul Saab #if MSDOS_COMPILER==WIN32C
175a5f0fb15SPaul Saab 		if (ABORT_SIGS())
176a5f0fb15SPaul Saab 			return (READ_INTR);
177b7780dbeSXin LI 		c = WIN32getch();
178a5f0fb15SPaul Saab #else
179a5f0fb15SPaul Saab 		c = getch();
180a5f0fb15SPaul Saab #endif
181a5f0fb15SPaul Saab 		result = 1;
182a5f0fb15SPaul Saab 		if (c == '\003')
183a5f0fb15SPaul Saab 			return (READ_INTR);
184a5f0fb15SPaul Saab #else
185f6b74a7dSXin LI 		{
186f6b74a7dSXin LI 			unsigned char uc;
187f6b74a7dSXin LI 			result = iread(tty, &uc, sizeof(char));
188f6b74a7dSXin LI 			c = (char) uc;
189f6b74a7dSXin LI 		}
190a5f0fb15SPaul Saab 		if (result == READ_INTR)
191a5f0fb15SPaul Saab 			return (READ_INTR);
192a5f0fb15SPaul Saab 		if (result < 0)
193a5f0fb15SPaul Saab 		{
194a5f0fb15SPaul Saab 			/*
195a5f0fb15SPaul Saab 			 * Don't call error() here,
196a5f0fb15SPaul Saab 			 * because error calls getchr!
197a5f0fb15SPaul Saab 			 */
198a5f0fb15SPaul Saab 			quit(QUIT_ERROR);
199a5f0fb15SPaul Saab 		}
200a5f0fb15SPaul Saab #endif
201*d713e089SXin LI #if LESSTEST
202*d713e089SXin LI 		if (c == LESS_DUMP_CHAR)
203*d713e089SXin LI 		{
204*d713e089SXin LI 			dump_screen();
205*d713e089SXin LI 			result = 0;
206*d713e089SXin LI 			continue;
207*d713e089SXin LI 		}
208*d713e089SXin LI #endif
2096dcb072bSXin LI #if 0 /* allow entering arbitrary hex chars for testing */
2106dcb072bSXin LI 		/* ctrl-A followed by two hex chars makes a byte */
2117f074f9cSXin LI 	{
212f6b74a7dSXin LI 		static int hex_in = 0;
213f6b74a7dSXin LI 		static int hex_value = 0;
2146dcb072bSXin LI 		if (c == CONTROL('A'))
2156dcb072bSXin LI 		{
2166dcb072bSXin LI 			hex_in = 2;
2176dcb072bSXin LI 			result = 0;
2186dcb072bSXin LI 			continue;
2196dcb072bSXin LI 		}
2206dcb072bSXin LI 		if (hex_in > 0)
2216dcb072bSXin LI 		{
2226dcb072bSXin LI 			int v;
2236dcb072bSXin LI 			if (c >= '0' && c <= '9')
2246dcb072bSXin LI 				v = c - '0';
2256dcb072bSXin LI 			else if (c >= 'a' && c <= 'f')
2266dcb072bSXin LI 				v = c - 'a' + 10;
2276dcb072bSXin LI 			else if (c >= 'A' && c <= 'F')
2286dcb072bSXin LI 				v = c - 'A' + 10;
2296dcb072bSXin LI 			else
230b7780dbeSXin LI 				v = 0;
2316dcb072bSXin LI 			hex_value = (hex_value << 4) | v;
2326dcb072bSXin LI 			if (--hex_in > 0)
2336dcb072bSXin LI 			{
2346dcb072bSXin LI 				result = 0;
2356dcb072bSXin LI 				continue;
2366dcb072bSXin LI 			}
2376dcb072bSXin LI 			c = hex_value;
2386dcb072bSXin LI 		}
2397f074f9cSXin LI 	}
2406dcb072bSXin LI #endif
241a5f0fb15SPaul Saab 		/*
242a5f0fb15SPaul Saab 		 * Various parts of the program cannot handle
243a5f0fb15SPaul Saab 		 * an input character of '\0'.
244a5f0fb15SPaul Saab 		 * If a '\0' was actually typed, convert it to '\340' here.
245a5f0fb15SPaul Saab 		 */
246a5f0fb15SPaul Saab 		if (c == '\0')
247a5f0fb15SPaul Saab 			c = '\340';
248a5f0fb15SPaul Saab 	} while (result != 1);
249a5f0fb15SPaul Saab 
2506dcb072bSXin LI 	return (c & 0xFF);
251a5f0fb15SPaul Saab }
252