1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright (c) 1995, by Sun Microsystems, Inc.
24 * All rights reserved.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 /*
30 * wgetch.c
31 *
32 * XCurses Library
33 *
34 * Copyright 1990, 1995 by Mortice Kern Systems Inc. All rights reserved.
35 *
36 */
37
38 #ifdef M_RCSID
39 #ifndef lint
40 static char rcsID[] = "$Header: /rd/src/libc/xcurses/rcs/wgetch.c 1.5 1995/06/19 16:12:13 ant Exp $";
41 #endif
42 #endif
43
44 #include <private.h>
45
46 /*
47 * Push single-byte character back onto the input queue.
48 *
49 * MKS EXTENSION permits the return value of wgetch(), which
50 * can be a KEY_ value, to be pushed back.
51 */
52 int
ungetch(ch)53 ungetch(ch)
54 int ch;
55 {
56 int code;
57
58 #ifdef M_CURSES_TRACE
59 __m_trace("ungetch(%d)", ch);
60 #endif
61 code = __xc_ungetc(ch, (WINDOW *) 0) == EOF ? ERR : OK;
62
63 return __m_return_code("ungetch", code);
64 }
65
66 /*
67 * Push a single-byte character or KEY_ value but onto the
68 * input queue. Ignore the window parameter.
69 */
70 int
__xc_ungetc(int ch,void * w)71 __xc_ungetc(int ch, void *w)
72 {
73 if (ISFULL())
74 return EOF;
75
76 PUSH(ch);
77
78 return 0;
79 }
80
81 /*
82 * Return true if the SCREEN's stream has an I/O error.
83 * Ignore the window parameter.
84 */
85 int
__xc_ferror(void * w)86 __xc_ferror(void *w)
87 {
88 return ferror(__m_screen->_if);
89 }
90
91 /*
92 * Return true if the SCREEN's stream has seen EOF.
93 * Ignore the window parameter.
94 */
95 int
__xc_feof(void * w)96 __xc_feof(void *w)
97 {
98 return feof(__m_screen->_if);
99 }
100
101 /*
102 * Clear the error and eof flags of the SCREEN's stream.
103 * Ignore the window parameter.
104 */
105 void
__xc_clearerr(void * w)106 __xc_clearerr(void *w)
107 {
108 clearerr(__m_screen->_if);
109 }
110
111 int
wgetch(w)112 wgetch(w)
113 WINDOW *w;
114 {
115 t_decode *node;
116 int ch, i, j, timeout;
117
118 #ifdef M_CURSES_TRACE
119 __m_trace("wgetch(%p) at (%d, %d).", w, w->_cury, w->_curx);
120 #endif
121
122 (void) wrefresh(w);
123
124 if (!ISEMPTY())
125 return __m_return_int("wgetch", POP());
126
127 /* Only change the terminal's input method if the window
128 * requires different settings from what is currently set.
129 * We do this because tcsetattr() on some systems can be
130 * _really_ slow to do for each character.
131 *
132 * NOTE that halfdelay() overrides nodelay() and wtimeout().
133 */
134 if (!(cur_term->_flags & __TERM_HALF_DELAY)
135 && (cur_term->_prog.c_cc[VMIN] != w->_vmin
136 || cur_term->_prog.c_cc[VTIME] != w->_vtime)) {
137 cur_term->_prog.c_cc[VMIN] = w->_vmin;
138 cur_term->_prog.c_cc[VTIME] = w->_vtime;
139
140 if (__m_tty_set(&cur_term->_prog) == ERR)
141 return __m_return_int("wgetch", EOF);
142 }
143
144 if (req_for_input != (char *) 0)
145 (void) tputs(req_for_input, 1, __m_outc);
146
147 clearerr(__m_screen->_if);
148 ch = fgetc(__m_screen->_if);
149
150 /* Only check for function keys if keypad is true and we
151 * did not read a KEY_ value (which are < 0), nor EOF.
152 * It is conceivable that a KEY_ was pushed back with
153 * ungetch().
154 */
155 if ((w->_flags & W_USE_KEYPAD) && 0 <= ch && ch != EOF) {
156 /* Treat the termios ERASE key the same as key_backspace.
157 *
158 * We used to change the key_backspace entry to be a string
159 * containing the ERASE key in setupterm(), but this would
160 * then disable the real terminfo entry for the backspace key.
161 * Apparently VT300 terminals change the key code/sequence
162 * of the backspace key in application keypad mode.
163 * See SR 6014.
164 *
165 * Refer to _shell instead of _prog, since _shell will
166 * correctly reflect the user's prefered settings, whereas
167 * _prog may not have been initialised if both input and
168 * output have been redirected.
169 */
170 #ifdef _POSIX_VDISABLE
171 if (cur_term->_shell.c_cc[VERASE] != _POSIX_VDISABLE)
172 #endif
173 if (ch == cur_term->_shell.c_cc[VERASE])
174 return __m_return_int("wgetch", KEY_BACKSPACE);
175
176 /* Begin check for function key. */
177 node = (t_decode *) __m_screen->_decode;
178
179 /* Use input stack as a queue. */
180 timeout = w->_flags & W_USE_TIMEOUT;
181 for (RESET(); !ISFULL(); ) {
182 PUSH(ch);
183
184 while (node->ch != ch) {
185 node = node->sibling;
186 if (node == (t_decode *) 0)
187 goto invalid;
188 }
189
190 /* Found funuction key? */
191 if (node->key != 0) {
192 RESET();
193 return __m_return_int("wgetch", node->key);
194 }
195
196 /* Setup interbyte timer (once only). fgetc() will
197 * return EOF if no input received, which may not be
198 * a true EOF.
199 */
200 if (timeout) {
201 cur_term->_prog.c_cc[VMIN] = 0;
202 cur_term->_prog.c_cc[VTIME] =
203 M_CURSES_INTERBYTE_TIME;
204 (void) __m_tty_set(&cur_term->_prog);
205 }
206 timeout = 0;
207
208 if ((ch = fgetc(__m_screen->_if)) == EOF)
209 /* Timeout or real eof. */
210 break;
211
212 /* Incomplete sequence, continue. */
213 node = node->child;
214 }
215 invalid:
216 /* Reverse contents of the input queue to form a stack. */
217 for (i = 0, j = __m_screen->_unget._count; i < --j; ++i) {
218 ch = __m_screen->_unget._stack[i];
219 __m_screen->_unget._stack[i] =
220 __m_screen->_unget._stack[j];
221 __m_screen->_unget._stack[j] = ch;
222 }
223
224 /* Return first byte received or EOF. */
225 ch = POP();
226 }
227
228 if ((__m_screen->_flags & S_ECHO) && 0 <= ch && ch != EOF) {
229 (void) waddch(w, ch);
230 (void) wrefresh(w);
231 }
232
233 return __m_return_int("wgetch", ch);
234 }
235
236