1a5f0fb15SPaul Saab /* 2*d713e089SXin LI * Copyright (C) 1984-2023 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 312235c7feSXin LI #if LESSTEST 322235c7feSXin LI public char *ttyin_name = NULL; 332235c7feSXin LI #endif /*LESSTEST*/ 34a5f0fb15SPaul Saab extern int sigs; 356dcb072bSXin LI extern int utf_mode; 36b7780dbeSXin LI extern int wheel_lines; 37a5f0fb15SPaul Saab 382235c7feSXin LI #if !MSDOS_COMPILER 39*d713e089SXin LI static int open_tty_device(constant char* dev) 402235c7feSXin LI { 4195270f73SXin LI #if OS2 4295270f73SXin LI /* The __open() system call translates "/dev/tty" to "con". */ 4395270f73SXin LI return __open(dev, OPEN_READ); 4495270f73SXin LI #else 4595270f73SXin LI return open(dev, OPEN_READ); 462235c7feSXin LI #endif 4795270f73SXin LI } 4895270f73SXin LI 4995270f73SXin LI /* 5095270f73SXin LI * Open the tty device. 5195270f73SXin LI * Try ttyname(), then try /dev/tty, then use file descriptor 2. 5295270f73SXin LI * In Unix, file descriptor 2 is usually attached to the screen, 5395270f73SXin LI * but also usually lets you read from the keyboard. 5495270f73SXin LI */ 55*d713e089SXin LI public int open_tty(void) 5695270f73SXin LI { 5795270f73SXin LI int fd = -1; 582235c7feSXin LI #if LESSTEST 592235c7feSXin LI if (ttyin_name != NULL) 6095270f73SXin LI fd = open_tty_device(ttyin_name); 612235c7feSXin LI #endif /*LESSTEST*/ 6295270f73SXin LI #if HAVE_TTYNAME 6395270f73SXin LI if (fd < 0) 6495270f73SXin LI { 6595270f73SXin LI constant char *dev = ttyname(2); 6695270f73SXin LI if (dev != NULL) 6795270f73SXin LI fd = open_tty_device(dev); 6895270f73SXin LI } 6995270f73SXin LI #endif 7095270f73SXin LI if (fd < 0) 7195270f73SXin LI fd = open_tty_device("/dev/tty"); 7295270f73SXin LI if (fd < 0) 7395270f73SXin LI fd = 2; 7495270f73SXin LI return fd; 752235c7feSXin LI } 762235c7feSXin LI #endif /* MSDOS_COMPILER */ 772235c7feSXin LI 782235c7feSXin LI /* 79a5f0fb15SPaul Saab * Open keyboard for input. 80a5f0fb15SPaul Saab */ 81*d713e089SXin LI public void open_getchr(void) 82a5f0fb15SPaul Saab { 83a5f0fb15SPaul Saab #if MSDOS_COMPILER==WIN32C 84a5f0fb15SPaul Saab /* Need this to let child processes inherit our console handle */ 85a5f0fb15SPaul Saab SECURITY_ATTRIBUTES sa; 86a5f0fb15SPaul Saab memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES)); 87a5f0fb15SPaul Saab sa.nLength = sizeof(SECURITY_ATTRIBUTES); 88a5f0fb15SPaul Saab sa.bInheritHandle = TRUE; 89b7780dbeSXin LI tty = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE, 90a5f0fb15SPaul Saab FILE_SHARE_READ, &sa, 91a5f0fb15SPaul Saab OPEN_EXISTING, 0L, NULL); 92b7780dbeSXin LI GetConsoleMode(tty, &console_mode); 93a5f0fb15SPaul Saab /* Make sure we get Ctrl+C events. */ 94b7780dbeSXin LI SetConsoleMode(tty, ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT); 95a5f0fb15SPaul Saab #else 96c9346414SPaul Saab #if MSDOS_COMPILER 97a5f0fb15SPaul Saab extern int fd0; 98a5f0fb15SPaul Saab /* 99a5f0fb15SPaul Saab * Open a new handle to CON: in binary mode 100a5f0fb15SPaul Saab * for unbuffered keyboard read. 101a5f0fb15SPaul Saab */ 102a5f0fb15SPaul Saab fd0 = dup(0); 103a5f0fb15SPaul Saab close(0); 104a5f0fb15SPaul Saab tty = open("CON", OPEN_READ); 105a5f0fb15SPaul Saab #if MSDOS_COMPILER==DJGPPC 106a5f0fb15SPaul Saab /* 107a5f0fb15SPaul Saab * Setting stdin to binary causes Ctrl-C to not 108a5f0fb15SPaul Saab * raise SIGINT. We must undo that side-effect. 109a5f0fb15SPaul Saab */ 110a5f0fb15SPaul Saab (void) __djgpp_set_ctrl_c(1); 111a5f0fb15SPaul Saab #endif 112a5f0fb15SPaul Saab #else 11395270f73SXin LI tty = open_tty(); 114a5f0fb15SPaul Saab #endif 115a5f0fb15SPaul Saab #endif 116a5f0fb15SPaul Saab } 117a5f0fb15SPaul Saab 118a5f0fb15SPaul Saab /* 119a5f0fb15SPaul Saab * Close the keyboard. 120a5f0fb15SPaul Saab */ 121*d713e089SXin LI public void close_getchr(void) 122a5f0fb15SPaul Saab { 123a5f0fb15SPaul Saab #if MSDOS_COMPILER==WIN32C 124b7780dbeSXin LI SetConsoleMode(tty, console_mode); 125b7780dbeSXin LI CloseHandle(tty); 126a5f0fb15SPaul Saab #endif 127a5f0fb15SPaul Saab } 128a5f0fb15SPaul Saab 129b7780dbeSXin LI #if MSDOS_COMPILER==WIN32C 130b7780dbeSXin LI /* 131b7780dbeSXin LI * Close the pipe, restoring the keyboard (CMD resets it, losing the mouse). 132b7780dbeSXin LI */ 133*d713e089SXin LI public int pclose(FILE *f) 134b7780dbeSXin LI { 135b7780dbeSXin LI int result; 136b7780dbeSXin LI 137b7780dbeSXin LI result = _pclose(f); 138b7780dbeSXin LI SetConsoleMode(tty, ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT); 139b7780dbeSXin LI return result; 140b7780dbeSXin LI } 141b7780dbeSXin LI #endif 142b7780dbeSXin LI 143b7780dbeSXin LI /* 144b7780dbeSXin LI * Get the number of lines to scroll when mouse wheel is moved. 145b7780dbeSXin LI */ 146*d713e089SXin LI public int default_wheel_lines(void) 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 159a5f0fb15SPaul Saab /* 160a5f0fb15SPaul Saab * Get a character from the keyboard. 161a5f0fb15SPaul Saab */ 162*d713e089SXin LI public int getchr(void) 163a5f0fb15SPaul Saab { 164a5f0fb15SPaul Saab char c; 165a5f0fb15SPaul Saab int result; 166a5f0fb15SPaul Saab 167a5f0fb15SPaul Saab do 168a5f0fb15SPaul Saab { 1692235c7feSXin LI flush(); 170a5f0fb15SPaul Saab #if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC 171a5f0fb15SPaul Saab /* 172a5f0fb15SPaul Saab * In raw read, we don't see ^C so look here for it. 173a5f0fb15SPaul Saab */ 174a5f0fb15SPaul Saab #if MSDOS_COMPILER==WIN32C 175a5f0fb15SPaul Saab if (ABORT_SIGS()) 176a5f0fb15SPaul Saab return (READ_INTR); 177b7780dbeSXin LI c = WIN32getch(); 178a5f0fb15SPaul Saab #else 179a5f0fb15SPaul Saab c = getch(); 180a5f0fb15SPaul Saab #endif 181a5f0fb15SPaul Saab result = 1; 182a5f0fb15SPaul Saab if (c == '\003') 183a5f0fb15SPaul Saab return (READ_INTR); 184a5f0fb15SPaul Saab #else 185f6b74a7dSXin LI { 186f6b74a7dSXin LI unsigned char uc; 187f6b74a7dSXin LI result = iread(tty, &uc, sizeof(char)); 188f6b74a7dSXin LI c = (char) uc; 189f6b74a7dSXin LI } 190a5f0fb15SPaul Saab if (result == READ_INTR) 191a5f0fb15SPaul Saab return (READ_INTR); 192a5f0fb15SPaul Saab if (result < 0) 193a5f0fb15SPaul Saab { 194a5f0fb15SPaul Saab /* 195a5f0fb15SPaul Saab * Don't call error() here, 196a5f0fb15SPaul Saab * because error calls getchr! 197a5f0fb15SPaul Saab */ 198a5f0fb15SPaul Saab quit(QUIT_ERROR); 199a5f0fb15SPaul Saab } 200a5f0fb15SPaul Saab #endif 201*d713e089SXin LI #if LESSTEST 202*d713e089SXin LI if (c == LESS_DUMP_CHAR) 203*d713e089SXin LI { 204*d713e089SXin LI dump_screen(); 205*d713e089SXin LI result = 0; 206*d713e089SXin LI continue; 207*d713e089SXin LI } 208*d713e089SXin LI #endif 2096dcb072bSXin LI #if 0 /* allow entering arbitrary hex chars for testing */ 2106dcb072bSXin LI /* ctrl-A followed by two hex chars makes a byte */ 2117f074f9cSXin LI { 212f6b74a7dSXin LI static int hex_in = 0; 213f6b74a7dSXin LI static int hex_value = 0; 2146dcb072bSXin LI if (c == CONTROL('A')) 2156dcb072bSXin LI { 2166dcb072bSXin LI hex_in = 2; 2176dcb072bSXin LI result = 0; 2186dcb072bSXin LI continue; 2196dcb072bSXin LI } 2206dcb072bSXin LI if (hex_in > 0) 2216dcb072bSXin LI { 2226dcb072bSXin LI int v; 2236dcb072bSXin LI if (c >= '0' && c <= '9') 2246dcb072bSXin LI v = c - '0'; 2256dcb072bSXin LI else if (c >= 'a' && c <= 'f') 2266dcb072bSXin LI v = c - 'a' + 10; 2276dcb072bSXin LI else if (c >= 'A' && c <= 'F') 2286dcb072bSXin LI v = c - 'A' + 10; 2296dcb072bSXin LI else 230b7780dbeSXin LI v = 0; 2316dcb072bSXin LI hex_value = (hex_value << 4) | v; 2326dcb072bSXin LI if (--hex_in > 0) 2336dcb072bSXin LI { 2346dcb072bSXin LI result = 0; 2356dcb072bSXin LI continue; 2366dcb072bSXin LI } 2376dcb072bSXin LI c = hex_value; 2386dcb072bSXin LI } 2397f074f9cSXin LI } 2406dcb072bSXin LI #endif 241a5f0fb15SPaul Saab /* 242a5f0fb15SPaul Saab * Various parts of the program cannot handle 243a5f0fb15SPaul Saab * an input character of '\0'. 244a5f0fb15SPaul Saab * If a '\0' was actually typed, convert it to '\340' here. 245a5f0fb15SPaul Saab */ 246a5f0fb15SPaul Saab if (c == '\0') 247a5f0fb15SPaul Saab c = '\340'; 248a5f0fb15SPaul Saab } while (result != 1); 249a5f0fb15SPaul Saab 2506dcb072bSXin LI return (c & 0xFF); 251a5f0fb15SPaul Saab } 252