xref: /freebsd/contrib/less/ttyin.c (revision 9336e0699bda8a301cd2bfa37106b6ec5e32012e)
1 /*
2  * Copyright (C) 1984-2007  Mark Nudelman
3  *
4  * You may distribute under the terms of either the GNU General Public
5  * License or the Less License, as specified in the README file.
6  *
7  * For more information about less, or for information on how to
8  * contact the author, see the README file.
9  */
10 
11 
12 /*
13  * Routines dealing with getting input from the keyboard (i.e. from the user).
14  */
15 
16 #include "less.h"
17 #if OS2
18 #include "cmd.h"
19 #include "pckeys.h"
20 #endif
21 #if MSDOS_COMPILER==WIN32C
22 #include "windows.h"
23 extern char WIN32getch();
24 static DWORD console_mode;
25 #endif
26 
27 public int tty;
28 extern int sigs;
29 extern int utf_mode;
30 
31 /*
32  * Open keyboard for input.
33  */
34 	public void
35 open_getchr()
36 {
37 #if MSDOS_COMPILER==WIN32C
38 	/* Need this to let child processes inherit our console handle */
39 	SECURITY_ATTRIBUTES sa;
40 	memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
41 	sa.nLength = sizeof(SECURITY_ATTRIBUTES);
42 	sa.bInheritHandle = TRUE;
43 	tty = (int) CreateFile("CONIN$", GENERIC_READ,
44 			FILE_SHARE_READ, &sa,
45 			OPEN_EXISTING, 0L, NULL);
46 	GetConsoleMode((HANDLE)tty, &console_mode);
47 	/* Make sure we get Ctrl+C events. */
48 	SetConsoleMode((HANDLE)tty, ENABLE_PROCESSED_INPUT);
49 #else
50 #if MSDOS_COMPILER
51 	extern int fd0;
52 	/*
53 	 * Open a new handle to CON: in binary mode
54 	 * for unbuffered keyboard read.
55 	 */
56 	 fd0 = dup(0);
57 	 close(0);
58 	 tty = open("CON", OPEN_READ);
59 #if MSDOS_COMPILER==DJGPPC
60 	/*
61 	 * Setting stdin to binary causes Ctrl-C to not
62 	 * raise SIGINT.  We must undo that side-effect.
63 	 */
64 	(void) __djgpp_set_ctrl_c(1);
65 #endif
66 #else
67 	/*
68 	 * Try /dev/tty.
69 	 * If that doesn't work, use file descriptor 2,
70 	 * which in Unix is usually attached to the screen,
71 	 * but also usually lets you read from the keyboard.
72 	 */
73 #if OS2
74 	/* The __open() system call translates "/dev/tty" to "con". */
75 	tty = __open("/dev/tty", OPEN_READ);
76 #else
77 	tty = open("/dev/tty", OPEN_READ);
78 #endif
79 	if (tty < 0)
80 		tty = 2;
81 #endif
82 #endif
83 }
84 
85 /*
86  * Close the keyboard.
87  */
88 	public void
89 close_getchr()
90 {
91 #if MSDOS_COMPILER==WIN32C
92 	SetConsoleMode((HANDLE)tty, console_mode);
93 	CloseHandle((HANDLE)tty);
94 #endif
95 }
96 
97 /*
98  * Get a character from the keyboard.
99  */
100 	public int
101 getchr()
102 {
103 	char c;
104 	int result;
105 
106 	do
107 	{
108 #if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC
109 		/*
110 		 * In raw read, we don't see ^C so look here for it.
111 		 */
112 		flush();
113 #if MSDOS_COMPILER==WIN32C
114 		if (ABORT_SIGS())
115 			return (READ_INTR);
116 		c = WIN32getch(tty);
117 #else
118 		c = getch();
119 #endif
120 		result = 1;
121 		if (c == '\003')
122 			return (READ_INTR);
123 #else
124 		result = iread(tty, &c, sizeof(char));
125 		if (result == READ_INTR)
126 			return (READ_INTR);
127 		if (result < 0)
128 		{
129 			/*
130 			 * Don't call error() here,
131 			 * because error calls getchr!
132 			 */
133 			quit(QUIT_ERROR);
134 		}
135 #endif
136 #if 0 /* allow entering arbitrary hex chars for testing */
137 		/* ctrl-A followed by two hex chars makes a byte */
138 	{
139 		int hex_in = 0;
140 		int hex_value = 0;
141 		if (c == CONTROL('A'))
142 		{
143 			hex_in = 2;
144 			result = 0;
145 			continue;
146 		}
147 		if (hex_in > 0)
148 		{
149 			int v;
150 			if (c >= '0' && c <= '9')
151 				v = c - '0';
152 			else if (c >= 'a' && c <= 'f')
153 				v = c - 'a' + 10;
154 			else if (c >= 'A' && c <= 'F')
155 				v = c - 'A' + 10;
156 			else
157 				hex_in = 0;
158 			hex_value = (hex_value << 4) | v;
159 			if (--hex_in > 0)
160 			{
161 				result = 0;
162 				continue;
163 			}
164 			c = hex_value;
165 		}
166 	}
167 #endif
168 		/*
169 		 * Various parts of the program cannot handle
170 		 * an input character of '\0'.
171 		 * If a '\0' was actually typed, convert it to '\340' here.
172 		 */
173 		if (c == '\0')
174 			c = '\340';
175 	} while (result != 1);
176 
177 	return (c & 0xFF);
178 }
179