| 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 |  |  | } |