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, by Sun Microsystems, Inc.
24 * All rights reserved.
25 */
26
27#pragma ident	"%Z%%M%	%I%	%E% SMI"
28
29/*
30 * newwin.c
31 *
32 * XCurses Library
33 *
34 * Copyright 1990, 1995 by Mortice Kern Systems.  All rights reserved.
35 *
36 */
37
38#ifdef M_RCSID
39#ifndef lint
40static char rcsID[] = "$Header: /rd/src/libc/xcurses/rcs/newwin.c 1.9 1995/09/28 20:15:58 ant Exp $";
41#endif
42#endif
43
44#include <private.h>
45#include <stdlib.h>
46
47/*f
48 * Create and return a pointer to a new window or pad.
49 *
50 * For a window, provide the dimensions and location of the upper
51 * left hand corner of the window.  If either dimension is zero (0)
52 * then the default sizes will be LINES-begy and COLS-begx.
53 *
54 * For a pad, provide the dimensions and -1 for begy and begx.
55 * If either dimension is zero (0) then the default sizes will be
56 * LINES and COLS.
57 *
58 * If parent is not null, then create a sub-window of the parent
59 * window.
60 */
61WINDOW *
62__m_newwin(parent, nlines, ncols, begy, begx)
63WINDOW *parent;
64int nlines, ncols, begy, begx;
65{
66	WINDOW *w;
67	int x, y, dx, dy;
68
69#ifdef M_CURSES_TRACE
70	__m_trace(
71		"__m_newwin(%p, %d, %d, %d, %d)",
72		parent, nlines, ncols, begy, begx
73	);
74#endif
75
76	if (parent == (WINDOW *) 0) {
77		/* Check for default dimensions. */
78		if (nlines == 0) {
79			nlines = lines;
80			if (0 <= begy)
81				nlines -= begy;
82		}
83		if (ncols == 0) {
84			ncols = columns;
85			if (0 <= begx)
86				ncols -= begx;
87		}
88	} else {
89		/* Make sure window dimensions remain within parent's
90		 * window so that the new subwindow is a proper subset
91		 * of the parent.
92		 */
93		if (begy < parent->_begy || begx < parent->_begx
94		|| parent->_maxy < (begy-parent->_begy) + nlines
95		|| parent->_maxx < (begx-parent->_begx) + ncols)
96			goto error_1;
97
98		/* If either dimension is zero (0), use the max size
99		 * for the dimension from the parent window less the
100		 * subwindow's starting location.
101		 */
102		if (nlines == 0)
103			nlines = parent->_maxy - (begy - parent->_begy);
104		if (ncols == 0)
105			ncols = parent->_maxx - (begx - parent->_begx);
106	}
107
108	/* Check that a window fits on the screen. */
109	if (0 <= begy) {
110		if (lines < begy + nlines)
111			goto error_1;
112	}
113	if (0 <= begx) {
114		if (columns < begx + ncols)
115			goto error_1;
116	}
117
118	w = (WINDOW *) calloc(1, sizeof *w);
119	if (w == (WINDOW *) 0)
120		goto error_1;
121
122	w->_first = (short *) calloc(
123		(size_t) (nlines + nlines), sizeof *w->_first
124	);
125	if (w->_first == (short *) 0)
126		goto error_2;
127
128	w->_last = &w->_first[nlines];
129
130	w->_line = (cchar_t **) calloc((size_t) nlines, sizeof *w->_line);
131	if (w->_line == (cchar_t **) 0)
132		goto error_2;
133
134	/* Window rendition. */
135	(void) setcchar(
136		&w->_bg, M_MB_L(" "), WA_NORMAL, 0, (void *) 0
137	);
138	(void) setcchar(
139		&w->_fg, M_MB_L(" "), WA_NORMAL, 0, (void *) 0
140	);
141
142	if (parent == (WINDOW *) 0) {
143		w->_base = (cchar_t *) malloc(
144			(size_t) (nlines * ncols) * sizeof *w->_base
145		);
146		if (w->_base == (cchar_t *) 0)
147			goto error_2;
148
149		w->_line[y = 0] = w->_base;
150		do {
151			for (x = 0; x < ncols; ++x)
152				w->_line[y][x] = w->_bg;
153			w->_line[y+1] = &w->_line[y][x];
154		} while (++y < nlines-1);
155	} else {
156		/* The new window's origin (0,0) maps to (begy, begx) in the
157		 * parent's window.  In effect, subwin() is a method by which
158		 * a portion of a parent's window can be addressed using a
159		 * (0,0) origin.
160		 */
161		dy = begy - parent->_begy;
162		dx = begx - parent->_begx;
163
164		w->_base = (cchar_t *) 0;
165
166		for (y = 0; y < nlines; ++y)
167			w->_line[y] = &parent->_line[dy++][dx];
168	}
169
170	w->_begy = (short) begy;
171	w->_begx = (short) begx;
172	w->_cury = w->_curx = 0;
173	w->_maxy = (short) nlines;
174	w->_maxx = (short) ncols;
175	w->_parent = parent;
176
177	/* Software scroll region. */
178	w->_top = 0;
179	w->_bottom = (short) nlines;
180	w->_scroll = 0;
181
182	/* Window initially blocks for input. */
183	w->_vmin = 1;
184	w->_vtime = 0;
185	w->_flags = W_USE_TIMEOUT;
186
187	/* Determine window properties. */
188	if ((begy < 0 && begx < 0)
189	|| (parent != (WINDOW *) 0 && (parent->_flags & W_IS_PAD))) {
190		w->_flags |= W_IS_PAD;
191		w->_begy = w->_begx = 0;
192	} else if (begx + ncols == columns) {
193		/* Writing to last column should trigger auto-margin wrap. */
194		w->_flags |= W_END_LINE;
195
196		if (begx == 0) {
197			w->_flags |= W_FULL_LINE;
198
199			if (begy == 0 && nlines == lines)
200				w->_flags |= W_FULL_WINDOW;
201		}
202
203		/* Will writing to bottom-right triggers scroll? */
204		if (begy + nlines == lines)
205			w->_flags |= W_SCROLL_WINDOW;
206	}
207
208	/* Initial screen clear for full screen windows only. */
209	if (w->_flags & W_FULL_WINDOW)
210		w->_flags |= W_CLEAR_WINDOW;
211
212	/* Reset dirty region markers. */
213	(void) wtouchln(w, 0, w->_maxy, 0);
214
215	return __m_return_pointer("__m_newwin", w);
216error_2:
217	(void) delwin(w);
218error_1:
219	return __m_return_pointer("__m_newwin", (WINDOW *) 0);
220}
221
222int
223delwin(w)
224WINDOW *w;
225{
226	if (w == (WINDOW *) 0)
227		return OK;
228
229#ifdef M_CURSES_TRACE
230	__m_trace(
231		"delwin(%p) which is a %s%s.", w,
232		(w->_parent == (WINDOW *) 0) ? "normal " : "sub-",
233		(w->_flags & W_IS_PAD) ? "pad" : "window"
234	);
235#endif
236
237	if (w->_line != (cchar_t **) 0) {
238		if (w->_base != (cchar_t *) 0)
239			free(w->_base);
240
241		free(w->_line);
242	}
243
244	if (w->_first != (short *) 0)
245		free(w->_first);
246
247        free(w);
248
249	return __m_return_code("delwin", OK);
250}
251
252WINDOW *
253derwin(parent, nlines, ncols, begy, begx)
254WINDOW *parent;
255int nlines, ncols, begy, begx;
256{
257	WINDOW *w;
258
259#ifdef M_CURSES_TRACE
260	__m_trace(
261		"derwin(%p, %d, %d, %d, %d)",
262		parent, nlines, ncols, begy, begx
263	);
264#endif
265
266	if (parent == (WINDOW *) 0)
267		return __m_return_pointer("derwin", (WINDOW *) 0);
268
269	/* Absolute screen address. */
270	begy += parent->_begy;
271	begx += parent->_begx;
272
273	w = __m_newwin(parent, nlines, ncols, begy, begx);
274
275	return __m_return_pointer("derwin", w);
276}
277
278WINDOW *
279newwin(nlines, ncols, begy, begx)
280int nlines, ncols, begy, begx;
281{
282	WINDOW *w;
283
284#ifdef M_CURSES_TRACE
285	__m_trace("newwin(%d, %d, %d, %d)", nlines, ncols, begy, begx);
286#endif
287
288	w = __m_newwin((WINDOW *) 0, nlines, ncols, begy, begx);
289
290	return __m_return_pointer("newwin", w);
291}
292
293WINDOW *
294subwin(parent, nlines, ncols, begy, begx)
295WINDOW *parent;
296int nlines, ncols, begy, begx;
297{
298	WINDOW *w;
299
300#ifdef M_CURSES_TRACE
301	__m_trace(
302		"subwin(%p, %d, %d, %d, %d)",
303		parent, nlines, ncols, begy, begx
304	);
305#endif
306
307	if (parent == (WINDOW *) 0)
308		return __m_return_pointer("subwin", (WINDOW *) 0);
309
310	w = __m_newwin(parent, nlines, ncols, begy, begx);
311
312	return __m_return_pointer("subwin", w);
313}
314
315