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