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