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