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