1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 * Copyright (c) 1995-1998 by Sun Microsystems, Inc.
24 * All rights reserved.
25 */
26
27#pragma ident	"%Z%%M%	%I%	%E% SMI"
28
29/* LINTLIBRARY */
30
31/*
32 * newwin.c
33 *
34 * XCurses Library
35 *
36 * Copyright 1990, 1995 by Mortice Kern Systems.  All rights reserved.
37 *
38 */
39
40#ifdef M_RCSID
41#ifndef lint
42static char rcsID[] =
43"$Header: /team/ps/sun_xcurses/archive/local_changes/xcurses/src/lib/"
44"libxcurses/src/libc/xcurses/rcs/newwin.c 1.11 1998/06/04 14:26:16 "
45"cbates Exp $";
46#endif
47#endif
48
49#include <private.h>
50#include <stdlib.h>
51
52#undef werase
53
54/*
55 * Create and return a pointer to a new window or pad.
56 *
57 * For a window, provide the dimensions and location of the upper
58 * left hand corner of the window.  If either dimension is zero (0)
59 * then the default sizes will be LINES-begy and COLS-begx.
60 *
61 * For a pad, provide the dimensions and -1 for begy and begx.
62 * If either dimension is zero (0) then the default sizes will be
63 * LINES and COLS.
64 *
65 * If parent is not null, then create a sub-window of the parent
66 * window.
67 */
68WINDOW *
69__m_newwin(WINDOW *parent,
70	int nlines, int ncols, int begy, int begx)
71{
72	WINDOW	*w;
73	int	x, y, dx, dy;
74	int	isPad;
75
76	isPad = ((begy < 0) && (begx < 0)) ||
77		(parent && (parent->_flags & W_IS_PAD));
78
79	if (parent == NULL) {
80		/* Check for default dimensions. */
81		if (nlines == 0) {
82			nlines = lines;
83			if (0 <= begy)
84				nlines -= begy;
85		}
86		if (ncols == 0) {
87			ncols = columns;
88			if (0 <= begx)
89				ncols -= begx;
90		}
91	} else {
92		/*
93		 * Make sure window dimensions remain within parent's
94		 * window so that the new subwindow is a proper subset
95		 * of the parent.
96		 */
97		if (begy < parent->_begy || begx < parent->_begx ||
98			parent->_maxy < (begy-parent->_begy) + nlines ||
99			parent->_maxx < (begx-parent->_begx) + ncols)
100			goto error_1;
101
102		/*
103		 * If either dimension is zero (0), use the max size
104		 * for the dimension from the parent window less the
105		 * subwindow's starting location.
106		 */
107		if (nlines == 0)
108			nlines = parent->_maxy - (begy - parent->_begy);
109		if (ncols == 0)
110			ncols = parent->_maxx - (begx - parent->_begx);
111	}
112
113	if (!isPad) {
114		/* Check that a window fits on the screen. */
115		if (0 <= begy) {
116			if (lines < begy + nlines) {
117				goto error_1;
118			}
119		}
120		if (0 <= begx) {
121			if (columns < begx + ncols) {
122				goto error_1;
123			}
124		}
125	}
126
127	w = (WINDOW *) calloc(1, sizeof (*w));
128	if (w == NULL)
129		goto error_1;
130
131	w->_first = (short *) calloc((size_t) (nlines + nlines),
132		sizeof (*w->_first));
133	if (w->_first == NULL)
134		goto error_2;
135
136	w->_last = &w->_first[nlines];
137
138	w->_line = (cchar_t **) calloc((size_t) nlines, sizeof (*w->_line));
139	if (w->_line == NULL)
140		goto error_2;
141
142	/* Window rendition. */
143	(void) setcchar(&w->_bg, L" ", WA_NORMAL, 0, (void *) 0);
144	(void) setcchar(&w->_fg, L" ", WA_NORMAL, 0, (void *) 0);
145	if (parent == NULL) {
146		w->_base = (cchar_t *) malloc((size_t) (nlines * ncols) *
147			sizeof (*w->_base));
148		if (w->_base == NULL)
149			goto error_2;
150
151		w->_line[0] = w->_base;
152		for (y = 0; y < nlines; y++) {
153			if (y)
154				w->_line[y] = &w->_line[y-1][ncols];
155			for (x = 0; x < ncols; ++x) {
156				w->_line[y][x] = w->_bg;
157			}
158		}
159	} else {
160		/*
161		 * The new window's origin (0,0) maps to (begy, begx) in the
162		 * parent's window.  In effect, subwin() is a method by which
163		 * a portion of a parent's window can be addressed using a
164		 * (0,0) origin.
165		 */
166		dy = begy - parent->_begy;
167		dx = begx - parent->_begx;
168
169		w->_base = NULL;
170
171		for (y = 0; y < nlines; ++y)
172			w->_line[y] = &parent->_line[dy++][dx];
173	}
174
175	w->_begy = (short) begy;
176	w->_begx = (short) begx;
177	w->_cury = w->_curx = 0;
178	w->_maxy = (short) nlines;
179	w->_maxx = (short) ncols;
180	w->_parent = parent;
181
182	/* Software scroll region. */
183	w->_top = 0;
184	w->_bottom = (short) nlines;
185	w->_scroll = 0;
186
187	/* Window initially blocks for input. */
188	w->_vmin = 1;
189	w->_vtime = 0;
190	w->_flags = W_USE_TIMEOUT;
191
192	/* Determine window properties. */
193	if (isPad) {
194		/* This window is a PAD */
195		w->_flags |= W_IS_PAD;	/* Inherit PAD attribute */
196		if (((begy < 0) && (begx < 0)) ||
197			(parent && !(parent->_flags & W_IS_PAD))) {
198			/* Child of a normal window */
199			w->_begy = w->_begx = 0;
200			/*
201			 * Map to upper left portion of
202			 * display by default (???)
203			 */
204			w->_sminy = w->_sminx = 0;
205			w->_smaxx = w->_maxx;
206			w->_smaxy = w->_maxy;
207		}
208	} else if (begx + ncols == columns) {
209		/* Writing to last column should trigger auto-margin wrap. */
210		w->_flags |= W_END_LINE;
211
212		if (begx == 0) {
213			w->_flags |= W_FULL_LINE;
214
215			if (begy == 0 && nlines == lines)
216				w->_flags |= W_FULL_WINDOW;
217		}
218
219		/* Will writing to bottom-right triggers scroll? */
220		if (begy + nlines == lines)
221			w->_flags |= W_SCROLL_WINDOW;
222	}
223
224	/* Initial screen clear for full screen windows only. */
225	if (w->_flags & W_FULL_WINDOW) {
226		w->_flags |= W_CLEAR_WINDOW;
227		/* Reset dirty region markers. */
228		(void) wtouchln(w, 0, w->_maxy, 0);
229	} else {
230		if (!parent) {
231			/* Do not erase sub windows */
232			(void) werase(w);
233		}
234	}
235
236	return (w);
237error_2:
238	(void) delwin(w);
239error_1:
240	return (NULL);
241}
242
243int
244delwin(WINDOW *w)
245{
246	if (w == NULL)
247		return (OK);
248
249
250	if (w->_line != NULL) {
251		if (w->_base != NULL)
252			free(w->_base);
253
254		free(w->_line);
255	}
256
257	if (w->_first != NULL)
258		free(w->_first);
259
260	free(w);
261
262	return (OK);
263}
264
265WINDOW *
266derwin(WINDOW *parent,
267	int nlines, int ncols, int begy, int begx)
268{
269	WINDOW	*w;
270
271	if (parent == NULL)
272		return (NULL);
273
274	/* Absolute screen address. */
275	begy += parent->_begy;
276	begx += parent->_begx;
277
278	w = __m_newwin(parent, nlines, ncols, begy, begx);
279
280	return (w);
281}
282
283WINDOW *
284newwin(int nlines, int ncols, int begy, int begx)
285{
286	WINDOW	*w;
287
288	w = __m_newwin(NULL, nlines, ncols, begy, begx);
289
290	return (w);
291}
292
293WINDOW *
294subwin(WINDOW *parent, int nlines, int ncols, int begy, int begx)
295{
296	WINDOW	*w;
297
298	if (parent == NULL)
299		return (NULL);
300
301	w = __m_newwin(parent, nlines, ncols, begy, begx);
302
303	return (w);
304}
305