1a5f0fb15SPaul Saab /* 2*2235c7feSXin LI * Copyright (C) 1984-2021 Mark Nudelman 3a5f0fb15SPaul Saab * 4a5f0fb15SPaul Saab * You may distribute under the terms of either the GNU General Public 5a5f0fb15SPaul Saab * License or the Less License, as specified in the README file. 6a5f0fb15SPaul Saab * 796e55cc7SXin LI * For more information, see the README file. 8a5f0fb15SPaul Saab */ 9a5f0fb15SPaul Saab 10a5f0fb15SPaul Saab 11a5f0fb15SPaul Saab /* 12a5f0fb15SPaul Saab * Routines dealing with getting input from the keyboard (i.e. from the user). 13a5f0fb15SPaul Saab */ 14a5f0fb15SPaul Saab 15a5f0fb15SPaul Saab #include "less.h" 16c9346414SPaul Saab #if OS2 17c9346414SPaul Saab #include "cmd.h" 18c9346414SPaul Saab #include "pckeys.h" 19c9346414SPaul Saab #endif 20a5f0fb15SPaul Saab #if MSDOS_COMPILER==WIN32C 21b7780dbeSXin LI #define WIN32_LEAN_AND_MEAN 22b7780dbeSXin LI #ifndef _WIN32_WINNT 23b7780dbeSXin LI #define _WIN32_WINNT 0x400 24a5f0fb15SPaul Saab #endif 25b7780dbeSXin LI #include <windows.h> 266f26c71dSXin LI public DWORD console_mode; 27b7780dbeSXin LI public HANDLE tty; 28b7780dbeSXin LI #else 29000ba3e8STim J. Robbins public int tty; 30b7780dbeSXin LI #endif 31*2235c7feSXin LI #if LESSTEST 32*2235c7feSXin LI public char *ttyin_name = NULL; 33*2235c7feSXin LI public int rstat_file = -1; 34*2235c7feSXin LI #endif /*LESSTEST*/ 35a5f0fb15SPaul Saab extern int sigs; 366dcb072bSXin LI extern int utf_mode; 37b7780dbeSXin LI extern int wheel_lines; 38a5f0fb15SPaul Saab 39a5f0fb15SPaul Saab /* 40*2235c7feSXin LI * Get name of tty device. 41*2235c7feSXin LI */ 42*2235c7feSXin LI #if !MSDOS_COMPILER 43*2235c7feSXin LI public char * 44*2235c7feSXin LI tty_device(VOID_PARAM) 45*2235c7feSXin LI { 46*2235c7feSXin LI char *dev = NULL; 47*2235c7feSXin LI #if HAVE_TTYNAME 48*2235c7feSXin LI dev = ttyname(2); 49*2235c7feSXin LI #endif 50*2235c7feSXin LI if (dev == NULL) 51*2235c7feSXin LI dev = "/dev/tty"; 52*2235c7feSXin LI #if LESSTEST 53*2235c7feSXin LI if (ttyin_name != NULL) 54*2235c7feSXin LI dev = ttyin_name; 55*2235c7feSXin LI #endif /*LESSTEST*/ 56*2235c7feSXin LI return dev; 57*2235c7feSXin LI } 58*2235c7feSXin LI #endif /* MSDOS_COMPILER */ 59*2235c7feSXin LI 60*2235c7feSXin LI /* 61a5f0fb15SPaul Saab * Open keyboard for input. 62a5f0fb15SPaul Saab */ 63a5f0fb15SPaul Saab public void 64b7780dbeSXin LI open_getchr(VOID_PARAM) 65a5f0fb15SPaul Saab { 66a5f0fb15SPaul Saab #if MSDOS_COMPILER==WIN32C 67a5f0fb15SPaul Saab /* Need this to let child processes inherit our console handle */ 68a5f0fb15SPaul Saab SECURITY_ATTRIBUTES sa; 69a5f0fb15SPaul Saab memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES)); 70a5f0fb15SPaul Saab sa.nLength = sizeof(SECURITY_ATTRIBUTES); 71a5f0fb15SPaul Saab sa.bInheritHandle = TRUE; 72b7780dbeSXin LI tty = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE, 73a5f0fb15SPaul Saab FILE_SHARE_READ, &sa, 74a5f0fb15SPaul Saab OPEN_EXISTING, 0L, NULL); 75b7780dbeSXin LI GetConsoleMode(tty, &console_mode); 76a5f0fb15SPaul Saab /* Make sure we get Ctrl+C events. */ 77b7780dbeSXin LI SetConsoleMode(tty, ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT); 78a5f0fb15SPaul Saab #else 79c9346414SPaul Saab #if MSDOS_COMPILER 80a5f0fb15SPaul Saab extern int fd0; 81a5f0fb15SPaul Saab /* 82a5f0fb15SPaul Saab * Open a new handle to CON: in binary mode 83a5f0fb15SPaul Saab * for unbuffered keyboard read. 84a5f0fb15SPaul Saab */ 85a5f0fb15SPaul Saab fd0 = dup(0); 86a5f0fb15SPaul Saab close(0); 87a5f0fb15SPaul Saab tty = open("CON", OPEN_READ); 88a5f0fb15SPaul Saab #if MSDOS_COMPILER==DJGPPC 89a5f0fb15SPaul Saab /* 90a5f0fb15SPaul Saab * Setting stdin to binary causes Ctrl-C to not 91a5f0fb15SPaul Saab * raise SIGINT. We must undo that side-effect. 92a5f0fb15SPaul Saab */ 93a5f0fb15SPaul Saab (void) __djgpp_set_ctrl_c(1); 94a5f0fb15SPaul Saab #endif 95a5f0fb15SPaul Saab #else 96a5f0fb15SPaul Saab /* 97a5f0fb15SPaul Saab * Try /dev/tty. 98a5f0fb15SPaul Saab * If that doesn't work, use file descriptor 2, 99a5f0fb15SPaul Saab * which in Unix is usually attached to the screen, 100a5f0fb15SPaul Saab * but also usually lets you read from the keyboard. 101a5f0fb15SPaul Saab */ 102c9346414SPaul Saab #if OS2 103c9346414SPaul Saab /* The __open() system call translates "/dev/tty" to "con". */ 104*2235c7feSXin LI tty = __open(tty_device(), OPEN_READ); 105c9346414SPaul Saab #else 106*2235c7feSXin LI tty = open(tty_device(), OPEN_READ); 107c9346414SPaul Saab #endif 108a5f0fb15SPaul Saab if (tty < 0) 109a5f0fb15SPaul Saab tty = 2; 110a5f0fb15SPaul Saab #endif 111a5f0fb15SPaul Saab #endif 112a5f0fb15SPaul Saab } 113a5f0fb15SPaul Saab 114a5f0fb15SPaul Saab /* 115a5f0fb15SPaul Saab * Close the keyboard. 116a5f0fb15SPaul Saab */ 117a5f0fb15SPaul Saab public void 118b7780dbeSXin LI close_getchr(VOID_PARAM) 119a5f0fb15SPaul Saab { 120a5f0fb15SPaul Saab #if MSDOS_COMPILER==WIN32C 121b7780dbeSXin LI SetConsoleMode(tty, console_mode); 122b7780dbeSXin LI CloseHandle(tty); 123a5f0fb15SPaul Saab #endif 124a5f0fb15SPaul Saab } 125a5f0fb15SPaul Saab 126b7780dbeSXin LI #if MSDOS_COMPILER==WIN32C 127b7780dbeSXin LI /* 128b7780dbeSXin LI * Close the pipe, restoring the keyboard (CMD resets it, losing the mouse). 129b7780dbeSXin LI */ 130b7780dbeSXin LI int 131b7780dbeSXin LI pclose(f) 132b7780dbeSXin LI FILE *f; 133b7780dbeSXin LI { 134b7780dbeSXin LI int result; 135b7780dbeSXin LI 136b7780dbeSXin LI result = _pclose(f); 137b7780dbeSXin LI SetConsoleMode(tty, ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT); 138b7780dbeSXin LI return result; 139b7780dbeSXin LI } 140b7780dbeSXin LI #endif 141b7780dbeSXin LI 142b7780dbeSXin LI /* 143b7780dbeSXin LI * Get the number of lines to scroll when mouse wheel is moved. 144b7780dbeSXin LI */ 145b7780dbeSXin LI public int 146b7780dbeSXin LI default_wheel_lines(VOID_PARAM) 147b7780dbeSXin LI { 148b7780dbeSXin LI int lines = 1; 149b7780dbeSXin LI #if MSDOS_COMPILER==WIN32C 150b7780dbeSXin LI if (SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &lines, 0)) 151b7780dbeSXin LI { 152b7780dbeSXin LI if (lines == WHEEL_PAGESCROLL) 153b7780dbeSXin LI lines = 3; 154b7780dbeSXin LI } 155b7780dbeSXin LI #endif 156b7780dbeSXin LI return lines; 157b7780dbeSXin LI } 158b7780dbeSXin LI 159*2235c7feSXin LI #if LESSTEST 160*2235c7feSXin LI public void 161*2235c7feSXin LI rstat(st) 162*2235c7feSXin LI char st; 163*2235c7feSXin LI { 164*2235c7feSXin LI if (rstat_file < 0) 165*2235c7feSXin LI return; 166*2235c7feSXin LI lseek(rstat_file, SEEK_SET, 0); 167*2235c7feSXin LI write(rstat_file, &st, 1); 168*2235c7feSXin LI } 169*2235c7feSXin LI #endif /*LESSTEST*/ 170*2235c7feSXin LI 171a5f0fb15SPaul Saab /* 172a5f0fb15SPaul Saab * Get a character from the keyboard. 173a5f0fb15SPaul Saab */ 174a5f0fb15SPaul Saab public int 175b7780dbeSXin LI getchr(VOID_PARAM) 176a5f0fb15SPaul Saab { 177a5f0fb15SPaul Saab char c; 178a5f0fb15SPaul Saab int result; 179a5f0fb15SPaul Saab 180a5f0fb15SPaul Saab do 181a5f0fb15SPaul Saab { 182*2235c7feSXin LI flush(); 183a5f0fb15SPaul Saab #if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC 184a5f0fb15SPaul Saab /* 185a5f0fb15SPaul Saab * In raw read, we don't see ^C so look here for it. 186a5f0fb15SPaul Saab */ 187a5f0fb15SPaul Saab #if MSDOS_COMPILER==WIN32C 188a5f0fb15SPaul Saab if (ABORT_SIGS()) 189a5f0fb15SPaul Saab return (READ_INTR); 190b7780dbeSXin LI c = WIN32getch(); 191a5f0fb15SPaul Saab #else 192a5f0fb15SPaul Saab c = getch(); 193a5f0fb15SPaul Saab #endif 194a5f0fb15SPaul Saab result = 1; 195a5f0fb15SPaul Saab if (c == '\003') 196a5f0fb15SPaul Saab return (READ_INTR); 197a5f0fb15SPaul Saab #else 198*2235c7feSXin LI #if LESSTEST 199*2235c7feSXin LI rstat('R'); 200*2235c7feSXin LI #endif /*LESSTEST*/ 201f6b74a7dSXin LI { 202f6b74a7dSXin LI unsigned char uc; 203f6b74a7dSXin LI result = iread(tty, &uc, sizeof(char)); 204f6b74a7dSXin LI c = (char) uc; 205f6b74a7dSXin LI } 206*2235c7feSXin LI #if LESSTEST 207*2235c7feSXin LI rstat('B'); 208*2235c7feSXin LI #endif /*LESSTEST*/ 209a5f0fb15SPaul Saab if (result == READ_INTR) 210a5f0fb15SPaul Saab return (READ_INTR); 211a5f0fb15SPaul Saab if (result < 0) 212a5f0fb15SPaul Saab { 213a5f0fb15SPaul Saab /* 214a5f0fb15SPaul Saab * Don't call error() here, 215a5f0fb15SPaul Saab * because error calls getchr! 216a5f0fb15SPaul Saab */ 217a5f0fb15SPaul Saab quit(QUIT_ERROR); 218a5f0fb15SPaul Saab } 219a5f0fb15SPaul Saab #endif 2206dcb072bSXin LI #if 0 /* allow entering arbitrary hex chars for testing */ 2216dcb072bSXin LI /* ctrl-A followed by two hex chars makes a byte */ 2227f074f9cSXin LI { 223f6b74a7dSXin LI static int hex_in = 0; 224f6b74a7dSXin LI static int hex_value = 0; 2256dcb072bSXin LI if (c == CONTROL('A')) 2266dcb072bSXin LI { 2276dcb072bSXin LI hex_in = 2; 2286dcb072bSXin LI result = 0; 2296dcb072bSXin LI continue; 2306dcb072bSXin LI } 2316dcb072bSXin LI if (hex_in > 0) 2326dcb072bSXin LI { 2336dcb072bSXin LI int v; 2346dcb072bSXin LI if (c >= '0' && c <= '9') 2356dcb072bSXin LI v = c - '0'; 2366dcb072bSXin LI else if (c >= 'a' && c <= 'f') 2376dcb072bSXin LI v = c - 'a' + 10; 2386dcb072bSXin LI else if (c >= 'A' && c <= 'F') 2396dcb072bSXin LI v = c - 'A' + 10; 2406dcb072bSXin LI else 241b7780dbeSXin LI v = 0; 2426dcb072bSXin LI hex_value = (hex_value << 4) | v; 2436dcb072bSXin LI if (--hex_in > 0) 2446dcb072bSXin LI { 2456dcb072bSXin LI result = 0; 2466dcb072bSXin LI continue; 2476dcb072bSXin LI } 2486dcb072bSXin LI c = hex_value; 2496dcb072bSXin LI } 2507f074f9cSXin LI } 2516dcb072bSXin LI #endif 252a5f0fb15SPaul Saab /* 253a5f0fb15SPaul Saab * Various parts of the program cannot handle 254a5f0fb15SPaul Saab * an input character of '\0'. 255a5f0fb15SPaul Saab * If a '\0' was actually typed, convert it to '\340' here. 256a5f0fb15SPaul Saab */ 257a5f0fb15SPaul Saab if (c == '\0') 258a5f0fb15SPaul Saab c = '\340'; 259a5f0fb15SPaul Saab } while (result != 1); 260a5f0fb15SPaul Saab 2616dcb072bSXin LI return (c & 0xFF); 262a5f0fb15SPaul Saab } 263