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