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