1 /* 2 * Copyright (C) 1984-2004 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 int hex_in = 0; 106 int hex_value = 0; 107 108 do 109 { 110 #if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC 111 /* 112 * In raw read, we don't see ^C so look here for it. 113 */ 114 flush(); 115 #if MSDOS_COMPILER==WIN32C 116 if (ABORT_SIGS()) 117 return (READ_INTR); 118 c = WIN32getch(tty); 119 #else 120 c = getch(); 121 #endif 122 result = 1; 123 if (c == '\003') 124 return (READ_INTR); 125 #else 126 result = iread(tty, &c, sizeof(char)); 127 if (result == READ_INTR) 128 return (READ_INTR); 129 if (result < 0) 130 { 131 /* 132 * Don't call error() here, 133 * because error calls getchr! 134 */ 135 quit(QUIT_ERROR); 136 } 137 #endif 138 #if 0 /* allow entering arbitrary hex chars for testing */ 139 /* ctrl-A followed by two hex chars makes a byte */ 140 if (c == CONTROL('A')) 141 { 142 hex_in = 2; 143 result = 0; 144 continue; 145 } 146 if (hex_in > 0) 147 { 148 int v; 149 if (c >= '0' && c <= '9') 150 v = c - '0'; 151 else if (c >= 'a' && c <= 'f') 152 v = c - 'a' + 10; 153 else if (c >= 'A' && c <= 'F') 154 v = c - 'A' + 10; 155 else 156 hex_in = 0; 157 hex_value = (hex_value << 4) | v; 158 if (--hex_in > 0) 159 { 160 result = 0; 161 continue; 162 } 163 c = hex_value; 164 } 165 #endif 166 /* 167 * Various parts of the program cannot handle 168 * an input character of '\0'. 169 * If a '\0' was actually typed, convert it to '\340' here. 170 */ 171 if (c == '\0') 172 c = '\340'; 173 } while (result != 1); 174 175 return (c & 0xFF); 176 } 177