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