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