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