1 /* 2 * Copyright (C) 1984-2011 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 } 179