1 |
|
|
/* $OpenBSD: lib_newwin.c,v 1.6 2010/01/12 23:22:06 nicm Exp $ */ |
2 |
|
|
|
3 |
|
|
/**************************************************************************** |
4 |
|
|
* Copyright (c) 1998-2007,2008 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 |
|
|
* and: Thomas E. Dickey 1996-on * |
35 |
|
|
****************************************************************************/ |
36 |
|
|
|
37 |
|
|
/* |
38 |
|
|
** lib_newwin.c |
39 |
|
|
** |
40 |
|
|
** The routines newwin(), subwin() and their dependent |
41 |
|
|
** |
42 |
|
|
*/ |
43 |
|
|
|
44 |
|
|
#include <curses.priv.h> |
45 |
|
|
#include <stddef.h> |
46 |
|
|
|
47 |
|
|
MODULE_ID("$Id: lib_newwin.c,v 1.6 2010/01/12 23:22:06 nicm Exp $") |
48 |
|
|
|
49 |
|
|
#define window_is(name) ((sp)->_##name == win) |
50 |
|
|
|
51 |
|
|
#if USE_REENTRANT |
52 |
|
|
#define remove_window(name) \ |
53 |
|
|
sp->_##name = 0 |
54 |
|
|
#else |
55 |
|
|
#define remove_window(name) \ |
56 |
|
|
sp->_##name = 0; \ |
57 |
|
|
if (win == name) \ |
58 |
|
|
name = 0 |
59 |
|
|
#endif |
60 |
|
|
|
61 |
|
|
static void |
62 |
|
|
remove_window_from_screen(WINDOW *win) |
63 |
|
|
{ |
64 |
|
|
SCREEN *sp; |
65 |
|
|
|
66 |
|
|
for (each_screen(sp)) { |
67 |
|
|
if (window_is(curscr)) { |
68 |
|
|
remove_window(curscr); |
69 |
|
|
break; |
70 |
|
|
} else if (window_is(stdscr)) { |
71 |
|
|
remove_window(stdscr); |
72 |
|
|
break; |
73 |
|
|
} else if (window_is(newscr)) { |
74 |
|
|
remove_window(newscr); |
75 |
|
|
break; |
76 |
|
|
} |
77 |
|
|
} |
78 |
|
|
} |
79 |
|
|
|
80 |
|
|
NCURSES_EXPORT(int) |
81 |
|
|
_nc_freewin(WINDOW *win) |
82 |
|
|
{ |
83 |
|
|
WINDOWLIST *p, *q; |
84 |
|
|
int i; |
85 |
|
|
int result = ERR; |
86 |
|
|
|
87 |
|
|
T((T_CALLED("_nc_freewin(%p)"), win)); |
88 |
|
|
|
89 |
|
|
if (win != 0) { |
90 |
|
|
if (_nc_try_global(curses) == 0) { |
91 |
|
|
q = 0; |
92 |
|
|
for (each_window(p)) { |
93 |
|
|
if (&(p->win) == win) { |
94 |
|
|
remove_window_from_screen(win); |
95 |
|
|
if (q == 0) |
96 |
|
|
_nc_windows = p->next; |
97 |
|
|
else |
98 |
|
|
q->next = p->next; |
99 |
|
|
|
100 |
|
|
if (!(win->_flags & _SUBWIN)) { |
101 |
|
|
for (i = 0; i <= win->_maxy; i++) |
102 |
|
|
FreeIfNeeded(win->_line[i].text); |
103 |
|
|
} |
104 |
|
|
free(win->_line); |
105 |
|
|
free(p); |
106 |
|
|
|
107 |
|
|
result = OK; |
108 |
|
|
T(("...deleted win=%p", win)); |
109 |
|
|
break; |
110 |
|
|
} |
111 |
|
|
q = p; |
112 |
|
|
} |
113 |
|
|
_nc_unlock_global(curses); |
114 |
|
|
} |
115 |
|
|
} |
116 |
|
|
returnCode(result); |
117 |
|
|
} |
118 |
|
|
|
119 |
|
|
NCURSES_EXPORT(WINDOW *) |
120 |
|
|
newwin(int num_lines, int num_columns, int begy, int begx) |
121 |
|
|
{ |
122 |
|
|
WINDOW *win; |
123 |
|
|
NCURSES_CH_T *ptr; |
124 |
|
|
int i; |
125 |
|
|
|
126 |
|
|
T((T_CALLED("newwin(%d,%d,%d,%d)"), num_lines, num_columns, begy, begx)); |
127 |
|
|
|
128 |
|
|
if (begy < 0 || begx < 0 || num_lines < 0 || num_columns < 0) |
129 |
|
|
returnWin(0); |
130 |
|
|
|
131 |
|
|
if (num_lines == 0) |
132 |
|
|
num_lines = SP->_lines_avail - begy; |
133 |
|
|
if (num_columns == 0) |
134 |
|
|
num_columns = screen_columns - begx; |
135 |
|
|
|
136 |
|
|
if ((win = _nc_makenew(num_lines, num_columns, begy, begx, 0)) == 0) |
137 |
|
|
returnWin(0); |
138 |
|
|
|
139 |
|
|
for (i = 0; i < num_lines; i++) { |
140 |
|
|
win->_line[i].text = typeCalloc(NCURSES_CH_T, (unsigned) num_columns); |
141 |
|
|
if (win->_line[i].text == 0) { |
142 |
|
|
(void) _nc_freewin(win); |
143 |
|
|
returnWin(0); |
144 |
|
|
} |
145 |
|
|
for (ptr = win->_line[i].text; |
146 |
|
|
ptr < win->_line[i].text + num_columns; |
147 |
|
|
ptr++) |
148 |
|
|
SetChar(*ptr, BLANK_TEXT, BLANK_ATTR); |
149 |
|
|
} |
150 |
|
|
|
151 |
|
|
returnWin(win); |
152 |
|
|
} |
153 |
|
|
|
154 |
|
|
NCURSES_EXPORT(WINDOW *) |
155 |
|
|
derwin(WINDOW *orig, int num_lines, int num_columns, int begy, int begx) |
156 |
|
|
{ |
157 |
|
|
WINDOW *win; |
158 |
|
|
int i; |
159 |
|
|
int flags = _SUBWIN; |
160 |
|
|
|
161 |
|
|
T((T_CALLED("derwin(%p,%d,%d,%d,%d)"), orig, num_lines, num_columns, |
162 |
|
|
begy, begx)); |
163 |
|
|
|
164 |
|
|
/* |
165 |
|
|
* make sure window fits inside the original one |
166 |
|
|
*/ |
167 |
|
|
if (begy < 0 || begx < 0 || orig == 0 || num_lines < 0 || num_columns < 0) |
168 |
|
|
returnWin(0); |
169 |
|
|
if (begy + num_lines > orig->_maxy + 1 |
170 |
|
|
|| begx + num_columns > orig->_maxx + 1) |
171 |
|
|
returnWin(0); |
172 |
|
|
|
173 |
|
|
if (num_lines == 0) |
174 |
|
|
num_lines = orig->_maxy + 1 - begy; |
175 |
|
|
|
176 |
|
|
if (num_columns == 0) |
177 |
|
|
num_columns = orig->_maxx + 1 - begx; |
178 |
|
|
|
179 |
|
|
if (orig->_flags & _ISPAD) |
180 |
|
|
flags |= _ISPAD; |
181 |
|
|
|
182 |
|
|
if ((win = _nc_makenew(num_lines, num_columns, orig->_begy + begy, |
183 |
|
|
orig->_begx + begx, flags)) == 0) |
184 |
|
|
returnWin(0); |
185 |
|
|
|
186 |
|
|
win->_pary = begy; |
187 |
|
|
win->_parx = begx; |
188 |
|
|
WINDOW_ATTRS(win) = WINDOW_ATTRS(orig); |
189 |
|
|
win->_nc_bkgd = orig->_nc_bkgd; |
190 |
|
|
|
191 |
|
|
for (i = 0; i < num_lines; i++) |
192 |
|
|
win->_line[i].text = &orig->_line[begy++].text[begx]; |
193 |
|
|
|
194 |
|
|
win->_parent = orig; |
195 |
|
|
|
196 |
|
|
returnWin(win); |
197 |
|
|
} |
198 |
|
|
|
199 |
|
|
NCURSES_EXPORT(WINDOW *) |
200 |
|
|
subwin(WINDOW *w, int l, int c, int y, int x) |
201 |
|
|
{ |
202 |
|
|
T((T_CALLED("subwin(%p, %d, %d, %d, %d)"), w, l, c, y, x)); |
203 |
|
|
T(("parent has begy = %ld, begx = %ld", (long) w->_begy, (long) w->_begx)); |
204 |
|
|
|
205 |
|
|
returnWin(derwin(w, l, c, y - w->_begy, x - w->_begx)); |
206 |
|
|
} |
207 |
|
|
|
208 |
|
|
static bool |
209 |
|
|
dimension_limit(int value) |
210 |
|
|
{ |
211 |
|
|
NCURSES_SIZE_T test = value; |
212 |
|
|
return (test == value && value > 0); |
213 |
|
|
} |
214 |
|
|
|
215 |
|
|
NCURSES_EXPORT(WINDOW *) |
216 |
|
|
_nc_makenew(int num_lines, int num_columns, int begy, int begx, int flags) |
217 |
|
|
{ |
218 |
|
|
int i; |
219 |
|
|
WINDOWLIST *wp; |
220 |
|
|
WINDOW *win; |
221 |
|
|
bool is_pad = (flags & _ISPAD); |
222 |
|
|
|
223 |
|
|
T((T_CALLED("_nc_makenew(%d,%d,%d,%d)"), num_lines, num_columns, begy, begx)); |
224 |
|
|
|
225 |
|
|
if (SP == 0) |
226 |
|
|
returnWin(0); |
227 |
|
|
|
228 |
|
|
if (!dimension_limit(num_lines) || !dimension_limit(num_columns)) |
229 |
|
|
returnWin(0); |
230 |
|
|
|
231 |
|
|
if ((wp = typeCalloc(WINDOWLIST, 1)) == 0) |
232 |
|
|
returnWin(0); |
233 |
|
|
|
234 |
|
|
win = &(wp->win); |
235 |
|
|
|
236 |
|
|
if ((win->_line = typeCalloc(struct ldat, ((unsigned) num_lines))) == 0) { |
237 |
|
|
free(wp); |
238 |
|
|
returnWin(0); |
239 |
|
|
} |
240 |
|
|
|
241 |
|
|
_nc_lock_global(curses); |
242 |
|
|
|
243 |
|
|
win->_curx = 0; |
244 |
|
|
win->_cury = 0; |
245 |
|
|
win->_maxy = num_lines - 1; |
246 |
|
|
win->_maxx = num_columns - 1; |
247 |
|
|
win->_begy = begy; |
248 |
|
|
win->_begx = begx; |
249 |
|
|
win->_yoffset = SP->_topstolen; |
250 |
|
|
|
251 |
|
|
win->_flags = flags; |
252 |
|
|
WINDOW_ATTRS(win) = A_NORMAL; |
253 |
|
|
SetChar(win->_nc_bkgd, BLANK_TEXT, BLANK_ATTR); |
254 |
|
|
|
255 |
|
|
win->_clear = is_pad ? FALSE : (num_lines == screen_lines |
256 |
|
|
&& num_columns == screen_columns); |
257 |
|
|
win->_idlok = FALSE; |
258 |
|
|
win->_idcok = TRUE; |
259 |
|
|
win->_scroll = FALSE; |
260 |
|
|
win->_leaveok = FALSE; |
261 |
|
|
win->_use_keypad = FALSE; |
262 |
|
|
win->_delay = -1; |
263 |
|
|
win->_immed = FALSE; |
264 |
|
|
win->_sync = 0; |
265 |
|
|
win->_parx = -1; |
266 |
|
|
win->_pary = -1; |
267 |
|
|
win->_parent = 0; |
268 |
|
|
|
269 |
|
|
win->_regtop = 0; |
270 |
|
|
win->_regbottom = num_lines - 1; |
271 |
|
|
|
272 |
|
|
win->_pad._pad_y = -1; |
273 |
|
|
win->_pad._pad_x = -1; |
274 |
|
|
win->_pad._pad_top = -1; |
275 |
|
|
win->_pad._pad_bottom = -1; |
276 |
|
|
win->_pad._pad_left = -1; |
277 |
|
|
win->_pad._pad_right = -1; |
278 |
|
|
|
279 |
|
|
for (i = 0; i < num_lines; i++) { |
280 |
|
|
/* |
281 |
|
|
* This used to do |
282 |
|
|
* |
283 |
|
|
* win->_line[i].firstchar = win->_line[i].lastchar = _NOCHANGE; |
284 |
|
|
* |
285 |
|
|
* which marks the whole window unchanged. That's how |
286 |
|
|
* SVr1 curses did it, but SVr4 curses marks the whole new |
287 |
|
|
* window changed. |
288 |
|
|
* |
289 |
|
|
* With the old SVr1-like code, say you have stdscr full of |
290 |
|
|
* characters, then create a new window with newwin(), |
291 |
|
|
* then do a printw(win, "foo ");, the trailing spaces are |
292 |
|
|
* completely ignored by the following refreshes. So, you |
293 |
|
|
* get "foojunkjunk" on the screen instead of "foo " as |
294 |
|
|
* you actually intended. |
295 |
|
|
* |
296 |
|
|
* SVr4 doesn't do this. Instead the spaces are actually written. |
297 |
|
|
* So that's how we want ncurses to behave. |
298 |
|
|
*/ |
299 |
|
|
win->_line[i].firstchar = 0; |
300 |
|
|
win->_line[i].lastchar = num_columns - 1; |
301 |
|
|
|
302 |
|
|
if_USE_SCROLL_HINTS(win->_line[i].oldindex = i); |
303 |
|
|
} |
304 |
|
|
|
305 |
|
|
if (!is_pad && (begx + num_columns == screen_columns)) { |
306 |
|
|
win->_flags |= _ENDLINE; |
307 |
|
|
|
308 |
|
|
if (begx == 0 && num_lines == screen_lines && begy == 0) |
309 |
|
|
win->_flags |= _FULLWIN; |
310 |
|
|
|
311 |
|
|
if (begy + num_lines == screen_lines) |
312 |
|
|
win->_flags |= _SCROLLWIN; |
313 |
|
|
} |
314 |
|
|
|
315 |
|
|
wp->next = _nc_windows; |
316 |
|
|
wp->screen = SP; |
317 |
|
|
_nc_windows = wp; |
318 |
|
|
|
319 |
|
|
T((T_CREATE("window %p"), win)); |
320 |
|
|
|
321 |
|
|
_nc_unlock_global(curses); |
322 |
|
|
returnWin(win); |
323 |
|
|
} |
324 |
|
|
|
325 |
|
|
/* |
326 |
|
|
* wgetch() and other functions with a WINDOW* parameter may use a SCREEN* |
327 |
|
|
* internally, and it is useful to allow those to be invoked without switching |
328 |
|
|
* SCREEN's, e.g., for multi-threaded applications. |
329 |
|
|
*/ |
330 |
|
|
NCURSES_EXPORT(SCREEN *) |
331 |
|
|
_nc_screen_of(WINDOW *win) |
332 |
|
|
{ |
333 |
|
|
SCREEN *sp = 0; |
334 |
|
|
|
335 |
|
|
if (win != 0) { |
336 |
|
|
WINDOWLIST *wp = (WINDOWLIST *) win; |
337 |
|
|
sp = wp->screen; |
338 |
|
|
} |
339 |
|
|
return (sp); |
340 |
|
|
} |