1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate *
4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate * with the License.
8*7c478bd9Sstevel@tonic-gate *
9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate *
14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate *
20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate */
26*7c478bd9Sstevel@tonic-gate
27*7c478bd9Sstevel@tonic-gate /*
28*7c478bd9Sstevel@tonic-gate * m_cc.c
29*7c478bd9Sstevel@tonic-gate *
30*7c478bd9Sstevel@tonic-gate * XCurses Library
31*7c478bd9Sstevel@tonic-gate *
32*7c478bd9Sstevel@tonic-gate * Copyright 1990, 1995 by Mortice Kern Systems Inc. All rights reserved.
33*7c478bd9Sstevel@tonic-gate *
34*7c478bd9Sstevel@tonic-gate */
35*7c478bd9Sstevel@tonic-gate
36*7c478bd9Sstevel@tonic-gate #if M_RCSID
37*7c478bd9Sstevel@tonic-gate #ifndef lint
38*7c478bd9Sstevel@tonic-gate static char rcsID[] = "$Header: /rd/src/libc/xcurses/rcs/m_cc.c 1.8 1995/09/20 15:26:52 ant Exp $";
39*7c478bd9Sstevel@tonic-gate #endif
40*7c478bd9Sstevel@tonic-gate #endif
41*7c478bd9Sstevel@tonic-gate
42*7c478bd9Sstevel@tonic-gate #include <private.h>
43*7c478bd9Sstevel@tonic-gate #include <errno.h>
44*7c478bd9Sstevel@tonic-gate #include <limits.h>
45*7c478bd9Sstevel@tonic-gate #include <string.h>
46*7c478bd9Sstevel@tonic-gate #include <m_wio.h>
47*7c478bd9Sstevel@tonic-gate
48*7c478bd9Sstevel@tonic-gate typedef struct {
49*7c478bd9Sstevel@tonic-gate int max;
50*7c478bd9Sstevel@tonic-gate int used;
51*7c478bd9Sstevel@tonic-gate char *mbs;
52*7c478bd9Sstevel@tonic-gate } t_string;
53*7c478bd9Sstevel@tonic-gate
54*7c478bd9Sstevel@tonic-gate static int
write_string(byte,sp)55*7c478bd9Sstevel@tonic-gate write_string(byte, sp)
56*7c478bd9Sstevel@tonic-gate int byte;
57*7c478bd9Sstevel@tonic-gate t_string *sp;
58*7c478bd9Sstevel@tonic-gate {
59*7c478bd9Sstevel@tonic-gate if (sp->max <= sp->used)
60*7c478bd9Sstevel@tonic-gate return EOF;
61*7c478bd9Sstevel@tonic-gate
62*7c478bd9Sstevel@tonic-gate sp->mbs[sp->used++] = byte;
63*7c478bd9Sstevel@tonic-gate
64*7c478bd9Sstevel@tonic-gate return byte;
65*7c478bd9Sstevel@tonic-gate }
66*7c478bd9Sstevel@tonic-gate
67*7c478bd9Sstevel@tonic-gate /*
68*7c478bd9Sstevel@tonic-gate * Convert a wint_t string into a multibyte string.
69*7c478bd9Sstevel@tonic-gate *
70*7c478bd9Sstevel@tonic-gate * The conversion stops at the end of string or the first WEOF.
71*7c478bd9Sstevel@tonic-gate * Return the number of bytes successfully placed into mbs.
72*7c478bd9Sstevel@tonic-gate */
73*7c478bd9Sstevel@tonic-gate int
wistombs(mbs,wis,n)74*7c478bd9Sstevel@tonic-gate wistombs(mbs, wis, n)
75*7c478bd9Sstevel@tonic-gate char *mbs;
76*7c478bd9Sstevel@tonic-gate const wint_t *wis;
77*7c478bd9Sstevel@tonic-gate int n;
78*7c478bd9Sstevel@tonic-gate {
79*7c478bd9Sstevel@tonic-gate int last;
80*7c478bd9Sstevel@tonic-gate t_string string = { 0 };
81*7c478bd9Sstevel@tonic-gate t_wide_io convert = { 0 };
82*7c478bd9Sstevel@tonic-gate
83*7c478bd9Sstevel@tonic-gate string.max = n;
84*7c478bd9Sstevel@tonic-gate string.mbs = mbs;
85*7c478bd9Sstevel@tonic-gate convert.object = (void *) &string;
86*7c478bd9Sstevel@tonic-gate convert.put = (int (*)(int, void *)) write_string;
87*7c478bd9Sstevel@tonic-gate
88*7c478bd9Sstevel@tonic-gate for (;; ++wis) {
89*7c478bd9Sstevel@tonic-gate /* In case of error, rewind string to the last character. */
90*7c478bd9Sstevel@tonic-gate last = string.used;
91*7c478bd9Sstevel@tonic-gate
92*7c478bd9Sstevel@tonic-gate if (m_wio_put(*wis, &convert) < 0) {
93*7c478bd9Sstevel@tonic-gate string.used = last;
94*7c478bd9Sstevel@tonic-gate break;
95*7c478bd9Sstevel@tonic-gate }
96*7c478bd9Sstevel@tonic-gate
97*7c478bd9Sstevel@tonic-gate /* Test for end of string AFTER trying to copy into the
98*7c478bd9Sstevel@tonic-gate * buffer, because m_wio_put() has to handle state changes
99*7c478bd9Sstevel@tonic-gate * back to the initial state on '\0' or WEOF.
100*7c478bd9Sstevel@tonic-gate */
101*7c478bd9Sstevel@tonic-gate if (*wis == '\0' || *wis == WEOF)
102*7c478bd9Sstevel@tonic-gate break;
103*7c478bd9Sstevel@tonic-gate }
104*7c478bd9Sstevel@tonic-gate
105*7c478bd9Sstevel@tonic-gate /* m_wio_put() does not write '\0', because the "stream"
106*7c478bd9Sstevel@tonic-gate * object is considered to be in "text" mode, which in the
107*7c478bd9Sstevel@tonic-gate * case of file I/O produces undefined results for systems
108*7c478bd9Sstevel@tonic-gate * using locking-shift character sets.
109*7c478bd9Sstevel@tonic-gate */
110*7c478bd9Sstevel@tonic-gate string.mbs[string.used] = '\0';
111*7c478bd9Sstevel@tonic-gate
112*7c478bd9Sstevel@tonic-gate return string.used;
113*7c478bd9Sstevel@tonic-gate }
114*7c478bd9Sstevel@tonic-gate
115*7c478bd9Sstevel@tonic-gate /*
116*7c478bd9Sstevel@tonic-gate * Convert a wint_t string (filled in by wgetn_wstr()) to a wchar_t string.
117*7c478bd9Sstevel@tonic-gate * The conversion stops at the end of string or the first WEOF. Return the
118*7c478bd9Sstevel@tonic-gate * number of successfully copied characters.
119*7c478bd9Sstevel@tonic-gate *
120*7c478bd9Sstevel@tonic-gate * This routinue should be used when sizeof (wchar_t) < sizeof (wint_t).
121*7c478bd9Sstevel@tonic-gate */
122*7c478bd9Sstevel@tonic-gate int
wistowcs(wcs,wis,n)123*7c478bd9Sstevel@tonic-gate wistowcs(wcs, wis, n)
124*7c478bd9Sstevel@tonic-gate wchar_t *wcs;
125*7c478bd9Sstevel@tonic-gate const wint_t *wis;
126*7c478bd9Sstevel@tonic-gate int n;
127*7c478bd9Sstevel@tonic-gate {
128*7c478bd9Sstevel@tonic-gate wchar_t *start;
129*7c478bd9Sstevel@tonic-gate
130*7c478bd9Sstevel@tonic-gate if (n < 0)
131*7c478bd9Sstevel@tonic-gate n = INT_MAX;
132*7c478bd9Sstevel@tonic-gate
133*7c478bd9Sstevel@tonic-gate for (start = wcs; *wis != '\0' && 0 < n; ++wis, ++wcs, --n) {
134*7c478bd9Sstevel@tonic-gate if (*wis == WEOF)
135*7c478bd9Sstevel@tonic-gate break;
136*7c478bd9Sstevel@tonic-gate *wcs = (wchar_t) *wis;
137*7c478bd9Sstevel@tonic-gate }
138*7c478bd9Sstevel@tonic-gate *wcs = '\0';
139*7c478bd9Sstevel@tonic-gate
140*7c478bd9Sstevel@tonic-gate return (int) (wcs - start);
141*7c478bd9Sstevel@tonic-gate }
142*7c478bd9Sstevel@tonic-gate
143*7c478bd9Sstevel@tonic-gate /*
144*7c478bd9Sstevel@tonic-gate * Convert a chtype to a cchar_t.
145*7c478bd9Sstevel@tonic-gate */
146*7c478bd9Sstevel@tonic-gate int
__m_chtype_cc(ch,cc)147*7c478bd9Sstevel@tonic-gate __m_chtype_cc(ch, cc)
148*7c478bd9Sstevel@tonic-gate chtype ch;
149*7c478bd9Sstevel@tonic-gate cchar_t *cc;
150*7c478bd9Sstevel@tonic-gate {
151*7c478bd9Sstevel@tonic-gate char mb;
152*7c478bd9Sstevel@tonic-gate
153*7c478bd9Sstevel@tonic-gate cc->_f = 1;
154*7c478bd9Sstevel@tonic-gate cc->_n = 1;
155*7c478bd9Sstevel@tonic-gate mb = (char)(ch & A_CHARTEXT);
156*7c478bd9Sstevel@tonic-gate
157*7c478bd9Sstevel@tonic-gate if (mbtowc(cc->_wc, &mb, 1) < 0)
158*7c478bd9Sstevel@tonic-gate return ERR;
159*7c478bd9Sstevel@tonic-gate
160*7c478bd9Sstevel@tonic-gate cc->_co = (short) PAIR_NUMBER(ch);
161*7c478bd9Sstevel@tonic-gate cc->_at = (attr_t) ((ch & (A_ATTRIBUTES & ~A_COLOR)) >> 16);
162*7c478bd9Sstevel@tonic-gate
163*7c478bd9Sstevel@tonic-gate return OK;
164*7c478bd9Sstevel@tonic-gate }
165*7c478bd9Sstevel@tonic-gate
166*7c478bd9Sstevel@tonic-gate /*
167*7c478bd9Sstevel@tonic-gate * Return a complex character as a chtype.
168*7c478bd9Sstevel@tonic-gate */
169*7c478bd9Sstevel@tonic-gate chtype
__m_cc_chtype(cc)170*7c478bd9Sstevel@tonic-gate __m_cc_chtype(cc)
171*7c478bd9Sstevel@tonic-gate const cchar_t *cc;
172*7c478bd9Sstevel@tonic-gate {
173*7c478bd9Sstevel@tonic-gate chtype ch;
174*7c478bd9Sstevel@tonic-gate unsigned char mb[MB_LEN_MAX];
175*7c478bd9Sstevel@tonic-gate
176*7c478bd9Sstevel@tonic-gate /* Is it a single-byte character? */
177*7c478bd9Sstevel@tonic-gate if (cc->_n != 1 || wctomb((char *) mb, cc->_wc[0]) != 1)
178*7c478bd9Sstevel@tonic-gate return (chtype) ERR;
179*7c478bd9Sstevel@tonic-gate
180*7c478bd9Sstevel@tonic-gate ch = ((chtype) cc->_at << 16) & ~A_COLOR;
181*7c478bd9Sstevel@tonic-gate ch |= COLOR_PAIR(cc->_co) | mb[0];
182*7c478bd9Sstevel@tonic-gate
183*7c478bd9Sstevel@tonic-gate return ch;
184*7c478bd9Sstevel@tonic-gate }
185*7c478bd9Sstevel@tonic-gate
186*7c478bd9Sstevel@tonic-gate /*
187*7c478bd9Sstevel@tonic-gate * Convert a complex character's "character" into a multibyte string.
188*7c478bd9Sstevel@tonic-gate * The attribute and colour are ignored.
189*7c478bd9Sstevel@tonic-gate *
190*7c478bd9Sstevel@tonic-gate * If 0 < n, set a new multibyte string and convert the first character,
191*7c478bd9Sstevel@tonic-gate * returning either -1 on error or the number of bytes used to convert the
192*7c478bd9Sstevel@tonic-gate * character.
193*7c478bd9Sstevel@tonic-gate *
194*7c478bd9Sstevel@tonic-gate * If n == 0, continue appending to the current multibyte string and return
195*7c478bd9Sstevel@tonic-gate * a value as for 0 < n case.
196*7c478bd9Sstevel@tonic-gate *
197*7c478bd9Sstevel@tonic-gate * If n < 0, return the accumulated byte length of the current multibyte
198*7c478bd9Sstevel@tonic-gate * string and do nothing else.
199*7c478bd9Sstevel@tonic-gate *
200*7c478bd9Sstevel@tonic-gate * When converting a character, a null cchar_t pointer will force the initial
201*7c478bd9Sstevel@tonic-gate * shift state and append a '\0' to the multibyte string. The return value
202*7c478bd9Sstevel@tonic-gate * will instead by the number of bytes used to shift to the initial state,
203*7c478bd9Sstevel@tonic-gate * and exclude the '\0'.
204*7c478bd9Sstevel@tonic-gate */
205*7c478bd9Sstevel@tonic-gate int
__m_cc_mbs(cc,mbs,n)206*7c478bd9Sstevel@tonic-gate __m_cc_mbs(cc, mbs, n)
207*7c478bd9Sstevel@tonic-gate const cchar_t *cc;
208*7c478bd9Sstevel@tonic-gate char *mbs;
209*7c478bd9Sstevel@tonic-gate int n;
210*7c478bd9Sstevel@tonic-gate {
211*7c478bd9Sstevel@tonic-gate cchar_t *cp;
212*7c478bd9Sstevel@tonic-gate int i, bytes, count, last;
213*7c478bd9Sstevel@tonic-gate mbstate_t initial = { 0 };
214*7c478bd9Sstevel@tonic-gate static t_string string = { 0 };
215*7c478bd9Sstevel@tonic-gate static t_wide_io convert = { 0 };
216*7c478bd9Sstevel@tonic-gate
217*7c478bd9Sstevel@tonic-gate if (n < 0) {
218*7c478bd9Sstevel@tonic-gate /* Return total number of bytes written to multibyte string. */
219*7c478bd9Sstevel@tonic-gate return string.used;
220*7c478bd9Sstevel@tonic-gate } else if (0 < n) {
221*7c478bd9Sstevel@tonic-gate /* Start a new conversion. */
222*7c478bd9Sstevel@tonic-gate string.max = n;
223*7c478bd9Sstevel@tonic-gate string.used = 0;
224*7c478bd9Sstevel@tonic-gate string.mbs = mbs;
225*7c478bd9Sstevel@tonic-gate
226*7c478bd9Sstevel@tonic-gate convert._state = initial;
227*7c478bd9Sstevel@tonic-gate convert._next = convert._size = 0;
228*7c478bd9Sstevel@tonic-gate convert.object = (void *) &string;
229*7c478bd9Sstevel@tonic-gate convert.put = (int (*)(int, void *)) write_string;
230*7c478bd9Sstevel@tonic-gate } /* else n == 0, continue appending to previous mbs. */
231*7c478bd9Sstevel@tonic-gate
232*7c478bd9Sstevel@tonic-gate /* In case of error, rewind string to the last character. */
233*7c478bd9Sstevel@tonic-gate last = string.used;
234*7c478bd9Sstevel@tonic-gate
235*7c478bd9Sstevel@tonic-gate if (cc == (cchar_t *) 0) {
236*7c478bd9Sstevel@tonic-gate /* Force initial shift state. */
237*7c478bd9Sstevel@tonic-gate if ((count = m_wio_put('\0', &convert)) < 0) {
238*7c478bd9Sstevel@tonic-gate string.used = last;
239*7c478bd9Sstevel@tonic-gate return -1;
240*7c478bd9Sstevel@tonic-gate }
241*7c478bd9Sstevel@tonic-gate
242*7c478bd9Sstevel@tonic-gate if (string.used < string.max)
243*7c478bd9Sstevel@tonic-gate string.mbs[string.used++] = '\0';
244*7c478bd9Sstevel@tonic-gate } else {
245*7c478bd9Sstevel@tonic-gate for (count = i = 0; i < cc->_n; ++i, count += bytes)
246*7c478bd9Sstevel@tonic-gate if ((bytes = m_wio_put(cc->_wc[i], &convert)) < 0) {
247*7c478bd9Sstevel@tonic-gate string.used = last;
248*7c478bd9Sstevel@tonic-gate return -1;
249*7c478bd9Sstevel@tonic-gate }
250*7c478bd9Sstevel@tonic-gate }
251*7c478bd9Sstevel@tonic-gate
252*7c478bd9Sstevel@tonic-gate return count;
253*7c478bd9Sstevel@tonic-gate }
254*7c478bd9Sstevel@tonic-gate
255*7c478bd9Sstevel@tonic-gate /*
256*7c478bd9Sstevel@tonic-gate * Convert a stty character into a wchar_t.
257*7c478bd9Sstevel@tonic-gate */
258*7c478bd9Sstevel@tonic-gate int
__m_tty_wc(index,wcp)259*7c478bd9Sstevel@tonic-gate __m_tty_wc(index, wcp)
260*7c478bd9Sstevel@tonic-gate int index;
261*7c478bd9Sstevel@tonic-gate wchar_t *wcp;
262*7c478bd9Sstevel@tonic-gate {
263*7c478bd9Sstevel@tonic-gate char mb;
264*7c478bd9Sstevel@tonic-gate int code;
265*7c478bd9Sstevel@tonic-gate
266*7c478bd9Sstevel@tonic-gate /* Refer to _shell instead of _prog, since _shell will
267*7c478bd9Sstevel@tonic-gate * correctly reflect the user's prefered settings, whereas
268*7c478bd9Sstevel@tonic-gate * _prog may not have been initialised if both input and
269*7c478bd9Sstevel@tonic-gate * output have been redirected.
270*7c478bd9Sstevel@tonic-gate */
271*7c478bd9Sstevel@tonic-gate mb = cur_term->_shell.c_cc[index];
272*7c478bd9Sstevel@tonic-gate code = mbtowc(wcp, &mb, 1) < 0 ? ERR : OK;
273*7c478bd9Sstevel@tonic-gate
274*7c478bd9Sstevel@tonic-gate return code;
275*7c478bd9Sstevel@tonic-gate }
276*7c478bd9Sstevel@tonic-gate
277*7c478bd9Sstevel@tonic-gate /*
278*7c478bd9Sstevel@tonic-gate * Build a cchar_t from the leading spacing and non-spacing characters
279*7c478bd9Sstevel@tonic-gate * in the multibyte character string. Only one spacing character is copied
280*7c478bd9Sstevel@tonic-gate * from the multibyte character string.
281*7c478bd9Sstevel@tonic-gate *
282*7c478bd9Sstevel@tonic-gate * Return the number of characters copied from the string, or -1 on error.
283*7c478bd9Sstevel@tonic-gate */
284*7c478bd9Sstevel@tonic-gate int
__m_mbs_cc(const char * mbs,attr_t at,short co,cchar_t * cc)285*7c478bd9Sstevel@tonic-gate __m_mbs_cc(const char *mbs, attr_t at, short co, cchar_t *cc)
286*7c478bd9Sstevel@tonic-gate {
287*7c478bd9Sstevel@tonic-gate wchar_t wc;
288*7c478bd9Sstevel@tonic-gate const char *start;
289*7c478bd9Sstevel@tonic-gate int i, nbytes, width, have_one;
290*7c478bd9Sstevel@tonic-gate
291*7c478bd9Sstevel@tonic-gate for (start = mbs, have_one = i = 0; *mbs != '\0'; mbs += nbytes, ++i) {
292*7c478bd9Sstevel@tonic-gate if (sizeof cc->_wc <= i)
293*7c478bd9Sstevel@tonic-gate /* Too many characters. */
294*7c478bd9Sstevel@tonic-gate return -1;
295*7c478bd9Sstevel@tonic-gate
296*7c478bd9Sstevel@tonic-gate if ((nbytes = mbtowc(&wc, mbs, UINT_MAX)) < 0)
297*7c478bd9Sstevel@tonic-gate /* Invalid multibyte sequence. */
298*7c478bd9Sstevel@tonic-gate return -1;
299*7c478bd9Sstevel@tonic-gate
300*7c478bd9Sstevel@tonic-gate if (nbytes == 0)
301*7c478bd9Sstevel@tonic-gate /* Remainder of string evaluates to the null byte. */
302*7c478bd9Sstevel@tonic-gate break;
303*7c478bd9Sstevel@tonic-gate
304*7c478bd9Sstevel@tonic-gate if (iscntrl(*mbs))
305*7c478bd9Sstevel@tonic-gate /* Treat control codes like a spacing character. */
306*7c478bd9Sstevel@tonic-gate width = 1;
307*7c478bd9Sstevel@tonic-gate else if ((width = wcwidth(wc)) < 0)
308*7c478bd9Sstevel@tonic-gate return -1;
309*7c478bd9Sstevel@tonic-gate
310*7c478bd9Sstevel@tonic-gate /* Do we have a spacing character? */
311*7c478bd9Sstevel@tonic-gate if (0 < width) {
312*7c478bd9Sstevel@tonic-gate if (have_one)
313*7c478bd9Sstevel@tonic-gate break;
314*7c478bd9Sstevel@tonic-gate have_one = 1;
315*7c478bd9Sstevel@tonic-gate }
316*7c478bd9Sstevel@tonic-gate
317*7c478bd9Sstevel@tonic-gate cc->_wc[i] = wc;
318*7c478bd9Sstevel@tonic-gate }
319*7c478bd9Sstevel@tonic-gate
320*7c478bd9Sstevel@tonic-gate cc->_f = 1;
321*7c478bd9Sstevel@tonic-gate cc->_n = i;
322*7c478bd9Sstevel@tonic-gate cc->_co = co;
323*7c478bd9Sstevel@tonic-gate cc->_at = at;
324*7c478bd9Sstevel@tonic-gate
325*7c478bd9Sstevel@tonic-gate (void) __m_cc_sort(cc);
326*7c478bd9Sstevel@tonic-gate
327*7c478bd9Sstevel@tonic-gate return (int) (mbs - start);
328*7c478bd9Sstevel@tonic-gate }
329*7c478bd9Sstevel@tonic-gate
330*7c478bd9Sstevel@tonic-gate /*
331*7c478bd9Sstevel@tonic-gate * Build a cchar_t from the leading spacing and non-spacing characters
332*7c478bd9Sstevel@tonic-gate * in the wide character string. Only one spacinig character is copied
333*7c478bd9Sstevel@tonic-gate * from the wide character string.
334*7c478bd9Sstevel@tonic-gate *
335*7c478bd9Sstevel@tonic-gate * Return the number of characters copied from the string, or -1 on error.
336*7c478bd9Sstevel@tonic-gate */
337*7c478bd9Sstevel@tonic-gate int
__m_wcs_cc(const wchar_t * wcs,attr_t at,short co,cchar_t * cc)338*7c478bd9Sstevel@tonic-gate __m_wcs_cc(const wchar_t *wcs, attr_t at, short co, cchar_t *cc)
339*7c478bd9Sstevel@tonic-gate {
340*7c478bd9Sstevel@tonic-gate short i;
341*7c478bd9Sstevel@tonic-gate int width, have_one;
342*7c478bd9Sstevel@tonic-gate const wchar_t *start;
343*7c478bd9Sstevel@tonic-gate
344*7c478bd9Sstevel@tonic-gate for (start = wcs, have_one = i = 0; *wcs != '\0'; ++wcs, ++i) {
345*7c478bd9Sstevel@tonic-gate if (sizeof cc->_wc <= i)
346*7c478bd9Sstevel@tonic-gate /* Too many characters. */
347*7c478bd9Sstevel@tonic-gate return -1;
348*7c478bd9Sstevel@tonic-gate
349*7c478bd9Sstevel@tonic-gate if ((width = wcwidth(*wcs)) < 0)
350*7c478bd9Sstevel@tonic-gate return -1;
351*7c478bd9Sstevel@tonic-gate
352*7c478bd9Sstevel@tonic-gate if (0 < width) {
353*7c478bd9Sstevel@tonic-gate if (have_one)
354*7c478bd9Sstevel@tonic-gate break;
355*7c478bd9Sstevel@tonic-gate have_one = 1;
356*7c478bd9Sstevel@tonic-gate }
357*7c478bd9Sstevel@tonic-gate
358*7c478bd9Sstevel@tonic-gate cc->_wc[i] = *wcs;
359*7c478bd9Sstevel@tonic-gate }
360*7c478bd9Sstevel@tonic-gate
361*7c478bd9Sstevel@tonic-gate cc->_f = 1;
362*7c478bd9Sstevel@tonic-gate cc->_n = i;
363*7c478bd9Sstevel@tonic-gate cc->_co = co;
364*7c478bd9Sstevel@tonic-gate cc->_at = at;
365*7c478bd9Sstevel@tonic-gate
366*7c478bd9Sstevel@tonic-gate (void) __m_cc_sort(cc);
367*7c478bd9Sstevel@tonic-gate
368*7c478bd9Sstevel@tonic-gate return (int) (wcs - start);
369*7c478bd9Sstevel@tonic-gate }
370*7c478bd9Sstevel@tonic-gate
371*7c478bd9Sstevel@tonic-gate /*
372*7c478bd9Sstevel@tonic-gate * Convert a single wide character into a complex character.
373*7c478bd9Sstevel@tonic-gate */
374*7c478bd9Sstevel@tonic-gate int
__m_wc_cc(wint_t wc,cchar_t * cc)375*7c478bd9Sstevel@tonic-gate __m_wc_cc(wint_t wc, cchar_t *cc)
376*7c478bd9Sstevel@tonic-gate {
377*7c478bd9Sstevel@tonic-gate wchar_t wcs[2];
378*7c478bd9Sstevel@tonic-gate
379*7c478bd9Sstevel@tonic-gate if (wc == WEOF)
380*7c478bd9Sstevel@tonic-gate return -1;
381*7c478bd9Sstevel@tonic-gate
382*7c478bd9Sstevel@tonic-gate wcs[0] = (wchar_t)wc;
383*7c478bd9Sstevel@tonic-gate wcs[1] = '\0';
384*7c478bd9Sstevel@tonic-gate (void) __m_wcs_cc(wcs, WA_NORMAL, 0, cc);
385*7c478bd9Sstevel@tonic-gate
386*7c478bd9Sstevel@tonic-gate return 0;
387*7c478bd9Sstevel@tonic-gate }
388*7c478bd9Sstevel@tonic-gate
389*7c478bd9Sstevel@tonic-gate /*
390*7c478bd9Sstevel@tonic-gate * Sort a complex character into a spacing character followed
391*7c478bd9Sstevel@tonic-gate * by any non-spacing characters in increasing order of oridinal
392*7c478bd9Sstevel@tonic-gate * values. This facilitates both comparision and writting of
393*7c478bd9Sstevel@tonic-gate * complex characters. More than one spacing character is
394*7c478bd9Sstevel@tonic-gate * considered an error.
395*7c478bd9Sstevel@tonic-gate *
396*7c478bd9Sstevel@tonic-gate * Return the spacing character's column width or -1 if more
397*7c478bd9Sstevel@tonic-gate * than one spacing character appears in cc.
398*7c478bd9Sstevel@tonic-gate */
399*7c478bd9Sstevel@tonic-gate int
__m_cc_sort(cc)400*7c478bd9Sstevel@tonic-gate __m_cc_sort(cc)
401*7c478bd9Sstevel@tonic-gate cchar_t *cc;
402*7c478bd9Sstevel@tonic-gate {
403*7c478bd9Sstevel@tonic-gate wchar_t wc;
404*7c478bd9Sstevel@tonic-gate int width, i, j, spacing;
405*7c478bd9Sstevel@tonic-gate
406*7c478bd9Sstevel@tonic-gate /* Find spacing character and place in as first element. */
407*7c478bd9Sstevel@tonic-gate for (width = spacing = i = 0; i < cc->_n; ++i) {
408*7c478bd9Sstevel@tonic-gate j = wcwidth(cc->_wc[i]);
409*7c478bd9Sstevel@tonic-gate if (0 < j) {
410*7c478bd9Sstevel@tonic-gate /* More than one spacing character is an error. */
411*7c478bd9Sstevel@tonic-gate if (0 < width)
412*7c478bd9Sstevel@tonic-gate return -1;
413*7c478bd9Sstevel@tonic-gate
414*7c478bd9Sstevel@tonic-gate wc = cc->_wc[0];
415*7c478bd9Sstevel@tonic-gate cc->_wc[0] = cc->_wc[i];
416*7c478bd9Sstevel@tonic-gate cc->_wc[i] = wc;
417*7c478bd9Sstevel@tonic-gate
418*7c478bd9Sstevel@tonic-gate spacing = 1;
419*7c478bd9Sstevel@tonic-gate width = j;
420*7c478bd9Sstevel@tonic-gate break;
421*7c478bd9Sstevel@tonic-gate }
422*7c478bd9Sstevel@tonic-gate }
423*7c478bd9Sstevel@tonic-gate
424*7c478bd9Sstevel@tonic-gate /* Bubble sort small array. */
425*7c478bd9Sstevel@tonic-gate for (i = spacing; i < cc->_n; ++i) {
426*7c478bd9Sstevel@tonic-gate for (j = cc->_n - 1; i < j; --j) {
427*7c478bd9Sstevel@tonic-gate if (cc->_wc[j-1] > cc->_wc[j]) {
428*7c478bd9Sstevel@tonic-gate wc = cc->_wc[j];
429*7c478bd9Sstevel@tonic-gate cc->_wc[j] = cc->_wc[j-1];
430*7c478bd9Sstevel@tonic-gate cc->_wc[j-1] = wc;
431*7c478bd9Sstevel@tonic-gate }
432*7c478bd9Sstevel@tonic-gate }
433*7c478bd9Sstevel@tonic-gate }
434*7c478bd9Sstevel@tonic-gate
435*7c478bd9Sstevel@tonic-gate return width;
436*7c478bd9Sstevel@tonic-gate }
437*7c478bd9Sstevel@tonic-gate
438*7c478bd9Sstevel@tonic-gate /*
439*7c478bd9Sstevel@tonic-gate * Return width inn screen columns of the character.
440*7c478bd9Sstevel@tonic-gate */
441*7c478bd9Sstevel@tonic-gate int
__m_cc_width(cc)442*7c478bd9Sstevel@tonic-gate __m_cc_width(cc)
443*7c478bd9Sstevel@tonic-gate const cchar_t *cc;
444*7c478bd9Sstevel@tonic-gate {
445*7c478bd9Sstevel@tonic-gate return wcwidth(cc->_wc[0]);
446*7c478bd9Sstevel@tonic-gate }
447*7c478bd9Sstevel@tonic-gate
448*7c478bd9Sstevel@tonic-gate /*
449*7c478bd9Sstevel@tonic-gate * Return the first column of a multi-column character, in window.
450*7c478bd9Sstevel@tonic-gate */
451*7c478bd9Sstevel@tonic-gate int
__m_cc_first(w,y,x)452*7c478bd9Sstevel@tonic-gate __m_cc_first(w, y, x)
453*7c478bd9Sstevel@tonic-gate WINDOW *w;
454*7c478bd9Sstevel@tonic-gate int y, x;
455*7c478bd9Sstevel@tonic-gate {
456*7c478bd9Sstevel@tonic-gate register cchar_t *lp;
457*7c478bd9Sstevel@tonic-gate
458*7c478bd9Sstevel@tonic-gate for (lp = w->_line[y]; 0 < x; --x) {
459*7c478bd9Sstevel@tonic-gate if (lp[x]._f)
460*7c478bd9Sstevel@tonic-gate break;
461*7c478bd9Sstevel@tonic-gate }
462*7c478bd9Sstevel@tonic-gate
463*7c478bd9Sstevel@tonic-gate return x;
464*7c478bd9Sstevel@tonic-gate }
465*7c478bd9Sstevel@tonic-gate
466*7c478bd9Sstevel@tonic-gate /*
467*7c478bd9Sstevel@tonic-gate * Return the start of the next multi-column character, in window.
468*7c478bd9Sstevel@tonic-gate */
469*7c478bd9Sstevel@tonic-gate int
__m_cc_next(w,y,x)470*7c478bd9Sstevel@tonic-gate __m_cc_next(w, y, x)
471*7c478bd9Sstevel@tonic-gate WINDOW *w;
472*7c478bd9Sstevel@tonic-gate int y, x;
473*7c478bd9Sstevel@tonic-gate {
474*7c478bd9Sstevel@tonic-gate cchar_t *lp;
475*7c478bd9Sstevel@tonic-gate
476*7c478bd9Sstevel@tonic-gate for (lp = w->_line[y]; ++x < w->_maxx; ) {
477*7c478bd9Sstevel@tonic-gate if (lp[x]._f)
478*7c478bd9Sstevel@tonic-gate break;
479*7c478bd9Sstevel@tonic-gate }
480*7c478bd9Sstevel@tonic-gate
481*7c478bd9Sstevel@tonic-gate return x;
482*7c478bd9Sstevel@tonic-gate }
483*7c478bd9Sstevel@tonic-gate
484*7c478bd9Sstevel@tonic-gate /*
485*7c478bd9Sstevel@tonic-gate * Return true if valid last column of a multi-column character.
486*7c478bd9Sstevel@tonic-gate */
487*7c478bd9Sstevel@tonic-gate int
__m_cc_islast(w,y,x)488*7c478bd9Sstevel@tonic-gate __m_cc_islast(w, y, x)
489*7c478bd9Sstevel@tonic-gate WINDOW *w;
490*7c478bd9Sstevel@tonic-gate int y, x;
491*7c478bd9Sstevel@tonic-gate {
492*7c478bd9Sstevel@tonic-gate int first, width;
493*7c478bd9Sstevel@tonic-gate
494*7c478bd9Sstevel@tonic-gate first = __m_cc_first(w, y, x);
495*7c478bd9Sstevel@tonic-gate width = __m_cc_width(&w->_line[y][x]);
496*7c478bd9Sstevel@tonic-gate
497*7c478bd9Sstevel@tonic-gate return first + width == x + 1;
498*7c478bd9Sstevel@tonic-gate }
499*7c478bd9Sstevel@tonic-gate
500*7c478bd9Sstevel@tonic-gate /*
501*7c478bd9Sstevel@tonic-gate * Replace the character at the current cursor location
502*7c478bd9Sstevel@tonic-gate * according to the column width of the character. The
503*7c478bd9Sstevel@tonic-gate * cursor does not advance.
504*7c478bd9Sstevel@tonic-gate *
505*7c478bd9Sstevel@tonic-gate * Return -1 if the character won't fit on the line and the background
506*7c478bd9Sstevel@tonic-gate * was written in its place; else return the width of the character in
507*7c478bd9Sstevel@tonic-gate * screen columns.
508*7c478bd9Sstevel@tonic-gate */
509*7c478bd9Sstevel@tonic-gate int
__m_cc_replace(w,y,x,cc,as_is)510*7c478bd9Sstevel@tonic-gate __m_cc_replace(w, y, x, cc, as_is)
511*7c478bd9Sstevel@tonic-gate WINDOW *w;
512*7c478bd9Sstevel@tonic-gate int y, x;
513*7c478bd9Sstevel@tonic-gate const cchar_t *cc;
514*7c478bd9Sstevel@tonic-gate int as_is;
515*7c478bd9Sstevel@tonic-gate {
516*7c478bd9Sstevel@tonic-gate int i, width;
517*7c478bd9Sstevel@tonic-gate cchar_t *cp, *np;
518*7c478bd9Sstevel@tonic-gate
519*7c478bd9Sstevel@tonic-gate width = __m_cc_width(cc);
520*7c478bd9Sstevel@tonic-gate
521*7c478bd9Sstevel@tonic-gate /* If we try to write a broad character that would exceed the
522*7c478bd9Sstevel@tonic-gate * right margin, then write the background character instead.
523*7c478bd9Sstevel@tonic-gate */
524*7c478bd9Sstevel@tonic-gate if (0 < width && w->_maxx < x + width) {
525*7c478bd9Sstevel@tonic-gate (void) __m_cc_erase(w, y, x, y, w->_maxx-1);
526*7c478bd9Sstevel@tonic-gate return -1;
527*7c478bd9Sstevel@tonic-gate }
528*7c478bd9Sstevel@tonic-gate
529*7c478bd9Sstevel@tonic-gate /* Erase the region to be occupied by the new character.
530*7c478bd9Sstevel@tonic-gate * __m_cc_erase() will erase whole characters so that
531*7c478bd9Sstevel@tonic-gate * writing a multicolumn character that overwrites the
532*7c478bd9Sstevel@tonic-gate * trailing and leading portions of two already existing
533*7c478bd9Sstevel@tonic-gate * multicolumn characters, erases the remaining portions.
534*7c478bd9Sstevel@tonic-gate */
535*7c478bd9Sstevel@tonic-gate (void) __m_cc_erase(w, y, x, y, x + width - 1);
536*7c478bd9Sstevel@tonic-gate
537*7c478bd9Sstevel@tonic-gate /* Write the first column of the character. */
538*7c478bd9Sstevel@tonic-gate cp = &w->_line[y][x++];
539*7c478bd9Sstevel@tonic-gate if (cc->_wc[0] == ' ' || cc->_wc[0] == M_MB_L(' ')) {
540*7c478bd9Sstevel@tonic-gate *cp = w->_bg;
541*7c478bd9Sstevel@tonic-gate cp->_at |= cc->_at;
542*7c478bd9Sstevel@tonic-gate if (cc->_co != 0)
543*7c478bd9Sstevel@tonic-gate cp->_co = cc->_co;
544*7c478bd9Sstevel@tonic-gate } else {
545*7c478bd9Sstevel@tonic-gate (void) __m_wacs_cc(cc, cp);
546*7c478bd9Sstevel@tonic-gate if (cc->_co == 0)
547*7c478bd9Sstevel@tonic-gate cp->_co = w->_fg._co;
548*7c478bd9Sstevel@tonic-gate }
549*7c478bd9Sstevel@tonic-gate
550*7c478bd9Sstevel@tonic-gate cp->_at |= w->_fg._at | w->_bg._at;
551*7c478bd9Sstevel@tonic-gate
552*7c478bd9Sstevel@tonic-gate /* Mark this as the first column of the character. */
553*7c478bd9Sstevel@tonic-gate cp->_f = 1;
554*7c478bd9Sstevel@tonic-gate
555*7c478bd9Sstevel@tonic-gate /* Duplicate the character in every column the character occupies. */
556*7c478bd9Sstevel@tonic-gate for (np = cp + 1, i = 1; i < width; ++i, ++x, ++np) {
557*7c478bd9Sstevel@tonic-gate *np = *cp;
558*7c478bd9Sstevel@tonic-gate np->_f = 0;
559*7c478bd9Sstevel@tonic-gate }
560*7c478bd9Sstevel@tonic-gate
561*7c478bd9Sstevel@tonic-gate return width;
562*7c478bd9Sstevel@tonic-gate }
563*7c478bd9Sstevel@tonic-gate
564*7c478bd9Sstevel@tonic-gate int
__m_do_scroll(WINDOW * w,int y,int x,int * yp,int * xp)565*7c478bd9Sstevel@tonic-gate __m_do_scroll(WINDOW *w, int y, int x, int *yp, int *xp)
566*7c478bd9Sstevel@tonic-gate {
567*7c478bd9Sstevel@tonic-gate if (w->_maxx <= x)
568*7c478bd9Sstevel@tonic-gate x = w->_maxx-1;
569*7c478bd9Sstevel@tonic-gate
570*7c478bd9Sstevel@tonic-gate ++y;
571*7c478bd9Sstevel@tonic-gate
572*7c478bd9Sstevel@tonic-gate if (y == w->_bottom) {
573*7c478bd9Sstevel@tonic-gate --y;
574*7c478bd9Sstevel@tonic-gate if (w->_flags & W_CAN_SCROLL) {
575*7c478bd9Sstevel@tonic-gate if (wscrl(w, 1) == ERR)
576*7c478bd9Sstevel@tonic-gate return ERR;
577*7c478bd9Sstevel@tonic-gate x = 0;
578*7c478bd9Sstevel@tonic-gate }
579*7c478bd9Sstevel@tonic-gate } else if (w->_maxy <= y) {
580*7c478bd9Sstevel@tonic-gate y = w->_maxy-1;
581*7c478bd9Sstevel@tonic-gate } else {
582*7c478bd9Sstevel@tonic-gate /* The cursor wraps for any line (in and out of the scroll
583*7c478bd9Sstevel@tonic-gate * region) except for the last line of the scroll region.
584*7c478bd9Sstevel@tonic-gate */
585*7c478bd9Sstevel@tonic-gate x = 0;
586*7c478bd9Sstevel@tonic-gate }
587*7c478bd9Sstevel@tonic-gate
588*7c478bd9Sstevel@tonic-gate *yp = y;
589*7c478bd9Sstevel@tonic-gate *xp = x;
590*7c478bd9Sstevel@tonic-gate
591*7c478bd9Sstevel@tonic-gate return OK;
592*7c478bd9Sstevel@tonic-gate }
593*7c478bd9Sstevel@tonic-gate
594*7c478bd9Sstevel@tonic-gate /*
595*7c478bd9Sstevel@tonic-gate * Add the character at the current cursor location
596*7c478bd9Sstevel@tonic-gate * according to the column width of the character.
597*7c478bd9Sstevel@tonic-gate * The cursor will be advanced.
598*7c478bd9Sstevel@tonic-gate *
599*7c478bd9Sstevel@tonic-gate * Return ERR if adding the character causes the
600*7c478bd9Sstevel@tonic-gate * screen to scroll, when it is disallowed.
601*7c478bd9Sstevel@tonic-gate */
602*7c478bd9Sstevel@tonic-gate int
__m_cc_add(w,y,x,cc,as_is,yp,xp)603*7c478bd9Sstevel@tonic-gate __m_cc_add(w, y, x, cc, as_is, yp, xp)
604*7c478bd9Sstevel@tonic-gate WINDOW *w;
605*7c478bd9Sstevel@tonic-gate int y, x;
606*7c478bd9Sstevel@tonic-gate const cchar_t *cc;
607*7c478bd9Sstevel@tonic-gate int as_is, *yp, *xp;
608*7c478bd9Sstevel@tonic-gate {
609*7c478bd9Sstevel@tonic-gate int nx, width, code = ERR;
610*7c478bd9Sstevel@tonic-gate
611*7c478bd9Sstevel@tonic-gate #ifdef M_CURSES_TRACE
612*7c478bd9Sstevel@tonic-gate __m_trace(
613*7c478bd9Sstevel@tonic-gate "__m_cc_add(%p, %d, %d, %p, %d, %p, %p)",
614*7c478bd9Sstevel@tonic-gate w, y, x, cc, as_is, yp, xp
615*7c478bd9Sstevel@tonic-gate );
616*7c478bd9Sstevel@tonic-gate #endif
617*7c478bd9Sstevel@tonic-gate
618*7c478bd9Sstevel@tonic-gate switch (cc->_wc[0]) {
619*7c478bd9Sstevel@tonic-gate case '\t':
620*7c478bd9Sstevel@tonic-gate nx = x + (8 - (x & 07));
621*7c478bd9Sstevel@tonic-gate if (__m_cc_erase(w, y, x, y, nx-1) == -1)
622*7c478bd9Sstevel@tonic-gate goto error;
623*7c478bd9Sstevel@tonic-gate x = nx;
624*7c478bd9Sstevel@tonic-gate
625*7c478bd9Sstevel@tonic-gate if (w->_maxx <= x) {
626*7c478bd9Sstevel@tonic-gate if (__m_do_scroll(w, y, x, &y, &x) == ERR)
627*7c478bd9Sstevel@tonic-gate goto error;
628*7c478bd9Sstevel@tonic-gate }
629*7c478bd9Sstevel@tonic-gate break;
630*7c478bd9Sstevel@tonic-gate case '\n':
631*7c478bd9Sstevel@tonic-gate if (__m_cc_erase(w, y, x, y, w->_maxx-1) == -1)
632*7c478bd9Sstevel@tonic-gate goto error;
633*7c478bd9Sstevel@tonic-gate
634*7c478bd9Sstevel@tonic-gate if (__m_do_scroll(w, y, x, &y, &x) == ERR)
635*7c478bd9Sstevel@tonic-gate goto error;
636*7c478bd9Sstevel@tonic-gate break;
637*7c478bd9Sstevel@tonic-gate case '\r':
638*7c478bd9Sstevel@tonic-gate x = 0;
639*7c478bd9Sstevel@tonic-gate break;
640*7c478bd9Sstevel@tonic-gate case '\b':
641*7c478bd9Sstevel@tonic-gate if (0 < x)
642*7c478bd9Sstevel@tonic-gate --x;
643*7c478bd9Sstevel@tonic-gate break;
644*7c478bd9Sstevel@tonic-gate default:
645*7c478bd9Sstevel@tonic-gate width = __m_cc_replace(w, y, x, cc, as_is);
646*7c478bd9Sstevel@tonic-gate
647*7c478bd9Sstevel@tonic-gate x += width;
648*7c478bd9Sstevel@tonic-gate
649*7c478bd9Sstevel@tonic-gate if (width < 0 || w->_maxx <= x) {
650*7c478bd9Sstevel@tonic-gate if (__m_do_scroll(w, y, x, &y, &x) == ERR)
651*7c478bd9Sstevel@tonic-gate goto error;
652*7c478bd9Sstevel@tonic-gate
653*7c478bd9Sstevel@tonic-gate if (width < 0)
654*7c478bd9Sstevel@tonic-gate x += __m_cc_replace(w, y, x, cc, as_is);
655*7c478bd9Sstevel@tonic-gate }
656*7c478bd9Sstevel@tonic-gate }
657*7c478bd9Sstevel@tonic-gate
658*7c478bd9Sstevel@tonic-gate code = OK;
659*7c478bd9Sstevel@tonic-gate error:
660*7c478bd9Sstevel@tonic-gate *yp = y;
661*7c478bd9Sstevel@tonic-gate *xp = x;
662*7c478bd9Sstevel@tonic-gate
663*7c478bd9Sstevel@tonic-gate return __m_return_code("__m_cc_add", code);
664*7c478bd9Sstevel@tonic-gate }
665*7c478bd9Sstevel@tonic-gate
666*7c478bd9Sstevel@tonic-gate /*
667*7c478bd9Sstevel@tonic-gate * Erase region from (y,x) to (ly, lx) inclusive. The
668*7c478bd9Sstevel@tonic-gate * region is extended left and right in the case where
669*7c478bd9Sstevel@tonic-gate * the portions of a multicolumn characters are erased.
670*7c478bd9Sstevel@tonic-gate *
671*7c478bd9Sstevel@tonic-gate * Return -1 if the region is not an integral multiple
672*7c478bd9Sstevel@tonic-gate * of the background character, else zero for success.
673*7c478bd9Sstevel@tonic-gate */
674*7c478bd9Sstevel@tonic-gate int
__m_cc_erase(w,y,x,ly,lx)675*7c478bd9Sstevel@tonic-gate __m_cc_erase(w, y, x, ly, lx)
676*7c478bd9Sstevel@tonic-gate WINDOW *w;
677*7c478bd9Sstevel@tonic-gate int y, x, ly, lx;
678*7c478bd9Sstevel@tonic-gate {
679*7c478bd9Sstevel@tonic-gate cchar_t *cp;
680*7c478bd9Sstevel@tonic-gate int i, width;
681*7c478bd9Sstevel@tonic-gate
682*7c478bd9Sstevel@tonic-gate if (ly < y)
683*7c478bd9Sstevel@tonic-gate return -1;
684*7c478bd9Sstevel@tonic-gate
685*7c478bd9Sstevel@tonic-gate if (w->_maxy <= ly)
686*7c478bd9Sstevel@tonic-gate ly = w->_maxy - 1;
687*7c478bd9Sstevel@tonic-gate if (w->_maxx <= lx)
688*7c478bd9Sstevel@tonic-gate lx = w->_maxx - 1;
689*7c478bd9Sstevel@tonic-gate
690*7c478bd9Sstevel@tonic-gate /* Erase from first whole character (inclusive) to next
691*7c478bd9Sstevel@tonic-gate * character (exclusive).
692*7c478bd9Sstevel@tonic-gate */
693*7c478bd9Sstevel@tonic-gate x = __m_cc_first(w, y, x);
694*7c478bd9Sstevel@tonic-gate lx = __m_cc_next(w, ly, lx) - 1;
695*7c478bd9Sstevel@tonic-gate
696*7c478bd9Sstevel@tonic-gate /* Is the region to blank out an integral width of the
697*7c478bd9Sstevel@tonic-gate * background character?
698*7c478bd9Sstevel@tonic-gate */
699*7c478bd9Sstevel@tonic-gate width = __m_cc_width(&w->_bg);
700*7c478bd9Sstevel@tonic-gate
701*7c478bd9Sstevel@tonic-gate if (y < ly && (lx + 1) % width != 0)
702*7c478bd9Sstevel@tonic-gate return -1;
703*7c478bd9Sstevel@tonic-gate if ((lx - x + 1) % width != 0)
704*7c478bd9Sstevel@tonic-gate return -1;
705*7c478bd9Sstevel@tonic-gate
706*7c478bd9Sstevel@tonic-gate for (; y < ly; ++y, x = 0) {
707*7c478bd9Sstevel@tonic-gate if (x < w->_first[y])
708*7c478bd9Sstevel@tonic-gate w->_first[y] = (short) x;
709*7c478bd9Sstevel@tonic-gate
710*7c478bd9Sstevel@tonic-gate for (cp = w->_line[y], i = 0; x < w->_maxx; ++x, ++i) {
711*7c478bd9Sstevel@tonic-gate cp[x] = w->_bg;
712*7c478bd9Sstevel@tonic-gate
713*7c478bd9Sstevel@tonic-gate /* The start of each new character will be set true
714*7c478bd9Sstevel@tonic-gate * while internal columns of the character will be
715*7c478bd9Sstevel@tonic-gate * reset to false.
716*7c478bd9Sstevel@tonic-gate */
717*7c478bd9Sstevel@tonic-gate cp[x]._f = (short) (i % width == 0);
718*7c478bd9Sstevel@tonic-gate }
719*7c478bd9Sstevel@tonic-gate
720*7c478bd9Sstevel@tonic-gate if (w->_last[y] < x)
721*7c478bd9Sstevel@tonic-gate w->_last[y] = (short) x;
722*7c478bd9Sstevel@tonic-gate }
723*7c478bd9Sstevel@tonic-gate
724*7c478bd9Sstevel@tonic-gate if (x < w->_first[y])
725*7c478bd9Sstevel@tonic-gate w->_first[y] = (short) x;
726*7c478bd9Sstevel@tonic-gate
727*7c478bd9Sstevel@tonic-gate for (cp = w->_line[y], i = 0; x <= lx; ++x, ++i) {
728*7c478bd9Sstevel@tonic-gate cp[x] = w->_bg;
729*7c478bd9Sstevel@tonic-gate
730*7c478bd9Sstevel@tonic-gate /* The start of each new character will be set true
731*7c478bd9Sstevel@tonic-gate * while internal columns of the character will be
732*7c478bd9Sstevel@tonic-gate * reset to false.
733*7c478bd9Sstevel@tonic-gate */
734*7c478bd9Sstevel@tonic-gate cp[x]._f = (short) (i % width == 0);
735*7c478bd9Sstevel@tonic-gate }
736*7c478bd9Sstevel@tonic-gate
737*7c478bd9Sstevel@tonic-gate if (w->_last[y] < x)
738*7c478bd9Sstevel@tonic-gate w->_last[y] = (short) x;
739*7c478bd9Sstevel@tonic-gate
740*7c478bd9Sstevel@tonic-gate return 0;
741*7c478bd9Sstevel@tonic-gate }
742*7c478bd9Sstevel@tonic-gate
743*7c478bd9Sstevel@tonic-gate /*
744*7c478bd9Sstevel@tonic-gate * Expand the character to the left or right of the given position.
745*7c478bd9Sstevel@tonic-gate * Return the value returned by __m_cc_replace().
746*7c478bd9Sstevel@tonic-gate */
747*7c478bd9Sstevel@tonic-gate int
__m_cc_expand(w,y,x,side)748*7c478bd9Sstevel@tonic-gate __m_cc_expand(w, y, x, side)
749*7c478bd9Sstevel@tonic-gate WINDOW *w;
750*7c478bd9Sstevel@tonic-gate int y, x, side;
751*7c478bd9Sstevel@tonic-gate {
752*7c478bd9Sstevel@tonic-gate cchar_t cc;
753*7c478bd9Sstevel@tonic-gate int dx, width;
754*7c478bd9Sstevel@tonic-gate
755*7c478bd9Sstevel@tonic-gate width = __m_cc_width(&w->_line[y][x]);
756*7c478bd9Sstevel@tonic-gate
757*7c478bd9Sstevel@tonic-gate if (side < 0)
758*7c478bd9Sstevel@tonic-gate dx = __m_cc_next(w, y, x) - width;
759*7c478bd9Sstevel@tonic-gate else if (0 < side)
760*7c478bd9Sstevel@tonic-gate dx = __m_cc_first(w, y, x);
761*7c478bd9Sstevel@tonic-gate else
762*7c478bd9Sstevel@tonic-gate return -1;
763*7c478bd9Sstevel@tonic-gate
764*7c478bd9Sstevel@tonic-gate /* __m_cc_replace() will erase the region containing
765*7c478bd9Sstevel@tonic-gate * the character we want to expand.
766*7c478bd9Sstevel@tonic-gate */
767*7c478bd9Sstevel@tonic-gate cc = w->_line[y][x];
768*7c478bd9Sstevel@tonic-gate
769*7c478bd9Sstevel@tonic-gate return __m_cc_replace(w, y, dx, &cc, 0);
770*7c478bd9Sstevel@tonic-gate }
771*7c478bd9Sstevel@tonic-gate
772*7c478bd9Sstevel@tonic-gate /*
773*7c478bd9Sstevel@tonic-gate * Return true if characters are equal.
774*7c478bd9Sstevel@tonic-gate *
775*7c478bd9Sstevel@tonic-gate * NOTE to guarantee correct results, make sure that both
776*7c478bd9Sstevel@tonic-gate * characters have been passed through __m_cc_sort().
777*7c478bd9Sstevel@tonic-gate */
778*7c478bd9Sstevel@tonic-gate int
__m_cc_compare(c1,c2,exact)779*7c478bd9Sstevel@tonic-gate __m_cc_compare(c1, c2, exact)
780*7c478bd9Sstevel@tonic-gate const cchar_t *c1, *c2;
781*7c478bd9Sstevel@tonic-gate int exact;
782*7c478bd9Sstevel@tonic-gate {
783*7c478bd9Sstevel@tonic-gate int i;
784*7c478bd9Sstevel@tonic-gate
785*7c478bd9Sstevel@tonic-gate if (exact && c1->_f != c2->_f)
786*7c478bd9Sstevel@tonic-gate return 0;
787*7c478bd9Sstevel@tonic-gate if (c1->_n != c2->_n)
788*7c478bd9Sstevel@tonic-gate return 0;
789*7c478bd9Sstevel@tonic-gate if ((c1->_at & ~WA_COOKIE) != (c2->_at & ~WA_COOKIE))
790*7c478bd9Sstevel@tonic-gate return 0;
791*7c478bd9Sstevel@tonic-gate if (c1->_co != c2->_co)
792*7c478bd9Sstevel@tonic-gate return 0;
793*7c478bd9Sstevel@tonic-gate
794*7c478bd9Sstevel@tonic-gate for (i = 0; i < c1->_n; ++i)
795*7c478bd9Sstevel@tonic-gate if (c1->_wc[i] != c2->_wc[i])
796*7c478bd9Sstevel@tonic-gate return 0;
797*7c478bd9Sstevel@tonic-gate
798*7c478bd9Sstevel@tonic-gate return 1;
799*7c478bd9Sstevel@tonic-gate }
800*7c478bd9Sstevel@tonic-gate
801*7c478bd9Sstevel@tonic-gate /*
802*7c478bd9Sstevel@tonic-gate * Write to the stream the character portion of a cchar_t.
803*7c478bd9Sstevel@tonic-gate */
804*7c478bd9Sstevel@tonic-gate int
__m_cc_write(cc)805*7c478bd9Sstevel@tonic-gate __m_cc_write(cc)
806*7c478bd9Sstevel@tonic-gate const cchar_t *cc;
807*7c478bd9Sstevel@tonic-gate {
808*7c478bd9Sstevel@tonic-gate size_t i, j;
809*7c478bd9Sstevel@tonic-gate char mb[MB_LEN_MAX];
810*7c478bd9Sstevel@tonic-gate
811*7c478bd9Sstevel@tonic-gate errno = 0;
812*7c478bd9Sstevel@tonic-gate for (i = 0; i < cc->_n; ++i) {
813*7c478bd9Sstevel@tonic-gate j = wcrtomb(mb, cc->_wc[i], &__m_screen->_state);
814*7c478bd9Sstevel@tonic-gate if (errno != 0)
815*7c478bd9Sstevel@tonic-gate return EOF;
816*7c478bd9Sstevel@tonic-gate if (fwrite(mb, sizeof *mb, j, __m_screen->_of) == 0)
817*7c478bd9Sstevel@tonic-gate return EOF;
818*7c478bd9Sstevel@tonic-gate }
819*7c478bd9Sstevel@tonic-gate
820*7c478bd9Sstevel@tonic-gate return 0;
821*7c478bd9Sstevel@tonic-gate }
822