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 } 182