17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*759f6fc9Srm  * Common Development and Distribution License (the "License").
6*759f6fc9Srm  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*759f6fc9Srm  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /* LINTLIBRARY */
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate /*
297c478bd9Sstevel@tonic-gate  * m_cc.c
307c478bd9Sstevel@tonic-gate  *
317c478bd9Sstevel@tonic-gate  * XCurses Library
327c478bd9Sstevel@tonic-gate  *
337c478bd9Sstevel@tonic-gate  * Copyright 1990, 1995 by Mortice Kern Systems Inc.  All rights reserved.
347c478bd9Sstevel@tonic-gate  *
357c478bd9Sstevel@tonic-gate  */
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate #if M_RCSID
387c478bd9Sstevel@tonic-gate #ifndef lint
397c478bd9Sstevel@tonic-gate static char rcsID[] =
407c478bd9Sstevel@tonic-gate "$Header: /team/ps/sun_xcurses/archive/local_changes/xcurses/src/lib/"
417c478bd9Sstevel@tonic-gate "libxcurses/src/libc/xcurses/rcs/m_cc.c 1.40 1998/06/12 12:45:39 "
427c478bd9Sstevel@tonic-gate "cbates Exp $";
437c478bd9Sstevel@tonic-gate #endif
447c478bd9Sstevel@tonic-gate #endif
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate #include <private.h>
477c478bd9Sstevel@tonic-gate #include <limits.h>
487c478bd9Sstevel@tonic-gate #include <m_wio.h>
497c478bd9Sstevel@tonic-gate #include <string.h>
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate typedef struct {
527c478bd9Sstevel@tonic-gate 	int	max;
537c478bd9Sstevel@tonic-gate 	int	used;
547c478bd9Sstevel@tonic-gate 	char	*mbs;
557c478bd9Sstevel@tonic-gate } t_string;
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate static int
write_string(int byte,t_string * sp)587c478bd9Sstevel@tonic-gate write_string(int byte, t_string *sp)
597c478bd9Sstevel@tonic-gate {
607c478bd9Sstevel@tonic-gate 	if (sp->max <= sp->used)
617c478bd9Sstevel@tonic-gate 		return (EOF);
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate 	sp->mbs[sp->used++] = (char)byte;
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate 	return (byte);
667c478bd9Sstevel@tonic-gate }
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate /*
697c478bd9Sstevel@tonic-gate  * Convert a wint_t string into a multibyte string.
707c478bd9Sstevel@tonic-gate  *
717c478bd9Sstevel@tonic-gate  * The conversion stops at the end of string or the first WEOF.
727c478bd9Sstevel@tonic-gate  * Return the number of bytes successfully placed into mbs.
737c478bd9Sstevel@tonic-gate  */
747c478bd9Sstevel@tonic-gate int
wistombs(char * mbs,const wint_t * wis,int n)757c478bd9Sstevel@tonic-gate wistombs(char *mbs, const wint_t *wis, int n)
767c478bd9Sstevel@tonic-gate {
777c478bd9Sstevel@tonic-gate 	int last;
787c478bd9Sstevel@tonic-gate 	t_string string = { 0 };
797c478bd9Sstevel@tonic-gate 	t_wide_io convert = { 0 };
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate 	string.max = n;
827c478bd9Sstevel@tonic-gate 	string.mbs = mbs;
837c478bd9Sstevel@tonic-gate 	convert.object = (void *) &string;
847c478bd9Sstevel@tonic-gate 	convert.put = (int (*)(int, void *)) write_string;
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate 	for (; ; ++wis) {
877c478bd9Sstevel@tonic-gate 		/* In case of error, rewind string to the last character. */
887c478bd9Sstevel@tonic-gate 		last = string.used;
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate 		if (m_wio_put(*wis, &convert) < 0) {
917c478bd9Sstevel@tonic-gate 			string.used = last;
927c478bd9Sstevel@tonic-gate 			break;
937c478bd9Sstevel@tonic-gate 		}
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate 		/*
967c478bd9Sstevel@tonic-gate 		 * Test for end of string AFTER trying to copy into the
977c478bd9Sstevel@tonic-gate 		 * buffer, because m_wio_put() has to handle state changes
987c478bd9Sstevel@tonic-gate 		 * back to the initial state on '\0' or WEOF.
997c478bd9Sstevel@tonic-gate 		 */
1007c478bd9Sstevel@tonic-gate 		if (*wis == '\0' || *wis == WEOF)
1017c478bd9Sstevel@tonic-gate 			break;
1027c478bd9Sstevel@tonic-gate 	}
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate 	/*
1057c478bd9Sstevel@tonic-gate 	 * m_wio_put() does not write '\0', because the "stream"
1067c478bd9Sstevel@tonic-gate 	 * object is considered to be in "text" mode, which in the
1077c478bd9Sstevel@tonic-gate 	 * case of file I/O produces undefined results for systems
1087c478bd9Sstevel@tonic-gate 	 * using locking-shift character sets.
1097c478bd9Sstevel@tonic-gate 	 */
1107c478bd9Sstevel@tonic-gate 	string.mbs[string.used] = '\0';
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate 	return (string.used);
1137c478bd9Sstevel@tonic-gate }
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate /*
1167c478bd9Sstevel@tonic-gate  * Convert a wint_t string (filled in by wgetn_wstr()) to a wchar_t string.
1177c478bd9Sstevel@tonic-gate  * The conversion stops at the end of string or the first WEOF.  Return the
1187c478bd9Sstevel@tonic-gate  * number of successfully copied characters.
1197c478bd9Sstevel@tonic-gate  *
1207c478bd9Sstevel@tonic-gate  * This routinue should be used when sizeof (wchar_t) < sizeof (wint_t).
1217c478bd9Sstevel@tonic-gate  */
1227c478bd9Sstevel@tonic-gate int
wistowcs(wchar_t * wcs,const wint_t * wis,int n)1237c478bd9Sstevel@tonic-gate wistowcs(wchar_t *wcs, const wint_t *wis, int n)
1247c478bd9Sstevel@tonic-gate {
1257c478bd9Sstevel@tonic-gate 	wchar_t	*start;
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate 	if (n < 0)
1287c478bd9Sstevel@tonic-gate 		n = INT_MAX;
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate 	for (start = wcs; *wis != '\0' && 0 < n; ++wis, ++wcs, --n) {
1317c478bd9Sstevel@tonic-gate 		if (*wis == WEOF)
1327c478bd9Sstevel@tonic-gate 			break;
1337c478bd9Sstevel@tonic-gate 		*wcs = (wchar_t)*wis;
1347c478bd9Sstevel@tonic-gate 	}
1357c478bd9Sstevel@tonic-gate 	*wcs = '\0';
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate 	/* (wcs - start) should be enough small to fit in "int" */
1387c478bd9Sstevel@tonic-gate 	return ((int)(wcs - start));
1397c478bd9Sstevel@tonic-gate }
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate void
__m_touch_locs(WINDOW * w,int row,int firstCol,int lastCol)1427c478bd9Sstevel@tonic-gate __m_touch_locs(WINDOW *w, int row, int firstCol, int lastCol)
1437c478bd9Sstevel@tonic-gate {
1447c478bd9Sstevel@tonic-gate 	if (w) {
1457c478bd9Sstevel@tonic-gate 		if (firstCol < w->_first[row])
1467c478bd9Sstevel@tonic-gate 			w->_first[row] = (short)firstCol;
1477c478bd9Sstevel@tonic-gate 		if (lastCol > w->_last[row])
1487c478bd9Sstevel@tonic-gate 			w->_last[row] = (short)lastCol;
1497c478bd9Sstevel@tonic-gate 	}
1507c478bd9Sstevel@tonic-gate }
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate /*
1537c478bd9Sstevel@tonic-gate  * Convert a chtype to a cchar_t.
1547c478bd9Sstevel@tonic-gate  */
1557c478bd9Sstevel@tonic-gate int
__m_chtype_cc(chtype ch,cchar_t * cc)1567c478bd9Sstevel@tonic-gate __m_chtype_cc(chtype ch, cchar_t *cc)
1577c478bd9Sstevel@tonic-gate {
1587c478bd9Sstevel@tonic-gate 	char	mb;
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate 	cc->_f = 1;
1617c478bd9Sstevel@tonic-gate 	cc->_n = 1;
1627c478bd9Sstevel@tonic-gate 	mb = (char)(ch & A_CHARTEXT);
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 	cc->_co = (short)PAIR_NUMBER((int)ch);
1657c478bd9Sstevel@tonic-gate 	cc->_at = (attr_t)((ch & (A_ATTRIBUTES & ~A_COLOR)) >> 16);
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate 	if (mb == 0)
1687c478bd9Sstevel@tonic-gate 		cc->_wc[0] = cc->_wc[1] = 0;
1697c478bd9Sstevel@tonic-gate 	else if (mbtowc(cc->_wc, &mb, 1) < 0) {
1707c478bd9Sstevel@tonic-gate 		return (ERR);
1717c478bd9Sstevel@tonic-gate 	}
1727c478bd9Sstevel@tonic-gate 	return (OK);
1737c478bd9Sstevel@tonic-gate }
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate /*
1767c478bd9Sstevel@tonic-gate  * Return a complex character as a chtype.
1777c478bd9Sstevel@tonic-gate  */
1787c478bd9Sstevel@tonic-gate chtype
__m_cc_chtype(const cchar_t * cc)1797c478bd9Sstevel@tonic-gate __m_cc_chtype(const cchar_t *cc)
1807c478bd9Sstevel@tonic-gate {
1817c478bd9Sstevel@tonic-gate 	chtype	ch;
1827c478bd9Sstevel@tonic-gate 	unsigned char	mb[MB_LEN_MAX];
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate 	/* Is it a single-byte character? */
1857c478bd9Sstevel@tonic-gate 	if (cc->_n != 1 || wctomb((char *)mb, cc->_wc[0]) != 1)
1867c478bd9Sstevel@tonic-gate 		return ((chtype) ERR);
1877c478bd9Sstevel@tonic-gate 
1887c478bd9Sstevel@tonic-gate 	ch = ((chtype) cc->_at << 16) & ~A_COLOR;
1897c478bd9Sstevel@tonic-gate 	ch |= COLOR_PAIR(cc->_co) | mb[0];
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate 	return (ch);
1927c478bd9Sstevel@tonic-gate }
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate /*
1957c478bd9Sstevel@tonic-gate  * Convert a complex character's "character" into a multibyte string.
1967c478bd9Sstevel@tonic-gate  * The attribute and colour are ignored.
1977c478bd9Sstevel@tonic-gate  *
1987c478bd9Sstevel@tonic-gate  * If 0 < n, set a new multibyte string and convert the first character,
1997c478bd9Sstevel@tonic-gate  * returning either -1 on error or the number of bytes used to convert the
2007c478bd9Sstevel@tonic-gate  * character.
2017c478bd9Sstevel@tonic-gate  *
2027c478bd9Sstevel@tonic-gate  * If n == 0, continue appending to the current multibyte string and return
2037c478bd9Sstevel@tonic-gate  * a value as for 0 < n case.
2047c478bd9Sstevel@tonic-gate  *
2057c478bd9Sstevel@tonic-gate  * If n < 0, return the accumulated byte length of the current multibyte
2067c478bd9Sstevel@tonic-gate  * string and do nothing else.
2077c478bd9Sstevel@tonic-gate  *
2087c478bd9Sstevel@tonic-gate  * When converting a character, a null cchar_t pointer will force the initial
2097c478bd9Sstevel@tonic-gate  * shift state and append a '\0' to the multibyte string.  The return value
2107c478bd9Sstevel@tonic-gate  * will instead by the number of bytes used to shift to the initial state,
2117c478bd9Sstevel@tonic-gate  * and exclude the '\0'.
2127c478bd9Sstevel@tonic-gate  */
2137c478bd9Sstevel@tonic-gate int
__m_cc_mbs(const cchar_t * cc,char * mbs,int n)2147c478bd9Sstevel@tonic-gate __m_cc_mbs(const cchar_t *cc, char *mbs, int n)
2157c478bd9Sstevel@tonic-gate {
2167c478bd9Sstevel@tonic-gate 	int	i, bytes, count, last;
2177c478bd9Sstevel@tonic-gate 	static t_string	string = { 0 };
2187c478bd9Sstevel@tonic-gate 	static t_wide_io	convert = { 0 };
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate 	if (n < 0) {
2217c478bd9Sstevel@tonic-gate 		/* Return total number of bytes written to multibyte string. */
2227c478bd9Sstevel@tonic-gate 		return (string.used);
2237c478bd9Sstevel@tonic-gate 	} else if (0 < n) {
2247c478bd9Sstevel@tonic-gate 		/* Start a new conversion. */
2257c478bd9Sstevel@tonic-gate 		string.max = n;
2267c478bd9Sstevel@tonic-gate 		string.used = 0;
2277c478bd9Sstevel@tonic-gate 		string.mbs = mbs;
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate 		convert._next = convert._size = 0;
2307c478bd9Sstevel@tonic-gate 		convert.object = (void *) &string;
2317c478bd9Sstevel@tonic-gate 		convert.put = (int (*)(int, void *)) write_string;
2327c478bd9Sstevel@tonic-gate 	} /* else n == 0, continue appending to previous mbs. */
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate 	/* In case of error, rewind string to the last character. */
2357c478bd9Sstevel@tonic-gate 	last = string.used;
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate 	if (cc == NULL) {
2387c478bd9Sstevel@tonic-gate 		/* Force initial shift state. */
2397c478bd9Sstevel@tonic-gate 		if ((count = m_wio_put('\0', &convert)) < 0) {
2407c478bd9Sstevel@tonic-gate 			string.used = last;
2417c478bd9Sstevel@tonic-gate 			return (-1);
2427c478bd9Sstevel@tonic-gate 		}
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate 		if (string.used < string.max)
2457c478bd9Sstevel@tonic-gate 			string.mbs[string.used++] = '\0';
2467c478bd9Sstevel@tonic-gate 	} else {
2477c478bd9Sstevel@tonic-gate 		for (count = i = 0; i < cc->_n; ++i, count += bytes)
2487c478bd9Sstevel@tonic-gate 			if ((bytes = m_wio_put(cc->_wc[i], &convert)) < 0) {
2497c478bd9Sstevel@tonic-gate 				string.used = last;
2507c478bd9Sstevel@tonic-gate 				return (-1);
2517c478bd9Sstevel@tonic-gate 			}
2527c478bd9Sstevel@tonic-gate 	}
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate 	return (count);
2557c478bd9Sstevel@tonic-gate }
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate /*
2587c478bd9Sstevel@tonic-gate  * Convert a stty character into a wchar_t.
2597c478bd9Sstevel@tonic-gate  */
2607c478bd9Sstevel@tonic-gate int
__m_tty_wc(int index,wchar_t * wcp)2617c478bd9Sstevel@tonic-gate __m_tty_wc(int index, wchar_t *wcp)
2627c478bd9Sstevel@tonic-gate {
2637c478bd9Sstevel@tonic-gate 	char	mb;
2647c478bd9Sstevel@tonic-gate 	int	code;
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate 	/*
2677c478bd9Sstevel@tonic-gate 	 * Refer to _shell instead of _prog, since _shell will
2687c478bd9Sstevel@tonic-gate 	 * correctly reflect the user's prefered settings, whereas
2697c478bd9Sstevel@tonic-gate 	 * _prog may not have been initialised if both input and
2707c478bd9Sstevel@tonic-gate 	 * output have been redirected.
2717c478bd9Sstevel@tonic-gate 	 */
2727c478bd9Sstevel@tonic-gate 	mb = (char)PTERMIOS(_shell)->c_cc[index];
2737c478bd9Sstevel@tonic-gate 	if (mb)
2747c478bd9Sstevel@tonic-gate 	    code = mbtowc(wcp, &mb, 1) < 0 ? ERR : OK;
2757c478bd9Sstevel@tonic-gate 	else
2767c478bd9Sstevel@tonic-gate 	    code = ERR;
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate 	return (code);
2797c478bd9Sstevel@tonic-gate }
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate /*
2827c478bd9Sstevel@tonic-gate  * Build a cchar_t from the leading spacing and non-spacing characters
2837c478bd9Sstevel@tonic-gate  * in the multibyte character string.  Only one spacing character is copied
2847c478bd9Sstevel@tonic-gate  * from the multibyte character string.
2857c478bd9Sstevel@tonic-gate  *
2867c478bd9Sstevel@tonic-gate  * Return the number of characters copied from the string, or -1 on error.
2877c478bd9Sstevel@tonic-gate  */
2887c478bd9Sstevel@tonic-gate int
__m_mbs_cc(const char * mbs,attr_t at,short co,cchar_t * cc)2897c478bd9Sstevel@tonic-gate __m_mbs_cc(const char *mbs, attr_t at, short co, cchar_t *cc)
2907c478bd9Sstevel@tonic-gate {
2917c478bd9Sstevel@tonic-gate 	wchar_t	wc;
2927c478bd9Sstevel@tonic-gate 	const char	*start;
2937c478bd9Sstevel@tonic-gate 	int	i, nbytes, width, have_one;
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate 	for (start = mbs, have_one = i = 0; *mbs != '\0'; mbs += nbytes, ++i) {
2967c478bd9Sstevel@tonic-gate 		if (sizeof (cc->_wc) <= i)
2977c478bd9Sstevel@tonic-gate 			/* Too many characters. */
2987c478bd9Sstevel@tonic-gate 			return (-1);
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate 		if ((nbytes = mbtowc(&wc, mbs, UINT_MAX)) < 0)
3017c478bd9Sstevel@tonic-gate 			/* Invalid multibyte sequence. */
3027c478bd9Sstevel@tonic-gate 			return (-1);
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate 		if (nbytes == 0)
3057c478bd9Sstevel@tonic-gate 			/* Remainder of string evaluates to the null byte. */
3067c478bd9Sstevel@tonic-gate 			break;
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate 		if (iscntrl(*mbs))
3097c478bd9Sstevel@tonic-gate 			/* Treat control codes like a spacing character. */
3107c478bd9Sstevel@tonic-gate 			width = 1;
3117c478bd9Sstevel@tonic-gate 		else
3127c478bd9Sstevel@tonic-gate 			width = wcwidth(wc);
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate 		/* Do we have a spacing character? */
3157c478bd9Sstevel@tonic-gate 		if (0 < width) {
3167c478bd9Sstevel@tonic-gate 			if (have_one)
3177c478bd9Sstevel@tonic-gate 				break;
3187c478bd9Sstevel@tonic-gate 			have_one = 1;
3197c478bd9Sstevel@tonic-gate 		}
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate 		cc->_wc[i] = wc;
3227c478bd9Sstevel@tonic-gate 	}
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate 	cc->_f = 1;
3257c478bd9Sstevel@tonic-gate 	cc->_n = (short)i;
3267c478bd9Sstevel@tonic-gate 	cc->_co = co;
3277c478bd9Sstevel@tonic-gate 	cc->_at = at;
3287c478bd9Sstevel@tonic-gate 
3297c478bd9Sstevel@tonic-gate 	(void) __m_cc_sort(cc);
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate 	/* (mbs - start) should be enough small to fit in "int" */
3327c478bd9Sstevel@tonic-gate 	return ((int)(mbs - start));
3337c478bd9Sstevel@tonic-gate }
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate /*
3367c478bd9Sstevel@tonic-gate  * Build a cchar_t from the leading spacing and non-spacing characters
3377c478bd9Sstevel@tonic-gate  * in the wide character string.  Only one spacinig character is copied
3387c478bd9Sstevel@tonic-gate  * from the wide character string.
3397c478bd9Sstevel@tonic-gate  *
3407c478bd9Sstevel@tonic-gate  * Return the number of characters copied from the string, or -1 on error.
3417c478bd9Sstevel@tonic-gate  */
3427c478bd9Sstevel@tonic-gate int
__m_wcs_cc(const wchar_t * wcs,attr_t at,short co,cchar_t * cc)3437c478bd9Sstevel@tonic-gate __m_wcs_cc(const wchar_t *wcs, attr_t at, short co, cchar_t *cc)
3447c478bd9Sstevel@tonic-gate {
3457c478bd9Sstevel@tonic-gate 	short	i;
3467c478bd9Sstevel@tonic-gate 	const wchar_t	*start;
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate 	for (start = wcs, i = 0; *wcs != '\0'; ++wcs, ++i) {
3497c478bd9Sstevel@tonic-gate 		if (sizeof (cc->_wc) <= i) {
3507c478bd9Sstevel@tonic-gate 			/* Too many characters. */
3517c478bd9Sstevel@tonic-gate 			return (-1);
3527c478bd9Sstevel@tonic-gate 		}
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate 		if (wcwidth(*wcs) > 0) {
3557c478bd9Sstevel@tonic-gate 			if (i != 0)
3567c478bd9Sstevel@tonic-gate 				break;
3577c478bd9Sstevel@tonic-gate 		} else if ((*wcs == L'\n') || (*wcs == L'\t') ||
3587c478bd9Sstevel@tonic-gate 			(*wcs == L'\b') || (*wcs == L'\r'))	{
3597c478bd9Sstevel@tonic-gate 			if (i != 0)
3607c478bd9Sstevel@tonic-gate 				break;
3617c478bd9Sstevel@tonic-gate 			cc->_wc[i++] = *wcs++;
3627c478bd9Sstevel@tonic-gate 			break;
3637c478bd9Sstevel@tonic-gate 		}
3647c478bd9Sstevel@tonic-gate 
3657c478bd9Sstevel@tonic-gate 		cc->_wc[i] = *wcs;
3667c478bd9Sstevel@tonic-gate 	}
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate 	cc->_f = 1;
3697c478bd9Sstevel@tonic-gate 	cc->_n = i;
3707c478bd9Sstevel@tonic-gate 	cc->_co = co;
3717c478bd9Sstevel@tonic-gate 	cc->_at = at;
3727c478bd9Sstevel@tonic-gate 
3737c478bd9Sstevel@tonic-gate 	/* (wcs - start) should be enough small to fit in "int" */
3747c478bd9Sstevel@tonic-gate 	return ((int)(wcs - start));
3757c478bd9Sstevel@tonic-gate }
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate /*
3787c478bd9Sstevel@tonic-gate  * Convert a single wide character into a complex character.
3797c478bd9Sstevel@tonic-gate  */
3807c478bd9Sstevel@tonic-gate int
__m_wc_cc(wint_t wc,cchar_t * cc)3817c478bd9Sstevel@tonic-gate __m_wc_cc(wint_t wc, cchar_t *cc)
3827c478bd9Sstevel@tonic-gate {
3837c478bd9Sstevel@tonic-gate 	wchar_t	wcs[2];
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate 	if (wc == WEOF)
3867c478bd9Sstevel@tonic-gate 		return (-1);
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate 	if (wc == 0) {
3897c478bd9Sstevel@tonic-gate 		/*
3907c478bd9Sstevel@tonic-gate 		 * converting a null character to a complex character.
3917c478bd9Sstevel@tonic-gate 		 * __m_wcs_cc assumes that the string is empty, so
3927c478bd9Sstevel@tonic-gate 		 * just do it here.
3937c478bd9Sstevel@tonic-gate 		 */
3947c478bd9Sstevel@tonic-gate 		cc->_f = 1;
3957c478bd9Sstevel@tonic-gate 		cc->_n = 1;
3967c478bd9Sstevel@tonic-gate 		cc->_co = 0;
3977c478bd9Sstevel@tonic-gate 		cc->_at = WA_NORMAL;
3987c478bd9Sstevel@tonic-gate 		cc->_wc[0] = 0;
3997c478bd9Sstevel@tonic-gate 		cc->_wc[1] = 0;
4007c478bd9Sstevel@tonic-gate 	} else {
4017c478bd9Sstevel@tonic-gate 		/* A real character */
4027c478bd9Sstevel@tonic-gate 		wcs[0] = (wchar_t)wc;
4037c478bd9Sstevel@tonic-gate 		wcs[1] = '\0';
4047c478bd9Sstevel@tonic-gate 		(void) __m_wcs_cc(wcs, WA_NORMAL, 0, cc);
4057c478bd9Sstevel@tonic-gate 	}
4067c478bd9Sstevel@tonic-gate 
4077c478bd9Sstevel@tonic-gate 	return (0);
4087c478bd9Sstevel@tonic-gate }
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate /*
4117c478bd9Sstevel@tonic-gate  * Sort a complex character into a spacing character followed
4127c478bd9Sstevel@tonic-gate  * by any non-spacing characters in increasing order of oridinal
4137c478bd9Sstevel@tonic-gate  * values.  This facilitates both comparision and writting of
4147c478bd9Sstevel@tonic-gate  * complex characters.  More than one spacing character is
4157c478bd9Sstevel@tonic-gate  * considered an error.
4167c478bd9Sstevel@tonic-gate  *
4177c478bd9Sstevel@tonic-gate  * Return the spacing character's column width or -1 if more
4187c478bd9Sstevel@tonic-gate  * than one spacing character appears in cc.
4197c478bd9Sstevel@tonic-gate  */
4207c478bd9Sstevel@tonic-gate int
__m_cc_sort(cchar_t * cc)4217c478bd9Sstevel@tonic-gate __m_cc_sort(cchar_t *cc)
4227c478bd9Sstevel@tonic-gate {
4237c478bd9Sstevel@tonic-gate 	wchar_t	wc;
4247c478bd9Sstevel@tonic-gate 	int	width, i, j, spacing;
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate 	/* Find spacing character and place in as first element. */
4277c478bd9Sstevel@tonic-gate 	for (width = spacing = i = 0; i < cc->_n; ++i) {
4287c478bd9Sstevel@tonic-gate 		j = wcwidth(cc->_wc[i]);
4297c478bd9Sstevel@tonic-gate 		if (0 < j) {
4307c478bd9Sstevel@tonic-gate 			/* More than one spacing character is an error. */
4317c478bd9Sstevel@tonic-gate 			if (0 < width)
4327c478bd9Sstevel@tonic-gate 				return (-1);
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate 			wc = cc->_wc[0];
4357c478bd9Sstevel@tonic-gate 			cc->_wc[0] = cc->_wc[i];
4367c478bd9Sstevel@tonic-gate 			cc->_wc[i] = wc;
4377c478bd9Sstevel@tonic-gate 
4387c478bd9Sstevel@tonic-gate 			spacing = 1;
4397c478bd9Sstevel@tonic-gate 			width = j;
4407c478bd9Sstevel@tonic-gate 			break;
4417c478bd9Sstevel@tonic-gate 		}
4427c478bd9Sstevel@tonic-gate 	}
4437c478bd9Sstevel@tonic-gate 
4447c478bd9Sstevel@tonic-gate 	/* Bubble sort small array. */
4457c478bd9Sstevel@tonic-gate 	for (i = spacing; i < cc->_n; ++i) {
4467c478bd9Sstevel@tonic-gate 		for (j = cc->_n - 1; i < j; --j) {
4477c478bd9Sstevel@tonic-gate 			if (cc->_wc[j-1] > cc->_wc[j]) {
4487c478bd9Sstevel@tonic-gate 				wc = cc->_wc[j];
4497c478bd9Sstevel@tonic-gate 				cc->_wc[j] = cc->_wc[j-1];
4507c478bd9Sstevel@tonic-gate 				cc->_wc[j-1]  = wc;
4517c478bd9Sstevel@tonic-gate 			}
4527c478bd9Sstevel@tonic-gate 		}
4537c478bd9Sstevel@tonic-gate 	}
4547c478bd9Sstevel@tonic-gate 
4557c478bd9Sstevel@tonic-gate 	return (width);
4567c478bd9Sstevel@tonic-gate }
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate /*
4597c478bd9Sstevel@tonic-gate  * Return the first column of a multi-column character, in window.
4607c478bd9Sstevel@tonic-gate  */
4617c478bd9Sstevel@tonic-gate int
__m_cc_first(WINDOW * w,int y,int x)4627c478bd9Sstevel@tonic-gate __m_cc_first(WINDOW *w, int y, int x)
4637c478bd9Sstevel@tonic-gate {
4647c478bd9Sstevel@tonic-gate 	cchar_t	*lp;
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate 	for (lp = w->_line[y]; 0 < x; --x) {
4677c478bd9Sstevel@tonic-gate 		if (lp[x]._f)
4687c478bd9Sstevel@tonic-gate 			break;
4697c478bd9Sstevel@tonic-gate 	}
4707c478bd9Sstevel@tonic-gate 
4717c478bd9Sstevel@tonic-gate 	return (x);
4727c478bd9Sstevel@tonic-gate }
4737c478bd9Sstevel@tonic-gate 
4747c478bd9Sstevel@tonic-gate /*
4757c478bd9Sstevel@tonic-gate  * Return the start of the next multi-column character, in window.
4767c478bd9Sstevel@tonic-gate  */
4777c478bd9Sstevel@tonic-gate int
__m_cc_next(WINDOW * w,int y,int x)4787c478bd9Sstevel@tonic-gate __m_cc_next(WINDOW *w, int y, int x)
4797c478bd9Sstevel@tonic-gate {
4807c478bd9Sstevel@tonic-gate 	cchar_t	*lp;
4817c478bd9Sstevel@tonic-gate 
4827c478bd9Sstevel@tonic-gate 	for (lp = w->_line[y]; ++x < w->_maxx; ) {
4837c478bd9Sstevel@tonic-gate 		if (lp[x]._f)
4847c478bd9Sstevel@tonic-gate 			break;
4857c478bd9Sstevel@tonic-gate 	}
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate 	return (x);
4887c478bd9Sstevel@tonic-gate }
4897c478bd9Sstevel@tonic-gate 
4907c478bd9Sstevel@tonic-gate /*
4917c478bd9Sstevel@tonic-gate  * Return true if valid last column of a multi-column character.
4927c478bd9Sstevel@tonic-gate  */
4937c478bd9Sstevel@tonic-gate int
__m_cc_islast(WINDOW * w,int y,int x)4947c478bd9Sstevel@tonic-gate __m_cc_islast(WINDOW *w, int y, int x)
4957c478bd9Sstevel@tonic-gate {
4967c478bd9Sstevel@tonic-gate 	int	first, width;
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate 	first = __m_cc_first(w, y, x);
4997c478bd9Sstevel@tonic-gate 	width = __m_cc_width(&w->_line[y][x]);
5007c478bd9Sstevel@tonic-gate 
5017c478bd9Sstevel@tonic-gate 	return ((first + width) == (x + 1));
5027c478bd9Sstevel@tonic-gate }
5037c478bd9Sstevel@tonic-gate 
5047c478bd9Sstevel@tonic-gate /*
5057c478bd9Sstevel@tonic-gate  * Replace the character at the current cursor location
5067c478bd9Sstevel@tonic-gate  * according to the column width of the character.  The
5077c478bd9Sstevel@tonic-gate  * cursor does not advance.
5087c478bd9Sstevel@tonic-gate  *
5097c478bd9Sstevel@tonic-gate  * Return -1 if the character won't fit on the line and the background
5107c478bd9Sstevel@tonic-gate  * was written in its place; else return the width of the character in
5117c478bd9Sstevel@tonic-gate  * screen columns.
5127c478bd9Sstevel@tonic-gate  */
5137c478bd9Sstevel@tonic-gate /* ARGSUSED */
5147c478bd9Sstevel@tonic-gate int
__m_cc_replace(WINDOW * w,int y,int x,const cchar_t * cc,int as_is)5157c478bd9Sstevel@tonic-gate __m_cc_replace(WINDOW *w, int y, int x,
5167c478bd9Sstevel@tonic-gate 	const cchar_t *cc, int as_is)
5177c478bd9Sstevel@tonic-gate {
5187c478bd9Sstevel@tonic-gate 	int	i, width;
5197c478bd9Sstevel@tonic-gate 	cchar_t	*cp, *np;
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate 	width = __m_cc_width(cc);
5227c478bd9Sstevel@tonic-gate 
5237c478bd9Sstevel@tonic-gate 	if (width <= 0)
5247c478bd9Sstevel@tonic-gate 		return (__m_cc_modify(w, y, x, cc));
5257c478bd9Sstevel@tonic-gate 
5267c478bd9Sstevel@tonic-gate 	/*
5277c478bd9Sstevel@tonic-gate 	 * If we try to write a broad character that would exceed the
5287c478bd9Sstevel@tonic-gate 	 * right margin, then write the background character instead.
5297c478bd9Sstevel@tonic-gate 	 */
5307c478bd9Sstevel@tonic-gate 	if (0 < width && w->_maxx < x + width) {
5317c478bd9Sstevel@tonic-gate 		(void) __m_cc_erase(w, y, x, y, w->_maxx-1);
5327c478bd9Sstevel@tonic-gate 		return (-1);
5337c478bd9Sstevel@tonic-gate 	}
5347c478bd9Sstevel@tonic-gate 
5357c478bd9Sstevel@tonic-gate 	/*
5367c478bd9Sstevel@tonic-gate 	 * Erase the region to be occupied by the new character.
5377c478bd9Sstevel@tonic-gate 	 * __m_cc_erase() will erase whole characters so that
5387c478bd9Sstevel@tonic-gate 	 * writing a multicolumn character that overwrites the
5397c478bd9Sstevel@tonic-gate 	 * trailing and leading portions of two already existing
5407c478bd9Sstevel@tonic-gate 	 * multicolumn characters, erases the remaining portions.
5417c478bd9Sstevel@tonic-gate 	 */
5427c478bd9Sstevel@tonic-gate 	(void) __m_cc_erase(w, y, x, y, x + width - 1);
5437c478bd9Sstevel@tonic-gate 
5447c478bd9Sstevel@tonic-gate 	/* Write the first column of the character. */
5457c478bd9Sstevel@tonic-gate 	cp = &w->_line[y][x++];
5467c478bd9Sstevel@tonic-gate 	if (cc->_wc[0] == L' ') {
5477c478bd9Sstevel@tonic-gate 		*cp = w->_bg;
5487c478bd9Sstevel@tonic-gate 		cp->_at = cc->_at | w->_fg._at;
5497c478bd9Sstevel@tonic-gate 		/*
5507c478bd9Sstevel@tonic-gate 		 * This method fixes:
5517c478bd9Sstevel@tonic-gate 		 * /tset/CAPIxcurses/fmvwaddchs/fmvwaddchs1{3}
5527c478bd9Sstevel@tonic-gate 		 * /tset/CAPIxcurses/fwins_wch/fwins_wch1{5}
5537c478bd9Sstevel@tonic-gate 		 */
5547c478bd9Sstevel@tonic-gate 		cp->_co = (cc->_co) ? cc->_co : w->_fg._co;
5557c478bd9Sstevel@tonic-gate 	} else {
5567c478bd9Sstevel@tonic-gate 		if (__m_wacs_cc(cc, cp)) {
5577c478bd9Sstevel@tonic-gate 			/*
5587c478bd9Sstevel@tonic-gate 			 * __m_wacs_cc says ALTCHARSET should be cleared
5597c478bd9Sstevel@tonic-gate 			 * ... Takes priority
5607c478bd9Sstevel@tonic-gate 			 */
5617c478bd9Sstevel@tonic-gate 		    cp->_at = (cc->_at | w->_fg._at) & ~WA_ALTCHARSET;
5627c478bd9Sstevel@tonic-gate 		} else {
5637c478bd9Sstevel@tonic-gate 		    cp->_at = cc->_at | w->_fg._at;
5647c478bd9Sstevel@tonic-gate 		}
5657c478bd9Sstevel@tonic-gate 		cp->_co = (cc->_co) ? cc->_co : w->_fg._co;
5667c478bd9Sstevel@tonic-gate 	}
5677c478bd9Sstevel@tonic-gate 
5687c478bd9Sstevel@tonic-gate 	/* Mark this as the first column of the character. */
5697c478bd9Sstevel@tonic-gate 	cp->_f = 1;
5707c478bd9Sstevel@tonic-gate 
5717c478bd9Sstevel@tonic-gate 	/* Duplicate the character in every column the character occupies. */
5727c478bd9Sstevel@tonic-gate 	for (np = cp + 1, i = 1; i < width; ++i, ++x, ++np) {
5737c478bd9Sstevel@tonic-gate 		*np = *cp;
5747c478bd9Sstevel@tonic-gate 		np->_f = 0;
5757c478bd9Sstevel@tonic-gate 	}
5767c478bd9Sstevel@tonic-gate 
5777c478bd9Sstevel@tonic-gate 	return (width);
5787c478bd9Sstevel@tonic-gate }
5797c478bd9Sstevel@tonic-gate 
5807c478bd9Sstevel@tonic-gate int
__m_do_scroll(WINDOW * w,int y,int x,int * yp,int * xp)5817c478bd9Sstevel@tonic-gate __m_do_scroll(WINDOW *w, int y, int x, int *yp, int *xp)
5827c478bd9Sstevel@tonic-gate {
5837c478bd9Sstevel@tonic-gate 	int	code = OK;
5847c478bd9Sstevel@tonic-gate 	if (w->_maxx <= x)
5857c478bd9Sstevel@tonic-gate 		x = w->_maxx - 1;
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate 	++y;
5887c478bd9Sstevel@tonic-gate 
5897c478bd9Sstevel@tonic-gate 	if (y == w->_bottom) {
5907c478bd9Sstevel@tonic-gate 		--y;
5917c478bd9Sstevel@tonic-gate 		if (w->_flags & W_CAN_SCROLL) {
5927c478bd9Sstevel@tonic-gate 			if (wscrl(w, 1) == ERR)
5937c478bd9Sstevel@tonic-gate 				return (ERR);
5947c478bd9Sstevel@tonic-gate 			x = 0;
5957c478bd9Sstevel@tonic-gate 			/* Test suite seems to want this */
5967c478bd9Sstevel@tonic-gate 			w->_flags |= W_FLUSH;
5977c478bd9Sstevel@tonic-gate 		} else {
5987c478bd9Sstevel@tonic-gate #ifdef	BREAKS
5997c478bd9Sstevel@tonic-gate 			w->_curx = x;	/* Cheezy doing it here	*/
6007c478bd9Sstevel@tonic-gate 			w->_cury = y;
6017c478bd9Sstevel@tonic-gate #endif	/* BREAKS */
6027c478bd9Sstevel@tonic-gate 			code = ERR;	/* No scrolling allowed */
6037c478bd9Sstevel@tonic-gate 		}
6047c478bd9Sstevel@tonic-gate 	} else if (w->_maxy <= y) {
6057c478bd9Sstevel@tonic-gate 		y = w->_maxy - 1;
6067c478bd9Sstevel@tonic-gate 	} else {
6077c478bd9Sstevel@tonic-gate 		/*
6087c478bd9Sstevel@tonic-gate 		 * The cursor wraps for any line (in and out of the scroll
6097c478bd9Sstevel@tonic-gate 		 * region) except for the last line of the scroll region.
6107c478bd9Sstevel@tonic-gate 		 */
6117c478bd9Sstevel@tonic-gate 		x = 0;
6127c478bd9Sstevel@tonic-gate 	}
6137c478bd9Sstevel@tonic-gate 
6147c478bd9Sstevel@tonic-gate 	*yp = y;
6157c478bd9Sstevel@tonic-gate 	*xp = x;
6167c478bd9Sstevel@tonic-gate 
6177c478bd9Sstevel@tonic-gate 	return (code);
6187c478bd9Sstevel@tonic-gate }
6197c478bd9Sstevel@tonic-gate 
6207c478bd9Sstevel@tonic-gate /*
6217c478bd9Sstevel@tonic-gate  * Add the character at the current cursor location
6227c478bd9Sstevel@tonic-gate  * according to the column width of the character.
6237c478bd9Sstevel@tonic-gate  * The cursor will be advanced.
6247c478bd9Sstevel@tonic-gate  * Wrapping is done.
6257c478bd9Sstevel@tonic-gate  *
6267c478bd9Sstevel@tonic-gate  * Return ERR if adding the character causes the
6277c478bd9Sstevel@tonic-gate  * screen to scroll, when it is disallowed.
6287c478bd9Sstevel@tonic-gate  */
6297c478bd9Sstevel@tonic-gate int
__m_cc_add(WINDOW * w,int y,int x,const cchar_t * cc,int as_is,int * yp,int * xp)6307c478bd9Sstevel@tonic-gate __m_cc_add(WINDOW *w, int y, int x,
6317c478bd9Sstevel@tonic-gate 	const cchar_t *cc, int as_is, int *yp, int *xp)
6327c478bd9Sstevel@tonic-gate {
6337c478bd9Sstevel@tonic-gate 	int	nx, width, code = ERR;
6347c478bd9Sstevel@tonic-gate 
6357c478bd9Sstevel@tonic-gate 	switch (cc->_wc[0]) {
6367c478bd9Sstevel@tonic-gate 	case L'\t':
6377c478bd9Sstevel@tonic-gate 		nx = x + (8 - (x & 07));
6387c478bd9Sstevel@tonic-gate 		if (nx >= w->_maxx)	{
6397c478bd9Sstevel@tonic-gate 			/* This fixes (scroll-disabled) */
6407c478bd9Sstevel@tonic-gate 			/* /tset/CAPIxcurses/fwaddch/fwaddch1{4} but */
6417c478bd9Sstevel@tonic-gate 			/* what does it break? */
6427c478bd9Sstevel@tonic-gate 			nx = w->_maxx;
6437c478bd9Sstevel@tonic-gate 		}
6447c478bd9Sstevel@tonic-gate 		if (__m_cc_erase(w, y, x, y, nx-1) == -1)
6457c478bd9Sstevel@tonic-gate 			goto error;
6467c478bd9Sstevel@tonic-gate 		x = nx;
6477c478bd9Sstevel@tonic-gate 
6487c478bd9Sstevel@tonic-gate 		if (w->_maxx <= x) {
6497c478bd9Sstevel@tonic-gate 			if (__m_do_scroll(w, y, x, &y, &x) == ERR)
6507c478bd9Sstevel@tonic-gate 				goto error;
6517c478bd9Sstevel@tonic-gate 		}
6527c478bd9Sstevel@tonic-gate 		break;
6537c478bd9Sstevel@tonic-gate 	case L'\n':
6547c478bd9Sstevel@tonic-gate 		if (__m_cc_erase(w, y, x, y, w->_maxx-1) == -1)
6557c478bd9Sstevel@tonic-gate 			goto error;
6567c478bd9Sstevel@tonic-gate 
6577c478bd9Sstevel@tonic-gate 		if (__m_do_scroll(w, y, x, &y, &x) == ERR)
6587c478bd9Sstevel@tonic-gate 			goto error;
6597c478bd9Sstevel@tonic-gate 		break;
6607c478bd9Sstevel@tonic-gate 	case L'\r':
6617c478bd9Sstevel@tonic-gate 		x = 0;
6627c478bd9Sstevel@tonic-gate 		break;
6637c478bd9Sstevel@tonic-gate 	case L'\b':
6647c478bd9Sstevel@tonic-gate 		if (0 < x)
6657c478bd9Sstevel@tonic-gate 			--x;
6667c478bd9Sstevel@tonic-gate 		else
6677c478bd9Sstevel@tonic-gate 			(void) beep();
6687c478bd9Sstevel@tonic-gate 		break;
6697c478bd9Sstevel@tonic-gate 	default:
6707c478bd9Sstevel@tonic-gate 		width = __m_cc_replace(w, y, x, cc, as_is);
6717c478bd9Sstevel@tonic-gate 
6727c478bd9Sstevel@tonic-gate 		x += width;
6737c478bd9Sstevel@tonic-gate 
6747c478bd9Sstevel@tonic-gate 		if (width < 0 || w->_maxx <= x) {
6757c478bd9Sstevel@tonic-gate 			if (__m_do_scroll(w, y, x, &y, &x) == ERR) {
6767c478bd9Sstevel@tonic-gate 				goto error;
6777c478bd9Sstevel@tonic-gate 			}
6787c478bd9Sstevel@tonic-gate 
6797c478bd9Sstevel@tonic-gate 			if (width < 0)
6807c478bd9Sstevel@tonic-gate 				x += __m_cc_replace(w, y, x, cc, as_is);
6817c478bd9Sstevel@tonic-gate 		}
6827c478bd9Sstevel@tonic-gate 	}
6837c478bd9Sstevel@tonic-gate 
6847c478bd9Sstevel@tonic-gate 	code = OK;
6857c478bd9Sstevel@tonic-gate error:
6867c478bd9Sstevel@tonic-gate 	*yp = y;
6877c478bd9Sstevel@tonic-gate 	*xp = x;
6887c478bd9Sstevel@tonic-gate 
6897c478bd9Sstevel@tonic-gate 	return (code);
6907c478bd9Sstevel@tonic-gate }
6917c478bd9Sstevel@tonic-gate 
6927c478bd9Sstevel@tonic-gate /*
6937c478bd9Sstevel@tonic-gate  * Stripped version of __m_cc_add which does much less special character
6947c478bd9Sstevel@tonic-gate  * processing. Functions such as waddchnstr() are not supposed to do
6957c478bd9Sstevel@tonic-gate  * any special character processing but what does one do when a '\n'
6967c478bd9Sstevel@tonic-gate  * is sent? The test suite expects a new line to start...
6977c478bd9Sstevel@tonic-gate  *
6987c478bd9Sstevel@tonic-gate  * Return ERR if adding the character causes the
6997c478bd9Sstevel@tonic-gate  * screen to scroll, when it is disallowed.
7007c478bd9Sstevel@tonic-gate  */
7017c478bd9Sstevel@tonic-gate int
__m_cc_add_k(WINDOW * w,int y,int x,const cchar_t * cc,int as_is,int * yp,int * xp)7027c478bd9Sstevel@tonic-gate __m_cc_add_k(WINDOW *w, int y, int x,
7037c478bd9Sstevel@tonic-gate 	const cchar_t *cc, int as_is, int *yp, int *xp)
7047c478bd9Sstevel@tonic-gate {
7057c478bd9Sstevel@tonic-gate 	int	width, code = ERR;
7067c478bd9Sstevel@tonic-gate 
7077c478bd9Sstevel@tonic-gate 	switch (cc->_wc[0]) {
7087c478bd9Sstevel@tonic-gate 	case L'\n':
7097c478bd9Sstevel@tonic-gate 		if (__m_cc_erase(w, y, x, y, w->_maxx-1) == -1)
7107c478bd9Sstevel@tonic-gate 			goto error;
7117c478bd9Sstevel@tonic-gate 
7127c478bd9Sstevel@tonic-gate 		if (__m_do_scroll(w, y, x, &y, &x) == ERR)
7137c478bd9Sstevel@tonic-gate 			goto error;
7147c478bd9Sstevel@tonic-gate 		break;
7157c478bd9Sstevel@tonic-gate 	default:
7167c478bd9Sstevel@tonic-gate 		width = __m_cc_replace(w, y, x, cc, as_is);
7177c478bd9Sstevel@tonic-gate 		x += width;
7187c478bd9Sstevel@tonic-gate 	}
7197c478bd9Sstevel@tonic-gate 
7207c478bd9Sstevel@tonic-gate 	code = OK;
7217c478bd9Sstevel@tonic-gate error:
7227c478bd9Sstevel@tonic-gate 	*yp = y;
7237c478bd9Sstevel@tonic-gate 	*xp = x;
7247c478bd9Sstevel@tonic-gate 
7257c478bd9Sstevel@tonic-gate 	return (code);
7267c478bd9Sstevel@tonic-gate }
7277c478bd9Sstevel@tonic-gate 
7287c478bd9Sstevel@tonic-gate /*
7297c478bd9Sstevel@tonic-gate  * Append non-spacing characters to the a spacing character at (y, x).
7307c478bd9Sstevel@tonic-gate  * Return -1 on error, else 0.
7317c478bd9Sstevel@tonic-gate  */
7327c478bd9Sstevel@tonic-gate int
__m_cc_modify(WINDOW * w,int y,int x,const cchar_t * cc)7337c478bd9Sstevel@tonic-gate __m_cc_modify(WINDOW *w, int y, int x, const cchar_t *cc)
7347c478bd9Sstevel@tonic-gate {
7357c478bd9Sstevel@tonic-gate 	cchar_t	*cp, tch;
7367c478bd9Sstevel@tonic-gate 	int	i, j, width;
7377c478bd9Sstevel@tonic-gate 
7387c478bd9Sstevel@tonic-gate 	x = __m_cc_first(w, y, x);
7397c478bd9Sstevel@tonic-gate 	cp = &w->_line[y][x];
7407c478bd9Sstevel@tonic-gate 
7417c478bd9Sstevel@tonic-gate 	/* Is there enough room for the non-spacing characters. */
7427c478bd9Sstevel@tonic-gate 	if (_M_CCHAR_MAX < cp->_n + cc->_n)
7437c478bd9Sstevel@tonic-gate 		return (-1);
7447c478bd9Sstevel@tonic-gate 
7457c478bd9Sstevel@tonic-gate 	for (i = cp->_n, j = 0; j < cc->_n; ++i, ++j)
7467c478bd9Sstevel@tonic-gate 		cp->_wc[i] = cc->_wc[j];
7477c478bd9Sstevel@tonic-gate 	cp->_n = (short)i;
7487c478bd9Sstevel@tonic-gate 
7497c478bd9Sstevel@tonic-gate 	width = __m_cc_width(cp);
7507c478bd9Sstevel@tonic-gate 
7517c478bd9Sstevel@tonic-gate 	__m_touch_locs(w, y, x, x + width);
7527c478bd9Sstevel@tonic-gate 
7537c478bd9Sstevel@tonic-gate 	/* Assert that the modified spacing character is sorted. */
7547c478bd9Sstevel@tonic-gate 	(void) __m_cc_sort(cp);
7557c478bd9Sstevel@tonic-gate 
7567c478bd9Sstevel@tonic-gate 	/* Dulicate in every column occupied by the spacing character. */
7577c478bd9Sstevel@tonic-gate 	while (0 < --width) {
7587c478bd9Sstevel@tonic-gate 		tch = *cp;
7597c478bd9Sstevel@tonic-gate 		cp[1] = tch;
7607c478bd9Sstevel@tonic-gate 		cp++;
7617c478bd9Sstevel@tonic-gate 	}
7627c478bd9Sstevel@tonic-gate 
7637c478bd9Sstevel@tonic-gate 	return (0);
7647c478bd9Sstevel@tonic-gate }
7657c478bd9Sstevel@tonic-gate 
7667c478bd9Sstevel@tonic-gate static void
__m_cc_erase_in_line(WINDOW * w,int y,int x,int lx,int bgWidth)7677c478bd9Sstevel@tonic-gate __m_cc_erase_in_line(WINDOW *w, int y, int x, int lx, int bgWidth)
7687c478bd9Sstevel@tonic-gate {
7697c478bd9Sstevel@tonic-gate 	cchar_t	*cp;
7707c478bd9Sstevel@tonic-gate 	int	i;
7717c478bd9Sstevel@tonic-gate 
7727c478bd9Sstevel@tonic-gate 	if (x < w->_first[y])
7737c478bd9Sstevel@tonic-gate 		w->_first[y] = (short)x;
7747c478bd9Sstevel@tonic-gate 
7757c478bd9Sstevel@tonic-gate 	for (cp = w->_line[y], i = 0; x <= lx; ++x, ++i) {
7767c478bd9Sstevel@tonic-gate 		cp[x] = w->_bg;
7777c478bd9Sstevel@tonic-gate 		/*
7787c478bd9Sstevel@tonic-gate 		 * The start of each new character will be set true
7797c478bd9Sstevel@tonic-gate 		 * while internal columns of the character will be
7807c478bd9Sstevel@tonic-gate 		 * reset to false.
7817c478bd9Sstevel@tonic-gate 		 */
7827c478bd9Sstevel@tonic-gate 		cp[x]._f = (short)(i % bgWidth == 0);
7837c478bd9Sstevel@tonic-gate 	}
7847c478bd9Sstevel@tonic-gate 	if (w->_last[y] < x)
7857c478bd9Sstevel@tonic-gate 		w->_last[y] = (short)x;
7867c478bd9Sstevel@tonic-gate }
7877c478bd9Sstevel@tonic-gate 
7887c478bd9Sstevel@tonic-gate /* Window has a parent. Handle width chars overlapping with parent */
7897c478bd9Sstevel@tonic-gate static void
__m_cc_erase_in_line_sub(WINDOW * w,int y,int x,int lx,int bgWidth,int parentBGWidth)7907c478bd9Sstevel@tonic-gate __m_cc_erase_in_line_sub(WINDOW *w, int y, int x,
7917c478bd9Sstevel@tonic-gate 	int lx, int bgWidth, int parentBGWidth)
7927c478bd9Sstevel@tonic-gate {
7937c478bd9Sstevel@tonic-gate 	cchar_t	*cp;
7947c478bd9Sstevel@tonic-gate 	int	i;
7957c478bd9Sstevel@tonic-gate 	int	xi;
7967c478bd9Sstevel@tonic-gate 	int	wmin, wmax;
7977c478bd9Sstevel@tonic-gate 	int	wlx;
7987c478bd9Sstevel@tonic-gate 	WINDOW	*parent = w->_parent;
799*759f6fc9Srm 	int 	parentY = w->_begy + y - parent->_begy;
800*759f6fc9Srm 	int	dx = w->_begx - parent->_begx;
8017c478bd9Sstevel@tonic-gate 
8027c478bd9Sstevel@tonic-gate 	/* Switch to parent context and calculate limits */
803*759f6fc9Srm 	xi = x = __m_cc_first(parent, parentY, dx + x);
804*759f6fc9Srm 	wlx = lx = __m_cc_next(parent, parentY, dx + lx) - 1;
805*759f6fc9Srm 	if (wlx >= dx + w->_maxx) wlx = dx + w->_maxx - 1;
8067c478bd9Sstevel@tonic-gate 
8077c478bd9Sstevel@tonic-gate 	for (cp = parent->_line[parentY]; x <= lx; ) {
808*759f6fc9Srm 		if ((x < dx) || (x >= (dx + w->_maxx))) {
8097c478bd9Sstevel@tonic-gate 			/* Outside target window */
8107c478bd9Sstevel@tonic-gate 			for (i = 0; x <= lx && i <= parentBGWidth; x++, i++) {
8117c478bd9Sstevel@tonic-gate 				cp[x] = parent->_bg;
8127c478bd9Sstevel@tonic-gate 				cp[x]._f = (i == 0);
8137c478bd9Sstevel@tonic-gate 			}
8147c478bd9Sstevel@tonic-gate 		} else {
8157c478bd9Sstevel@tonic-gate 			/* Inside target window */
8167c478bd9Sstevel@tonic-gate 			for (i = 0; x <= wlx; x++, i++) {
8177c478bd9Sstevel@tonic-gate 				cp[x] = w->_bg;
8187c478bd9Sstevel@tonic-gate 				cp[x]._f = (short)(i % bgWidth == 0);
8197c478bd9Sstevel@tonic-gate 			}
8207c478bd9Sstevel@tonic-gate 		}
8217c478bd9Sstevel@tonic-gate 	}
822*759f6fc9Srm 	wmax = x - dx;		/* Defaults */
823*759f6fc9Srm 	wmin = xi - dx;
824*759f6fc9Srm 	if ((xi < dx) || (x >= dx + w->_maxx)) {
8257c478bd9Sstevel@tonic-gate 		/* Overlaps parent. Must touch parent and child */
8267c478bd9Sstevel@tonic-gate 		int	pmin, pmax;
8277c478bd9Sstevel@tonic-gate 
828*759f6fc9Srm 		pmax = dx;		/* Defaults */
829*759f6fc9Srm 		pmin = dx + w->_maxx;
830*759f6fc9Srm 		if (xi < dx) {
8317c478bd9Sstevel@tonic-gate 			wmin = 0;
8327c478bd9Sstevel@tonic-gate 			pmin = xi;
8337c478bd9Sstevel@tonic-gate 		}
834*759f6fc9Srm 		if (x >= dx + w->_maxx) {
8357c478bd9Sstevel@tonic-gate 			/* Ends right of target window */
8367c478bd9Sstevel@tonic-gate 			wmax = w->_maxx;
8377c478bd9Sstevel@tonic-gate 			pmax = x;
8387c478bd9Sstevel@tonic-gate 		}
8397c478bd9Sstevel@tonic-gate 		if (pmin < parent->_first[parentY])
8407c478bd9Sstevel@tonic-gate 			parent->_first[parentY] = (short)pmin;
8417c478bd9Sstevel@tonic-gate 		if (pmax > parent->_last[parentY])
8427c478bd9Sstevel@tonic-gate 			parent->_last[parentY] = (short)pmax;
8437c478bd9Sstevel@tonic-gate 	}
8447c478bd9Sstevel@tonic-gate 	if (wmin < w->_first[y])
8457c478bd9Sstevel@tonic-gate 		w->_first[y] = (short)wmin;
8467c478bd9Sstevel@tonic-gate 	if (wmax > w->_last[y])
8477c478bd9Sstevel@tonic-gate 		w->_last[y] = (short)wmax;
8487c478bd9Sstevel@tonic-gate }
8497c478bd9Sstevel@tonic-gate 
8507c478bd9Sstevel@tonic-gate /*
8517c478bd9Sstevel@tonic-gate  * Erase region from (y,x) to (ly, lx) inclusive.  The
8527c478bd9Sstevel@tonic-gate  * region is extended left and right in the case where
8537c478bd9Sstevel@tonic-gate  * the portions of a multicolumn characters are erased.
8547c478bd9Sstevel@tonic-gate  *
8557c478bd9Sstevel@tonic-gate  * Return -1 if the region is not an integral multiple
8567c478bd9Sstevel@tonic-gate  * of the background character, else zero for success.
8577c478bd9Sstevel@tonic-gate  */
8587c478bd9Sstevel@tonic-gate int
__m_cc_erase(WINDOW * w,int y,int x,int ly,int lx)8597c478bd9Sstevel@tonic-gate __m_cc_erase(WINDOW *w, int y, int x, int ly, int lx)
8607c478bd9Sstevel@tonic-gate {
8617c478bd9Sstevel@tonic-gate 	int	bgWidth;
8627c478bd9Sstevel@tonic-gate 
8637c478bd9Sstevel@tonic-gate 	if (ly < y)
8647c478bd9Sstevel@tonic-gate 		return (-1);
8657c478bd9Sstevel@tonic-gate 
8667c478bd9Sstevel@tonic-gate 	if (w->_maxy <= ly)
8677c478bd9Sstevel@tonic-gate 		ly = w->_maxy - 1;
8687c478bd9Sstevel@tonic-gate 
8697c478bd9Sstevel@tonic-gate 	/*
8707c478bd9Sstevel@tonic-gate 	 * Is the region to blank out an integral width of the
8717c478bd9Sstevel@tonic-gate 	 * background character?
8727c478bd9Sstevel@tonic-gate 	 */
8737c478bd9Sstevel@tonic-gate 	bgWidth = __m_cc_width(&w->_bg);
8747c478bd9Sstevel@tonic-gate 
8757c478bd9Sstevel@tonic-gate 	if (bgWidth <= 0)
8767c478bd9Sstevel@tonic-gate 		return (-1);
8777c478bd9Sstevel@tonic-gate 
8787c478bd9Sstevel@tonic-gate 	/*
8797c478bd9Sstevel@tonic-gate 	 * Erase Pattern will look like:
8807c478bd9Sstevel@tonic-gate 	 *			EEEEEEE|
8817c478bd9Sstevel@tonic-gate 	 *	EEEEEEEEEEEEEEE|
8827c478bd9Sstevel@tonic-gate 	 *	EEEEEEEEEEE    |
8837c478bd9Sstevel@tonic-gate 	 */
8847c478bd9Sstevel@tonic-gate 	if (w->_parent) {
8857c478bd9Sstevel@tonic-gate 		/*
8867c478bd9Sstevel@tonic-gate 		 * Use slower alg. for subwindows.
8877c478bd9Sstevel@tonic-gate 		 * They might erase stuff in parent-context
8887c478bd9Sstevel@tonic-gate 		 */
8897c478bd9Sstevel@tonic-gate 		int	parentBGWidth = __m_cc_width(&w->_parent->_bg);
8907c478bd9Sstevel@tonic-gate 		for (; y < ly; ++y, x = 0) {
8917c478bd9Sstevel@tonic-gate 			__m_cc_erase_in_line_sub(w, y, x, w->_maxx-1,
8927c478bd9Sstevel@tonic-gate 				bgWidth, parentBGWidth);
8937c478bd9Sstevel@tonic-gate 		}
8947c478bd9Sstevel@tonic-gate 		__m_cc_erase_in_line_sub(w, y, x, lx, bgWidth, parentBGWidth);
8957c478bd9Sstevel@tonic-gate 	} else {
8967c478bd9Sstevel@tonic-gate 		/* Root windows - no need to work in parent context at all */
8977c478bd9Sstevel@tonic-gate 		if (w->_maxx <= lx)
8987c478bd9Sstevel@tonic-gate 			lx = w->_maxx - 1;
8997c478bd9Sstevel@tonic-gate 
9007c478bd9Sstevel@tonic-gate 		/*
9017c478bd9Sstevel@tonic-gate 		 * Erase from first whole character (inclusive) to next
9027c478bd9Sstevel@tonic-gate 		 * character (exclusive).
9037c478bd9Sstevel@tonic-gate 		 */
9047c478bd9Sstevel@tonic-gate 		x = __m_cc_first(w, y, x);
9057c478bd9Sstevel@tonic-gate 		lx = __m_cc_next(w, ly, lx) - 1;
9067c478bd9Sstevel@tonic-gate 
9077c478bd9Sstevel@tonic-gate 		for (; y < ly; ++y, x = 0) {
9087c478bd9Sstevel@tonic-gate 			__m_cc_erase_in_line(w, y, x, w->_maxx-1, bgWidth);
9097c478bd9Sstevel@tonic-gate 		}
9107c478bd9Sstevel@tonic-gate 		__m_cc_erase_in_line(w, y, x, lx, bgWidth);
9117c478bd9Sstevel@tonic-gate 	}
9127c478bd9Sstevel@tonic-gate 	return (0);
9137c478bd9Sstevel@tonic-gate }
9147c478bd9Sstevel@tonic-gate 
9157c478bd9Sstevel@tonic-gate /*
9167c478bd9Sstevel@tonic-gate  * Expand the character to the left or right of the given position.
9177c478bd9Sstevel@tonic-gate  * Return the value returned by __m_cc_replace().
9187c478bd9Sstevel@tonic-gate  */
9197c478bd9Sstevel@tonic-gate int
__m_cc_expand(WINDOW * w,int y,int x,int side)9207c478bd9Sstevel@tonic-gate __m_cc_expand(WINDOW *w, int y, int x, int side)
9217c478bd9Sstevel@tonic-gate {
9227c478bd9Sstevel@tonic-gate 	cchar_t	cc;
9237c478bd9Sstevel@tonic-gate 	int	dx, width;
9247c478bd9Sstevel@tonic-gate 
9257c478bd9Sstevel@tonic-gate 	width = __m_cc_width(&w->_line[y][x]);
9267c478bd9Sstevel@tonic-gate 
9277c478bd9Sstevel@tonic-gate 	if (side < 0)
9287c478bd9Sstevel@tonic-gate 		dx = __m_cc_next(w, y, x) - width;
9297c478bd9Sstevel@tonic-gate 	else if (0 < side)
9307c478bd9Sstevel@tonic-gate 		dx = __m_cc_first(w, y, x);
9317c478bd9Sstevel@tonic-gate 	else
9327c478bd9Sstevel@tonic-gate 		return (-1);
9337c478bd9Sstevel@tonic-gate 
9347c478bd9Sstevel@tonic-gate 	/*
9357c478bd9Sstevel@tonic-gate 	 * __m_cc_replace() will erase the region containing
9367c478bd9Sstevel@tonic-gate 	 * the character we want to expand.
9377c478bd9Sstevel@tonic-gate 	 */
9387c478bd9Sstevel@tonic-gate 	cc = w->_line[y][x];
9397c478bd9Sstevel@tonic-gate 
9407c478bd9Sstevel@tonic-gate 	return (__m_cc_replace(w, y, dx, &cc, 0));
9417c478bd9Sstevel@tonic-gate }
9427c478bd9Sstevel@tonic-gate 
9437c478bd9Sstevel@tonic-gate /* Revised version of __m_cc_compare() to compare only the char parts */
9447c478bd9Sstevel@tonic-gate 
9457c478bd9Sstevel@tonic-gate int
__m_cc_equal(const cchar_t * c1,const cchar_t * c2)9467c478bd9Sstevel@tonic-gate __m_cc_equal(const cchar_t *c1, const cchar_t *c2)
9477c478bd9Sstevel@tonic-gate {
9487c478bd9Sstevel@tonic-gate 	int	i;
9497c478bd9Sstevel@tonic-gate 
9507c478bd9Sstevel@tonic-gate 	if (c1->_f != c2->_f)
9517c478bd9Sstevel@tonic-gate 		return (0);
9527c478bd9Sstevel@tonic-gate 	if (c1->_n != c2->_n)
9537c478bd9Sstevel@tonic-gate 		return (0);
9547c478bd9Sstevel@tonic-gate 	for (i = 0; i < c1->_n; ++i)
9557c478bd9Sstevel@tonic-gate 		if (c1->_wc[i] != c2->_wc[i])
9567c478bd9Sstevel@tonic-gate 			return (0);
9577c478bd9Sstevel@tonic-gate 	return (1);
9587c478bd9Sstevel@tonic-gate }
9597c478bd9Sstevel@tonic-gate 
9607c478bd9Sstevel@tonic-gate /*
9617c478bd9Sstevel@tonic-gate  * Return true if characters are equal.
9627c478bd9Sstevel@tonic-gate  *
9637c478bd9Sstevel@tonic-gate  * NOTE to guarantee correct results, make sure that both
9647c478bd9Sstevel@tonic-gate  * characters have been passed through __m_cc_sort().
9657c478bd9Sstevel@tonic-gate  */
9667c478bd9Sstevel@tonic-gate int
__m_cc_compare(const cchar_t * c1,const cchar_t * c2,int exact)9677c478bd9Sstevel@tonic-gate __m_cc_compare(const cchar_t *c1, const cchar_t *c2, int exact)
9687c478bd9Sstevel@tonic-gate {
9697c478bd9Sstevel@tonic-gate 	int	i;
9707c478bd9Sstevel@tonic-gate 
9717c478bd9Sstevel@tonic-gate 	if (exact && c1->_f != c2->_f)
9727c478bd9Sstevel@tonic-gate 		return (0);
9737c478bd9Sstevel@tonic-gate 	if (c1->_n != c2->_n)
9747c478bd9Sstevel@tonic-gate 		return (0);
9757c478bd9Sstevel@tonic-gate 	if ((c1->_at & ~WA_COOKIE) != (c2->_at & ~WA_COOKIE))
9767c478bd9Sstevel@tonic-gate 		return (0);
9777c478bd9Sstevel@tonic-gate 	if (c1->_co != c2->_co)
9787c478bd9Sstevel@tonic-gate 		return (0);
9797c478bd9Sstevel@tonic-gate 
9807c478bd9Sstevel@tonic-gate 	for (i = 0; i < c1->_n; ++i)
9817c478bd9Sstevel@tonic-gate 		if (c1->_wc[i] != c2->_wc[i])
9827c478bd9Sstevel@tonic-gate 			return (0);
9837c478bd9Sstevel@tonic-gate 
9847c478bd9Sstevel@tonic-gate 	return (1);
9857c478bd9Sstevel@tonic-gate }
9867c478bd9Sstevel@tonic-gate 
9877c478bd9Sstevel@tonic-gate /*
9887c478bd9Sstevel@tonic-gate  * Write to the stream the character portion of a cchar_t.
9897c478bd9Sstevel@tonic-gate  */
9907c478bd9Sstevel@tonic-gate int
__m_cc_write(const cchar_t * cc)9917c478bd9Sstevel@tonic-gate __m_cc_write(const cchar_t *cc)
9927c478bd9Sstevel@tonic-gate {
9937c478bd9Sstevel@tonic-gate 	int	j;
9947c478bd9Sstevel@tonic-gate 	size_t	i;
9957c478bd9Sstevel@tonic-gate 	char	mb[MB_LEN_MAX];
9967c478bd9Sstevel@tonic-gate /*
9977c478bd9Sstevel@tonic-gate  * 4131273 UNIX98: xcurses library renders complex characters incorrectly
9987c478bd9Sstevel@tonic-gate  */
9997c478bd9Sstevel@tonic-gate 	int	backed_up = 0;
10007c478bd9Sstevel@tonic-gate 
10017c478bd9Sstevel@tonic-gate 	for (i = 0; i < cc->_n; ++i) {
10027c478bd9Sstevel@tonic-gate 		j = wctomb(mb, cc->_wc[i]);
10037c478bd9Sstevel@tonic-gate 		if (j == -1)
10047c478bd9Sstevel@tonic-gate 			return (EOF);
10057c478bd9Sstevel@tonic-gate 		if (i == 1) {
10067c478bd9Sstevel@tonic-gate 			/*
10077c478bd9Sstevel@tonic-gate 			 * Move cursor back where it was
10087c478bd9Sstevel@tonic-gate 			 */
10097c478bd9Sstevel@tonic-gate 			if (fwrite(cursor_left, 1, strlen(cursor_left),
10107c478bd9Sstevel@tonic-gate 				__m_screen->_of) == 0) {
10117c478bd9Sstevel@tonic-gate 				return (EOF);
10127c478bd9Sstevel@tonic-gate 			}
10137c478bd9Sstevel@tonic-gate 			backed_up = 1;
10147c478bd9Sstevel@tonic-gate 		}
10157c478bd9Sstevel@tonic-gate 		if (fwrite(mb, sizeof (*mb), (size_t)j, __m_screen->_of) == 0) {
10167c478bd9Sstevel@tonic-gate 			return (EOF);
10177c478bd9Sstevel@tonic-gate 		}
10187c478bd9Sstevel@tonic-gate 	}
10197c478bd9Sstevel@tonic-gate 	if (backed_up) {
10207c478bd9Sstevel@tonic-gate 		/*
10217c478bd9Sstevel@tonic-gate 		 * Move cursor back where it was
10227c478bd9Sstevel@tonic-gate 		 */
10237c478bd9Sstevel@tonic-gate 		if (fwrite(cursor_right, 1, strlen(cursor_right),
10247c478bd9Sstevel@tonic-gate 			__m_screen->_of) == 0) {
10257c478bd9Sstevel@tonic-gate 			return (EOF);
10267c478bd9Sstevel@tonic-gate 		}
10277c478bd9Sstevel@tonic-gate 	}
10287c478bd9Sstevel@tonic-gate 
10297c478bd9Sstevel@tonic-gate 	__m_screen->_flags |= W_FLUSH;
10307c478bd9Sstevel@tonic-gate 	return (0);
10317c478bd9Sstevel@tonic-gate }
1032