xref: /netbsd-src/lib/libcurses/newwin.c (revision 001c68bd94f75ce9270b69227c4199fbf34ee396)
1 /*	$NetBSD: newwin.c,v 1.38 2003/07/05 19:03:32 jdc Exp $	*/
2 
3 /*
4  * Copyright (c) 1981, 1993, 1994
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *	This product includes software developed by the University of
18  *	California, Berkeley and its contributors.
19  * 4. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 #include <sys/cdefs.h>
37 #ifndef lint
38 #if 0
39 static char sccsid[] = "@(#)newwin.c	8.3 (Berkeley) 7/27/94";
40 #else
41 __RCSID("$NetBSD: newwin.c,v 1.38 2003/07/05 19:03:32 jdc Exp $");
42 #endif
43 #endif				/* not lint */
44 
45 #include <stdlib.h>
46 
47 #include "curses.h"
48 #include "curses_private.h"
49 
50 extern struct __winlist	*winlistp;
51 
52 static WINDOW *__makenew(SCREEN *screen, int nlines, int ncols, int by,
53 			 int bx, int sub, int ispad);
54 static WINDOW *__subwin(WINDOW *orig, int nlines, int ncols, int by, int bx,
55 			 int ispad);
56 
57 /*
58  * derwin --
59  *      Create a new window in the same manner as subwin but (by, bx)
60  *      are relative to the origin of window orig instead of absolute.
61  */
62 WINDOW *
63 derwin(WINDOW *orig, int nlines, int ncols, int by, int bx)
64 {
65 
66 	return __subwin(orig, nlines, ncols, orig->begy + by, orig->begx + bx,
67 	    FALSE);
68 }
69 
70 /*
71  * subpad --
72  *      Create a new pad in the same manner as subwin but (by, bx)
73  *      are relative to the origin of window orig instead of absolute.
74  */
75 WINDOW *
76 subpad(WINDOW *orig, int nlines, int ncols, int by, int bx)
77 {
78 
79 	return __subwin(orig, nlines, ncols, orig->begy + by, orig->begx + bx,
80 	    TRUE);
81 }
82 
83 /*
84  * dupwin --
85  *      Create a copy of the given window.
86  */
87 WINDOW *
88 dupwin(WINDOW *win)
89 {
90 	WINDOW *new_one;
91 
92 	if ((new_one = __newwin(_cursesi_screen, win->maxy, win->maxx,
93 				win->begy, win->begx, FALSE)) == NULL)
94 		return NULL;
95 
96 	overwrite(win, new_one);
97 	return new_one;
98 }
99 
100 /*
101  * newwin --
102  *	Allocate space for and set up defaults for a new window.
103  */
104 WINDOW *
105 newwin(int nlines, int ncols, int by, int bx)
106 {
107 	return __newwin(_cursesi_screen, nlines, ncols, by, bx, FALSE);
108 }
109 
110 /*
111  * newpad --
112  *	Allocate space for and set up defaults for a new pad.
113  */
114 WINDOW *
115 newpad(int nlines, int ncols)
116 {
117 	if (nlines < 1 || ncols < 1)
118 		return NULL;
119 	return __newwin(_cursesi_screen, nlines, ncols, 0, 0, TRUE);
120 }
121 
122 WINDOW *
123 __newwin(SCREEN *screen, int nlines, int ncols, int by, int bx, int ispad)
124 {
125 	WINDOW *win;
126 	__LINE *lp;
127 	int     i, j;
128 	int	maxy, maxx;
129 	__LDATA *sp;
130 
131 	if (by < 0 || bx < 0)
132 		return (NULL);
133 
134 	maxy = nlines > 0 ? nlines : LINES - by + nlines;
135 	maxx = ncols > 0 ? ncols : COLS - bx + ncols;
136 
137 	if ((win = __makenew(screen, maxy, maxx, by, bx, 0, ispad)) == NULL)
138 		return (NULL);
139 
140 	win->nextp = win;
141 	win->ch_off = 0;
142 	win->orig = NULL;
143 	win->reqy = nlines;
144 	win->reqx = ncols;
145 
146 #ifdef DEBUG
147 	__CTRACE("newwin: win->ch_off = %d\n", win->ch_off);
148 #endif
149 
150 	for (i = 0; i < maxy; i++) {
151 		lp = win->lines[i];
152 		if (ispad)
153 			lp->flags = __ISDIRTY;
154 		else
155 			lp->flags = 0;
156 		for (sp = lp->line, j = 0; j < maxx; j++, sp++) {
157 			sp->ch = ' ';
158 			sp->bch = ' ';
159 			sp->attr = 0;
160 			if (__using_color)
161 				sp->battr = __default_color;
162 			else
163 				sp->battr = 0;
164 		}
165 		lp->hash = __hash((char *)(void *)lp->line,
166 		    (size_t) (ncols * __LDATASIZE));
167 	}
168 	return (win);
169 }
170 
171 WINDOW *
172 subwin(WINDOW *orig, int nlines, int ncols, int by, int bx)
173 {
174 
175 	return __subwin(orig, nlines, ncols, by, bx, FALSE);
176 }
177 
178 WINDOW *
179 __subwin(WINDOW *orig, int nlines, int ncols, int by, int bx, int ispad)
180 {
181 	int     i;
182 	__LINE *lp;
183 	WINDOW *win;
184 	int	maxy, maxx;
185 
186 #ifdef	DEBUG
187 	__CTRACE("subwin: (%p, %d, %d, %d, %d, %d)\n", orig, nlines, ncols,
188 	    by, bx, ispad);
189 #endif
190 	if (orig == NULL || orig->orig != NULL)
191 		return NULL;
192 
193 	/* Make sure window fits inside the original one. */
194 	maxy = nlines > 0 ? nlines : orig->maxy + orig->begy - by + nlines;
195 	maxx = ncols > 0 ? ncols : orig->maxx + orig->begx - bx + ncols;
196 	if (by < orig->begy || bx < orig->begx
197 	    || by + maxy > orig->maxy + orig->begy
198 	    || bx + maxx > orig->maxx + orig->begx)
199 		return (NULL);
200 	if ((win = __makenew(_cursesi_screen, maxy, maxx,
201 			     by, bx, 1, ispad)) == NULL)
202 		return (NULL);
203 	win->reqy = nlines;
204 	win->reqx = ncols;
205 	win->nextp = orig->nextp;
206 	orig->nextp = win;
207 	win->orig = orig;
208 
209 	/* Initialize flags here so that refresh can also use __set_subwin. */
210 	for (lp = win->lspace, i = 0; i < win->maxy; i++, lp++)
211 		lp->flags = 0;
212 	__set_subwin(orig, win);
213 	return (win);
214 }
215 /*
216  * This code is shared with mvwin().
217  */
218 void
219 __set_subwin(WINDOW *orig, WINDOW *win)
220 {
221 	int     i;
222 	__LINE *lp, *olp;
223 
224 	win->ch_off = win->begx - orig->begx;
225 	/* Point line pointers to line space. */
226 	for (lp = win->lspace, i = 0; i < win->maxy; i++, lp++) {
227 		win->lines[i] = lp;
228 		olp = orig->lines[i + win->begy - orig->begy];
229 #ifdef DEBUG
230 		lp->sentinel = SENTINEL_VALUE;
231 #endif
232 		lp->line = &olp->line[win->ch_off];
233 		lp->firstchp = &olp->firstch;
234 		lp->lastchp = &olp->lastch;
235 		lp->hash = __hash((char *)(void *)lp->line,
236 		    (size_t) (win->maxx * __LDATASIZE));
237 	}
238 
239 #ifdef DEBUG
240 	__CTRACE("__set_subwin: win->ch_off = %d\n", win->ch_off);
241 #endif
242 }
243 /*
244  * __makenew --
245  *	Set up a window buffer and returns a pointer to it.
246  */
247 static WINDOW *
248 __makenew(SCREEN *screen, int nlines, int ncols, int by, int bx, int sub,
249 	int ispad)
250 {
251 	WINDOW			*win;
252 	__LINE			*lp;
253 	struct __winlist	*wlp, *wlp2;
254 	int			 i;
255 
256 
257 #ifdef	DEBUG
258 	__CTRACE("makenew: (%d, %d, %d, %d)\n", nlines, ncols, by, bx);
259 #endif
260 	if (nlines <= 0 || ncols <= 0)
261 		return NULL;
262 
263 	if ((win = malloc(sizeof(WINDOW))) == NULL)
264 		return (NULL);
265 #ifdef DEBUG
266 	__CTRACE("makenew: win = %p\n", win);
267 #endif
268 
269 	/* Set up line pointer array and line space. */
270 	if ((win->lines = malloc(nlines * sizeof(__LINE *))) == NULL) {
271 		free(win);
272 		return NULL;
273 	}
274 	if ((win->lspace = malloc(nlines * sizeof(__LINE))) == NULL) {
275 		free(win);
276 		free(win->lines);
277 		return NULL;
278 	}
279 	/* Don't allocate window and line space if it's a subwindow */
280 	if (!sub) {
281 		/*
282 		 * Allocate window space in one chunk.
283 		 */
284 		if ((win->wspace =
285 			malloc(ncols * nlines * sizeof(__LDATA))) == NULL) {
286 			free(win->lines);
287 			free(win->lspace);
288 			free(win);
289 			return NULL;
290 		}
291 		/*
292 		 * Append window to window list.
293 		 */
294 		if ((wlp = malloc(sizeof(struct __winlist))) == NULL) {
295 			free(win->wspace);
296 			free(win->lines);
297 			free(win->lspace);
298 			free(win);
299 			return NULL;
300 		}
301 		wlp->winp = win;
302 		wlp->nextp = NULL;
303 		if (screen->winlistp == NULL)
304 			screen->winlistp = wlp;
305 		else {
306 			wlp2 = screen->winlistp;
307 			while (wlp2->nextp != NULL)
308 				wlp2 = wlp2->nextp;
309 			wlp2->nextp = wlp;
310 		}
311 		/*
312 		 * Point line pointers to line space, and lines themselves into
313 		 * window space.
314 		 */
315 		for (lp = win->lspace, i = 0; i < nlines; i++, lp++) {
316 			win->lines[i] = lp;
317 			lp->line = &win->wspace[i * ncols];
318 #ifdef DEBUG
319 			lp->sentinel = SENTINEL_VALUE;
320 #endif
321 			lp->firstchp = &lp->firstch;
322 			lp->lastchp = &lp->lastch;
323 			if (ispad) {
324 				lp->firstch = 0;
325 				lp->lastch = ncols;
326 			} else {
327 				lp->firstch = ncols;
328 				lp->lastch = 0;
329 			}
330 		}
331 	}
332 #ifdef DEBUG
333 	__CTRACE("makenew: ncols = %d\n", ncols);
334 #endif
335 	win->cury = win->curx = 0;
336 	win->maxy = nlines;
337 	win->maxx = ncols;
338 	win->reqy = nlines;
339 	win->reqx = ncols;
340 
341 	win->begy = by;
342 	win->begx = bx;
343 	win->flags = (__IDLINE | __IDCHAR);
344 	win->delay = -1;
345 	win->wattr = 0;
346 	win->bch = ' ';
347 	if (__using_color)
348 		win->battr = __default_color;
349 	else
350 		win->battr = 0;
351 	win->scr_t = 0;
352 	win->scr_b = win->maxy - 1;
353 	if (ispad)
354 		win->flags |= __ISPAD;
355 	else
356 		__swflags(win);
357 #ifdef DEBUG
358 	__CTRACE("makenew: win->wattr = %08x\n", win->wattr);
359 	__CTRACE("makenew: win->flags = %#.4x\n", win->flags);
360 	__CTRACE("makenew: win->maxy = %d\n", win->maxy);
361 	__CTRACE("makenew: win->maxx = %d\n", win->maxx);
362 	__CTRACE("makenew: win->begy = %d\n", win->begy);
363 	__CTRACE("makenew: win->begx = %d\n", win->begx);
364 	__CTRACE("makenew: win->bch = %s\n", unctrl(win->bch));
365 	__CTRACE("makenew: win->battr = %08x\n", win->battr);
366 	__CTRACE("makenew: win->scr_t = %d\n", win->scr_t);
367 	__CTRACE("makenew: win->scr_b = %d\n", win->scr_b);
368 #endif
369 	return (win);
370 }
371 
372 void
373 __swflags(WINDOW *win)
374 {
375 	win->flags &= ~(__ENDLINE | __FULLWIN | __SCROLLWIN | __LEAVEOK);
376 	if (win->begx + win->maxx == COLS && !(win->flags & __ISPAD)) {
377 		win->flags |= __ENDLINE;
378 		if (win->begx == 0 && win->maxy == LINES && win->begy == 0)
379 			win->flags |= __FULLWIN;
380 		if (win->begy + win->maxy == LINES)
381 			win->flags |= __SCROLLWIN;
382 	}
383 }
384