xref: /illumos-gate/usr/src/lib/libxcurses/src/libc/xcurses/wget_wch.c (revision ed093b41a93e8563e6e1e5dae0768dda2a7bcc27)
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 /*
28  * wget_wch.c
29  *
30  * XCurses Library
31  *
32  * Copyright 1990, 1995 by Mortice Kern Systems Inc.  All rights reserved.
33  *
34  */
35 
36 #ifdef M_RCSID
37 #ifndef lint
38 static char rcsID[] = "$Header: /rd/src/libc/xcurses/rcs/wget_wch.c 1.2 1995/06/08 19:00:47 ant Exp $";
39 #endif
40 #endif
41 
42 #include <private.h>
43 #include <m_wio.h>
44 #include <stdlib.h>
45 
46 /*
47  * Push a wide character back onto the input queue.
48  *
49  * XPG4 is silent as to whether wget_wch() and wgetch()
50  * can both be used in an applicaton.  Assume they can,
51  * in which case we have to push the multibyte equivalent
52  * back onto the input queue.
53  */
54 int
55 unget_wch(const wchar_t wc)
56 {
57 	int i, len;
58 	char mb[MB_LEN_MAX];
59 
60 #ifdef M_CURSES_TRACE
61 	__m_trace("unget_wch(%ld)", (long) wc);
62 #endif
63 
64 	if (!ISEMPTY() || (len = wctomb(mb, wc)) < 0)
65 		return __m_return_code("unget_wch", ERR);
66 
67 	for (i = 0; i < len; ++i)
68 		PUSH(mb[i]);
69 
70 	return __m_return_code("unget_wch", OK);
71 }
72 
73 int
74 wget_wch(w, wcp)
75 WINDOW *w;
76 wint_t *wcp;
77 {
78 	cchar_t cc;
79 	int ch, oecho;
80 	t_wide_io *wio;
81 
82 #ifdef M_CURSES_TRACE
83 	__m_trace("wget_wch(%p, %p)", w, wcp);
84 #endif
85 
86 	/* Disable echo temporarily, because we're using
87 	 * wgetch() to read in individual bytes and only
88 	 * want echo the resulting character, not the
89 	 * individual bytes composing the character.
90 	 */
91 	oecho = __m_set_echo(0);
92 
93 	/* Input function is wgetch(), which takes a WINDOW * for
94 	 * a parameter.  The WINDOW * is used to set the "focus" by
95 	 * updatng and position the cursor in the relevant window and
96 	 * provide window specific settings.  Input for all windows
97 	 * comes from one stream (__m_screen->_if), which is normally
98 	 * the terminal, but can be redirected.
99 	 */
100 	wio = (t_wide_io *) __m_screen->_in;
101 	wio->object = w;
102 
103 	/* Get the first byte or KEY_ value. */
104 	if ((ch = wgetch(w)) < __KEY_BASE) {
105 		*wcp = ch;
106 		(void) __m_set_echo(oecho);
107 		return __m_return_code("wget_wch", KEY_CODE_YES);
108 	}
109 
110 	/* Push the byte back onto the input stream so that
111 	 * it can be processed by __m_wio_get().
112 	 */
113 	(void) ungetc(ch, __m_screen->_if);
114 
115 	/* Fetch a wide character from a narrow input stream.
116 	 * Invalid sequences are preserved as individual bytes.
117 	 * Handles insignificant and redundant shifts in the input
118 	 * stream.
119 	 */
120 	*wcp = m_wio_get(wio);
121 
122 	/* Restore echo. */
123 	(void) __m_set_echo(oecho);
124 
125 	/* Push any invalid multibyte sequence back onto the
126 	 * input stack, so that no data is lost, just in case
127 	 * the application mixes wide (wget_wch()) and narrow
128 	 * (wgetch()) input methods.
129 	 */
130 	while (wio->_next < wio->_size)
131 		PUSH(wio->_mb[--wio->_size]);
132 
133 	/* Now echo wide character if necessary. */
134 	if ((__m_screen->_flags & S_ECHO) && *wcp != WEOF) {
135 		(void) __m_wc_cc(*wcp, &cc);
136 		(void) wadd_wch(w, &cc);
137 		(void) wrefresh(w);
138 	}
139 
140 	return __m_return_code("wget_wch", OK);
141 }
142