1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
|
/*
* Copyright (C) 1984-2024 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
*
* For more information, see the README file.
*/
/*
* Routines dealing with getting input from the keyboard (i.e. from the user).
*/
#include "less.h"
#if OS2
#include "cmd.h"
#include "pckeys.h"
#endif
#if MSDOS_COMPILER==WIN32C
#define WIN32_LEAN_AND_MEAN
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x400
#endif
#include <windows.h>
#ifndef ENABLE_EXTENDED_FLAGS
#define ENABLE_EXTENDED_FLAGS 0x80
#define ENABLE_QUICK_EDIT_MODE 0x40
#endif
#ifndef ENABLE_VIRTUAL_TERMINAL_INPUT
#define ENABLE_VIRTUAL_TERMINAL_INPUT 0x0200
#endif
public HANDLE tty;
public DWORD init_console_input_mode;
public DWORD curr_console_input_mode;
public DWORD base_console_input_mode;
public DWORD mouse_console_input_mode;
#else
public int tty;
#endif
extern int sigs;
#if LESSTEST
public char *ttyin_name = NULL;
public lbool is_lesstest(void)
{
return ttyin_name != NULL;
}
#endif /*LESSTEST*/
#if !MSDOS_COMPILER
static int open_tty_device(constant char* dev)
{
#if OS2
/* The __open() system call translates "/dev/tty" to "con". */
return __open(dev, OPEN_READ);
#else
return open(dev, OPEN_READ);
#endif
}
/*
* Open the tty device.
* Try ttyname(), then try /dev/tty, then use file descriptor 2.
* In Unix, file descriptor 2 is usually attached to the screen,
* but also usually lets you read from the keyboard.
*/
public int open_tty(void)
{
int fd = -1;
#if LESSTEST
if (is_lesstest())
fd = open_tty_device(ttyin_name);
#endif /*LESSTEST*/
#if HAVE_TTYNAME
if (fd < 0)
{
constant char *dev = ttyname(2);
if (dev != NULL)
fd = open_tty_device(dev);
}
#endif
if (fd < 0)
fd = open_tty_device("/dev/tty");
if (fd < 0)
fd = 2;
#ifdef __MVS__
struct f_cnvrt cvtreq = {SETCVTON, 0, 1047};
fcntl(fd, F_CONTROL_CVT, &cvtreq);
#endif
return fd;
}
#endif /* MSDOS_COMPILER */
/*
* Open keyboard for input.
*/
public void open_getchr(void)
{
#if MSDOS_COMPILER==WIN32C
/* Need this to let child processes inherit our console handle */
SECURITY_ATTRIBUTES sa;
memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = TRUE;
tty = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ, &sa,
OPEN_EXISTING, 0L, NULL);
GetConsoleMode(tty, &init_console_input_mode);
/* base mode: ensure we get ctrl-C events, and don't get VT input. */
base_console_input_mode = (init_console_input_mode | ENABLE_PROCESSED_INPUT) & ~ENABLE_VIRTUAL_TERMINAL_INPUT;
/* mouse mode: enable mouse and disable quick edit. */
mouse_console_input_mode = (base_console_input_mode | ENABLE_MOUSE_INPUT | ENABLE_EXTENDED_FLAGS) & ~ENABLE_QUICK_EDIT_MODE;
/* Start with base mode. If --mouse is given, switch to mouse mode in init_mouse. */
curr_console_input_mode = base_console_input_mode;
SetConsoleMode(tty, curr_console_input_mode);
#else
#if MSDOS_COMPILER
extern int fd0;
/*
* Open a new handle to CON: in binary mode
* for unbuffered keyboard read.
*/
fd0 = dup(0);
close(0);
tty = open("CON", OPEN_READ);
#if MSDOS_COMPILER==DJGPPC
/*
* Setting stdin to binary causes Ctrl-C to not
* raise SIGINT. We must undo that side-effect.
*/
(void) __djgpp_set_ctrl_c(1);
#endif
#else
tty = open_tty();
#endif
#endif
}
/*
* Close the keyboard.
*/
public void close_getchr(void)
{
#if MSDOS_COMPILER==WIN32C
SetConsoleMode(tty, init_console_input_mode);
CloseHandle(tty);
#endif
}
#if MSDOS_COMPILER==WIN32C
/*
* Close the pipe, restoring the console mode (CMD resets it, losing the mouse).
*/
public int pclose(FILE *f)
{
int result;
result = _pclose(f);
SetConsoleMode(tty, curr_console_input_mode);
return result;
}
#endif
/*
* Get the number of lines to scroll when mouse wheel is moved.
*/
public int default_wheel_lines(void)
{
int lines = 1;
#if MSDOS_COMPILER==WIN32C
if (SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &lines, 0))
{
if (lines == WHEEL_PAGESCROLL)
lines = 3;
}
#endif
return lines;
}
/*
* Get a character from the keyboard.
*/
public int getchr(void)
{
char c;
ssize_t result;
do
{
flush();
#if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC
/*
* In raw read, we don't see ^C so look here for it.
*/
#if MSDOS_COMPILER==WIN32C
if (ABORT_SIGS())
return (READ_INTR);
c = WIN32getch();
#else
c = getch();
#endif
result = 1;
if (c == '\003')
return (READ_INTR);
#else
{
unsigned char uc;
result = iread(tty, &uc, sizeof(char));
c = (char) uc;
}
if (result == READ_INTR)
return (READ_INTR);
if (result < 0)
{
/*
* Don't call error() here,
* because error calls getchr!
*/
quit(QUIT_ERROR);
}
#endif
#if LESSTEST
if (c == LESS_DUMP_CHAR)
{
dump_screen();
result = 0;
continue;
}
#endif
#if 0 /* allow entering arbitrary hex chars for testing */
/* ctrl-A followed by two hex chars makes a byte */
{
static int hex_in = 0;
static int hex_value = 0;
if (c == CONTROL('A'))
{
hex_in = 2;
result = 0;
continue;
}
if (hex_in > 0)
{
int v;
if (c >= '0' && c <= '9')
v = c - '0';
else if (c >= 'a' && c <= 'f')
v = c - 'a' + 10;
else if (c >= 'A' && c <= 'F')
v = c - 'A' + 10;
else
v = 0;
hex_value = (hex_value << 4) | v;
if (--hex_in > 0)
{
result = 0;
continue;
}
c = hex_value;
}
}
#endif
/*
* Various parts of the program cannot handle
* an input character of '\0'.
* If a '\0' was actually typed, convert it to '\340' here.
*/
if (c == '\0')
c = '\340';
} while (result != 1);
return (c & 0xFF);
}
|