/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* Copyright (c) 1988 AT&T */ /* All Rights Reserved */ /* * Copyright (c) 1997, by Sun Microsystems, Inc. * All rights reserved. */ /*LINTLIBRARY*/ #include #include "curses_inc.h" /* * Clear the space occupied by a multicolumn character */ int _mbclrch(WINDOW *win, int y, int x) { chtype *wcp, *ep, *wp, wc; /* ASSERT(_scrmax > 1); */ wcp = win->_y[y]; wp = wcp + x; /* compute the bounds for the character */ if (ISCBIT(*wp)) { for (; wp >= wcp; --wp) if (!ISCBIT(*wp)) break; if (wp < wcp) return (ERR); } wc = RBYTE(*wp); ep = wp + _curs_scrwidth[TYPE(wc)]; if (ep > wcp + win->_maxx) return (ERR); /* update the change structure */ /*LINTED*/ if ((x = (int)(wp - wcp)) < win->_firstch[y]) /*LINTED*/ win->_firstch[y] = (short)x; /*LINTED*/ if ((x = (int)(ep - wcp) - 1) > win->_lastch[y]) /*LINTED*/ win->_lastch[y] = (short)x; /* clear the character */ for (; wp < ep; ++wp) *wp = win->_bkgd; return (OK); } /* * Make sure the window cursor point to a valid place. * If win->_insmode or isedge, the cursor has to * point to the start of a whole character; otherwise, the * cursor has to point to a part of a whole character. */ int _mbvalid(WINDOW *win) { chtype *wp, *wcp, *ecp, wc; int x; bool isedge; /* ASSERT(_scrmax > 1); */ x = win->_curx; wcp = win->_y[win->_cury]; wp = wcp + x; if (!ISMBIT(*wp)) return (OK); ecp = wcp + win->_maxx; isedge = FALSE; /* make wp points to the start column of a mb-character */ if (ISCBIT(*wp)) { for (; wp >= wcp; --wp) if (!ISCBIT(*wp)) break; if (wp < wcp) { for (wp = wcp + x + 1; wp < ecp; ++wp) if (!ISCBIT(*wp)) break; if (wp >= ecp) return (ERR); isedge = TRUE; } } /* make sure that wp points to a whole character */ wc = RBYTE(*wp); if (wp + _curs_scrwidth[TYPE(wc)] > ecp) { for (wp -= 1; wp >= wcp; --wp) if (!ISCBIT(*wp)) break; if (wp < wcp) return (ERR); isedge = TRUE; } if (isedge || win->_insmode) /*LINTED*/ win->_curx = (short)(wp-wcp); return (OK); } /* * Add/insert multi-byte characters */ int _mbaddch(WINDOW *win, chtype a, chtype c) { int n, x, y, nc, m, len, nbyte, ty; chtype *wcp, wc; char *wch, rc[2]; /* ASSERT(_mbtrue); */ /* decode the character into a sequence of bytes */ nc = 0; if (ISCBIT(c)) /*LINTED*/ rc[nc++] = (char)(LBYTE(c)|MBIT); if (ISMBIT(c)) /*LINTED*/ rc[nc++] = (char)RBYTE(c); a |= win->_attrs; /* add the sequence to the image */ for (n = 0; n < nc; ++n) { wc = RBYTE(rc[n]); ty = TYPE(wc); wch = win->_waitc; /* first byte of a multi-byte character */ if (ty > 0 || win->_nbyte < 0) { /*LINTED*/ wch[0] = (char)wc; win->_nbyte = cswidth[ty] + (ty == 0 ? 0 : 1); win->_index = 1; } else { /* non-first byte */ /*LINTED*/ wch[win->_index] = (char)wc; win->_index += 1; } /* if character is not ready to process */ if (win->_index < win->_nbyte) continue; /* begin processing the character */ nbyte = win->_nbyte; win->_nbyte = -1; wc = RBYTE(wch[0]); len = _curs_scrwidth[TYPE(wc)]; /* window too small or char cannot be stored */ if (len > win->_maxx || 2*len < nbyte) continue; /* if the character won't fit into the line */ if ((win->_curx + len) > win->_maxx && (win->_insmode || waddch(win, '\n') == ERR)) continue; y = win->_cury; x = win->_curx; wcp = win->_y[y] + x; if (win->_insmode) { /* perform the right shift */ if (_mbinsshift(win, len) == ERR) continue; } else if (_scrmax > 1) { /* clear any multi-byte char about to be overwritten */ for (m = 0; m < len; ++m) if (ISMBIT(wcp[m]) && _mbclrch(win, y, x + m) == ERR) break; if (m < len) continue; } /* pack two bytes at a time */ for (m = nbyte/2; m > 0; m -= 1, wch += 2) *wcp++ = _CHAR((RBYTE(wch[1]) << 8) | RBYTE(wch[0])) | CBIT | a; /* do the remaining byte if any */ if ((nbyte%2) != 0) *wcp++ = RBYTE(wch[0]) | CBIT | a; /* fill-in for remaining display columns */ for (m = (nbyte / 2) + (nbyte % 2); m < len; ++m) *wcp++ = (CBIT|MBIT) | a; /* the first column has Continue BIT off */ win->_y[y][x] &= ~CBIT; if (win->_insmode == FALSE) { if (x < win->_firstch[y]) /*LINTED*/ win->_firstch[y] = (short)x; if ((x += len-1) >= win->_maxx) x = win->_maxx-1; if (x > win->_lastch[y]) /*LINTED*/ win->_lastch[y] = (short)x; if ((win->_curx += len) >= win->_maxx) { if (y >= (win->_maxy-1) || y == win->_bmarg) { win->_curx = win->_maxx-1; if (wscrl(win, 1) == ERR) continue; } else { win->_cury += 1; win->_curx = 0; } } } } return (OK); }