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 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 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 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