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