xref: /onnv-gate/usr/src/lib/libcurses/screen/mbaddch.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*  Copyright (c) 1988 AT&T */
23*0Sstevel@tonic-gate /*    All Rights Reserved   */
24*0Sstevel@tonic-gate 
25*0Sstevel@tonic-gate 
26*0Sstevel@tonic-gate /*
27*0Sstevel@tonic-gate  *      Copyright (c) 1997, by Sun Microsystems, Inc.
28*0Sstevel@tonic-gate  *      All rights reserved.
29*0Sstevel@tonic-gate  */
30*0Sstevel@tonic-gate 
31*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
32*0Sstevel@tonic-gate 
33*0Sstevel@tonic-gate /*LINTLIBRARY*/
34*0Sstevel@tonic-gate 
35*0Sstevel@tonic-gate #include	<sys/types.h>
36*0Sstevel@tonic-gate #include	"curses_inc.h"
37*0Sstevel@tonic-gate 
38*0Sstevel@tonic-gate /*
39*0Sstevel@tonic-gate  *	Clear the space occupied by a multicolumn character
40*0Sstevel@tonic-gate  */
41*0Sstevel@tonic-gate 
42*0Sstevel@tonic-gate int
_mbclrch(WINDOW * win,int y,int x)43*0Sstevel@tonic-gate _mbclrch(WINDOW *win, int y, int x)
44*0Sstevel@tonic-gate {
45*0Sstevel@tonic-gate 	chtype	*wcp, *ep, *wp, wc;
46*0Sstevel@tonic-gate 
47*0Sstevel@tonic-gate 	/* ASSERT(_scrmax > 1); */
48*0Sstevel@tonic-gate 
49*0Sstevel@tonic-gate 	wcp = win->_y[y];
50*0Sstevel@tonic-gate 	wp = wcp + x;
51*0Sstevel@tonic-gate 
52*0Sstevel@tonic-gate 	/* compute the bounds for the character */
53*0Sstevel@tonic-gate 	if (ISCBIT(*wp)) {
54*0Sstevel@tonic-gate 		for (; wp >= wcp; --wp)
55*0Sstevel@tonic-gate 			if (!ISCBIT(*wp))
56*0Sstevel@tonic-gate 				break;
57*0Sstevel@tonic-gate 		if (wp < wcp)
58*0Sstevel@tonic-gate 			return (ERR);
59*0Sstevel@tonic-gate 	}
60*0Sstevel@tonic-gate 	wc = RBYTE(*wp);
61*0Sstevel@tonic-gate 	ep = wp + _curs_scrwidth[TYPE(wc)];
62*0Sstevel@tonic-gate 	if (ep > wcp + win->_maxx)
63*0Sstevel@tonic-gate 		return (ERR);
64*0Sstevel@tonic-gate 
65*0Sstevel@tonic-gate 	/* update the change structure */
66*0Sstevel@tonic-gate 	/*LINTED*/
67*0Sstevel@tonic-gate 	if ((x = (int)(wp - wcp)) < win->_firstch[y])
68*0Sstevel@tonic-gate 		/*LINTED*/
69*0Sstevel@tonic-gate 		win->_firstch[y] = (short)x;
70*0Sstevel@tonic-gate 	/*LINTED*/
71*0Sstevel@tonic-gate 	if ((x = (int)(ep - wcp) - 1) > win->_lastch[y])
72*0Sstevel@tonic-gate 		/*LINTED*/
73*0Sstevel@tonic-gate 		win->_lastch[y] = (short)x;
74*0Sstevel@tonic-gate 
75*0Sstevel@tonic-gate 	/* clear the character */
76*0Sstevel@tonic-gate 	for (; wp < ep; ++wp)
77*0Sstevel@tonic-gate 		*wp = win->_bkgd;
78*0Sstevel@tonic-gate 	return (OK);
79*0Sstevel@tonic-gate }
80*0Sstevel@tonic-gate 
81*0Sstevel@tonic-gate 
82*0Sstevel@tonic-gate 
83*0Sstevel@tonic-gate /*
84*0Sstevel@tonic-gate  *	Make sure the window cursor point to a valid place.
85*0Sstevel@tonic-gate  *	If win->_insmode or isedge, the cursor has to
86*0Sstevel@tonic-gate  *	point to the start of a whole character; otherwise, the
87*0Sstevel@tonic-gate  *	cursor has to point to a part of a whole character.
88*0Sstevel@tonic-gate  */
89*0Sstevel@tonic-gate 
90*0Sstevel@tonic-gate int
_mbvalid(WINDOW * win)91*0Sstevel@tonic-gate _mbvalid(WINDOW *win)
92*0Sstevel@tonic-gate {
93*0Sstevel@tonic-gate 	chtype	*wp, *wcp, *ecp, wc;
94*0Sstevel@tonic-gate 	int		x;
95*0Sstevel@tonic-gate 	bool	isedge;
96*0Sstevel@tonic-gate 
97*0Sstevel@tonic-gate 	/* ASSERT(_scrmax > 1); */
98*0Sstevel@tonic-gate 
99*0Sstevel@tonic-gate 	x = win->_curx;
100*0Sstevel@tonic-gate 	wcp = win->_y[win->_cury];
101*0Sstevel@tonic-gate 	wp = wcp + x;
102*0Sstevel@tonic-gate 	if (!ISMBIT(*wp))
103*0Sstevel@tonic-gate 		return (OK);
104*0Sstevel@tonic-gate 
105*0Sstevel@tonic-gate 	ecp = wcp + win->_maxx;
106*0Sstevel@tonic-gate 	isedge = FALSE;
107*0Sstevel@tonic-gate 
108*0Sstevel@tonic-gate 	/* make wp points to the start column of a mb-character */
109*0Sstevel@tonic-gate 	if (ISCBIT(*wp)) {
110*0Sstevel@tonic-gate 		for (; wp >= wcp; --wp)
111*0Sstevel@tonic-gate 			if (!ISCBIT(*wp))
112*0Sstevel@tonic-gate 				break;
113*0Sstevel@tonic-gate 		if (wp < wcp) {
114*0Sstevel@tonic-gate 			for (wp = wcp + x + 1; wp < ecp; ++wp)
115*0Sstevel@tonic-gate 				if (!ISCBIT(*wp))
116*0Sstevel@tonic-gate 					break;
117*0Sstevel@tonic-gate 			if (wp >= ecp)
118*0Sstevel@tonic-gate 				return (ERR);
119*0Sstevel@tonic-gate 			isedge = TRUE;
120*0Sstevel@tonic-gate 		}
121*0Sstevel@tonic-gate 	}
122*0Sstevel@tonic-gate 
123*0Sstevel@tonic-gate 	/* make sure that wp points to a whole character */
124*0Sstevel@tonic-gate 	wc = RBYTE(*wp);
125*0Sstevel@tonic-gate 	if (wp + _curs_scrwidth[TYPE(wc)] > ecp) {
126*0Sstevel@tonic-gate 		for (wp -= 1; wp >= wcp; --wp)
127*0Sstevel@tonic-gate 			if (!ISCBIT(*wp))
128*0Sstevel@tonic-gate 				break;
129*0Sstevel@tonic-gate 		if (wp < wcp)
130*0Sstevel@tonic-gate 			return (ERR);
131*0Sstevel@tonic-gate 		isedge = TRUE;
132*0Sstevel@tonic-gate 	}
133*0Sstevel@tonic-gate 
134*0Sstevel@tonic-gate 	if (isedge || win->_insmode)
135*0Sstevel@tonic-gate 		/*LINTED*/
136*0Sstevel@tonic-gate 		win->_curx = (short)(wp-wcp);
137*0Sstevel@tonic-gate 	return (OK);
138*0Sstevel@tonic-gate }
139*0Sstevel@tonic-gate 
140*0Sstevel@tonic-gate 
141*0Sstevel@tonic-gate 
142*0Sstevel@tonic-gate /*
143*0Sstevel@tonic-gate  *	Add/insert multi-byte characters
144*0Sstevel@tonic-gate  */
145*0Sstevel@tonic-gate 
146*0Sstevel@tonic-gate int
_mbaddch(WINDOW * win,chtype a,chtype c)147*0Sstevel@tonic-gate _mbaddch(WINDOW *win, chtype a, chtype c)
148*0Sstevel@tonic-gate {
149*0Sstevel@tonic-gate 	int		n, x, y, nc, m, len, nbyte, ty;
150*0Sstevel@tonic-gate 	chtype		*wcp, wc;
151*0Sstevel@tonic-gate 	char		*wch, rc[2];
152*0Sstevel@tonic-gate 
153*0Sstevel@tonic-gate 	/* ASSERT(_mbtrue); */
154*0Sstevel@tonic-gate 
155*0Sstevel@tonic-gate 	/* decode the character into a sequence of bytes */
156*0Sstevel@tonic-gate 	nc = 0;
157*0Sstevel@tonic-gate 	if (ISCBIT(c))
158*0Sstevel@tonic-gate 		/*LINTED*/
159*0Sstevel@tonic-gate 		rc[nc++] = (char)(LBYTE(c)|MBIT);
160*0Sstevel@tonic-gate 	if (ISMBIT(c))
161*0Sstevel@tonic-gate 		/*LINTED*/
162*0Sstevel@tonic-gate 		rc[nc++] = (char)RBYTE(c);
163*0Sstevel@tonic-gate 
164*0Sstevel@tonic-gate 	a |= win->_attrs;
165*0Sstevel@tonic-gate 
166*0Sstevel@tonic-gate 	/* add the sequence to the image */
167*0Sstevel@tonic-gate 	for (n = 0; n < nc; ++n) {
168*0Sstevel@tonic-gate 		wc = RBYTE(rc[n]);
169*0Sstevel@tonic-gate 		ty = TYPE(wc);
170*0Sstevel@tonic-gate 		wch = win->_waitc;
171*0Sstevel@tonic-gate 
172*0Sstevel@tonic-gate 		/* first byte of a multi-byte character */
173*0Sstevel@tonic-gate 		if (ty > 0 || win->_nbyte < 0) {
174*0Sstevel@tonic-gate 			/*LINTED*/
175*0Sstevel@tonic-gate 			wch[0] = (char)wc;
176*0Sstevel@tonic-gate 			win->_nbyte = cswidth[ty] + (ty == 0 ? 0 : 1);
177*0Sstevel@tonic-gate 			win->_index = 1;
178*0Sstevel@tonic-gate 		} else {
179*0Sstevel@tonic-gate 		/* non-first byte */
180*0Sstevel@tonic-gate 			/*LINTED*/
181*0Sstevel@tonic-gate 			wch[win->_index] = (char)wc;
182*0Sstevel@tonic-gate 			win->_index += 1;
183*0Sstevel@tonic-gate 		}
184*0Sstevel@tonic-gate 
185*0Sstevel@tonic-gate 		/* if character is not ready to process */
186*0Sstevel@tonic-gate 		if (win->_index < win->_nbyte)
187*0Sstevel@tonic-gate 			continue;
188*0Sstevel@tonic-gate 
189*0Sstevel@tonic-gate 		/* begin processing the character */
190*0Sstevel@tonic-gate 		nbyte = win->_nbyte;
191*0Sstevel@tonic-gate 		win->_nbyte = -1;
192*0Sstevel@tonic-gate 		wc = RBYTE(wch[0]);
193*0Sstevel@tonic-gate 		len = _curs_scrwidth[TYPE(wc)];
194*0Sstevel@tonic-gate 
195*0Sstevel@tonic-gate 		/* window too small or char cannot be stored */
196*0Sstevel@tonic-gate 		if (len > win->_maxx || 2*len < nbyte)
197*0Sstevel@tonic-gate 			continue;
198*0Sstevel@tonic-gate 
199*0Sstevel@tonic-gate 		/* if the character won't fit into the line */
200*0Sstevel@tonic-gate 		if ((win->_curx + len) > win->_maxx &&
201*0Sstevel@tonic-gate 		    (win->_insmode || waddch(win, '\n') == ERR))
202*0Sstevel@tonic-gate 			continue;
203*0Sstevel@tonic-gate 
204*0Sstevel@tonic-gate 		y = win->_cury;
205*0Sstevel@tonic-gate 		x = win->_curx;
206*0Sstevel@tonic-gate 		wcp = win->_y[y] + x;
207*0Sstevel@tonic-gate 
208*0Sstevel@tonic-gate 		if (win->_insmode) {
209*0Sstevel@tonic-gate 			/* perform the right shift */
210*0Sstevel@tonic-gate 			if (_mbinsshift(win, len) == ERR)
211*0Sstevel@tonic-gate 				continue;
212*0Sstevel@tonic-gate 		} else if (_scrmax > 1) {
213*0Sstevel@tonic-gate 			/* clear any multi-byte char about to be overwritten */
214*0Sstevel@tonic-gate 			for (m = 0; m < len; ++m)
215*0Sstevel@tonic-gate 				if (ISMBIT(wcp[m]) &&
216*0Sstevel@tonic-gate 				    _mbclrch(win, y, x + m) == ERR)
217*0Sstevel@tonic-gate 					break;
218*0Sstevel@tonic-gate 			if (m < len)
219*0Sstevel@tonic-gate 				continue;
220*0Sstevel@tonic-gate 		}
221*0Sstevel@tonic-gate 
222*0Sstevel@tonic-gate 		/* pack two bytes at a time */
223*0Sstevel@tonic-gate 		for (m = nbyte/2; m > 0; m -= 1, wch += 2)
224*0Sstevel@tonic-gate 			*wcp++ = _CHAR((RBYTE(wch[1]) << 8) |
225*0Sstevel@tonic-gate 			    RBYTE(wch[0])) | CBIT | a;
226*0Sstevel@tonic-gate 
227*0Sstevel@tonic-gate 		/* do the remaining byte if any */
228*0Sstevel@tonic-gate 		if ((nbyte%2) != 0)
229*0Sstevel@tonic-gate 			*wcp++ = RBYTE(wch[0]) | CBIT | a;
230*0Sstevel@tonic-gate 
231*0Sstevel@tonic-gate 		/* fill-in for remaining display columns */
232*0Sstevel@tonic-gate 		for (m = (nbyte / 2) + (nbyte % 2); m < len; ++m)
233*0Sstevel@tonic-gate 			*wcp++ = (CBIT|MBIT) | a;
234*0Sstevel@tonic-gate 
235*0Sstevel@tonic-gate 		/* the first column has Continue BIT off */
236*0Sstevel@tonic-gate 		win->_y[y][x] &= ~CBIT;
237*0Sstevel@tonic-gate 
238*0Sstevel@tonic-gate 		if (win->_insmode == FALSE) {
239*0Sstevel@tonic-gate 			if (x < win->_firstch[y])
240*0Sstevel@tonic-gate 				/*LINTED*/
241*0Sstevel@tonic-gate 				win->_firstch[y] = (short)x;
242*0Sstevel@tonic-gate 			if ((x += len-1) >= win->_maxx)
243*0Sstevel@tonic-gate 				x = win->_maxx-1;
244*0Sstevel@tonic-gate 			if (x > win->_lastch[y])
245*0Sstevel@tonic-gate 				/*LINTED*/
246*0Sstevel@tonic-gate 				win->_lastch[y] = (short)x;
247*0Sstevel@tonic-gate 
248*0Sstevel@tonic-gate 			if ((win->_curx += len) >= win->_maxx) {
249*0Sstevel@tonic-gate 				if (y >= (win->_maxy-1) || y == win->_bmarg) {
250*0Sstevel@tonic-gate 					win->_curx = win->_maxx-1;
251*0Sstevel@tonic-gate 					if (wscrl(win, 1) == ERR)
252*0Sstevel@tonic-gate 						continue;
253*0Sstevel@tonic-gate 				} else {
254*0Sstevel@tonic-gate 					win->_cury += 1;
255*0Sstevel@tonic-gate 					win->_curx = 0;
256*0Sstevel@tonic-gate 				}
257*0Sstevel@tonic-gate 			}
258*0Sstevel@tonic-gate 		}
259*0Sstevel@tonic-gate 	}
260*0Sstevel@tonic-gate 
261*0Sstevel@tonic-gate 	return (OK);
262*0Sstevel@tonic-gate }
263