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