1 /* 2 * Copyright (C) 1984-2000 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 MSDOS_COMPILER==WIN32C 18 #include "windows.h" 19 extern char WIN32getch(); 20 static DWORD console_mode; 21 #endif 22 23 static int tty; 24 extern int sigs; 25 26 /* 27 * Open keyboard for input. 28 */ 29 public void 30 open_getchr() 31 { 32 #if MSDOS_COMPILER==WIN32C 33 /* Need this to let child processes inherit our console handle */ 34 SECURITY_ATTRIBUTES sa; 35 memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES)); 36 sa.nLength = sizeof(SECURITY_ATTRIBUTES); 37 sa.bInheritHandle = TRUE; 38 tty = (int) CreateFile("CONIN$", GENERIC_READ, 39 FILE_SHARE_READ, &sa, 40 OPEN_EXISTING, 0L, NULL); 41 GetConsoleMode((HANDLE)tty, &console_mode); 42 /* Make sure we get Ctrl+C events. */ 43 SetConsoleMode((HANDLE)tty, ENABLE_PROCESSED_INPUT); 44 #else 45 #if MSDOS_COMPILER || OS2 46 extern int fd0; 47 /* 48 * Open a new handle to CON: in binary mode 49 * for unbuffered keyboard read. 50 */ 51 fd0 = dup(0); 52 close(0); 53 tty = open("CON", OPEN_READ); 54 #if MSDOS_COMPILER==DJGPPC 55 /* 56 * Setting stdin to binary causes Ctrl-C to not 57 * raise SIGINT. We must undo that side-effect. 58 */ 59 (void) __djgpp_set_ctrl_c(1); 60 #endif 61 #else 62 /* 63 * Try /dev/tty. 64 * If that doesn't work, use file descriptor 2, 65 * which in Unix is usually attached to the screen, 66 * but also usually lets you read from the keyboard. 67 */ 68 tty = open("/dev/tty", OPEN_READ); 69 if (tty < 0) 70 tty = 2; 71 #endif 72 #endif 73 } 74 75 /* 76 * Close the keyboard. 77 */ 78 public void 79 close_getchr() 80 { 81 #if MSDOS_COMPILER==WIN32C 82 SetConsoleMode((HANDLE)tty, console_mode); 83 CloseHandle((HANDLE)tty); 84 #endif 85 } 86 87 /* 88 * Get a character from the keyboard. 89 */ 90 public int 91 getchr() 92 { 93 char c; 94 int result; 95 96 do 97 { 98 #if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC 99 /* 100 * In raw read, we don't see ^C so look here for it. 101 */ 102 flush(); 103 #if MSDOS_COMPILER==WIN32C 104 if (ABORT_SIGS()) 105 return (READ_INTR); 106 c = WIN32getch(tty); 107 #else 108 c = getch(); 109 #endif 110 result = 1; 111 if (c == '\003') 112 return (READ_INTR); 113 #else 114 #if OS2 115 { 116 static int scan = -1; 117 flush(); 118 if (scan >= 0) 119 { 120 c = scan; 121 scan = -1; 122 } else 123 { 124 if ((c = _read_kbd(0, 1, 0)) == -1) 125 return (READ_INTR); 126 if (c == '\0') 127 { 128 /* 129 * Zero is usually followed by another byte, 130 * since certain keys send two bytes. 131 */ 132 scan = _read_kbd(0, 0, 0); 133 } 134 } 135 result = 1; 136 } 137 #else 138 result = iread(tty, &c, sizeof(char)); 139 if (result == READ_INTR) 140 return (READ_INTR); 141 if (result < 0) 142 { 143 /* 144 * Don't call error() here, 145 * because error calls getchr! 146 */ 147 quit(QUIT_ERROR); 148 } 149 #endif 150 #endif 151 /* 152 * Various parts of the program cannot handle 153 * an input character of '\0'. 154 * If a '\0' was actually typed, convert it to '\340' here. 155 */ 156 if (c == '\0') 157 c = '\340'; 158 } while (result != 1); 159 160 return (c & 0377); 161 } 162