1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 1995-1998 by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 27 /* LINTLIBRARY */ 28 29 /* 30 * newwin.c 31 * 32 * XCurses Library 33 * 34 * Copyright 1990, 1995 by Mortice Kern Systems. All rights reserved. 35 * 36 */ 37 38 #ifdef M_RCSID 39 #ifndef lint 40 static char rcsID[] = 41 "$Header: /team/ps/sun_xcurses/archive/local_changes/xcurses/src/lib/" 42 "libxcurses/src/libc/xcurses/rcs/newwin.c 1.11 1998/06/04 14:26:16 " 43 "cbates Exp $"; 44 #endif 45 #endif 46 47 #include <private.h> 48 #include <stdlib.h> 49 50 #undef werase 51 52 /* 53 * Create and return a pointer to a new window or pad. 54 * 55 * For a window, provide the dimensions and location of the upper 56 * left hand corner of the window. If either dimension is zero (0) 57 * then the default sizes will be LINES-begy and COLS-begx. 58 * 59 * For a pad, provide the dimensions and -1 for begy and begx. 60 * If either dimension is zero (0) then the default sizes will be 61 * LINES and COLS. 62 * 63 * If parent is not null, then create a sub-window of the parent 64 * window. 65 */ 66 WINDOW * 67 __m_newwin(WINDOW *parent, 68 int nlines, int ncols, int begy, int begx) 69 { 70 WINDOW *w; 71 int x, y, dx, dy; 72 int isPad; 73 74 isPad = ((begy < 0) && (begx < 0)) || 75 (parent && (parent->_flags & W_IS_PAD)); 76 77 if (parent == NULL) { 78 /* Check for default dimensions. */ 79 if (nlines == 0) { 80 nlines = lines; 81 if (0 <= begy) 82 nlines -= begy; 83 } 84 if (ncols == 0) { 85 ncols = columns; 86 if (0 <= begx) 87 ncols -= begx; 88 } 89 } else { 90 /* 91 * Make sure window dimensions remain within parent's 92 * window so that the new subwindow is a proper subset 93 * of the parent. 94 */ 95 if (begy < parent->_begy || begx < parent->_begx || 96 parent->_maxy < (begy-parent->_begy) + nlines || 97 parent->_maxx < (begx-parent->_begx) + ncols) 98 goto error_1; 99 100 /* 101 * If either dimension is zero (0), use the max size 102 * for the dimension from the parent window less the 103 * subwindow's starting location. 104 */ 105 if (nlines == 0) 106 nlines = parent->_maxy - (begy - parent->_begy); 107 if (ncols == 0) 108 ncols = parent->_maxx - (begx - parent->_begx); 109 } 110 111 if (!isPad) { 112 /* Check that a window fits on the screen. */ 113 if (0 <= begy) { 114 if (lines < begy + nlines) { 115 goto error_1; 116 } 117 } 118 if (0 <= begx) { 119 if (columns < begx + ncols) { 120 goto error_1; 121 } 122 } 123 } 124 125 w = (WINDOW *) calloc(1, sizeof (*w)); 126 if (w == NULL) 127 goto error_1; 128 129 w->_first = (short *) calloc((size_t) (nlines + nlines), 130 sizeof (*w->_first)); 131 if (w->_first == NULL) 132 goto error_2; 133 134 w->_last = &w->_first[nlines]; 135 136 w->_line = (cchar_t **) calloc((size_t) nlines, sizeof (*w->_line)); 137 if (w->_line == NULL) 138 goto error_2; 139 140 /* Window rendition. */ 141 (void) setcchar(&w->_bg, L" ", WA_NORMAL, 0, (void *) 0); 142 (void) setcchar(&w->_fg, L" ", WA_NORMAL, 0, (void *) 0); 143 if (parent == NULL) { 144 w->_base = (cchar_t *) malloc((size_t) (nlines * ncols) * 145 sizeof (*w->_base)); 146 if (w->_base == NULL) 147 goto error_2; 148 149 w->_line[0] = w->_base; 150 for (y = 0; y < nlines; y++) { 151 if (y) 152 w->_line[y] = &w->_line[y-1][ncols]; 153 for (x = 0; x < ncols; ++x) { 154 w->_line[y][x] = w->_bg; 155 } 156 } 157 } else { 158 /* 159 * The new window's origin (0,0) maps to (begy, begx) in the 160 * parent's window. In effect, subwin() is a method by which 161 * a portion of a parent's window can be addressed using a 162 * (0,0) origin. 163 */ 164 dy = begy - parent->_begy; 165 dx = begx - parent->_begx; 166 167 w->_base = NULL; 168 169 for (y = 0; y < nlines; ++y) 170 w->_line[y] = &parent->_line[dy++][dx]; 171 } 172 173 w->_begy = (short) begy; 174 w->_begx = (short) begx; 175 w->_cury = w->_curx = 0; 176 w->_maxy = (short) nlines; 177 w->_maxx = (short) ncols; 178 w->_parent = parent; 179 180 /* Software scroll region. */ 181 w->_top = 0; 182 w->_bottom = (short) nlines; 183 w->_scroll = 0; 184 185 /* Window initially blocks for input. */ 186 w->_vmin = 1; 187 w->_vtime = 0; 188 w->_flags = W_USE_TIMEOUT; 189 190 /* Determine window properties. */ 191 if (isPad) { 192 /* This window is a PAD */ 193 w->_flags |= W_IS_PAD; /* Inherit PAD attribute */ 194 if (((begy < 0) && (begx < 0)) || 195 (parent && !(parent->_flags & W_IS_PAD))) { 196 /* Child of a normal window */ 197 w->_begy = w->_begx = 0; 198 /* 199 * Map to upper left portion of 200 * display by default (???) 201 */ 202 w->_sminy = w->_sminx = 0; 203 w->_smaxx = w->_maxx; 204 w->_smaxy = w->_maxy; 205 } 206 } else if (begx + ncols == columns) { 207 /* Writing to last column should trigger auto-margin wrap. */ 208 w->_flags |= W_END_LINE; 209 210 if (begx == 0) { 211 w->_flags |= W_FULL_LINE; 212 213 if (begy == 0 && nlines == lines) 214 w->_flags |= W_FULL_WINDOW; 215 } 216 217 /* Will writing to bottom-right triggers scroll? */ 218 if (begy + nlines == lines) 219 w->_flags |= W_SCROLL_WINDOW; 220 } 221 222 /* Initial screen clear for full screen windows only. */ 223 if (w->_flags & W_FULL_WINDOW) { 224 w->_flags |= W_CLEAR_WINDOW; 225 /* Reset dirty region markers. */ 226 (void) wtouchln(w, 0, w->_maxy, 0); 227 } else { 228 if (!parent) { 229 /* Do not erase sub windows */ 230 (void) werase(w); 231 } 232 } 233 234 return (w); 235 error_2: 236 (void) delwin(w); 237 error_1: 238 return (NULL); 239 } 240 241 int 242 delwin(WINDOW *w) 243 { 244 if (w == NULL) 245 return (OK); 246 247 248 if (w->_line != NULL) { 249 if (w->_base != NULL) 250 free(w->_base); 251 252 free(w->_line); 253 } 254 255 if (w->_first != NULL) 256 free(w->_first); 257 258 free(w); 259 260 return (OK); 261 } 262 263 WINDOW * 264 derwin(WINDOW *parent, 265 int nlines, int ncols, int begy, int begx) 266 { 267 WINDOW *w; 268 269 if (parent == NULL) 270 return (NULL); 271 272 /* Absolute screen address. */ 273 begy += parent->_begy; 274 begx += parent->_begx; 275 276 w = __m_newwin(parent, nlines, ncols, begy, begx); 277 278 return (w); 279 } 280 281 WINDOW * 282 newwin(int nlines, int ncols, int begy, int begx) 283 { 284 WINDOW *w; 285 286 w = __m_newwin(NULL, nlines, ncols, begy, begx); 287 288 return (w); 289 } 290 291 WINDOW * 292 subwin(WINDOW *parent, int nlines, int ncols, int begy, int begx) 293 { 294 WINDOW *w; 295 296 if (parent == NULL) 297 return (NULL); 298 299 w = __m_newwin(parent, nlines, ncols, begy, begx); 300 301 return (w); 302 } 303