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 *
__m_newwin(WINDOW * parent,int nlines,int ncols,int begy,int begx)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
delwin(WINDOW * w)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 *
derwin(WINDOW * parent,int nlines,int ncols,int begy,int begx)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 *
newwin(int nlines,int ncols,int begy,int begx)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 *
subwin(WINDOW * parent,int nlines,int ncols,int begy,int begx)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