xref: /openbsd-src/lib/libcurses/base/lib_newwin.c (revision 62a742911104f98b9185b2c6b6007d9b1c36396c)
1 /*	$OpenBSD: lib_newwin.c,v 1.1 1999/01/18 19:09:54 millert Exp $	*/
2 
3 /****************************************************************************
4  * Copyright (c) 1998 Free Software Foundation, Inc.                        *
5  *                                                                          *
6  * Permission is hereby granted, free of charge, to any person obtaining a  *
7  * copy of this software and associated documentation files (the            *
8  * "Software"), to deal in the Software without restriction, including      *
9  * without limitation the rights to use, copy, modify, merge, publish,      *
10  * distribute, distribute with modifications, sublicense, and/or sell       *
11  * copies of the Software, and to permit persons to whom the Software is    *
12  * furnished to do so, subject to the following conditions:                 *
13  *                                                                          *
14  * The above copyright notice and this permission notice shall be included  *
15  * in all copies or substantial portions of the Software.                   *
16  *                                                                          *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
20  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
21  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
22  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
23  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
24  *                                                                          *
25  * Except as contained in this notice, the name(s) of the above copyright   *
26  * holders shall not be used in advertising or otherwise to promote the     *
27  * sale, use or other dealings in this Software without prior written       *
28  * authorization.                                                           *
29  ****************************************************************************/
30 
31 /****************************************************************************
32  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
33  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
34  ****************************************************************************/
35 
36 
37 
38 /*
39 **	lib_newwin.c
40 **
41 **	The routines newwin(), subwin() and their dependent
42 **
43 */
44 
45 #include <curses.priv.h>
46 
47 MODULE_ID("$From: lib_newwin.c,v 1.20 1998/05/23 23:21:32 Alexander.V.Lukyanov Exp $")
48 
49 void _nc_freewin(WINDOW *win)
50 {
51 WINDOWLIST *p, *q;
52 int	i;
53 
54 	if (win != 0) {
55 		for (p = _nc_windows, q = 0; p != 0; q = p, p = p->next) {
56 			if (p->win == win) {
57 				if (q == 0)
58 					_nc_windows = p->next;
59 				else
60 					q->next = p->next;
61 				free(p);
62 
63 				if (! (win->_flags & _SUBWIN)) {
64 					for (i = 0; i <= win->_maxy && win->_line[i].text; i++)
65 						free(win->_line[i].text);
66 				}
67 				free(win->_line);
68 				free(win);
69 
70 				if (win == curscr) curscr = 0;
71 				if (win == stdscr) stdscr = 0;
72 				if (win == newscr) newscr = 0;
73 
74 				T(("...deleted win=%p", win));
75 				break;
76 			}
77 		}
78 	}
79 }
80 
81 WINDOW * newwin(int num_lines, int num_columns, int begy, int begx)
82 {
83 WINDOW	*win;
84 chtype	*ptr;
85 int	i;
86 
87 	T((T_CALLED("newwin(%d,%d,%d,%d)"), num_lines, num_columns, begy, begx));
88 
89 	if (begy < 0 || begx < 0 || num_lines < 0 || num_columns < 0)
90 		returnWin(0);
91 
92 	if (num_lines == 0)
93 	    num_lines = SP->_lines_avail - begy;
94 	if (num_columns == 0)
95 	    num_columns = screen_columns - begx;
96 
97 	if (num_columns + begx > SP->_columns || num_lines + begy > SP->_lines_avail)
98 		returnWin(0);
99 
100 	if ((win = _nc_makenew(num_lines, num_columns, begy, begx, 0)) == 0)
101 		returnWin(0);
102 
103 	for (i = 0; i < num_lines; i++) {
104 	    if ((win->_line[i].text = typeCalloc(chtype, (unsigned)num_columns)) == 0) {
105 		_nc_freewin(win);
106 		returnWin(0);
107 	    }
108 	    for (ptr = win->_line[i].text; ptr < win->_line[i].text + num_columns; )
109 		*ptr++ = ' ';
110 	}
111 
112 	T(("newwin: returned window is %p", win));
113 
114 	returnWin(win);
115 }
116 
117 WINDOW * derwin(WINDOW *orig, int num_lines, int num_columns, int begy, int begx)
118 {
119 WINDOW	*win;
120 int	i;
121 int     flags = _SUBWIN;
122 
123 	T((T_CALLED("derwin(%p,%d,%d,%d,%d)"), orig, num_lines, num_columns, begy, begx));
124 
125 	/*
126 	** make sure window fits inside the original one
127 	*/
128 	if ( begy < 0 || begx < 0 || orig == 0 || num_lines < 0 || num_columns < 0)
129 	    returnWin(0);
130 	if ( begy + num_lines > orig->_maxy + 1
131 		|| begx + num_columns > orig->_maxx + 1)
132 	    returnWin(0);
133 
134 	if (num_lines == 0)
135 	    num_lines = orig->_maxy + 1 - begy;
136 
137 	if (num_columns == 0)
138 	    num_columns = orig->_maxx + 1 - begx;
139 
140 	if (orig->_flags & _ISPAD)
141 	  flags |= _ISPAD;
142 
143 	if ((win = _nc_makenew(num_lines, num_columns, orig->_begy + begy, orig->_begx + begx, flags)) == 0)
144 	    returnWin(0);
145 
146 	win->_pary = begy;
147 	win->_parx = begx;
148 	win->_attrs = orig->_attrs;
149 	win->_bkgd = orig->_bkgd;
150 
151 	for (i = 0; i < num_lines; i++)
152 	    win->_line[i].text = &orig->_line[begy++].text[begx];
153 
154 	win->_parent = orig;
155 
156 	T(("derwin: returned window is %p", win));
157 
158 	returnWin(win);
159 }
160 
161 
162 WINDOW *subwin(WINDOW *w, int l, int c, int y, int x)
163 {
164 	T((T_CALLED("subwin(%p, %d, %d, %d, %d)"), w, l, c, y, x));
165 	T(("parent has begy = %d, begx = %d", w->_begy, w->_begx));
166 
167 	returnWin(derwin(w, l, c, y - w->_begy, x - w->_begx));
168 }
169 
170 WINDOW *
171 _nc_makenew(int num_lines, int num_columns, int begy, int begx, int flags)
172 {
173 int	i;
174 WINDOWLIST *wp;
175 WINDOW	*win;
176 bool    is_pad = (flags & _ISPAD);
177 
178 	T(("_nc_makenew(%d,%d,%d,%d)", num_lines, num_columns, begy, begx));
179 
180 	if (num_lines <= 0 || num_columns <= 0)
181 		return 0;
182 
183 	if ((wp = typeCalloc(WINDOWLIST, 1)) == 0)
184 		return 0;
185 
186 	if ((win = typeCalloc(WINDOW, 1)) == 0)
187 		return 0;
188 
189 	if ((win->_line = typeCalloc(struct ldat, ((unsigned)num_lines))) == 0) {
190 		free(win);
191 		return 0;
192 	}
193 
194 	win->_curx       = 0;
195 	win->_cury       = 0;
196 	win->_maxy       = num_lines - 1;
197 	win->_maxx       = num_columns - 1;
198 	win->_begy       = begy;
199 	win->_begx       = begx;
200 	win->_yoffset    = SP->_topstolen;
201 
202 	win->_flags      = flags;
203 	win->_attrs      = A_NORMAL;
204 	win->_bkgd       = BLANK;
205 
206 	win->_clear      = is_pad ? FALSE : (num_lines == screen_lines  &&  num_columns == screen_columns);
207 	win->_idlok      = FALSE;
208 	win->_idcok      = TRUE;
209 	win->_scroll     = FALSE;
210 	win->_leaveok    = FALSE;
211 	win->_use_keypad = FALSE;
212 	win->_delay      = -1;
213 	win->_immed      = FALSE;
214 	win->_sync       = 0;
215 	win->_parx       = -1;
216 	win->_pary       = -1;
217 	win->_parent     = 0;
218 
219 	win->_regtop     = 0;
220 	win->_regbottom  = num_lines - 1;
221 
222 	win->_pad._pad_y      = -1;
223 	win->_pad._pad_x      = -1;
224 	win->_pad._pad_top    = -1;
225 	win->_pad._pad_bottom = -1;
226 	win->_pad._pad_left   = -1;
227 	win->_pad._pad_right  = -1;
228 
229 	for (i = 0; i < num_lines; i++)
230 	{
231 	    /*
232 	     * This used to do
233 	     *
234 	     * win->_line[i].firstchar = win->_line[i].lastchar = _NOCHANGE;
235 	     *
236 	     * which marks the whole window unchanged.  That's how
237 	     * SVr1 curses did it, but SVr4 curses marks the whole new
238 	     * window changed.
239 	     *
240 	     * With the old SVr1-like code, say you have stdscr full of
241 	     * characters, then create a new window with newwin(),
242 	     * then do a printw(win, "foo        ");, the trailing spaces are
243 	     * completely ignored by the following refreshes.  So, you
244 	     * get "foojunkjunk" on the screen instead of "foo        " as
245 	     * you actually intended.
246 	     *
247 	     * SVr4 doesn't do this.  Instead the spaces are actually written.
248 	     * So that's how we want ncurses to behave.
249 	     */
250 	    win->_line[i].firstchar = 0;
251 	    win->_line[i].lastchar = num_columns-1;
252 
253 	    if_USE_SCROLL_HINTS(win->_line[i].oldindex = i);
254 	}
255 
256 	if (!is_pad && (begx + num_columns == screen_columns)) {
257 		win->_flags |= _ENDLINE;
258 
259 		if (begx == 0  &&  num_lines == screen_lines  &&  begy == 0)
260 			win->_flags |= _FULLWIN;
261 
262 		if (begy + num_lines == screen_lines)
263 			win->_flags |= _SCROLLWIN;
264 	}
265 
266 	wp->next = _nc_windows;
267 	wp->win  = win;
268 	_nc_windows = wp;
269 
270 	T((T_CREATE("window %p"), win));
271 
272 	return(win);
273 }
274