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.69 2011/03/07 21:58:17 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 || begx < 0 || num_lines < 0 || num_columns < 0) 145 returnWin(0); 146 147 if (num_lines == 0) 148 num_lines = SP_PARM->_lines_avail - begy; 149 if (num_columns == 0) 150 num_columns = screen_columns(SP_PARM) - begx; 151 152 win = NCURSES_SP_NAME(_nc_makenew) (NCURSES_SP_ARGx 153 num_lines, num_columns, begy, begx, 0); 154 if (win == 0) 155 returnWin(0); 156 157 for (i = 0; i < num_lines; i++) { 158 win->_line[i].text = typeCalloc(NCURSES_CH_T, (unsigned) num_columns); 159 if (win->_line[i].text == 0) { 160 (void) _nc_freewin(win); 161 returnWin(0); 162 } 163 for (ptr = win->_line[i].text; 164 ptr < win->_line[i].text + num_columns; 165 ptr++) 166 SetChar(*ptr, BLANK_TEXT, BLANK_ATTR); 167 } 168 169 returnWin(win); 170 } 171 172 #if NCURSES_SP_FUNCS 173 NCURSES_EXPORT(WINDOW *) 174 newwin(int num_lines, int num_columns, int begy, int begx) 175 { 176 WINDOW *win; 177 _nc_sp_lock_global(curses); 178 win = NCURSES_SP_NAME(newwin) (CURRENT_SCREEN, 179 num_lines, num_columns, begy, begx); 180 _nc_sp_unlock_global(curses); 181 return (win); 182 } 183 #endif 184 185 NCURSES_EXPORT(WINDOW *) 186 derwin(WINDOW *orig, int num_lines, int num_columns, int begy, int begx) 187 { 188 WINDOW *win; 189 int i; 190 int flags = _SUBWIN; 191 #if NCURSES_SP_FUNCS 192 SCREEN *sp = _nc_screen_of(orig); 193 #endif 194 195 T((T_CALLED("derwin(%p,%d,%d,%d,%d)"), (void *) orig, num_lines, num_columns, 196 begy, begx)); 197 198 /* 199 * make sure window fits inside the original one 200 */ 201 if (begy < 0 || begx < 0 || orig == 0 || num_lines < 0 || num_columns < 0) 202 returnWin(0); 203 if (begy + num_lines > orig->_maxy + 1 204 || begx + num_columns > orig->_maxx + 1) 205 returnWin(0); 206 207 if (num_lines == 0) 208 num_lines = orig->_maxy + 1 - begy; 209 210 if (num_columns == 0) 211 num_columns = orig->_maxx + 1 - begx; 212 213 if (orig->_flags & _ISPAD) 214 flags |= _ISPAD; 215 216 win = NCURSES_SP_NAME(_nc_makenew) (NCURSES_SP_ARGx num_lines, num_columns, 217 orig->_begy + begy, 218 orig->_begx + begx, flags); 219 if (win == 0) 220 returnWin(0); 221 222 win->_pary = begy; 223 win->_parx = begx; 224 WINDOW_ATTRS(win) = WINDOW_ATTRS(orig); 225 win->_nc_bkgd = orig->_nc_bkgd; 226 227 for (i = 0; i < num_lines; i++) 228 win->_line[i].text = &orig->_line[begy++].text[begx]; 229 230 win->_parent = orig; 231 232 returnWin(win); 233 } 234 235 NCURSES_EXPORT(WINDOW *) 236 subwin(WINDOW *w, int l, int c, int y, int x) 237 { 238 T((T_CALLED("subwin(%p, %d, %d, %d, %d)"), (void *) w, l, c, y, x)); 239 T(("parent has begy = %ld, begx = %ld", (long) w->_begy, (long) w->_begx)); 240 241 returnWin(derwin(w, l, c, y - w->_begy, x - w->_begx)); 242 } 243 244 static bool 245 dimension_limit(int value) 246 { 247 NCURSES_SIZE_T test = (NCURSES_SIZE_T) value; 248 return (test == value && value > 0); 249 } 250 251 NCURSES_EXPORT(WINDOW *) 252 NCURSES_SP_NAME(_nc_makenew) (NCURSES_SP_DCLx 253 int num_lines, 254 int num_columns, 255 int begy, 256 int begx, 257 int flags) 258 { 259 int i; 260 WINDOWLIST *wp; 261 WINDOW *win; 262 bool is_padwin = (flags & _ISPAD); 263 264 T((T_CALLED("_nc_makenew(%p,%d,%d,%d,%d)"), 265 (void *) SP_PARM, num_lines, num_columns, begy, begx)); 266 267 if (SP_PARM == 0) 268 returnWin(0); 269 270 if (!dimension_limit(num_lines) || !dimension_limit(num_columns)) 271 returnWin(0); 272 273 if ((wp = typeCalloc(WINDOWLIST, 1)) == 0) 274 returnWin(0); 275 276 win = &(wp->win); 277 278 if ((win->_line = typeCalloc(struct ldat, ((unsigned) num_lines))) == 0) { 279 free(wp); 280 returnWin(0); 281 } 282 283 _nc_nonsp_lock_global(curses); 284 285 win->_curx = 0; 286 win->_cury = 0; 287 win->_maxy = (NCURSES_SIZE_T) (num_lines - 1); 288 win->_maxx = (NCURSES_SIZE_T) (num_columns - 1); 289 win->_begy = (NCURSES_SIZE_T) begy; 290 win->_begx = (NCURSES_SIZE_T) begx; 291 win->_yoffset = SP_PARM->_topstolen; 292 293 win->_flags = (short) flags; 294 WINDOW_ATTRS(win) = A_NORMAL; 295 SetChar(win->_nc_bkgd, BLANK_TEXT, BLANK_ATTR); 296 297 win->_clear = (is_padwin 298 ? FALSE 299 : (num_lines == screen_lines(SP_PARM) 300 && num_columns == screen_columns(SP_PARM))); 301 win->_idlok = FALSE; 302 win->_idcok = TRUE; 303 win->_scroll = FALSE; 304 win->_leaveok = FALSE; 305 win->_use_keypad = FALSE; 306 win->_delay = -1; 307 win->_immed = FALSE; 308 win->_sync = 0; 309 win->_parx = -1; 310 win->_pary = -1; 311 win->_parent = 0; 312 313 win->_regtop = 0; 314 win->_regbottom = (NCURSES_SIZE_T) (num_lines - 1); 315 316 win->_pad._pad_y = -1; 317 win->_pad._pad_x = -1; 318 win->_pad._pad_top = -1; 319 win->_pad._pad_bottom = -1; 320 win->_pad._pad_left = -1; 321 win->_pad._pad_right = -1; 322 323 for (i = 0; i < num_lines; i++) { 324 /* 325 * This used to do 326 * 327 * win->_line[i].firstchar = win->_line[i].lastchar = _NOCHANGE; 328 * 329 * which marks the whole window unchanged. That's how 330 * SVr1 curses did it, but SVr4 curses marks the whole new 331 * window changed. 332 * 333 * With the old SVr1-like code, say you have stdscr full of 334 * characters, then create a new window with newwin(), 335 * then do a printw(win, "foo ");, the trailing spaces are 336 * completely ignored by the following refreshes. So, you 337 * get "foojunkjunk" on the screen instead of "foo " as 338 * you actually intended. 339 * 340 * SVr4 doesn't do this. Instead the spaces are actually written. 341 * So that's how we want ncurses to behave. 342 */ 343 win->_line[i].firstchar = 0; 344 win->_line[i].lastchar = (NCURSES_SIZE_T) (num_columns - 1); 345 346 if_USE_SCROLL_HINTS(win->_line[i].oldindex = i); 347 } 348 349 if (!is_padwin && (begx + num_columns == screen_columns(SP_PARM))) { 350 win->_flags |= _ENDLINE; 351 352 if (begx == 0 && num_lines == screen_lines(SP_PARM) && begy == 0) 353 win->_flags |= _FULLWIN; 354 355 if (begy + num_lines == screen_lines(SP_PARM)) 356 win->_flags |= _SCROLLWIN; 357 } 358 359 wp->next = WindowList(SP_PARM); 360 wp->screen = SP_PARM; 361 WindowList(SP_PARM) = wp; 362 363 T((T_CREATE("window %p"), (void *) win)); 364 365 _nc_nonsp_unlock_global(curses); 366 returnWin(win); 367 } 368 369 /* 370 * wgetch() and other functions with a WINDOW* parameter may use a SCREEN* 371 * internally, and it is useful to allow those to be invoked without switching 372 * SCREEN's, e.g., for multi-threaded applications. 373 */ 374 #if NCURSES_SP_FUNCS 375 NCURSES_EXPORT(WINDOW *) 376 _nc_curscr_of(SCREEN *sp) 377 { 378 return sp == 0 ? 0 : CurScreen(sp); 379 } 380 381 NCURSES_EXPORT(WINDOW *) 382 _nc_newscr_of(SCREEN *sp) 383 { 384 return sp == 0 ? 0 : NewScreen(sp); 385 } 386 387 NCURSES_EXPORT(WINDOW *) 388 _nc_stdscr_of(SCREEN *sp) 389 { 390 return sp == 0 ? 0 : StdScreen(sp); 391 } 392 #endif 393