xref: /freebsd/contrib/less/ttyin.c (revision 2235c7feac959bcc9ddfd6a2bc6be32102b1f84c)
1a5f0fb15SPaul Saab /*
2*2235c7feSXin LI  * Copyright (C) 1984-2021  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
31*2235c7feSXin LI #if LESSTEST
32*2235c7feSXin LI public char *ttyin_name = NULL;
33*2235c7feSXin LI public int rstat_file = -1;
34*2235c7feSXin LI #endif /*LESSTEST*/
35a5f0fb15SPaul Saab extern int sigs;
366dcb072bSXin LI extern int utf_mode;
37b7780dbeSXin LI extern int wheel_lines;
38a5f0fb15SPaul Saab 
39a5f0fb15SPaul Saab /*
40*2235c7feSXin LI  * Get name of tty device.
41*2235c7feSXin LI  */
42*2235c7feSXin LI #if !MSDOS_COMPILER
43*2235c7feSXin LI 	public char *
44*2235c7feSXin LI tty_device(VOID_PARAM)
45*2235c7feSXin LI {
46*2235c7feSXin LI 	char *dev = NULL;
47*2235c7feSXin LI #if HAVE_TTYNAME
48*2235c7feSXin LI 	dev = ttyname(2);
49*2235c7feSXin LI #endif
50*2235c7feSXin LI 	if (dev == NULL)
51*2235c7feSXin LI 		dev = "/dev/tty";
52*2235c7feSXin LI #if LESSTEST
53*2235c7feSXin LI 	if (ttyin_name != NULL)
54*2235c7feSXin LI 		dev = ttyin_name;
55*2235c7feSXin LI #endif /*LESSTEST*/
56*2235c7feSXin LI 	return dev;
57*2235c7feSXin LI }
58*2235c7feSXin LI #endif /* MSDOS_COMPILER */
59*2235c7feSXin LI 
60*2235c7feSXin LI /*
61a5f0fb15SPaul Saab  * Open keyboard for input.
62a5f0fb15SPaul Saab  */
63a5f0fb15SPaul Saab 	public void
64b7780dbeSXin LI open_getchr(VOID_PARAM)
65a5f0fb15SPaul Saab {
66a5f0fb15SPaul Saab #if MSDOS_COMPILER==WIN32C
67a5f0fb15SPaul Saab 	/* Need this to let child processes inherit our console handle */
68a5f0fb15SPaul Saab 	SECURITY_ATTRIBUTES sa;
69a5f0fb15SPaul Saab 	memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
70a5f0fb15SPaul Saab 	sa.nLength = sizeof(SECURITY_ATTRIBUTES);
71a5f0fb15SPaul Saab 	sa.bInheritHandle = TRUE;
72b7780dbeSXin LI 	tty = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
73a5f0fb15SPaul Saab 			FILE_SHARE_READ, &sa,
74a5f0fb15SPaul Saab 			OPEN_EXISTING, 0L, NULL);
75b7780dbeSXin LI 	GetConsoleMode(tty, &console_mode);
76a5f0fb15SPaul Saab 	/* Make sure we get Ctrl+C events. */
77b7780dbeSXin LI 	SetConsoleMode(tty, ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT);
78a5f0fb15SPaul Saab #else
79c9346414SPaul Saab #if MSDOS_COMPILER
80a5f0fb15SPaul Saab 	extern int fd0;
81a5f0fb15SPaul Saab 	/*
82a5f0fb15SPaul Saab 	 * Open a new handle to CON: in binary mode
83a5f0fb15SPaul Saab 	 * for unbuffered keyboard read.
84a5f0fb15SPaul Saab 	 */
85a5f0fb15SPaul Saab 	 fd0 = dup(0);
86a5f0fb15SPaul Saab 	 close(0);
87a5f0fb15SPaul Saab 	 tty = open("CON", OPEN_READ);
88a5f0fb15SPaul Saab #if MSDOS_COMPILER==DJGPPC
89a5f0fb15SPaul Saab 	/*
90a5f0fb15SPaul Saab 	 * Setting stdin to binary causes Ctrl-C to not
91a5f0fb15SPaul Saab 	 * raise SIGINT.  We must undo that side-effect.
92a5f0fb15SPaul Saab 	 */
93a5f0fb15SPaul Saab 	(void) __djgpp_set_ctrl_c(1);
94a5f0fb15SPaul Saab #endif
95a5f0fb15SPaul Saab #else
96a5f0fb15SPaul Saab 	/*
97a5f0fb15SPaul Saab 	 * Try /dev/tty.
98a5f0fb15SPaul Saab 	 * If that doesn't work, use file descriptor 2,
99a5f0fb15SPaul Saab 	 * which in Unix is usually attached to the screen,
100a5f0fb15SPaul Saab 	 * but also usually lets you read from the keyboard.
101a5f0fb15SPaul Saab 	 */
102c9346414SPaul Saab #if OS2
103c9346414SPaul Saab 	/* The __open() system call translates "/dev/tty" to "con". */
104*2235c7feSXin LI 	tty = __open(tty_device(), OPEN_READ);
105c9346414SPaul Saab #else
106*2235c7feSXin LI 	tty = open(tty_device(), OPEN_READ);
107c9346414SPaul Saab #endif
108a5f0fb15SPaul Saab 	if (tty < 0)
109a5f0fb15SPaul Saab 		tty = 2;
110a5f0fb15SPaul Saab #endif
111a5f0fb15SPaul Saab #endif
112a5f0fb15SPaul Saab }
113a5f0fb15SPaul Saab 
114a5f0fb15SPaul Saab /*
115a5f0fb15SPaul Saab  * Close the keyboard.
116a5f0fb15SPaul Saab  */
117a5f0fb15SPaul Saab 	public void
118b7780dbeSXin LI close_getchr(VOID_PARAM)
119a5f0fb15SPaul Saab {
120a5f0fb15SPaul Saab #if MSDOS_COMPILER==WIN32C
121b7780dbeSXin LI 	SetConsoleMode(tty, console_mode);
122b7780dbeSXin LI 	CloseHandle(tty);
123a5f0fb15SPaul Saab #endif
124a5f0fb15SPaul Saab }
125a5f0fb15SPaul Saab 
126b7780dbeSXin LI #if MSDOS_COMPILER==WIN32C
127b7780dbeSXin LI /*
128b7780dbeSXin LI  * Close the pipe, restoring the keyboard (CMD resets it, losing the mouse).
129b7780dbeSXin LI  */
130b7780dbeSXin LI 	int
131b7780dbeSXin LI pclose(f)
132b7780dbeSXin LI 	FILE *f;
133b7780dbeSXin LI {
134b7780dbeSXin LI 	int result;
135b7780dbeSXin LI 
136b7780dbeSXin LI 	result = _pclose(f);
137b7780dbeSXin LI 	SetConsoleMode(tty, ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT);
138b7780dbeSXin LI 	return result;
139b7780dbeSXin LI }
140b7780dbeSXin LI #endif
141b7780dbeSXin LI 
142b7780dbeSXin LI /*
143b7780dbeSXin LI  * Get the number of lines to scroll when mouse wheel is moved.
144b7780dbeSXin LI  */
145b7780dbeSXin LI 	public int
146b7780dbeSXin LI default_wheel_lines(VOID_PARAM)
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 
159*2235c7feSXin LI #if LESSTEST
160*2235c7feSXin LI 	public void
161*2235c7feSXin LI rstat(st)
162*2235c7feSXin LI 	char st;
163*2235c7feSXin LI {
164*2235c7feSXin LI 	if (rstat_file < 0)
165*2235c7feSXin LI 		return;
166*2235c7feSXin LI 	lseek(rstat_file, SEEK_SET, 0);
167*2235c7feSXin LI 	write(rstat_file, &st, 1);
168*2235c7feSXin LI }
169*2235c7feSXin LI #endif /*LESSTEST*/
170*2235c7feSXin LI 
171a5f0fb15SPaul Saab /*
172a5f0fb15SPaul Saab  * Get a character from the keyboard.
173a5f0fb15SPaul Saab  */
174a5f0fb15SPaul Saab 	public int
175b7780dbeSXin LI getchr(VOID_PARAM)
176a5f0fb15SPaul Saab {
177a5f0fb15SPaul Saab 	char c;
178a5f0fb15SPaul Saab 	int result;
179a5f0fb15SPaul Saab 
180a5f0fb15SPaul Saab 	do
181a5f0fb15SPaul Saab 	{
182*2235c7feSXin LI 		flush();
183a5f0fb15SPaul Saab #if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC
184a5f0fb15SPaul Saab 		/*
185a5f0fb15SPaul Saab 		 * In raw read, we don't see ^C so look here for it.
186a5f0fb15SPaul Saab 		 */
187a5f0fb15SPaul Saab #if MSDOS_COMPILER==WIN32C
188a5f0fb15SPaul Saab 		if (ABORT_SIGS())
189a5f0fb15SPaul Saab 			return (READ_INTR);
190b7780dbeSXin LI 		c = WIN32getch();
191a5f0fb15SPaul Saab #else
192a5f0fb15SPaul Saab 		c = getch();
193a5f0fb15SPaul Saab #endif
194a5f0fb15SPaul Saab 		result = 1;
195a5f0fb15SPaul Saab 		if (c == '\003')
196a5f0fb15SPaul Saab 			return (READ_INTR);
197a5f0fb15SPaul Saab #else
198*2235c7feSXin LI #if LESSTEST
199*2235c7feSXin LI 		rstat('R');
200*2235c7feSXin LI #endif /*LESSTEST*/
201f6b74a7dSXin LI 		{
202f6b74a7dSXin LI 			unsigned char uc;
203f6b74a7dSXin LI 			result = iread(tty, &uc, sizeof(char));
204f6b74a7dSXin LI 			c = (char) uc;
205f6b74a7dSXin LI 		}
206*2235c7feSXin LI #if LESSTEST
207*2235c7feSXin LI 		rstat('B');
208*2235c7feSXin LI #endif /*LESSTEST*/
209a5f0fb15SPaul Saab 		if (result == READ_INTR)
210a5f0fb15SPaul Saab 			return (READ_INTR);
211a5f0fb15SPaul Saab 		if (result < 0)
212a5f0fb15SPaul Saab 		{
213a5f0fb15SPaul Saab 			/*
214a5f0fb15SPaul Saab 			 * Don't call error() here,
215a5f0fb15SPaul Saab 			 * because error calls getchr!
216a5f0fb15SPaul Saab 			 */
217a5f0fb15SPaul Saab 			quit(QUIT_ERROR);
218a5f0fb15SPaul Saab 		}
219a5f0fb15SPaul Saab #endif
2206dcb072bSXin LI #if 0 /* allow entering arbitrary hex chars for testing */
2216dcb072bSXin LI 		/* ctrl-A followed by two hex chars makes a byte */
2227f074f9cSXin LI 	{
223f6b74a7dSXin LI 		static int hex_in = 0;
224f6b74a7dSXin LI 		static int hex_value = 0;
2256dcb072bSXin LI 		if (c == CONTROL('A'))
2266dcb072bSXin LI 		{
2276dcb072bSXin LI 			hex_in = 2;
2286dcb072bSXin LI 			result = 0;
2296dcb072bSXin LI 			continue;
2306dcb072bSXin LI 		}
2316dcb072bSXin LI 		if (hex_in > 0)
2326dcb072bSXin LI 		{
2336dcb072bSXin LI 			int v;
2346dcb072bSXin LI 			if (c >= '0' && c <= '9')
2356dcb072bSXin LI 				v = c - '0';
2366dcb072bSXin LI 			else if (c >= 'a' && c <= 'f')
2376dcb072bSXin LI 				v = c - 'a' + 10;
2386dcb072bSXin LI 			else if (c >= 'A' && c <= 'F')
2396dcb072bSXin LI 				v = c - 'A' + 10;
2406dcb072bSXin LI 			else
241b7780dbeSXin LI 				v = 0;
2426dcb072bSXin LI 			hex_value = (hex_value << 4) | v;
2436dcb072bSXin LI 			if (--hex_in > 0)
2446dcb072bSXin LI 			{
2456dcb072bSXin LI 				result = 0;
2466dcb072bSXin LI 				continue;
2476dcb072bSXin LI 			}
2486dcb072bSXin LI 			c = hex_value;
2496dcb072bSXin LI 		}
2507f074f9cSXin LI 	}
2516dcb072bSXin LI #endif
252a5f0fb15SPaul Saab 		/*
253a5f0fb15SPaul Saab 		 * Various parts of the program cannot handle
254a5f0fb15SPaul Saab 		 * an input character of '\0'.
255a5f0fb15SPaul Saab 		 * If a '\0' was actually typed, convert it to '\340' here.
256a5f0fb15SPaul Saab 		 */
257a5f0fb15SPaul Saab 		if (c == '\0')
258a5f0fb15SPaul Saab 			c = '\340';
259a5f0fb15SPaul Saab 	} while (result != 1);
260a5f0fb15SPaul Saab 
2616dcb072bSXin LI 	return (c & 0xFF);
262a5f0fb15SPaul Saab }
263