xref: /illumos-gate/usr/src/lib/libeti/panel/common/misc.c (revision d48be21240dfd051b689384ce2b23479d757f2d8)
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