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