]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/less/ttyin.c
vfs: fix MNT_SYNCHRONOUS check in vn_write
[FreeBSD/FreeBSD.git] / contrib / less / ttyin.c
1 /*
2  * Copyright (C) 1984-2021  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 #define WIN32_LEAN_AND_MEAN
22 #ifndef _WIN32_WINNT
23 #define _WIN32_WINNT 0x400
24 #endif
25 #include <windows.h>
26 public DWORD console_mode;
27 public HANDLE tty;
28 #else
29 public int tty;
30 #endif
31 #if LESSTEST
32 public char *ttyin_name = NULL;
33 public int rstat_file = -1;
34 #endif /*LESSTEST*/
35 extern int sigs;
36 extern int utf_mode;
37 extern int wheel_lines;
38
39 /*
40  * Get name of tty device.
41  */
42 #if !MSDOS_COMPILER
43         public char *
44 tty_device(VOID_PARAM)
45 {
46         char *dev = NULL;
47 #if HAVE_TTYNAME
48         dev = ttyname(2);
49 #endif
50         if (dev == NULL)
51                 dev = "/dev/tty";
52 #if LESSTEST
53         if (ttyin_name != NULL)
54                 dev = ttyin_name;
55 #endif /*LESSTEST*/
56         return dev;
57 }
58 #endif /* MSDOS_COMPILER */
59
60 /*
61  * Open keyboard for input.
62  */
63         public void
64 open_getchr(VOID_PARAM)
65 {
66 #if MSDOS_COMPILER==WIN32C
67         /* Need this to let child processes inherit our console handle */
68         SECURITY_ATTRIBUTES sa;
69         memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
70         sa.nLength = sizeof(SECURITY_ATTRIBUTES);
71         sa.bInheritHandle = TRUE;
72         tty = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
73                         FILE_SHARE_READ, &sa, 
74                         OPEN_EXISTING, 0L, NULL);
75         GetConsoleMode(tty, &console_mode);
76         /* Make sure we get Ctrl+C events. */
77         SetConsoleMode(tty, ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT);
78 #else
79 #if MSDOS_COMPILER
80         extern int fd0;
81         /*
82          * Open a new handle to CON: in binary mode 
83          * for unbuffered keyboard read.
84          */
85          fd0 = dup(0);
86          close(0);
87          tty = open("CON", OPEN_READ);
88 #if MSDOS_COMPILER==DJGPPC
89         /*
90          * Setting stdin to binary causes Ctrl-C to not
91          * raise SIGINT.  We must undo that side-effect.
92          */
93         (void) __djgpp_set_ctrl_c(1);
94 #endif
95 #else
96         /*
97          * Try /dev/tty.
98          * If that doesn't work, use file descriptor 2,
99          * which in Unix is usually attached to the screen,
100          * but also usually lets you read from the keyboard.
101          */
102 #if OS2
103         /* The __open() system call translates "/dev/tty" to "con". */
104         tty = __open(tty_device(), OPEN_READ);
105 #else
106         tty = open(tty_device(), OPEN_READ);
107 #endif
108         if (tty < 0)
109                 tty = 2;
110 #endif
111 #endif
112 }
113
114 /*
115  * Close the keyboard.
116  */
117         public void
118 close_getchr(VOID_PARAM)
119 {
120 #if MSDOS_COMPILER==WIN32C
121         SetConsoleMode(tty, console_mode);
122         CloseHandle(tty);
123 #endif
124 }
125
126 #if MSDOS_COMPILER==WIN32C
127 /*
128  * Close the pipe, restoring the keyboard (CMD resets it, losing the mouse).
129  */
130         int
131 pclose(f)
132         FILE *f;
133 {
134         int result;
135
136         result = _pclose(f);
137         SetConsoleMode(tty, ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT);
138         return result;
139 }
140 #endif
141
142 /*
143  * Get the number of lines to scroll when mouse wheel is moved.
144  */
145         public int
146 default_wheel_lines(VOID_PARAM)
147 {
148         int lines = 1;
149 #if MSDOS_COMPILER==WIN32C
150         if (SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &lines, 0))
151         {
152                 if (lines == WHEEL_PAGESCROLL)
153                         lines = 3;
154         }
155 #endif
156         return lines;
157 }
158
159 #if LESSTEST
160         public void
161 rstat(st)
162         char st;
163 {
164         if (rstat_file < 0)
165                 return;
166         lseek(rstat_file, SEEK_SET, 0);
167         write(rstat_file, &st, 1);
168 }
169 #endif /*LESSTEST*/
170
171 /*
172  * Get a character from the keyboard.
173  */
174         public int
175 getchr(VOID_PARAM)
176 {
177         char c;
178         int result;
179
180         do
181         {
182                 flush();
183 #if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC
184                 /*
185                  * In raw read, we don't see ^C so look here for it.
186                  */
187 #if MSDOS_COMPILER==WIN32C
188                 if (ABORT_SIGS())
189                         return (READ_INTR);
190                 c = WIN32getch();
191 #else
192                 c = getch();
193 #endif
194                 result = 1;
195                 if (c == '\003')
196                         return (READ_INTR);
197 #else
198 #if LESSTEST
199                 rstat('R');
200 #endif /*LESSTEST*/
201                 {
202                         unsigned char uc;
203                         result = iread(tty, &uc, sizeof(char));
204                         c = (char) uc;
205                 }
206 #if LESSTEST
207                 rstat('B');
208 #endif /*LESSTEST*/
209                 if (result == READ_INTR)
210                         return (READ_INTR);
211                 if (result < 0)
212                 {
213                         /*
214                          * Don't call error() here,
215                          * because error calls getchr!
216                          */
217                         quit(QUIT_ERROR);
218                 }
219 #endif
220 #if 0 /* allow entering arbitrary hex chars for testing */
221                 /* ctrl-A followed by two hex chars makes a byte */
222         {
223                 static int hex_in = 0;
224                 static int hex_value = 0;
225                 if (c == CONTROL('A'))
226                 {
227                         hex_in = 2;
228                         result = 0;
229                         continue;
230                 }
231                 if (hex_in > 0)
232                 {
233                         int v;
234                         if (c >= '0' && c <= '9')
235                                 v = c - '0';
236                         else if (c >= 'a' && c <= 'f')
237                                 v = c - 'a' + 10;
238                         else if (c >= 'A' && c <= 'F')
239                                 v = c - 'A' + 10;
240                         else
241                                 v = 0;
242                         hex_value = (hex_value << 4) | v;
243                         if (--hex_in > 0)
244                         {
245                                 result = 0;
246                                 continue;
247                         }
248                         c = hex_value;
249                 }
250         }
251 #endif
252                 /*
253                  * Various parts of the program cannot handle
254                  * an input character of '\0'.
255                  * If a '\0' was actually typed, convert it to '\340' here.
256                  */
257                 if (c == '\0')
258                         c = '\340';
259         } while (result != 1);
260
261         return (c & 0xFF);
262 }