xref: /freebsd/contrib/less/ttyin.c (revision b7780dbe98fc88da65024e697529ea7883064275)
1a5f0fb15SPaul Saab /*
2*b7780dbeSXin LI  * Copyright (C) 1984-2019  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
21*b7780dbeSXin LI #define WIN32_LEAN_AND_MEAN
22*b7780dbeSXin LI #ifndef _WIN32_WINNT
23*b7780dbeSXin LI #define _WIN32_WINNT 0x400
24a5f0fb15SPaul Saab #endif
25*b7780dbeSXin LI #include <windows.h>
26*b7780dbeSXin LI static DWORD console_mode;
27*b7780dbeSXin LI public HANDLE tty;
28*b7780dbeSXin LI #else
29000ba3e8STim J. Robbins public int tty;
30*b7780dbeSXin LI #endif
31a5f0fb15SPaul Saab extern int sigs;
326dcb072bSXin LI extern int utf_mode;
33*b7780dbeSXin LI extern int wheel_lines;
34a5f0fb15SPaul Saab 
35a5f0fb15SPaul Saab /*
36a5f0fb15SPaul Saab  * Open keyboard for input.
37a5f0fb15SPaul Saab  */
38a5f0fb15SPaul Saab 	public void
39*b7780dbeSXin LI open_getchr(VOID_PARAM)
40a5f0fb15SPaul Saab {
41a5f0fb15SPaul Saab #if MSDOS_COMPILER==WIN32C
42a5f0fb15SPaul Saab 	/* Need this to let child processes inherit our console handle */
43a5f0fb15SPaul Saab 	SECURITY_ATTRIBUTES sa;
44a5f0fb15SPaul Saab 	memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
45a5f0fb15SPaul Saab 	sa.nLength = sizeof(SECURITY_ATTRIBUTES);
46a5f0fb15SPaul Saab 	sa.bInheritHandle = TRUE;
47*b7780dbeSXin LI 	tty = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
48a5f0fb15SPaul Saab 			FILE_SHARE_READ, &sa,
49a5f0fb15SPaul Saab 			OPEN_EXISTING, 0L, NULL);
50*b7780dbeSXin LI 	GetConsoleMode(tty, &console_mode);
51a5f0fb15SPaul Saab 	/* Make sure we get Ctrl+C events. */
52*b7780dbeSXin LI 	SetConsoleMode(tty, ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT);
53a5f0fb15SPaul Saab #else
54c9346414SPaul Saab #if MSDOS_COMPILER
55a5f0fb15SPaul Saab 	extern int fd0;
56a5f0fb15SPaul Saab 	/*
57a5f0fb15SPaul Saab 	 * Open a new handle to CON: in binary mode
58a5f0fb15SPaul Saab 	 * for unbuffered keyboard read.
59a5f0fb15SPaul Saab 	 */
60a5f0fb15SPaul Saab 	 fd0 = dup(0);
61a5f0fb15SPaul Saab 	 close(0);
62a5f0fb15SPaul Saab 	 tty = open("CON", OPEN_READ);
63a5f0fb15SPaul Saab #if MSDOS_COMPILER==DJGPPC
64a5f0fb15SPaul Saab 	/*
65a5f0fb15SPaul Saab 	 * Setting stdin to binary causes Ctrl-C to not
66a5f0fb15SPaul Saab 	 * raise SIGINT.  We must undo that side-effect.
67a5f0fb15SPaul Saab 	 */
68a5f0fb15SPaul Saab 	(void) __djgpp_set_ctrl_c(1);
69a5f0fb15SPaul Saab #endif
70a5f0fb15SPaul Saab #else
71a5f0fb15SPaul Saab 	/*
72a5f0fb15SPaul Saab 	 * Try /dev/tty.
73a5f0fb15SPaul Saab 	 * If that doesn't work, use file descriptor 2,
74a5f0fb15SPaul Saab 	 * which in Unix is usually attached to the screen,
75a5f0fb15SPaul Saab 	 * but also usually lets you read from the keyboard.
76a5f0fb15SPaul Saab 	 */
77c9346414SPaul Saab #if OS2
78c9346414SPaul Saab 	/* The __open() system call translates "/dev/tty" to "con". */
79c9346414SPaul Saab 	tty = __open("/dev/tty", OPEN_READ);
80c9346414SPaul Saab #else
81a5f0fb15SPaul Saab 	tty = open("/dev/tty", OPEN_READ);
82c9346414SPaul Saab #endif
83a5f0fb15SPaul Saab 	if (tty < 0)
84a5f0fb15SPaul Saab 		tty = 2;
85a5f0fb15SPaul Saab #endif
86a5f0fb15SPaul Saab #endif
87a5f0fb15SPaul Saab }
88a5f0fb15SPaul Saab 
89a5f0fb15SPaul Saab /*
90a5f0fb15SPaul Saab  * Close the keyboard.
91a5f0fb15SPaul Saab  */
92a5f0fb15SPaul Saab 	public void
93*b7780dbeSXin LI close_getchr(VOID_PARAM)
94a5f0fb15SPaul Saab {
95a5f0fb15SPaul Saab #if MSDOS_COMPILER==WIN32C
96*b7780dbeSXin LI 	SetConsoleMode(tty, console_mode);
97*b7780dbeSXin LI 	CloseHandle(tty);
98a5f0fb15SPaul Saab #endif
99a5f0fb15SPaul Saab }
100a5f0fb15SPaul Saab 
101*b7780dbeSXin LI #if MSDOS_COMPILER==WIN32C
102*b7780dbeSXin LI /*
103*b7780dbeSXin LI  * Close the pipe, restoring the keyboard (CMD resets it, losing the mouse).
104*b7780dbeSXin LI  */
105*b7780dbeSXin LI 	int
106*b7780dbeSXin LI pclose(f)
107*b7780dbeSXin LI 	FILE *f;
108*b7780dbeSXin LI {
109*b7780dbeSXin LI 	int result;
110*b7780dbeSXin LI 
111*b7780dbeSXin LI 	result = _pclose(f);
112*b7780dbeSXin LI 	SetConsoleMode(tty, ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT);
113*b7780dbeSXin LI 	return result;
114*b7780dbeSXin LI }
115*b7780dbeSXin LI #endif
116*b7780dbeSXin LI 
117*b7780dbeSXin LI /*
118*b7780dbeSXin LI  * Get the number of lines to scroll when mouse wheel is moved.
119*b7780dbeSXin LI  */
120*b7780dbeSXin LI 	public int
121*b7780dbeSXin LI default_wheel_lines(VOID_PARAM)
122*b7780dbeSXin LI {
123*b7780dbeSXin LI 	int lines = 1;
124*b7780dbeSXin LI #if MSDOS_COMPILER==WIN32C
125*b7780dbeSXin LI 	if (SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &lines, 0))
126*b7780dbeSXin LI 	{
127*b7780dbeSXin LI 		if (lines == WHEEL_PAGESCROLL)
128*b7780dbeSXin LI 			lines = 3;
129*b7780dbeSXin LI 	}
130*b7780dbeSXin LI #endif
131*b7780dbeSXin LI 	return lines;
132*b7780dbeSXin LI }
133*b7780dbeSXin LI 
134a5f0fb15SPaul Saab /*
135a5f0fb15SPaul Saab  * Get a character from the keyboard.
136a5f0fb15SPaul Saab  */
137a5f0fb15SPaul Saab 	public int
138*b7780dbeSXin LI getchr(VOID_PARAM)
139a5f0fb15SPaul Saab {
140a5f0fb15SPaul Saab 	char c;
141a5f0fb15SPaul Saab 	int result;
142a5f0fb15SPaul Saab 
143a5f0fb15SPaul Saab 	do
144a5f0fb15SPaul Saab 	{
145a5f0fb15SPaul Saab #if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC
146a5f0fb15SPaul Saab 		/*
147a5f0fb15SPaul Saab 		 * In raw read, we don't see ^C so look here for it.
148a5f0fb15SPaul Saab 		 */
149a5f0fb15SPaul Saab 		flush();
150a5f0fb15SPaul Saab #if MSDOS_COMPILER==WIN32C
151a5f0fb15SPaul Saab 		if (ABORT_SIGS())
152a5f0fb15SPaul Saab 			return (READ_INTR);
153*b7780dbeSXin LI 		c = WIN32getch();
154a5f0fb15SPaul Saab #else
155a5f0fb15SPaul Saab 		c = getch();
156a5f0fb15SPaul Saab #endif
157a5f0fb15SPaul Saab 		result = 1;
158a5f0fb15SPaul Saab 		if (c == '\003')
159a5f0fb15SPaul Saab 			return (READ_INTR);
160a5f0fb15SPaul Saab #else
161f6b74a7dSXin LI 		{
162f6b74a7dSXin LI 			unsigned char uc;
163f6b74a7dSXin LI 			result = iread(tty, &uc, sizeof(char));
164f6b74a7dSXin LI 			c = (char) uc;
165f6b74a7dSXin LI 		}
166a5f0fb15SPaul Saab 		if (result == READ_INTR)
167a5f0fb15SPaul Saab 			return (READ_INTR);
168a5f0fb15SPaul Saab 		if (result < 0)
169a5f0fb15SPaul Saab 		{
170a5f0fb15SPaul Saab 			/*
171a5f0fb15SPaul Saab 			 * Don't call error() here,
172a5f0fb15SPaul Saab 			 * because error calls getchr!
173a5f0fb15SPaul Saab 			 */
174a5f0fb15SPaul Saab 			quit(QUIT_ERROR);
175a5f0fb15SPaul Saab 		}
176a5f0fb15SPaul Saab #endif
1776dcb072bSXin LI #if 0 /* allow entering arbitrary hex chars for testing */
1786dcb072bSXin LI 		/* ctrl-A followed by two hex chars makes a byte */
1797f074f9cSXin LI 	{
180f6b74a7dSXin LI 		static int hex_in = 0;
181f6b74a7dSXin LI 		static int hex_value = 0;
1826dcb072bSXin LI 		if (c == CONTROL('A'))
1836dcb072bSXin LI 		{
1846dcb072bSXin LI 			hex_in = 2;
1856dcb072bSXin LI 			result = 0;
1866dcb072bSXin LI 			continue;
1876dcb072bSXin LI 		}
1886dcb072bSXin LI 		if (hex_in > 0)
1896dcb072bSXin LI 		{
1906dcb072bSXin LI 			int v;
1916dcb072bSXin LI 			if (c >= '0' && c <= '9')
1926dcb072bSXin LI 				v = c - '0';
1936dcb072bSXin LI 			else if (c >= 'a' && c <= 'f')
1946dcb072bSXin LI 				v = c - 'a' + 10;
1956dcb072bSXin LI 			else if (c >= 'A' && c <= 'F')
1966dcb072bSXin LI 				v = c - 'A' + 10;
1976dcb072bSXin LI 			else
198*b7780dbeSXin LI 				v = 0;
1996dcb072bSXin LI 			hex_value = (hex_value << 4) | v;
2006dcb072bSXin LI 			if (--hex_in > 0)
2016dcb072bSXin LI 			{
2026dcb072bSXin LI 				result = 0;
2036dcb072bSXin LI 				continue;
2046dcb072bSXin LI 			}
2056dcb072bSXin LI 			c = hex_value;
2066dcb072bSXin LI 		}
2077f074f9cSXin LI 	}
2086dcb072bSXin LI #endif
209a5f0fb15SPaul Saab 		/*
210a5f0fb15SPaul Saab 		 * Various parts of the program cannot handle
211a5f0fb15SPaul Saab 		 * an input character of '\0'.
212a5f0fb15SPaul Saab 		 * If a '\0' was actually typed, convert it to '\340' here.
213a5f0fb15SPaul Saab 		 */
214a5f0fb15SPaul Saab 		if (c == '\0')
215a5f0fb15SPaul Saab 			c = '\340';
216a5f0fb15SPaul Saab 	} while (result != 1);
217a5f0fb15SPaul Saab 
2186dcb072bSXin LI 	return (c & 0xFF);
219a5f0fb15SPaul Saab }
220