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