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