ttyin.c revision 238730
160107Sobrien/*
234919Simp * Copyright (C) 1984-2012  Mark Nudelman
334919Simp *
434919Simp * You may distribute under the terms of either the GNU General Public
534919Simp * License or the Less License, as specified in the README file.
634919Simp *
746664Simp * For more information, see the README file.
834919Simp */
934919Simp
1034919Simp
1134919Simp/*
1234919Simp * Routines dealing with getting input from the keyboard (i.e. from the user).
1334919Simp */
1434919Simp
1534919Simp#include "less.h"
1634919Simp#if OS2
1734919Simp#include "cmd.h"
1838140Syokota#include "pckeys.h"
1934919Simp#endif
2034919Simp#if MSDOS_COMPILER==WIN32C
2134919Simp#include "windows.h"
2234919Simpextern char WIN32getch();
2334919Simpstatic DWORD console_mode;
2434919Simp#endif
2534919Simp
2634919Simppublic int tty;
2734919Simpextern int sigs;
2834919Simpextern int utf_mode;
2934919Simp
3034919Simp/*
3134919Simp * Open keyboard for input.
3234919Simp */
3334919Simp	public void
3434919Simpopen_getchr()
3534919Simp{
3634919Simp#if MSDOS_COMPILER==WIN32C
3734919Simp	/* Need this to let child processes inherit our console handle */
3834919Simp	SECURITY_ATTRIBUTES sa;
3934919Simp	memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
4034919Simp	sa.nLength = sizeof(SECURITY_ATTRIBUTES);
4134919Simp	sa.bInheritHandle = TRUE;
4234919Simp	tty = (int) CreateFile("CONIN$", GENERIC_READ,
4334919Simp			FILE_SHARE_READ, &sa,
4434919Simp			OPEN_EXISTING, 0L, NULL);
4534919Simp	GetConsoleMode((HANDLE)tty, &console_mode);
4634919Simp	/* Make sure we get Ctrl+C events. */
4746664Simp	SetConsoleMode((HANDLE)tty, ENABLE_PROCESSED_INPUT);
4834919Simp#else
4934919Simp#if MSDOS_COMPILER
5034919Simp	extern int fd0;
5134919Simp	/*
5234919Simp	 * Open a new handle to CON: in binary mode
5334919Simp	 * for unbuffered keyboard read.
5434919Simp	 */
5534919Simp	 fd0 = dup(0);
5634919Simp	 close(0);
5734919Simp	 tty = open("CON", OPEN_READ);
5834919Simp#if MSDOS_COMPILER==DJGPPC
5934919Simp	/*
6034919Simp	 * Setting stdin to binary causes Ctrl-C to not
6146664Simp	 * raise SIGINT.  We must undo that side-effect.
6234919Simp	 */
6346664Simp	(void) __djgpp_set_ctrl_c(1);
6434919Simp#endif
6534919Simp#else
6634919Simp	/*
6734919Simp	 * Try /dev/tty.
6834919Simp	 * If that doesn't work, use file descriptor 2,
6934919Simp	 * which in Unix is usually attached to the screen,
7034919Simp	 * but also usually lets you read from the keyboard.
7134919Simp	 */
7234919Simp#if OS2
7334919Simp	/* The __open() system call translates "/dev/tty" to "con". */
7434919Simp	tty = __open("/dev/tty", OPEN_READ);
7534919Simp#else
7634919Simp	tty = open("/dev/tty", OPEN_READ);
7734919Simp#endif
7834919Simp	if (tty < 0)
7934919Simp		tty = 2;
8034919Simp#endif
8134919Simp#endif
8234919Simp}
8334919Simp
8434919Simp/*
8534919Simp * Close the keyboard.
8634919Simp */
8734919Simp	public void
8834919Simpclose_getchr()
8934956Simp{
9046664Simp#if MSDOS_COMPILER==WIN32C
9134919Simp	SetConsoleMode((HANDLE)tty, console_mode);
9234919Simp	CloseHandle((HANDLE)tty);
9334919Simp#endif
9434919Simp}
9534919Simp
9634919Simp/*
9734919Simp * Get a character from the keyboard.
9846664Simp */
9934919Simp	public int
10034919Simpgetchr()
10134919Simp{
10234919Simp	char c;
10334919Simp	int result;
10434919Simp
10534919Simp	do
10634919Simp	{
10734919Simp#if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC
10834919Simp		/*
10946664Simp		 * In raw read, we don't see ^C so look here for it.
11046664Simp		 */
11146664Simp		flush();
11246664Simp#if MSDOS_COMPILER==WIN32C
11346664Simp		if (ABORT_SIGS())
11446664Simp			return (READ_INTR);
115		c = WIN32getch(tty);
116#else
117		c = getch();
118#endif
119		result = 1;
120		if (c == '\003')
121			return (READ_INTR);
122#else
123		result = iread(tty, &c, sizeof(char));
124		if (result == READ_INTR)
125			return (READ_INTR);
126		if (result < 0)
127		{
128			/*
129			 * Don't call error() here,
130			 * because error calls getchr!
131			 */
132			quit(QUIT_ERROR);
133		}
134#endif
135#if 0 /* allow entering arbitrary hex chars for testing */
136		/* ctrl-A followed by two hex chars makes a byte */
137	{
138		int hex_in = 0;
139		int hex_value = 0;
140		if (c == CONTROL('A'))
141		{
142			hex_in = 2;
143			result = 0;
144			continue;
145		}
146		if (hex_in > 0)
147		{
148			int v;
149			if (c >= '0' && c <= '9')
150				v = c - '0';
151			else if (c >= 'a' && c <= 'f')
152				v = c - 'a' + 10;
153			else if (c >= 'A' && c <= 'F')
154				v = c - 'A' + 10;
155			else
156				hex_in = 0;
157			hex_value = (hex_value << 4) | v;
158			if (--hex_in > 0)
159			{
160				result = 0;
161				continue;
162			}
163			c = hex_value;
164		}
165	}
166#endif
167		/*
168		 * Various parts of the program cannot handle
169		 * an input character of '\0'.
170		 * If a '\0' was actually typed, convert it to '\340' here.
171		 */
172		if (c == '\0')
173			c = '\340';
174	} while (result != 1);
175
176	return (c & 0xFF);
177}
178