Move less-4/ to less/. No need for versioned directories.
[dragonfly.git] / contrib / less / ttyin.c
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 }