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