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 /* Copyright (c) 1988 AT&T */ 23 /* All Rights Reserved */ 24 25 26 /* 27 * Copyright (c) 1997, by Sun Microsystems, Inc. 28 * All rights reserved. 29 */ 30 31 /* A panels subsystem built on curses--Miscellaneous routines */ 32 33 #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.4 */ 34 35 /*LINTLIBRARY*/ 36 37 #include <sys/types.h> 38 #include <stdlib.h> 39 #include <curses.h> 40 #include "private.h" 41 42 PANEL *_Bottom_panel; 43 PANEL *_Top_panel; 44 int _Panel_cnt; 45 46 static _obscured_list *_Free_list; 47 static int _Free_list_cnt; 48 49 50 /* panel_window - Return the window pointer */ 51 WINDOW * 52 panel_window(PANEL *panel) 53 { 54 return (panel ? panel -> win : 0); 55 } 56 57 /* panel_userptr - Return the user pointer */ 58 char * 59 panel_userptr(PANEL *panel) 60 { 61 return (panel ? panel -> user : 0); 62 } 63 64 /* set_panel_userptr - set the user pointer */ 65 int 66 set_panel_userptr(PANEL *panel, char *ptr) 67 { 68 if (panel) { 69 panel -> user = ptr; 70 return (OK); 71 } else 72 return (ERR); 73 } 74 75 /* 76 * panel_above - Return the panel above the 77 * given panel (or the bottom panel in 0) 78 */ 79 PANEL * 80 panel_above(PANEL *panel) 81 { 82 83 if (!panel) 84 return (_Bottom_panel); 85 86 return ((panel == panel -> below) ? ((PANEL *) 0) : panel -> above); 87 } 88 89 90 /* 91 * panel_below - Return the panel below the 92 * given panel (or the top panel in 0) 93 */ 94 PANEL * 95 panel_below(PANEL *panel) 96 { 97 98 if (!panel) 99 return (_Top_panel); 100 101 return ((panel == panel -> below) ? ((PANEL *) 0) : panel -> below); 102 } 103 104 /* panel_hidden - Return TRUE if the panel is hidden, FALSE if not. */ 105 int 106 panel_hidden(PANEL *panel) 107 { 108 return ((!panel || (panel != panel -> below)) ? FALSE : TRUE); 109 } 110 111 /* _get_overlap - Get an overlap node from the free list. */ 112 static _obscured_list * 113 _get_overlap(void) 114 { 115 _obscured_list *overlap; 116 117 if (_Free_list_cnt-- > 0) { 118 overlap = _Free_list; 119 _Free_list = _Free_list -> next; 120 } else { 121 _Free_list_cnt = 0; 122 overlap = 0; 123 } 124 125 return (overlap); 126 } 127 128 129 /* 130 * _unlink_obs - Find the obscured node, if any, 131 * in the first panel which refers the second panel. 132 */ 133 _obscured_list * 134 _unlink_obs(PANEL *pnl, PANEL *panel) 135 { 136 _obscured_list *obs; 137 _obscured_list *prev_obs; 138 139 if (!pnl -> obscured || !_panels_intersect(pnl, panel)) 140 return ((_obscured_list *) 0); 141 142 obs = pnl -> obscured; 143 do { 144 prev_obs = obs; 145 obs = obs -> next; 146 } 147 while (obs->panel_p != panel && obs != pnl->obscured); 148 if (obs -> panel_p != panel) { 149 #ifdef DEBUG 150 fprintf(stderr, "_unlink_obs: Obscured panel lost\n"); 151 #endif 152 return ((_obscured_list *) 0); 153 } 154 155 if (obs == prev_obs) 156 pnl -> obscured = 0; 157 else { 158 prev_obs -> next = obs -> next; 159 if (obs == pnl -> obscured) 160 pnl -> obscured = prev_obs; 161 } 162 return (obs); 163 } 164 165 /* 166 * add_obs - Add an obscured node to a panel, ensuring 167 * that the obscured list is ordered from top to bottom. 168 */ 169 static void 170 add_obs(PANEL *panel, _obscured_list *obs) 171 { 172 PANEL *pnl; 173 _obscured_list *curr_obs; 174 _obscured_list *prev_obs; 175 176 if ((prev_obs = panel -> obscured) == 0) { 177 panel -> obscured = obs -> next = obs; 178 return; 179 } 180 181 curr_obs = prev_obs -> next; 182 183 for (pnl = _Top_panel; pnl != panel; pnl = pnl->below) { 184 if (curr_obs -> panel_p == pnl) { 185 prev_obs = curr_obs; 186 curr_obs = curr_obs -> next; 187 if (prev_obs == panel -> obscured) { 188 panel -> obscured = obs; 189 break; 190 } 191 } 192 } 193 194 obs -> next = curr_obs; 195 prev_obs -> next = obs; 196 } 197 198 199 /* 200 * _intersect_panel 201 * Create an obscured node for each panel that the given panel intersects. 202 * The overlap record is always attached to the panel which is covered up. 203 * 204 * This routine assumes that _alloc_overlap() has been called to ensure 205 * that there are enough overlap nodes to satisfy the requests. 206 */ 207 void 208 _intersect_panel(PANEL *panel) 209 { 210 PANEL *pnl; 211 _obscured_list *obs; 212 int above_panel; 213 214 above_panel = FALSE; 215 216 for (pnl = _Bottom_panel; pnl; pnl = pnl -> above) { 217 if (pnl == panel) { 218 above_panel = TRUE; 219 continue; 220 } 221 222 if (!_panels_intersect(pnl, panel)) 223 continue; /* no overlap */ 224 225 obs = _get_overlap(); 226 obs->start = (panel->wstarty >= pnl->wstarty) ? 227 panel->wstarty : pnl->wstarty; 228 obs->end = (panel->wendy <= pnl->wendy) ? 229 panel->wendy : pnl->wendy; 230 231 if (above_panel) { 232 obs -> panel_p = pnl; 233 if (panel -> obscured) { 234 obs -> next = panel -> obscured -> next; 235 panel -> obscured -> next = obs; 236 } else 237 obs -> next = panel -> obscured = obs; 238 } else { 239 obs -> panel_p = panel; 240 add_obs(pnl, obs); 241 } 242 243 } 244 } 245 246 /* 247 * _alloc_overlap 248 * Create enough obscured nodes to record all overlaps of a given 249 * panel. The obscured nodes must be pre-allocated by this routine 250 * to preserve the integrity of the pile during move. 251 * If the move operation fails, the pile is supposed to remain 252 * unchanged. If the obscured nodes are not allocated in advance, 253 * then an allocation failure in the middle of a move could 254 * leave the pile in a corrupted state with possibly no way to 255 * restore the pile to its original state. 256 * 257 * The cnt parameter is the(worst case) number of overlap nodes which 258 * are required to satisfy any request. Return 0 on error, else non-zero 259 */ 260 int 261 _alloc_overlap(int cnt) 262 { 263 _obscured_list *overlap; 264 int i; 265 266 for (i = cnt-_Free_list_cnt; i > 0; i--) { 267 if (!(overlap = (_obscured_list *) 268 malloc(sizeof (_obscured_list)))) 269 return (0); 270 271 overlap -> next = _Free_list; 272 _Free_list = overlap; 273 _Free_list_cnt++; 274 } 275 276 return (1); 277 } 278 279 280 /* 281 * _free_overlap - Free a single overlap node. Don't 282 * really free it; just save it on a list. 283 */ 284 void 285 _free_overlap(_obscured_list *overlap) 286 { 287 overlap -> next = _Free_list; 288 _Free_list = overlap; 289 _Free_list_cnt++; 290 } 291