]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/less/ttyin.c
MFC r368207,368607:
[FreeBSD/stable/10.git] / contrib / less / ttyin.c
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
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
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
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 }