1*838f5788Ssimonb /* $NetBSD: ttyin.c,v 1.4 2023/10/06 05:49:49 simonb Exp $ */
220006a0bStron
320006a0bStron /*
4*838f5788Ssimonb * Copyright (C) 1984-2023 Mark Nudelman
520006a0bStron *
620006a0bStron * You may distribute under the terms of either the GNU General Public
720006a0bStron * License or the Less License, as specified in the README file.
820006a0bStron *
9ec18bca0Stron * For more information, see the README file.
1020006a0bStron */
1120006a0bStron
1220006a0bStron
1320006a0bStron /*
1420006a0bStron * Routines dealing with getting input from the keyboard (i.e. from the user).
1520006a0bStron */
1620006a0bStron
1720006a0bStron #include "less.h"
1820006a0bStron #if OS2
1920006a0bStron #include "cmd.h"
2020006a0bStron #include "pckeys.h"
2120006a0bStron #endif
2220006a0bStron #if MSDOS_COMPILER==WIN32C
23*838f5788Ssimonb #define WIN32_LEAN_AND_MEAN
24*838f5788Ssimonb #ifndef _WIN32_WINNT
25*838f5788Ssimonb #define _WIN32_WINNT 0x400
2620006a0bStron #endif
27*838f5788Ssimonb #include <windows.h>
28*838f5788Ssimonb public DWORD console_mode;
29*838f5788Ssimonb public HANDLE tty;
30*838f5788Ssimonb #else
3120006a0bStron public int tty;
32*838f5788Ssimonb #endif
33*838f5788Ssimonb #if LESSTEST
34*838f5788Ssimonb public char *ttyin_name = NULL;
35*838f5788Ssimonb #endif /*LESSTEST*/
3620006a0bStron extern int sigs;
3720006a0bStron extern int utf_mode;
38*838f5788Ssimonb extern int wheel_lines;
39*838f5788Ssimonb
40*838f5788Ssimonb #if !MSDOS_COMPILER
open_tty_device(constant char * dev)41*838f5788Ssimonb static int open_tty_device(constant char* dev)
42*838f5788Ssimonb {
43*838f5788Ssimonb #if OS2
44*838f5788Ssimonb /* The __open() system call translates "/dev/tty" to "con". */
45*838f5788Ssimonb return __open(dev, OPEN_READ);
46*838f5788Ssimonb #else
47*838f5788Ssimonb return open(dev, OPEN_READ);
48*838f5788Ssimonb #endif
49*838f5788Ssimonb }
50*838f5788Ssimonb
51*838f5788Ssimonb /*
52*838f5788Ssimonb * Open the tty device.
53*838f5788Ssimonb * Try ttyname(), then try /dev/tty, then use file descriptor 2.
54*838f5788Ssimonb * In Unix, file descriptor 2 is usually attached to the screen,
55*838f5788Ssimonb * but also usually lets you read from the keyboard.
56*838f5788Ssimonb */
open_tty(void)57*838f5788Ssimonb public int open_tty(void)
58*838f5788Ssimonb {
59*838f5788Ssimonb int fd = -1;
60*838f5788Ssimonb #if LESSTEST
61*838f5788Ssimonb if (ttyin_name != NULL)
62*838f5788Ssimonb fd = open_tty_device(ttyin_name);
63*838f5788Ssimonb #endif /*LESSTEST*/
64*838f5788Ssimonb #if HAVE_TTYNAME
65*838f5788Ssimonb if (fd < 0)
66*838f5788Ssimonb {
67*838f5788Ssimonb constant char *dev = ttyname(2);
68*838f5788Ssimonb if (dev != NULL)
69*838f5788Ssimonb fd = open_tty_device(dev);
70*838f5788Ssimonb }
71*838f5788Ssimonb #endif
72*838f5788Ssimonb if (fd < 0)
73*838f5788Ssimonb fd = open_tty_device("/dev/tty");
74*838f5788Ssimonb if (fd < 0)
75*838f5788Ssimonb fd = 2;
76*838f5788Ssimonb return fd;
77*838f5788Ssimonb }
78*838f5788Ssimonb #endif /* MSDOS_COMPILER */
7920006a0bStron
8020006a0bStron /*
8120006a0bStron * Open keyboard for input.
8220006a0bStron */
open_getchr(void)83*838f5788Ssimonb public void open_getchr(void)
8420006a0bStron {
8520006a0bStron #if MSDOS_COMPILER==WIN32C
8620006a0bStron /* Need this to let child processes inherit our console handle */
8720006a0bStron SECURITY_ATTRIBUTES sa;
8820006a0bStron memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
8920006a0bStron sa.nLength = sizeof(SECURITY_ATTRIBUTES);
9020006a0bStron sa.bInheritHandle = TRUE;
91*838f5788Ssimonb tty = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
9220006a0bStron FILE_SHARE_READ, &sa,
9320006a0bStron OPEN_EXISTING, 0L, NULL);
94*838f5788Ssimonb GetConsoleMode(tty, &console_mode);
9520006a0bStron /* Make sure we get Ctrl+C events. */
96*838f5788Ssimonb SetConsoleMode(tty, ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT);
9720006a0bStron #else
9820006a0bStron #if MSDOS_COMPILER
9920006a0bStron extern int fd0;
10020006a0bStron /*
10120006a0bStron * Open a new handle to CON: in binary mode
10220006a0bStron * for unbuffered keyboard read.
10320006a0bStron */
10420006a0bStron fd0 = dup(0);
10520006a0bStron close(0);
10620006a0bStron tty = open("CON", OPEN_READ);
10720006a0bStron #if MSDOS_COMPILER==DJGPPC
10820006a0bStron /*
10920006a0bStron * Setting stdin to binary causes Ctrl-C to not
11020006a0bStron * raise SIGINT. We must undo that side-effect.
11120006a0bStron */
11220006a0bStron (void) __djgpp_set_ctrl_c(1);
11320006a0bStron #endif
11420006a0bStron #else
115*838f5788Ssimonb tty = open_tty();
11620006a0bStron #endif
11720006a0bStron #endif
11820006a0bStron }
11920006a0bStron
12020006a0bStron /*
12120006a0bStron * Close the keyboard.
12220006a0bStron */
close_getchr(void)123*838f5788Ssimonb public void close_getchr(void)
12420006a0bStron {
12520006a0bStron #if MSDOS_COMPILER==WIN32C
126*838f5788Ssimonb SetConsoleMode(tty, console_mode);
127*838f5788Ssimonb CloseHandle(tty);
12820006a0bStron #endif
12920006a0bStron }
13020006a0bStron
131*838f5788Ssimonb #if MSDOS_COMPILER==WIN32C
132*838f5788Ssimonb /*
133*838f5788Ssimonb * Close the pipe, restoring the keyboard (CMD resets it, losing the mouse).
134*838f5788Ssimonb */
pclose(FILE * f)135*838f5788Ssimonb public int pclose(FILE *f)
136*838f5788Ssimonb {
137*838f5788Ssimonb int result;
138*838f5788Ssimonb
139*838f5788Ssimonb result = _pclose(f);
140*838f5788Ssimonb SetConsoleMode(tty, ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT);
141*838f5788Ssimonb return result;
142*838f5788Ssimonb }
143*838f5788Ssimonb #endif
144*838f5788Ssimonb
145*838f5788Ssimonb /*
146*838f5788Ssimonb * Get the number of lines to scroll when mouse wheel is moved.
147*838f5788Ssimonb */
default_wheel_lines(void)148*838f5788Ssimonb public int default_wheel_lines(void)
149*838f5788Ssimonb {
150*838f5788Ssimonb int lines = 1;
151*838f5788Ssimonb #if MSDOS_COMPILER==WIN32C
152*838f5788Ssimonb if (SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &lines, 0))
153*838f5788Ssimonb {
154*838f5788Ssimonb if (lines == WHEEL_PAGESCROLL)
155*838f5788Ssimonb lines = 3;
156*838f5788Ssimonb }
157*838f5788Ssimonb #endif
158*838f5788Ssimonb return lines;
159*838f5788Ssimonb }
160*838f5788Ssimonb
16120006a0bStron /*
16220006a0bStron * Get a character from the keyboard.
16320006a0bStron */
getchr(void)164*838f5788Ssimonb public int getchr(void)
16520006a0bStron {
16620006a0bStron char c;
16720006a0bStron int result;
16820006a0bStron
16920006a0bStron do
17020006a0bStron {
171*838f5788Ssimonb flush();
17220006a0bStron #if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC
17320006a0bStron /*
17420006a0bStron * In raw read, we don't see ^C so look here for it.
17520006a0bStron */
17620006a0bStron #if MSDOS_COMPILER==WIN32C
17720006a0bStron if (ABORT_SIGS())
17820006a0bStron return (READ_INTR);
179*838f5788Ssimonb c = WIN32getch();
18020006a0bStron #else
18120006a0bStron c = getch();
18220006a0bStron #endif
18320006a0bStron result = 1;
18420006a0bStron if (c == '\003')
18520006a0bStron return (READ_INTR);
18620006a0bStron #else
187*838f5788Ssimonb {
188*838f5788Ssimonb unsigned char uc;
189*838f5788Ssimonb result = iread(tty, &uc, sizeof(char));
190*838f5788Ssimonb c = (char) uc;
191*838f5788Ssimonb }
19220006a0bStron if (result == READ_INTR)
19320006a0bStron return (READ_INTR);
19420006a0bStron if (result < 0)
19520006a0bStron {
19620006a0bStron /*
19720006a0bStron * Don't call error() here,
19820006a0bStron * because error calls getchr!
19920006a0bStron */
20020006a0bStron quit(QUIT_ERROR);
20120006a0bStron }
20220006a0bStron #endif
203*838f5788Ssimonb #if LESSTEST
204*838f5788Ssimonb if (c == LESS_DUMP_CHAR)
205*838f5788Ssimonb {
206*838f5788Ssimonb dump_screen();
207*838f5788Ssimonb result = 0;
208*838f5788Ssimonb continue;
209*838f5788Ssimonb }
210*838f5788Ssimonb #endif
21120006a0bStron #if 0 /* allow entering arbitrary hex chars for testing */
21220006a0bStron /* ctrl-A followed by two hex chars makes a byte */
21320006a0bStron {
214*838f5788Ssimonb static int hex_in = 0;
215*838f5788Ssimonb static int hex_value = 0;
21620006a0bStron if (c == CONTROL('A'))
21720006a0bStron {
21820006a0bStron hex_in = 2;
21920006a0bStron result = 0;
22020006a0bStron continue;
22120006a0bStron }
22220006a0bStron if (hex_in > 0)
22320006a0bStron {
22420006a0bStron int v;
22520006a0bStron if (c >= '0' && c <= '9')
22620006a0bStron v = c - '0';
22720006a0bStron else if (c >= 'a' && c <= 'f')
22820006a0bStron v = c - 'a' + 10;
22920006a0bStron else if (c >= 'A' && c <= 'F')
23020006a0bStron v = c - 'A' + 10;
23120006a0bStron else
232*838f5788Ssimonb v = 0;
23320006a0bStron hex_value = (hex_value << 4) | v;
23420006a0bStron if (--hex_in > 0)
23520006a0bStron {
23620006a0bStron result = 0;
23720006a0bStron continue;
23820006a0bStron }
23920006a0bStron c = hex_value;
24020006a0bStron }
24120006a0bStron }
24220006a0bStron #endif
24320006a0bStron /*
24420006a0bStron * Various parts of the program cannot handle
24520006a0bStron * an input character of '\0'.
24620006a0bStron * If a '\0' was actually typed, convert it to '\340' here.
24720006a0bStron */
24820006a0bStron if (c == '\0')
24920006a0bStron c = '\340';
25020006a0bStron } while (result != 1);
25120006a0bStron
25220006a0bStron return (c & 0xFF);
25320006a0bStron }
254