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