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 #pragma ident "%Z%%M% %I% %E% SMI" 32 33 /*LINTLIBRARY*/ 34 35 #include <sys/types.h> 36 #include "curses_inc.h" 37 38 /* 39 * Clear the space occupied by a multicolumn character 40 */ 41 42 int 43 _mbclrch(WINDOW *win, int y, int x) 44 { 45 chtype *wcp, *ep, *wp, wc; 46 47 /* ASSERT(_scrmax > 1); */ 48 49 wcp = win->_y[y]; 50 wp = wcp + x; 51 52 /* compute the bounds for the character */ 53 if (ISCBIT(*wp)) { 54 for (; wp >= wcp; --wp) 55 if (!ISCBIT(*wp)) 56 break; 57 if (wp < wcp) 58 return (ERR); 59 } 60 wc = RBYTE(*wp); 61 ep = wp + _curs_scrwidth[TYPE(wc)]; 62 if (ep > wcp + win->_maxx) 63 return (ERR); 64 65 /* update the change structure */ 66 /*LINTED*/ 67 if ((x = (int)(wp - wcp)) < win->_firstch[y]) 68 /*LINTED*/ 69 win->_firstch[y] = (short)x; 70 /*LINTED*/ 71 if ((x = (int)(ep - wcp) - 1) > win->_lastch[y]) 72 /*LINTED*/ 73 win->_lastch[y] = (short)x; 74 75 /* clear the character */ 76 for (; wp < ep; ++wp) 77 *wp = win->_bkgd; 78 return (OK); 79 } 80 81 82 83 /* 84 * Make sure the window cursor point to a valid place. 85 * If win->_insmode or isedge, the cursor has to 86 * point to the start of a whole character; otherwise, the 87 * cursor has to point to a part of a whole character. 88 */ 89 90 int 91 _mbvalid(WINDOW *win) 92 { 93 chtype *wp, *wcp, *ecp, wc; 94 int x; 95 bool isedge; 96 97 /* ASSERT(_scrmax > 1); */ 98 99 x = win->_curx; 100 wcp = win->_y[win->_cury]; 101 wp = wcp + x; 102 if (!ISMBIT(*wp)) 103 return (OK); 104 105 ecp = wcp + win->_maxx; 106 isedge = FALSE; 107 108 /* make wp points to the start column of a mb-character */ 109 if (ISCBIT(*wp)) { 110 for (; wp >= wcp; --wp) 111 if (!ISCBIT(*wp)) 112 break; 113 if (wp < wcp) { 114 for (wp = wcp + x + 1; wp < ecp; ++wp) 115 if (!ISCBIT(*wp)) 116 break; 117 if (wp >= ecp) 118 return (ERR); 119 isedge = TRUE; 120 } 121 } 122 123 /* make sure that wp points to a whole character */ 124 wc = RBYTE(*wp); 125 if (wp + _curs_scrwidth[TYPE(wc)] > ecp) { 126 for (wp -= 1; wp >= wcp; --wp) 127 if (!ISCBIT(*wp)) 128 break; 129 if (wp < wcp) 130 return (ERR); 131 isedge = TRUE; 132 } 133 134 if (isedge || win->_insmode) 135 /*LINTED*/ 136 win->_curx = (short)(wp-wcp); 137 return (OK); 138 } 139 140 141 142 /* 143 * Add/insert multi-byte characters 144 */ 145 146 int 147 _mbaddch(WINDOW *win, chtype a, chtype c) 148 { 149 int n, x, y, nc, m, len, nbyte, ty; 150 chtype *wcp, wc; 151 char *wch, rc[2]; 152 153 /* ASSERT(_mbtrue); */ 154 155 /* decode the character into a sequence of bytes */ 156 nc = 0; 157 if (ISCBIT(c)) 158 /*LINTED*/ 159 rc[nc++] = (char)(LBYTE(c)|MBIT); 160 if (ISMBIT(c)) 161 /*LINTED*/ 162 rc[nc++] = (char)RBYTE(c); 163 164 a |= win->_attrs; 165 166 /* add the sequence to the image */ 167 for (n = 0; n < nc; ++n) { 168 wc = RBYTE(rc[n]); 169 ty = TYPE(wc); 170 wch = win->_waitc; 171 172 /* first byte of a multi-byte character */ 173 if (ty > 0 || win->_nbyte < 0) { 174 /*LINTED*/ 175 wch[0] = (char)wc; 176 win->_nbyte = cswidth[ty] + (ty == 0 ? 0 : 1); 177 win->_index = 1; 178 } else { 179 /* non-first byte */ 180 /*LINTED*/ 181 wch[win->_index] = (char)wc; 182 win->_index += 1; 183 } 184 185 /* if character is not ready to process */ 186 if (win->_index < win->_nbyte) 187 continue; 188 189 /* begin processing the character */ 190 nbyte = win->_nbyte; 191 win->_nbyte = -1; 192 wc = RBYTE(wch[0]); 193 len = _curs_scrwidth[TYPE(wc)]; 194 195 /* window too small or char cannot be stored */ 196 if (len > win->_maxx || 2*len < nbyte) 197 continue; 198 199 /* if the character won't fit into the line */ 200 if ((win->_curx + len) > win->_maxx && 201 (win->_insmode || waddch(win, '\n') == ERR)) 202 continue; 203 204 y = win->_cury; 205 x = win->_curx; 206 wcp = win->_y[y] + x; 207 208 if (win->_insmode) { 209 /* perform the right shift */ 210 if (_mbinsshift(win, len) == ERR) 211 continue; 212 } else if (_scrmax > 1) { 213 /* clear any multi-byte char about to be overwritten */ 214 for (m = 0; m < len; ++m) 215 if (ISMBIT(wcp[m]) && 216 _mbclrch(win, y, x + m) == ERR) 217 break; 218 if (m < len) 219 continue; 220 } 221 222 /* pack two bytes at a time */ 223 for (m = nbyte/2; m > 0; m -= 1, wch += 2) 224 *wcp++ = _CHAR((RBYTE(wch[1]) << 8) | 225 RBYTE(wch[0])) | CBIT | a; 226 227 /* do the remaining byte if any */ 228 if ((nbyte%2) != 0) 229 *wcp++ = RBYTE(wch[0]) | CBIT | a; 230 231 /* fill-in for remaining display columns */ 232 for (m = (nbyte / 2) + (nbyte % 2); m < len; ++m) 233 *wcp++ = (CBIT|MBIT) | a; 234 235 /* the first column has Continue BIT off */ 236 win->_y[y][x] &= ~CBIT; 237 238 if (win->_insmode == FALSE) { 239 if (x < win->_firstch[y]) 240 /*LINTED*/ 241 win->_firstch[y] = (short)x; 242 if ((x += len-1) >= win->_maxx) 243 x = win->_maxx-1; 244 if (x > win->_lastch[y]) 245 /*LINTED*/ 246 win->_lastch[y] = (short)x; 247 248 if ((win->_curx += len) >= win->_maxx) { 249 if (y >= (win->_maxy-1) || y == win->_bmarg) { 250 win->_curx = win->_maxx-1; 251 if (wscrl(win, 1) == ERR) 252 continue; 253 } else { 254 win->_cury += 1; 255 win->_curx = 0; 256 } 257 } 258 } 259 } 260 261 return (OK); 262 } 263