xref: /freebsd/contrib/less/ttyin.c (revision f6b74a7d164b5fada266d00e723155a178a4529f)
1a5f0fb15SPaul Saab /*
2*f6b74a7dSXin LI  * Copyright (C) 1984-2017  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
21a5f0fb15SPaul Saab #include "windows.h"
22a5f0fb15SPaul Saab extern char WIN32getch();
23a5f0fb15SPaul Saab static DWORD console_mode;
24a5f0fb15SPaul Saab #endif
25a5f0fb15SPaul Saab 
26000ba3e8STim J. Robbins public int tty;
27a5f0fb15SPaul Saab extern int sigs;
286dcb072bSXin LI extern int utf_mode;
29a5f0fb15SPaul Saab 
30a5f0fb15SPaul Saab /*
31a5f0fb15SPaul Saab  * Open keyboard for input.
32a5f0fb15SPaul Saab  */
33a5f0fb15SPaul Saab 	public void
34*f6b74a7dSXin LI open_getchr()
35a5f0fb15SPaul Saab {
36a5f0fb15SPaul Saab #if MSDOS_COMPILER==WIN32C
37a5f0fb15SPaul Saab 	/* Need this to let child processes inherit our console handle */
38a5f0fb15SPaul Saab 	SECURITY_ATTRIBUTES sa;
39a5f0fb15SPaul Saab 	memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
40a5f0fb15SPaul Saab 	sa.nLength = sizeof(SECURITY_ATTRIBUTES);
41a5f0fb15SPaul Saab 	sa.bInheritHandle = TRUE;
42a5f0fb15SPaul Saab 	tty = (int) CreateFile("CONIN$", GENERIC_READ,
43a5f0fb15SPaul Saab 			FILE_SHARE_READ, &sa,
44a5f0fb15SPaul Saab 			OPEN_EXISTING, 0L, NULL);
45a5f0fb15SPaul Saab 	GetConsoleMode((HANDLE)tty, &console_mode);
46a5f0fb15SPaul Saab 	/* Make sure we get Ctrl+C events. */
47a5f0fb15SPaul Saab 	SetConsoleMode((HANDLE)tty, ENABLE_PROCESSED_INPUT);
48a5f0fb15SPaul Saab #else
49c9346414SPaul Saab #if MSDOS_COMPILER
50a5f0fb15SPaul Saab 	extern int fd0;
51a5f0fb15SPaul Saab 	/*
52a5f0fb15SPaul Saab 	 * Open a new handle to CON: in binary mode
53a5f0fb15SPaul Saab 	 * for unbuffered keyboard read.
54a5f0fb15SPaul Saab 	 */
55a5f0fb15SPaul Saab 	 fd0 = dup(0);
56a5f0fb15SPaul Saab 	 close(0);
57a5f0fb15SPaul Saab 	 tty = open("CON", OPEN_READ);
58a5f0fb15SPaul Saab #if MSDOS_COMPILER==DJGPPC
59a5f0fb15SPaul Saab 	/*
60a5f0fb15SPaul Saab 	 * Setting stdin to binary causes Ctrl-C to not
61a5f0fb15SPaul Saab 	 * raise SIGINT.  We must undo that side-effect.
62a5f0fb15SPaul Saab 	 */
63a5f0fb15SPaul Saab 	(void) __djgpp_set_ctrl_c(1);
64a5f0fb15SPaul Saab #endif
65a5f0fb15SPaul Saab #else
66a5f0fb15SPaul Saab 	/*
67a5f0fb15SPaul Saab 	 * Try /dev/tty.
68a5f0fb15SPaul Saab 	 * If that doesn't work, use file descriptor 2,
69a5f0fb15SPaul Saab 	 * which in Unix is usually attached to the screen,
70a5f0fb15SPaul Saab 	 * but also usually lets you read from the keyboard.
71a5f0fb15SPaul Saab 	 */
72c9346414SPaul Saab #if OS2
73c9346414SPaul Saab 	/* The __open() system call translates "/dev/tty" to "con". */
74c9346414SPaul Saab 	tty = __open("/dev/tty", OPEN_READ);
75c9346414SPaul Saab #else
76a5f0fb15SPaul Saab 	tty = open("/dev/tty", OPEN_READ);
77c9346414SPaul Saab #endif
78a5f0fb15SPaul Saab 	if (tty < 0)
79a5f0fb15SPaul Saab 		tty = 2;
80a5f0fb15SPaul Saab #endif
81a5f0fb15SPaul Saab #endif
82a5f0fb15SPaul Saab }
83a5f0fb15SPaul Saab 
84a5f0fb15SPaul Saab /*
85a5f0fb15SPaul Saab  * Close the keyboard.
86a5f0fb15SPaul Saab  */
87a5f0fb15SPaul Saab 	public void
88*f6b74a7dSXin LI close_getchr()
89a5f0fb15SPaul Saab {
90a5f0fb15SPaul Saab #if MSDOS_COMPILER==WIN32C
91a5f0fb15SPaul Saab 	SetConsoleMode((HANDLE)tty, console_mode);
92a5f0fb15SPaul Saab 	CloseHandle((HANDLE)tty);
93a5f0fb15SPaul Saab #endif
94a5f0fb15SPaul Saab }
95a5f0fb15SPaul Saab 
96a5f0fb15SPaul Saab /*
97a5f0fb15SPaul Saab  * Get a character from the keyboard.
98a5f0fb15SPaul Saab  */
99a5f0fb15SPaul Saab 	public int
100*f6b74a7dSXin LI getchr()
101a5f0fb15SPaul Saab {
102a5f0fb15SPaul Saab 	char c;
103a5f0fb15SPaul Saab 	int result;
104a5f0fb15SPaul Saab 
105a5f0fb15SPaul Saab 	do
106a5f0fb15SPaul Saab 	{
107a5f0fb15SPaul Saab #if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC
108a5f0fb15SPaul Saab 		/*
109a5f0fb15SPaul Saab 		 * In raw read, we don't see ^C so look here for it.
110a5f0fb15SPaul Saab 		 */
111a5f0fb15SPaul Saab 		flush();
112a5f0fb15SPaul Saab #if MSDOS_COMPILER==WIN32C
113a5f0fb15SPaul Saab 		if (ABORT_SIGS())
114a5f0fb15SPaul Saab 			return (READ_INTR);
115a5f0fb15SPaul Saab 		c = WIN32getch(tty);
116a5f0fb15SPaul Saab #else
117a5f0fb15SPaul Saab 		c = getch();
118a5f0fb15SPaul Saab #endif
119a5f0fb15SPaul Saab 		result = 1;
120a5f0fb15SPaul Saab 		if (c == '\003')
121a5f0fb15SPaul Saab 			return (READ_INTR);
122a5f0fb15SPaul Saab #else
123*f6b74a7dSXin LI 		{
124*f6b74a7dSXin LI 			unsigned char uc;
125*f6b74a7dSXin LI 			result = iread(tty, &uc, sizeof(char));
126*f6b74a7dSXin LI 			c = (char) uc;
127*f6b74a7dSXin LI 		}
128a5f0fb15SPaul Saab 		if (result == READ_INTR)
129a5f0fb15SPaul Saab 			return (READ_INTR);
130a5f0fb15SPaul Saab 		if (result < 0)
131a5f0fb15SPaul Saab 		{
132a5f0fb15SPaul Saab 			/*
133a5f0fb15SPaul Saab 			 * Don't call error() here,
134a5f0fb15SPaul Saab 			 * because error calls getchr!
135a5f0fb15SPaul Saab 			 */
136a5f0fb15SPaul Saab 			quit(QUIT_ERROR);
137a5f0fb15SPaul Saab 		}
138a5f0fb15SPaul Saab #endif
1396dcb072bSXin LI #if 0 /* allow entering arbitrary hex chars for testing */
1406dcb072bSXin LI 		/* ctrl-A followed by two hex chars makes a byte */
1417f074f9cSXin LI 	{
142*f6b74a7dSXin LI 		static int hex_in = 0;
143*f6b74a7dSXin LI 		static int hex_value = 0;
1446dcb072bSXin LI 		if (c == CONTROL('A'))
1456dcb072bSXin LI 		{
1466dcb072bSXin LI 			hex_in = 2;
1476dcb072bSXin LI 			result = 0;
1486dcb072bSXin LI 			continue;
1496dcb072bSXin LI 		}
1506dcb072bSXin LI 		if (hex_in > 0)
1516dcb072bSXin LI 		{
1526dcb072bSXin LI 			int v;
1536dcb072bSXin LI 			if (c >= '0' && c <= '9')
1546dcb072bSXin LI 				v = c - '0';
1556dcb072bSXin LI 			else if (c >= 'a' && c <= 'f')
1566dcb072bSXin LI 				v = c - 'a' + 10;
1576dcb072bSXin LI 			else if (c >= 'A' && c <= 'F')
1586dcb072bSXin LI 				v = c - 'A' + 10;
1596dcb072bSXin LI 			else
1606dcb072bSXin LI 				hex_in = 0;
1616dcb072bSXin LI 			hex_value = (hex_value << 4) | v;
1626dcb072bSXin LI 			if (--hex_in > 0)
1636dcb072bSXin LI 			{
1646dcb072bSXin LI 				result = 0;
1656dcb072bSXin LI 				continue;
1666dcb072bSXin LI 			}
1676dcb072bSXin LI 			c = hex_value;
1686dcb072bSXin LI 		}
1697f074f9cSXin LI 	}
1706dcb072bSXin LI #endif
171a5f0fb15SPaul Saab 		/*
172a5f0fb15SPaul Saab 		 * Various parts of the program cannot handle
173a5f0fb15SPaul Saab 		 * an input character of '\0'.
174a5f0fb15SPaul Saab 		 * If a '\0' was actually typed, convert it to '\340' here.
175a5f0fb15SPaul Saab 		 */
176a5f0fb15SPaul Saab 		if (c == '\0')
177a5f0fb15SPaul Saab 			c = '\340';
178a5f0fb15SPaul Saab 	} while (result != 1);
179a5f0fb15SPaul Saab 
1806dcb072bSXin LI 	return (c & 0xFF);
181a5f0fb15SPaul Saab }
182