summaryrefslogtreecommitdiff
path: root/usr/src/lib/libcurses/screen/mbaddch.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libcurses/screen/mbaddch.c')
-rw-r--r--usr/src/lib/libcurses/screen/mbaddch.c262
1 files changed, 262 insertions, 0 deletions
diff --git a/usr/src/lib/libcurses/screen/mbaddch.c b/usr/src/lib/libcurses/screen/mbaddch.c
new file mode 100644
index 0000000000..b4807f5fa8
--- /dev/null
+++ b/usr/src/lib/libcurses/screen/mbaddch.c
@@ -0,0 +1,262 @@
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*LINTLIBRARY*/
+
+#include <sys/types.h>
+#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);
+}