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