1a5f0fb15SPaul Saab /* 2*c77c4889SXin LI * Copyright (C) 1984-2024 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> 26*c77c4889SXin LI #ifndef ENABLE_EXTENDED_FLAGS 27*c77c4889SXin LI #define ENABLE_EXTENDED_FLAGS 0x80 28*c77c4889SXin LI #define ENABLE_QUICK_EDIT_MODE 0x40 29*c77c4889SXin LI #endif 30*c77c4889SXin LI #ifndef ENABLE_VIRTUAL_TERMINAL_INPUT 31*c77c4889SXin LI #define ENABLE_VIRTUAL_TERMINAL_INPUT 0x0200 32*c77c4889SXin LI #endif 33b7780dbeSXin LI public HANDLE tty; 34*c77c4889SXin LI public DWORD init_console_input_mode; 35*c77c4889SXin LI public DWORD curr_console_input_mode; 36*c77c4889SXin LI public DWORD base_console_input_mode; 37*c77c4889SXin LI public DWORD mouse_console_input_mode; 38b7780dbeSXin LI #else 39000ba3e8STim J. Robbins public int tty; 40b7780dbeSXin LI #endif 41*c77c4889SXin LI extern int sigs; 422235c7feSXin LI #if LESSTEST 432235c7feSXin LI public char *ttyin_name = NULL; 44*c77c4889SXin LI public lbool is_lesstest(void) 45*c77c4889SXin LI { 46*c77c4889SXin LI return ttyin_name != NULL; 47*c77c4889SXin LI } 482235c7feSXin LI #endif /*LESSTEST*/ 49a5f0fb15SPaul Saab 502235c7feSXin LI #if !MSDOS_COMPILER 51d713e089SXin LI static int open_tty_device(constant char* dev) 522235c7feSXin LI { 5395270f73SXin LI #if OS2 5495270f73SXin LI /* The __open() system call translates "/dev/tty" to "con". */ 5595270f73SXin LI return __open(dev, OPEN_READ); 5695270f73SXin LI #else 5795270f73SXin LI return open(dev, OPEN_READ); 582235c7feSXin LI #endif 5995270f73SXin LI } 6095270f73SXin LI 6195270f73SXin LI /* 6295270f73SXin LI * Open the tty device. 6395270f73SXin LI * Try ttyname(), then try /dev/tty, then use file descriptor 2. 6495270f73SXin LI * In Unix, file descriptor 2 is usually attached to the screen, 6595270f73SXin LI * but also usually lets you read from the keyboard. 6695270f73SXin LI */ 67d713e089SXin LI public int open_tty(void) 6895270f73SXin LI { 6995270f73SXin LI int fd = -1; 702235c7feSXin LI #if LESSTEST 71*c77c4889SXin LI if (is_lesstest()) 7295270f73SXin LI fd = open_tty_device(ttyin_name); 732235c7feSXin LI #endif /*LESSTEST*/ 7495270f73SXin LI #if HAVE_TTYNAME 7595270f73SXin LI if (fd < 0) 7695270f73SXin LI { 7795270f73SXin LI constant char *dev = ttyname(2); 7895270f73SXin LI if (dev != NULL) 7995270f73SXin LI fd = open_tty_device(dev); 8095270f73SXin LI } 8195270f73SXin LI #endif 8295270f73SXin LI if (fd < 0) 8395270f73SXin LI fd = open_tty_device("/dev/tty"); 8495270f73SXin LI if (fd < 0) 8595270f73SXin LI fd = 2; 86*c77c4889SXin LI #ifdef __MVS__ 87*c77c4889SXin LI struct f_cnvrt cvtreq = {SETCVTON, 0, 1047}; 88*c77c4889SXin LI fcntl(fd, F_CONTROL_CVT, &cvtreq); 89*c77c4889SXin LI #endif 9095270f73SXin LI return fd; 912235c7feSXin LI } 922235c7feSXin LI #endif /* MSDOS_COMPILER */ 932235c7feSXin LI 942235c7feSXin LI /* 95a5f0fb15SPaul Saab * Open keyboard for input. 96a5f0fb15SPaul Saab */ 97d713e089SXin LI public void open_getchr(void) 98a5f0fb15SPaul Saab { 99a5f0fb15SPaul Saab #if MSDOS_COMPILER==WIN32C 100a5f0fb15SPaul Saab /* Need this to let child processes inherit our console handle */ 101a5f0fb15SPaul Saab SECURITY_ATTRIBUTES sa; 102a5f0fb15SPaul Saab memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES)); 103a5f0fb15SPaul Saab sa.nLength = sizeof(SECURITY_ATTRIBUTES); 104a5f0fb15SPaul Saab sa.bInheritHandle = TRUE; 105b7780dbeSXin LI tty = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE, 106a5f0fb15SPaul Saab FILE_SHARE_READ, &sa, 107a5f0fb15SPaul Saab OPEN_EXISTING, 0L, NULL); 108*c77c4889SXin LI GetConsoleMode(tty, &init_console_input_mode); 109*c77c4889SXin LI /* base mode: ensure we get ctrl-C events, and don't get VT input. */ 110*c77c4889SXin LI base_console_input_mode = (init_console_input_mode | ENABLE_PROCESSED_INPUT) & ~ENABLE_VIRTUAL_TERMINAL_INPUT; 111*c77c4889SXin LI /* mouse mode: enable mouse and disable quick edit. */ 112*c77c4889SXin LI mouse_console_input_mode = (base_console_input_mode | ENABLE_MOUSE_INPUT | ENABLE_EXTENDED_FLAGS) & ~ENABLE_QUICK_EDIT_MODE; 113*c77c4889SXin LI /* Start with base mode. If --mouse is given, switch to mouse mode in init_mouse. */ 114*c77c4889SXin LI curr_console_input_mode = base_console_input_mode; 115*c77c4889SXin LI SetConsoleMode(tty, curr_console_input_mode); 116a5f0fb15SPaul Saab #else 117c9346414SPaul Saab #if MSDOS_COMPILER 118a5f0fb15SPaul Saab extern int fd0; 119a5f0fb15SPaul Saab /* 120a5f0fb15SPaul Saab * Open a new handle to CON: in binary mode 121a5f0fb15SPaul Saab * for unbuffered keyboard read. 122a5f0fb15SPaul Saab */ 123a5f0fb15SPaul Saab fd0 = dup(0); 124a5f0fb15SPaul Saab close(0); 125a5f0fb15SPaul Saab tty = open("CON", OPEN_READ); 126a5f0fb15SPaul Saab #if MSDOS_COMPILER==DJGPPC 127a5f0fb15SPaul Saab /* 128a5f0fb15SPaul Saab * Setting stdin to binary causes Ctrl-C to not 129a5f0fb15SPaul Saab * raise SIGINT. We must undo that side-effect. 130a5f0fb15SPaul Saab */ 131a5f0fb15SPaul Saab (void) __djgpp_set_ctrl_c(1); 132a5f0fb15SPaul Saab #endif 133a5f0fb15SPaul Saab #else 13495270f73SXin LI tty = open_tty(); 135a5f0fb15SPaul Saab #endif 136a5f0fb15SPaul Saab #endif 137a5f0fb15SPaul Saab } 138a5f0fb15SPaul Saab 139a5f0fb15SPaul Saab /* 140a5f0fb15SPaul Saab * Close the keyboard. 141a5f0fb15SPaul Saab */ 142d713e089SXin LI public void close_getchr(void) 143a5f0fb15SPaul Saab { 144a5f0fb15SPaul Saab #if MSDOS_COMPILER==WIN32C 145*c77c4889SXin LI SetConsoleMode(tty, init_console_input_mode); 146b7780dbeSXin LI CloseHandle(tty); 147a5f0fb15SPaul Saab #endif 148a5f0fb15SPaul Saab } 149a5f0fb15SPaul Saab 150b7780dbeSXin LI #if MSDOS_COMPILER==WIN32C 151b7780dbeSXin LI /* 152*c77c4889SXin LI * Close the pipe, restoring the console mode (CMD resets it, losing the mouse). 153b7780dbeSXin LI */ 154d713e089SXin LI public int pclose(FILE *f) 155b7780dbeSXin LI { 156b7780dbeSXin LI int result; 157b7780dbeSXin LI 158b7780dbeSXin LI result = _pclose(f); 159*c77c4889SXin LI SetConsoleMode(tty, curr_console_input_mode); 160b7780dbeSXin LI return result; 161b7780dbeSXin LI } 162b7780dbeSXin LI #endif 163b7780dbeSXin LI 164b7780dbeSXin LI /* 165b7780dbeSXin LI * Get the number of lines to scroll when mouse wheel is moved. 166b7780dbeSXin LI */ 167d713e089SXin LI public int default_wheel_lines(void) 168b7780dbeSXin LI { 169b7780dbeSXin LI int lines = 1; 170b7780dbeSXin LI #if MSDOS_COMPILER==WIN32C 171b7780dbeSXin LI if (SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &lines, 0)) 172b7780dbeSXin LI { 173b7780dbeSXin LI if (lines == WHEEL_PAGESCROLL) 174b7780dbeSXin LI lines = 3; 175b7780dbeSXin LI } 176b7780dbeSXin LI #endif 177b7780dbeSXin LI return lines; 178b7780dbeSXin LI } 179b7780dbeSXin LI 180a5f0fb15SPaul Saab /* 181a5f0fb15SPaul Saab * Get a character from the keyboard. 182a5f0fb15SPaul Saab */ 183d713e089SXin LI public int getchr(void) 184a5f0fb15SPaul Saab { 185a5f0fb15SPaul Saab char c; 186*c77c4889SXin LI ssize_t result; 187a5f0fb15SPaul Saab 188a5f0fb15SPaul Saab do 189a5f0fb15SPaul Saab { 1902235c7feSXin LI flush(); 191a5f0fb15SPaul Saab #if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC 192a5f0fb15SPaul Saab /* 193a5f0fb15SPaul Saab * In raw read, we don't see ^C so look here for it. 194a5f0fb15SPaul Saab */ 195a5f0fb15SPaul Saab #if MSDOS_COMPILER==WIN32C 196a5f0fb15SPaul Saab if (ABORT_SIGS()) 197a5f0fb15SPaul Saab return (READ_INTR); 198b7780dbeSXin LI c = WIN32getch(); 199a5f0fb15SPaul Saab #else 200a5f0fb15SPaul Saab c = getch(); 201a5f0fb15SPaul Saab #endif 202a5f0fb15SPaul Saab result = 1; 203a5f0fb15SPaul Saab if (c == '\003') 204a5f0fb15SPaul Saab return (READ_INTR); 205a5f0fb15SPaul Saab #else 206f6b74a7dSXin LI { 207f6b74a7dSXin LI unsigned char uc; 208f6b74a7dSXin LI result = iread(tty, &uc, sizeof(char)); 209f6b74a7dSXin LI c = (char) uc; 210f6b74a7dSXin LI } 211a5f0fb15SPaul Saab if (result == READ_INTR) 212a5f0fb15SPaul Saab return (READ_INTR); 213a5f0fb15SPaul Saab if (result < 0) 214a5f0fb15SPaul Saab { 215a5f0fb15SPaul Saab /* 216a5f0fb15SPaul Saab * Don't call error() here, 217a5f0fb15SPaul Saab * because error calls getchr! 218a5f0fb15SPaul Saab */ 219a5f0fb15SPaul Saab quit(QUIT_ERROR); 220a5f0fb15SPaul Saab } 221a5f0fb15SPaul Saab #endif 222d713e089SXin LI #if LESSTEST 223d713e089SXin LI if (c == LESS_DUMP_CHAR) 224d713e089SXin LI { 225d713e089SXin LI dump_screen(); 226d713e089SXin LI result = 0; 227d713e089SXin LI continue; 228d713e089SXin LI } 229d713e089SXin LI #endif 2306dcb072bSXin LI #if 0 /* allow entering arbitrary hex chars for testing */ 2316dcb072bSXin LI /* ctrl-A followed by two hex chars makes a byte */ 2327f074f9cSXin LI { 233f6b74a7dSXin LI static int hex_in = 0; 234f6b74a7dSXin LI static int hex_value = 0; 2356dcb072bSXin LI if (c == CONTROL('A')) 2366dcb072bSXin LI { 2376dcb072bSXin LI hex_in = 2; 2386dcb072bSXin LI result = 0; 2396dcb072bSXin LI continue; 2406dcb072bSXin LI } 2416dcb072bSXin LI if (hex_in > 0) 2426dcb072bSXin LI { 2436dcb072bSXin LI int v; 2446dcb072bSXin LI if (c >= '0' && c <= '9') 2456dcb072bSXin LI v = c - '0'; 2466dcb072bSXin LI else if (c >= 'a' && c <= 'f') 2476dcb072bSXin LI v = c - 'a' + 10; 2486dcb072bSXin LI else if (c >= 'A' && c <= 'F') 2496dcb072bSXin LI v = c - 'A' + 10; 2506dcb072bSXin LI else 251b7780dbeSXin LI v = 0; 2526dcb072bSXin LI hex_value = (hex_value << 4) | v; 2536dcb072bSXin LI if (--hex_in > 0) 2546dcb072bSXin LI { 2556dcb072bSXin LI result = 0; 2566dcb072bSXin LI continue; 2576dcb072bSXin LI } 2586dcb072bSXin LI c = hex_value; 2596dcb072bSXin LI } 2607f074f9cSXin LI } 2616dcb072bSXin LI #endif 262a5f0fb15SPaul Saab /* 263a5f0fb15SPaul Saab * Various parts of the program cannot handle 264a5f0fb15SPaul Saab * an input character of '\0'. 265a5f0fb15SPaul Saab * If a '\0' was actually typed, convert it to '\340' here. 266a5f0fb15SPaul Saab */ 267a5f0fb15SPaul Saab if (c == '\0') 268a5f0fb15SPaul Saab c = '\340'; 269a5f0fb15SPaul Saab } while (result != 1); 270a5f0fb15SPaul Saab 2716dcb072bSXin LI return (c & 0xFF); 272a5f0fb15SPaul Saab } 273