17c478bdstevel@tonic-gate/*
27c478bdstevel@tonic-gate * CDDL HEADER START
37c478bdstevel@tonic-gate *
47c478bdstevel@tonic-gate * The contents of this file are subject to the terms of the
57c478bdstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
67c478bdstevel@tonic-gate * (the "License").  You may not use this file except in compliance
77c478bdstevel@tonic-gate * with the License.
87c478bdstevel@tonic-gate *
97c478bdstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bdstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bdstevel@tonic-gate * See the License for the specific language governing permissions
127c478bdstevel@tonic-gate * and limitations under the License.
137c478bdstevel@tonic-gate *
147c478bdstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bdstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bdstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bdstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bdstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bdstevel@tonic-gate *
207c478bdstevel@tonic-gate * CDDL HEADER END
217c478bdstevel@tonic-gate */
227c478bdstevel@tonic-gate/*
237c478bdstevel@tonic-gate * Copyright (c) 1995-1998 by Sun Microsystems, Inc.
247c478bdstevel@tonic-gate * All rights reserved.
257c478bdstevel@tonic-gate */
267c478bdstevel@tonic-gate
277c478bdstevel@tonic-gate#pragma ident	"%Z%%M%	%I%	%E% SMI"
287c478bdstevel@tonic-gate
297c478bdstevel@tonic-gate/* LINTLIBRARY */
307c478bdstevel@tonic-gate
317c478bdstevel@tonic-gate/*
327c478bdstevel@tonic-gate * newwin.c
337c478bdstevel@tonic-gate *
347c478bdstevel@tonic-gate * XCurses Library
357c478bdstevel@tonic-gate *
367c478bdstevel@tonic-gate * Copyright 1990, 1995 by Mortice Kern Systems.  All rights reserved.
377c478bdstevel@tonic-gate *
387c478bdstevel@tonic-gate */
397c478bdstevel@tonic-gate
407c478bdstevel@tonic-gate#ifdef M_RCSID
417c478bdstevel@tonic-gate#ifndef lint
427c478bdstevel@tonic-gatestatic char rcsID[] =
437c478bdstevel@tonic-gate"$Header: /team/ps/sun_xcurses/archive/local_changes/xcurses/src/lib/"
447c478bdstevel@tonic-gate"libxcurses/src/libc/xcurses/rcs/newwin.c 1.11 1998/06/04 14:26:16 "
457c478bdstevel@tonic-gate"cbates Exp $";
467c478bdstevel@tonic-gate#endif
477c478bdstevel@tonic-gate#endif
487c478bdstevel@tonic-gate
497c478bdstevel@tonic-gate#include <private.h>
507c478bdstevel@tonic-gate#include <stdlib.h>
517c478bdstevel@tonic-gate
527c478bdstevel@tonic-gate#undef werase
537c478bdstevel@tonic-gate
547c478bdstevel@tonic-gate/*
557c478bdstevel@tonic-gate * Create and return a pointer to a new window or pad.
567c478bdstevel@tonic-gate *
577c478bdstevel@tonic-gate * For a window, provide the dimensions and location of the upper
587c478bdstevel@tonic-gate * left hand corner of the window.  If either dimension is zero (0)
597c478bdstevel@tonic-gate * then the default sizes will be LINES-begy and COLS-begx.
607c478bdstevel@tonic-gate *
617c478bdstevel@tonic-gate * For a pad, provide the dimensions and -1 for begy and begx.
627c478bdstevel@tonic-gate * If either dimension is zero (0) then the default sizes will be
637c478bdstevel@tonic-gate * LINES and COLS.
647c478bdstevel@tonic-gate *
657c478bdstevel@tonic-gate * If parent is not null, then create a sub-window of the parent
667c478bdstevel@tonic-gate * window.
677c478bdstevel@tonic-gate */
687c478bdstevel@tonic-gateWINDOW *
697c478bdstevel@tonic-gate__m_newwin(WINDOW *parent,
707c478bdstevel@tonic-gate	int nlines, int ncols, int begy, int begx)
717c478bdstevel@tonic-gate{
727c478bdstevel@tonic-gate	WINDOW	*w;
737c478bdstevel@tonic-gate	int	x, y, dx, dy;
747c478bdstevel@tonic-gate	int	isPad;
757c478bdstevel@tonic-gate
767c478bdstevel@tonic-gate	isPad = ((begy < 0) && (begx < 0)) ||
777c478bdstevel@tonic-gate		(parent && (parent->_flags & W_IS_PAD));
787c478bdstevel@tonic-gate
797c478bdstevel@tonic-gate	if (parent == NULL) {
807c478bdstevel@tonic-gate		/* Check for default dimensions. */
817c478bdstevel@tonic-gate		if (nlines == 0) {
827c478bdstevel@tonic-gate			nlines = lines;
837c478bdstevel@tonic-gate			if (0 <= begy)
847c478bdstevel@tonic-gate				nlines -= begy;
857c478bdstevel@tonic-gate		}
867c478bdstevel@tonic-gate		if (ncols == 0) {
877c478bdstevel@tonic-gate			ncols = columns;
887c478bdstevel@tonic-gate			if (0 <= begx)
897c478bdstevel@tonic-gate				ncols -= begx;
907c478bdstevel@tonic-gate		}
917c478bdstevel@tonic-gate	} else {
927c478bdstevel@tonic-gate		/*
937c478bdstevel@tonic-gate		 * Make sure window dimensions remain within parent's
947c478bdstevel@tonic-gate		 * window so that the new subwindow is a proper subset
957c478bdstevel@tonic-gate		 * of the parent.
967c478bdstevel@tonic-gate		 */
977c478bdstevel@tonic-gate		if (begy < parent->_begy || begx < parent->_begx ||
987c478bdstevel@tonic-gate			parent->_maxy < (begy-parent->_begy) + nlines ||
997c478bdstevel@tonic-gate			parent->_maxx < (begx-parent->_begx) + ncols)
1007c478bdstevel@tonic-gate			goto error_1;
1017c478bdstevel@tonic-gate
1027c478bdstevel@tonic-gate		/*
1037c478bdstevel@tonic-gate		 * If either dimension is zero (0), use the max size
1047c478bdstevel@tonic-gate		 * for the dimension from the parent window less the
1057c478bdstevel@tonic-gate		 * subwindow's starting location.
1067c478bdstevel@tonic-gate		 */
1077c478bdstevel@tonic-gate		if (nlines == 0)
1087c478bdstevel@tonic-gate			nlines = parent->_maxy - (begy - parent->_begy);
1097c478bdstevel@tonic-gate		if (ncols == 0)
1107c478bdstevel@tonic-gate			ncols = parent->_maxx - (begx - parent->_begx);
1117c478bdstevel@tonic-gate	}
1127c478bdstevel@tonic-gate
1137c478bdstevel@tonic-gate	if (!isPad) {
1147c478bdstevel@tonic-gate		/* Check that a window fits on the screen. */
1157c478bdstevel@tonic-gate		if (0 <= begy) {
1167c478bdstevel@tonic-gate			if (lines < begy + nlines) {
1177c478bdstevel@tonic-gate				goto error_1;
1187c478bdstevel@tonic-gate			}
1197c478bdstevel@tonic-gate		}
1207c478bdstevel@tonic-gate		if (0 <= begx) {
1217c478bdstevel@tonic-gate			if (columns < begx + ncols) {
1227c478bdstevel@tonic-gate				goto error_1;
1237c478bdstevel@tonic-gate			}
1247c478bdstevel@tonic-gate		}
1257c478bdstevel@tonic-gate	}
1267c478bdstevel@tonic-gate
1277c478bdstevel@tonic-gate	w = (WINDOW *) calloc(1, sizeof (*w));
1287c478bdstevel@tonic-gate	if (w == NULL)
1297c478bdstevel@tonic-gate		goto error_1;
1307c478bdstevel@tonic-gate
1317c478bdstevel@tonic-gate	w->_first = (short *) calloc((size_t) (nlines + nlines),
1327c478bdstevel@tonic-gate		sizeof (*w->_first));
1337c478bdstevel@tonic-gate	if (w->_first == NULL)
1347c478bdstevel@tonic-gate		goto error_2;
1357c478bdstevel@tonic-gate
1367c478bdstevel@tonic-gate	w->_last = &w->_first[nlines];
1377c478bdstevel@tonic-gate
1387c478bdstevel@tonic-gate	w->_line = (cchar_t **) calloc((size_t) nlines, sizeof (*w->_line));
1397c478bdstevel@tonic-gate	if (w->_line == NULL)
1407c478bdstevel@tonic-gate		goto error_2;
1417c478bdstevel@tonic-gate
1427c478bdstevel@tonic-gate	/* Window rendition. */
1437c478bdstevel@tonic-gate	(void) setcchar(&w->_bg, L" ", WA_NORMAL, 0, (void *) 0);
1447c478bdstevel@tonic-gate	(void) setcchar(&w->_fg, L" ", WA_NORMAL, 0, (void *) 0);
1457c478bdstevel@tonic-gate	if (parent == NULL) {
1467c478bdstevel@tonic-gate		w->_base = (cchar_t *) malloc((size_t) (nlines * ncols) *
1477c478bdstevel@tonic-gate			sizeof (*w->_base));
1487c478bdstevel@tonic-gate		if (w->_base == NULL)
1497c478bdstevel@tonic-gate			goto error_2;
1507c478bdstevel@tonic-gate
1517c478bdstevel@tonic-gate		w->_line[0] = w->_base;
1527c478bdstevel@tonic-gate		for (y = 0; y < nlines; y++) {
1537c478bdstevel@tonic-gate			if (y)
1547c478bdstevel@tonic-gate				w->_line[y] = &w->_line[y-1][ncols];
1557c478bdstevel@tonic-gate			for (x = 0; x < ncols; ++x) {
1567c478bdstevel@tonic-gate				w->_line[y][x] = w->_bg;
1577c478bdstevel@tonic-gate			}
1587c478bdstevel@tonic-gate		}
1597c478bdstevel@tonic-gate	} else {
1607c478bdstevel@tonic-gate		/*
1617c478bdstevel@tonic-gate		 * The new window's origin (0,0) maps to (begy, begx) in the
1627c478bdstevel@tonic-gate		 * parent's window.  In effect, subwin() is a method by which
1637c478bdstevel@tonic-gate		 * a portion of a parent's window can be addressed using a
1647c478bdstevel@tonic-gate		 * (0,0) origin.
1657c478bdstevel@tonic-gate		 */
1667c478bdstevel@tonic-gate		dy = begy - parent->_begy;
1677c478bdstevel@tonic-gate		dx = begx - parent->_begx;
1687c478bdstevel@tonic-gate
1697c478bdstevel@tonic-gate		w->_base = NULL;
1707c478bdstevel@tonic-gate
1717c478bdstevel@tonic-gate		for (y = 0; y < nlines; ++y)
1727c478bdstevel@tonic-gate			w->_line[y] = &parent->_line[dy++][dx];
1737c478bdstevel@tonic-gate	}
1747c478bdstevel@tonic-gate
1757c478bdstevel@tonic-gate	w->_begy = (short) begy;
1767c478bdstevel@tonic-gate	w->_begx = (short) begx;
1777c478bdstevel@tonic-gate	w->_cury = w->_curx = 0;
1787c478bdstevel@tonic-gate	w->_maxy = (short) nlines;
1797c478bdstevel@tonic-gate	w->_maxx = (short) ncols;
1807c478bdstevel@tonic-gate	w->_parent = parent;
1817c478bdstevel@tonic-gate
1827c478bdstevel@tonic-gate	/* Software scroll region. */
1837c478bdstevel@tonic-gate	w->_top = 0;
1847c478bdstevel@tonic-gate	w->_bottom = (short) nlines;
1857c478bdstevel@tonic-gate	w->_scroll = 0;
1867c478bdstevel@tonic-gate
1877c478bdstevel@tonic-gate	/* Window initially blocks for input. */
1887c478bdstevel@tonic-gate	w->_vmin = 1;
1897c478bdstevel@tonic-gate	w->_vtime = 0;
1907c478bdstevel@tonic-gate	w->_flags = W_USE_TIMEOUT;
1917c478bdstevel@tonic-gate
1927c478bdstevel@tonic-gate	/* Determine window properties. */
1937c478bdstevel@tonic-gate	if (isPad) {
1947c478bdstevel@tonic-gate		/* This window is a PAD */
1957c478bdstevel@tonic-gate		w->_flags |= W_IS_PAD;	/* Inherit PAD attribute */
1967c478bdstevel@tonic-gate		if (((begy < 0) && (begx < 0)) ||
1977c478bdstevel@tonic-gate			(parent && !(parent->_flags & W_IS_PAD))) {
1987c478bdstevel@tonic-gate			/* Child of a normal window */
1997c478bdstevel@tonic-gate			w->_begy = w->_begx = 0;
2007c478bdstevel@tonic-gate			/*
2017c478bdstevel@tonic-gate			 * Map to upper left portion of
2027c478bdstevel@tonic-gate			 * display by default (???)
2037c478bdstevel@tonic-gate			 */
2047c478bdstevel@tonic-gate			w->_sminy = w->_sminx = 0;
2057c478bdstevel@tonic-gate			w->_smaxx = w->_maxx;
2067c478bdstevel@tonic-gate			w->_smaxy = w->_maxy;
2077c478bdstevel@tonic-gate		}
2087c478bdstevel@tonic-gate	} else if (begx + ncols == columns) {
2097c478bdstevel@tonic-gate		/* Writing to last column should trigger auto-margin wrap. */
2107c478bdstevel@tonic-gate		w->_flags |= W_END_LINE;
2117c478bdstevel@tonic-gate
2127c478bdstevel@tonic-gate		if (begx == 0) {
2137c478bdstevel@tonic-gate			w->_flags |= W_FULL_LINE;
2147c478bdstevel@tonic-gate
2157c478bdstevel@tonic-gate			if (begy == 0 && nlines == lines)
2167c478bdstevel@tonic-gate				w->_flags |= W_FULL_WINDOW;
2177c478bdstevel@tonic-gate		}
2187c478bdstevel@tonic-gate
2197c478bdstevel@tonic-gate		/* Will writing to bottom-right triggers scroll? */
2207c478bdstevel@tonic-gate		if (begy + nlines == lines)
2217c478bdstevel@tonic-gate			w->_flags |= W_SCROLL_WINDOW;
2227c478bdstevel@tonic-gate	}
2237c478bdstevel@tonic-gate
2247c478bdstevel@tonic-gate	/* Initial screen clear for full screen windows only. */
2257c478bdstevel@tonic-gate	if (w->_flags & W_FULL_WINDOW) {
2267c478bdstevel@tonic-gate		w->_flags |= W_CLEAR_WINDOW;
2277c478bdstevel@tonic-gate		/* Reset dirty region markers. */
2287c478bdstevel@tonic-gate		(void) wtouchln(w, 0, w->_maxy, 0);
2297c478bdstevel@tonic-gate	} else {
2307c478bdstevel@tonic-gate		if (!parent) {
2317c478bdstevel@tonic-gate			/* Do not erase sub windows */
2327c478bdstevel@tonic-gate			(void) werase(w);
2337c478bdstevel@tonic-gate		}
2347c478bdstevel@tonic-gate	}
2357c478bdstevel@tonic-gate
2367c478bdstevel@tonic-gate	return (w);
2377c478bdstevel@tonic-gateerror_2:
2387c478bdstevel@tonic-gate	(void) delwin(w);
2397c478bdstevel@tonic-gateerror_1:
2407c478bdstevel@tonic-gate	return (NULL);
2417c478bdstevel@tonic-gate}
2427c478bdstevel@tonic-gate
2437c478bdstevel@tonic-gateint
2447c478bdstevel@tonic-gatedelwin(WINDOW *w)
2457c478bdstevel@tonic-gate{
2467c478bdstevel@tonic-gate	if (w == NULL)
2477c478bdstevel@tonic-gate		return (OK);
2487c478bdstevel@tonic-gate
2497c478bdstevel@tonic-gate
2507c478bdstevel@tonic-gate	if (w->_line != NULL) {
2517c478bdstevel@tonic-gate		if (w->_base != NULL)
2527c478bdstevel@tonic-gate			free(w->_base);
2537c478bdstevel@tonic-gate
2547c478bdstevel@tonic-gate		free(w->_line);
2557c478bdstevel@tonic-gate	}
2567c478bdstevel@tonic-gate
2577c478bdstevel@tonic-gate	if (w->_first != NULL)
2587c478bdstevel@tonic-gate		free(w->_first);
2597c478bdstevel@tonic-gate
2607c478bdstevel@tonic-gate	free(w);
2617c478bdstevel@tonic-gate
2627c478bdstevel@tonic-gate	return (OK);
2637c478bdstevel@tonic-gate}
2647c478bdstevel@tonic-gate
2657c478bdstevel@tonic-gateWINDOW *
2667c478bdstevel@tonic-gatederwin(WINDOW *parent,
2677c478bdstevel@tonic-gate	int nlines, int ncols, int begy, int begx)
2687c478bdstevel@tonic-gate{
2697c478bdstevel@tonic-gate	WINDOW	*w;
2707c478bdstevel@tonic-gate
2717c478bdstevel@tonic-gate	if (parent == NULL)
2727c478bdstevel@tonic-gate		return (NULL);
2737c478bdstevel@tonic-gate
2747c478bdstevel@tonic-gate	/* Absolute screen address. */
2757c478bdstevel@tonic-gate	begy += parent->_begy;
2767c478bdstevel@tonic-gate	begx += parent->_begx;
2777c478bdstevel@tonic-gate
2787c478bdstevel@tonic-gate	w = __m_newwin(parent, nlines, ncols, begy, begx);
2797c478bdstevel@tonic-gate
2807c478bdstevel@tonic-gate	return (w);
2817c478bdstevel@tonic-gate}
2827c478bdstevel@tonic-gate
2837c478bdstevel@tonic-gateWINDOW *
2847c478bdstevel@tonic-gatenewwin(int nlines, int ncols, int begy, int begx)
2857c478bdstevel@tonic-gate{
2867c478bdstevel@tonic-gate	WINDOW	*w;
2877c478bdstevel@tonic-gate
2887c478bdstevel@tonic-gate	w = __m_newwin(NULL, nlines, ncols, begy, begx);
2897c478bdstevel@tonic-gate
2907c478bdstevel@tonic-gate	return (w);
2917c478bdstevel@tonic-gate}
2927c478bdstevel@tonic-gate
2937c478bdstevel@tonic-gateWINDOW *
2947c478bdstevel@tonic-gatesubwin(WINDOW *parent, int nlines, int ncols, int begy, int begx)
2957c478bdstevel@tonic-gate{
2967c478bdstevel@tonic-gate	WINDOW	*w;
2977c478bdstevel@tonic-gate
2987c478bdstevel@tonic-gate	if (parent == NULL)
2997c478bdstevel@tonic-gate		return (NULL);
3007c478bdstevel@tonic-gate
3017c478bdstevel@tonic-gate	w = __m_newwin(parent, nlines, ncols, begy, begx);
3027c478bdstevel@tonic-gate
3037c478bdstevel@tonic-gate	return (w);
3047c478bdstevel@tonic-gate}
305