xref: /illumos-gate/usr/src/lib/libxcurses2/src/libc/xcurses/wget_wch.c (revision b30d193948be5a7794d7ae3ba0ed9c2f72c88e0f)
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-1998 by Sun Microsystems, Inc.
24  * All rights reserved.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /* LINTLIBRARY */
30 
31 /*
32  * wget_wch.c
33  *
34  * XCurses Library
35  *
36  * Copyright 1990, 1995 by Mortice Kern Systems Inc.  All rights reserved.
37  *
38  */
39 
40 #ifdef M_RCSID
41 #ifndef lint
42 static char rcsID[] =
43 "$Header: /team/ps/sun_xcurses/archive/local_changes/xcurses/src/lib/"
44 "libxcurses/src/libc/xcurses/rcs/wget_wch.c 1.7 1998/05/22 17:57:03 "
45 "cbates Exp $";
46 #endif
47 #endif
48 
49 #include <private.h>
50 #include <m_wio.h>
51 #include <stdlib.h>
52 
53 /*
54  * Push a wide character back onto the input queue.
55  *
56  * XPG4 is silent as to whether wget_wch() and wgetch()
57  * can both be used in an applicaton.  Assume they can,
58  * in which case we have to push the multibyte equivalent
59  * back onto the input queue.
60  */
61 int
62 unget_wch(const wchar_t wc)
63 {
64 	int	i, len;
65 	char	mb[MB_LEN_MAX];
66 
67 	if (!iqIsEmpty() || (len = wctomb(mb, wc)) < 0)
68 		return (ERR);
69 
70 	for (i = 0; i < len; ++i) {
71 		iqAdd((unsigned char)mb[i]);
72 	}
73 
74 	return (OK);
75 }
76 
77 int
78 wget_wch(WINDOW *w, wint_t *wcp)
79 {
80 	cchar_t	cc;
81 	int	ch, oecho;
82 	t_wide_io	*wio;
83 
84 
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 	/*
94 	 * Input function is wgetch(), which takes a WINDOW * for
95 	 * a parameter.  The WINDOW * is used to set the "focus" by
96 	 * updatng and position the cursor in the relevant window and
97 	 * provide window specific settings.  Input for all windows
98 	 * comes from one stream (__m_screen->_if), which is normally
99 	 * the terminal, but can be redirected.
100 	 */
101 	wio = (t_wide_io *) __m_screen->_in;
102 	wio->object = w;
103 
104 	/* Get the first byte or KEY_ value. */
105 	if ((ch = wgetch(w)) == ERR) {
106 		(void) __m_set_echo(oecho);
107 		return (ERR);
108 	}
109 	if (ch < __KEY_BASE) {
110 		(void) __m_set_echo(oecho);
111 		if (oecho) {
112 			(void) beep();
113 			return (ERR);
114 		} else {
115 			*wcp = ch;
116 			return (KEY_CODE_YES);
117 		}
118 	}
119 
120 	/*
121 	 * Push the byte back onto the input stream so that
122 	 * it can be processed by __m_wio_get().
123 	 */
124 	iqPush(ch);
125 
126 	/*
127 	 * Fetch a wide character from a narrow input stream.
128 	 * Invalid sequences are preserved as individual bytes.
129 	 * Handles insignificant and redundant shifts in the input
130 	 * stream.
131 	 */
132 	*wcp = m_wio_get(wio);
133 
134 	/* Restore echo. */
135 	(void) __m_set_echo(oecho);
136 
137 	/*
138 	 * Push any invalid multibyte sequence back onto the
139 	 * input stack, so that no data is lost, just in case
140 	 * the application mixes wide (wget_wch()) and narrow
141 	 * (wgetch()) input methods.
142 	 */
143 	while (wio->_next < wio->_size)
144 		iqPush(wio->_mb[--wio->_size]);
145 
146 	/* Now echo wide character if necessary. */
147 	if ((__m_screen->_flags & S_ECHO) && *wcp != WEOF) {
148 		if (*wcp == L'\b') {
149 			if (w->_curx <= 0) {
150 				(void) beep();
151 				return (ch);
152 			}
153 			w->_curx--;
154 			(void) wdelch(w);
155 		} else {
156 			(void) __m_wc_cc(*wcp, &cc);
157 			(void) wadd_wch(w, &cc);
158 		}
159 		(void) wrefresh(w);
160 	}
161 
162 	return (OK);
163 }
164