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