1*84d9c625SLionel Sambuc /* $NetBSD: ttyin.c,v 1.3 2013/09/04 19:44:21 tron Exp $ */
2f7cf2976SLionel Sambuc
3f7cf2976SLionel Sambuc /*
4*84d9c625SLionel Sambuc * Copyright (C) 1984-2012 Mark Nudelman
5f7cf2976SLionel Sambuc *
6f7cf2976SLionel Sambuc * You may distribute under the terms of either the GNU General Public
7f7cf2976SLionel Sambuc * License or the Less License, as specified in the README file.
8f7cf2976SLionel Sambuc *
9*84d9c625SLionel Sambuc * For more information, see the README file.
10f7cf2976SLionel Sambuc */
11f7cf2976SLionel Sambuc
12f7cf2976SLionel Sambuc
13f7cf2976SLionel Sambuc /*
14f7cf2976SLionel Sambuc * Routines dealing with getting input from the keyboard (i.e. from the user).
15f7cf2976SLionel Sambuc */
16f7cf2976SLionel Sambuc
17f7cf2976SLionel Sambuc #include "less.h"
18f7cf2976SLionel Sambuc #if OS2
19f7cf2976SLionel Sambuc #include "cmd.h"
20f7cf2976SLionel Sambuc #include "pckeys.h"
21f7cf2976SLionel Sambuc #endif
22f7cf2976SLionel Sambuc #if MSDOS_COMPILER==WIN32C
23f7cf2976SLionel Sambuc #include "windows.h"
24f7cf2976SLionel Sambuc extern char WIN32getch();
25f7cf2976SLionel Sambuc static DWORD console_mode;
26f7cf2976SLionel Sambuc #endif
27f7cf2976SLionel Sambuc
28f7cf2976SLionel Sambuc public int tty;
29f7cf2976SLionel Sambuc extern int sigs;
30f7cf2976SLionel Sambuc extern int utf_mode;
31f7cf2976SLionel Sambuc
32f7cf2976SLionel Sambuc /*
33f7cf2976SLionel Sambuc * Open keyboard for input.
34f7cf2976SLionel Sambuc */
35f7cf2976SLionel Sambuc public void
open_getchr()36f7cf2976SLionel Sambuc open_getchr()
37f7cf2976SLionel Sambuc {
38f7cf2976SLionel Sambuc #if MSDOS_COMPILER==WIN32C
39f7cf2976SLionel Sambuc /* Need this to let child processes inherit our console handle */
40f7cf2976SLionel Sambuc SECURITY_ATTRIBUTES sa;
41f7cf2976SLionel Sambuc memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
42f7cf2976SLionel Sambuc sa.nLength = sizeof(SECURITY_ATTRIBUTES);
43f7cf2976SLionel Sambuc sa.bInheritHandle = TRUE;
44f7cf2976SLionel Sambuc tty = (int) CreateFile("CONIN$", GENERIC_READ,
45f7cf2976SLionel Sambuc FILE_SHARE_READ, &sa,
46f7cf2976SLionel Sambuc OPEN_EXISTING, 0L, NULL);
47f7cf2976SLionel Sambuc GetConsoleMode((HANDLE)tty, &console_mode);
48f7cf2976SLionel Sambuc /* Make sure we get Ctrl+C events. */
49f7cf2976SLionel Sambuc SetConsoleMode((HANDLE)tty, ENABLE_PROCESSED_INPUT);
50f7cf2976SLionel Sambuc #else
51f7cf2976SLionel Sambuc #if MSDOS_COMPILER
52f7cf2976SLionel Sambuc extern int fd0;
53f7cf2976SLionel Sambuc /*
54f7cf2976SLionel Sambuc * Open a new handle to CON: in binary mode
55f7cf2976SLionel Sambuc * for unbuffered keyboard read.
56f7cf2976SLionel Sambuc */
57f7cf2976SLionel Sambuc fd0 = dup(0);
58f7cf2976SLionel Sambuc close(0);
59f7cf2976SLionel Sambuc tty = open("CON", OPEN_READ);
60f7cf2976SLionel Sambuc #if MSDOS_COMPILER==DJGPPC
61f7cf2976SLionel Sambuc /*
62f7cf2976SLionel Sambuc * Setting stdin to binary causes Ctrl-C to not
63f7cf2976SLionel Sambuc * raise SIGINT. We must undo that side-effect.
64f7cf2976SLionel Sambuc */
65f7cf2976SLionel Sambuc (void) __djgpp_set_ctrl_c(1);
66f7cf2976SLionel Sambuc #endif
67f7cf2976SLionel Sambuc #else
68f7cf2976SLionel Sambuc /*
69f7cf2976SLionel Sambuc * Try /dev/tty.
70f7cf2976SLionel Sambuc * If that doesn't work, use file descriptor 2,
71f7cf2976SLionel Sambuc * which in Unix is usually attached to the screen,
72f7cf2976SLionel Sambuc * but also usually lets you read from the keyboard.
73f7cf2976SLionel Sambuc */
74f7cf2976SLionel Sambuc #if OS2
75f7cf2976SLionel Sambuc /* The __open() system call translates "/dev/tty" to "con". */
76f7cf2976SLionel Sambuc tty = __open("/dev/tty", OPEN_READ);
77f7cf2976SLionel Sambuc #else
78f7cf2976SLionel Sambuc tty = open("/dev/tty", OPEN_READ);
79f7cf2976SLionel Sambuc #endif
80f7cf2976SLionel Sambuc if (tty < 0)
81f7cf2976SLionel Sambuc tty = 2;
82f7cf2976SLionel Sambuc #endif
83f7cf2976SLionel Sambuc #endif
84f7cf2976SLionel Sambuc }
85f7cf2976SLionel Sambuc
86f7cf2976SLionel Sambuc /*
87f7cf2976SLionel Sambuc * Close the keyboard.
88f7cf2976SLionel Sambuc */
89f7cf2976SLionel Sambuc public void
close_getchr()90f7cf2976SLionel Sambuc close_getchr()
91f7cf2976SLionel Sambuc {
92f7cf2976SLionel Sambuc #if MSDOS_COMPILER==WIN32C
93f7cf2976SLionel Sambuc SetConsoleMode((HANDLE)tty, console_mode);
94f7cf2976SLionel Sambuc CloseHandle((HANDLE)tty);
95f7cf2976SLionel Sambuc #endif
96f7cf2976SLionel Sambuc }
97f7cf2976SLionel Sambuc
98f7cf2976SLionel Sambuc /*
99f7cf2976SLionel Sambuc * Get a character from the keyboard.
100f7cf2976SLionel Sambuc */
101f7cf2976SLionel Sambuc public int
getchr()102f7cf2976SLionel Sambuc getchr()
103f7cf2976SLionel Sambuc {
104f7cf2976SLionel Sambuc char c;
105f7cf2976SLionel Sambuc int result;
106f7cf2976SLionel Sambuc
107f7cf2976SLionel Sambuc do
108f7cf2976SLionel Sambuc {
109f7cf2976SLionel Sambuc #if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC
110f7cf2976SLionel Sambuc /*
111f7cf2976SLionel Sambuc * In raw read, we don't see ^C so look here for it.
112f7cf2976SLionel Sambuc */
113f7cf2976SLionel Sambuc flush();
114f7cf2976SLionel Sambuc #if MSDOS_COMPILER==WIN32C
115f7cf2976SLionel Sambuc if (ABORT_SIGS())
116f7cf2976SLionel Sambuc return (READ_INTR);
117f7cf2976SLionel Sambuc c = WIN32getch(tty);
118f7cf2976SLionel Sambuc #else
119f7cf2976SLionel Sambuc c = getch();
120f7cf2976SLionel Sambuc #endif
121f7cf2976SLionel Sambuc result = 1;
122f7cf2976SLionel Sambuc if (c == '\003')
123f7cf2976SLionel Sambuc return (READ_INTR);
124f7cf2976SLionel Sambuc #else
125f7cf2976SLionel Sambuc result = iread(tty, &c, sizeof(char));
126f7cf2976SLionel Sambuc if (result == READ_INTR)
127f7cf2976SLionel Sambuc return (READ_INTR);
128f7cf2976SLionel Sambuc if (result < 0)
129f7cf2976SLionel Sambuc {
130f7cf2976SLionel Sambuc /*
131f7cf2976SLionel Sambuc * Don't call error() here,
132f7cf2976SLionel Sambuc * because error calls getchr!
133f7cf2976SLionel Sambuc */
134f7cf2976SLionel Sambuc quit(QUIT_ERROR);
135f7cf2976SLionel Sambuc }
136f7cf2976SLionel Sambuc #endif
137f7cf2976SLionel Sambuc #if 0 /* allow entering arbitrary hex chars for testing */
138f7cf2976SLionel Sambuc /* ctrl-A followed by two hex chars makes a byte */
139f7cf2976SLionel Sambuc {
140f7cf2976SLionel Sambuc int hex_in = 0;
141f7cf2976SLionel Sambuc int hex_value = 0;
142f7cf2976SLionel Sambuc if (c == CONTROL('A'))
143f7cf2976SLionel Sambuc {
144f7cf2976SLionel Sambuc hex_in = 2;
145f7cf2976SLionel Sambuc result = 0;
146f7cf2976SLionel Sambuc continue;
147f7cf2976SLionel Sambuc }
148f7cf2976SLionel Sambuc if (hex_in > 0)
149f7cf2976SLionel Sambuc {
150f7cf2976SLionel Sambuc int v;
151f7cf2976SLionel Sambuc if (c >= '0' && c <= '9')
152f7cf2976SLionel Sambuc v = c - '0';
153f7cf2976SLionel Sambuc else if (c >= 'a' && c <= 'f')
154f7cf2976SLionel Sambuc v = c - 'a' + 10;
155f7cf2976SLionel Sambuc else if (c >= 'A' && c <= 'F')
156f7cf2976SLionel Sambuc v = c - 'A' + 10;
157f7cf2976SLionel Sambuc else
158f7cf2976SLionel Sambuc hex_in = 0;
159f7cf2976SLionel Sambuc hex_value = (hex_value << 4) | v;
160f7cf2976SLionel Sambuc if (--hex_in > 0)
161f7cf2976SLionel Sambuc {
162f7cf2976SLionel Sambuc result = 0;
163f7cf2976SLionel Sambuc continue;
164f7cf2976SLionel Sambuc }
165f7cf2976SLionel Sambuc c = hex_value;
166f7cf2976SLionel Sambuc }
167f7cf2976SLionel Sambuc }
168f7cf2976SLionel Sambuc #endif
169f7cf2976SLionel Sambuc /*
170f7cf2976SLionel Sambuc * Various parts of the program cannot handle
171f7cf2976SLionel Sambuc * an input character of '\0'.
172f7cf2976SLionel Sambuc * If a '\0' was actually typed, convert it to '\340' here.
173f7cf2976SLionel Sambuc */
174f7cf2976SLionel Sambuc if (c == '\0')
175f7cf2976SLionel Sambuc c = '\340';
176f7cf2976SLionel Sambuc } while (result != 1);
177f7cf2976SLionel Sambuc
178f7cf2976SLionel Sambuc return (c & 0xFF);
179f7cf2976SLionel Sambuc }
180