2 /***************************************************************************
4 ****************************************************************************
5 * panels is copyright (C) 1995 *
7 * zmbenhal@netcom.com *
9 * esr@snark.thyrsus.com *
11 * All praise to the original author, Warren Tucker. *
13 * Permission is hereby granted to reproduce and distribute panels *
14 * by any means and for any fee, whether alone or as part of a *
15 * larger distribution, in source or in binary form, PROVIDED *
16 * this notice is included with any such distribution, and is not *
17 * removed from any of its header files. Mention of panels in any *
18 * applications linked with it is highly appreciated. *
20 * panels comes AS IS with no warranty, implied or expressed. *
22 ***************************************************************************/
24 /* panel.c -- implementation of panels library */
25 #include "panel.priv.h"
27 MODULE_ID("$Id: panel.c,v 1.10 1997/05/05 09:42:11 tom Exp $")
30 extern char *_nc_visbuf(const char *);
32 #define USER_PTR(ptr) _nc_visbuf((const char *)ptr)
34 static char *my_nc_visbuf(const void *ptr)
38 sprintf(temp, "ptr:%p", ptr);
40 strcpy(temp, "<null>");
41 return _nc_visbuf(temp);
43 #define USER_PTR(ptr) my_nc_visbuf((const char *)ptr)
47 static PANEL *__bottom_panel = (PANEL *)0;
48 static PANEL *__top_panel = (PANEL *)0;
50 static PANEL __stdscr_pseudo_panel = { (WINDOW *)0,
52 (PANEL *)0, (PANEL *)0,
57 static void __panel_link_bottom(PANEL *pan);
59 /*+-------------------------------------------------------------------------
61 --------------------------------------------------------------------------*/
64 dPanel(const char *text, const PANEL *pan)
66 _tracef("%s id=%s b=%s a=%s y=%d x=%d",
67 text, USER_PTR(pan->user),
68 (pan->below) ? USER_PTR(pan->below->user) : "--",
69 (pan->above) ? USER_PTR(pan->above->user) : "--",
70 pan->wstarty, pan->wstartx);
73 # define dPanel(text,pan)
76 /*+-------------------------------------------------------------------------
78 --------------------------------------------------------------------------*/
81 dStack(const char *fmt, int num, const PANEL *pan)
85 sprintf(s80,fmt,num,pan);
86 _tracef("%s b=%s t=%s",s80,
87 (__bottom_panel) ? USER_PTR(__bottom_panel->user) : "--",
88 (__top_panel) ? USER_PTR(__top_panel->user) : "--");
90 _tracef("pan id=%s", USER_PTR(pan->user));
99 # define dStack(fmt,num,pan)
102 /*+-------------------------------------------------------------------------
103 Wnoutrefresh(pan) - debugging hook for wnoutrefresh
104 --------------------------------------------------------------------------*/
107 Wnoutrefresh(const PANEL *pan)
109 dPanel("wnoutrefresh",pan);
110 wnoutrefresh(pan->win);
111 } /* end of Wnoutrefresh */
113 # define Wnoutrefresh(pan) wnoutrefresh((pan)->win)
116 /*+-------------------------------------------------------------------------
118 --------------------------------------------------------------------------*/
121 Touchpan(const PANEL *pan)
123 dPanel("Touchpan",pan);
125 } /* end of Touchpan */
127 # define Touchpan(pan) touchwin((pan)->win)
130 /*+-------------------------------------------------------------------------
131 Touchline(pan,start,count)
132 --------------------------------------------------------------------------*/
135 Touchline(const PANEL *pan, int start, int count)
138 sprintf(s80,"Touchline s=%d c=%d",start,count);
140 touchline(pan->win,start,count);
141 } /* end of Touchline */
143 # define Touchline(pan,start,count) touchline((pan)->win,start,count)
146 /*+-------------------------------------------------------------------------
147 __panels_overlapped(pan1,pan2) - check panel overlapped
148 --------------------------------------------------------------------------*/
150 __panels_overlapped(register const PANEL *pan1, register const PANEL *pan2)
154 dBug(("__panels_overlapped %s %s", USER_PTR(pan1->user), USER_PTR(pan2->user)));
155 /* pan1 intersects with pan2 ? */
156 if((pan1->wstarty >= pan2->wstarty) && (pan1->wstarty < pan2->wendy) &&
157 (pan1->wstartx >= pan2->wstartx) && (pan1->wstartx < pan2->wendx))
159 /* or vice versa test */
160 if((pan2->wstarty >= pan1->wstarty) && (pan2->wstarty < pan1->wendy) &&
161 (pan2->wstartx >= pan1->wstartx) && (pan2->wstartx < pan1->wendx))
165 } /* end of __panels_overlapped */
167 /*+-------------------------------------------------------------------------
169 --------------------------------------------------------------------------*/
171 __free_obscure(PANEL *pan)
173 PANELCONS *tobs = pan->obscure; /* "this" one */
174 PANELCONS *nobs; /* "next" one */
182 pan->obscure = (PANELCONS *)0;
183 } /* end of __free_obscure */
185 /*+-------------------------------------------------------------------------
186 Get root (i.e. stdscr's) panel.
187 Establish the pseudo panel for stdscr if necessary.
188 --------------------------------------------------------------------------*/
192 if(!__stdscr_pseudo_panel.win)
193 { /* initialize those fields not already statically initialized */
194 assert(stdscr && !__bottom_panel && !__top_panel);
195 __stdscr_pseudo_panel.win = stdscr;
196 __stdscr_pseudo_panel.wendy = LINES;
197 __stdscr_pseudo_panel.wendx = COLS;
199 __stdscr_pseudo_panel.user = "stdscr";
201 __panel_link_bottom(&__stdscr_pseudo_panel);
203 return &__stdscr_pseudo_panel;
206 /*+-------------------------------------------------------------------------
208 --------------------------------------------------------------------------*/
210 __override(const PANEL *pan, int show)
214 PANELCONS *tobs = pan->obscure; /* "this" one */
216 dBug(("__override %s,%d", USER_PTR(pan->user),show));
222 /* The following while loop will now mark all panel window lines
223 * obscured by use or obscuring us as touched, so they will be
228 while(tobs && (tobs->pan != pan))
230 /* The next loop will now only go through the panels obscuring pan;
231 * it updates all the lines in the obscuring panels in sync. with
232 * the lines touched in pan itself. This is called in update_panels()
233 * in a loop from the bottom_panel to the top_panel, resulting in
234 * the desired update effect.
243 if((pan2 = tobs->pan) != pan) {
244 dBug(("test obs pan=%s pan2=%s", USER_PTR(pan->user), USER_PTR(pan2->user)));
245 for(y = pan->wstarty; y < pan->wendy; y++) {
246 if( (y >= pan2->wstarty) && (y < pan2->wendy) &&
247 ((is_linetouched(pan->win,y - pan->wstarty) == TRUE)) )
248 Touchline(pan2,y - pan2->wstarty,1);
253 } /* end of __override */
255 /*+-------------------------------------------------------------------------
256 __calculate_obscure()
257 --------------------------------------------------------------------------*/
259 __calculate_obscure(void)
263 PANELCONS *tobs; /* "this" one */
264 PANELCONS *lobs = (PANELCONS *)0; /* last one */
266 pan = __bottom_panel;
271 dBug(("--> __calculate_obscure %s", USER_PTR(pan->user)));
272 lobs = (PANELCONS *)0; /* last one */
273 pan2 = __bottom_panel;
274 /* This loop builds a list of panels obsured by pan or obscuring
275 pan; pan itself is in the list; all panels before pan are
276 obscured by pan, all panels after pan are obscuring pan. */
279 if(__panels_overlapped(pan,pan2))
281 if(!(tobs = (PANELCONS *)malloc(sizeof(PANELCONS))))
284 dPanel("obscured",pan2);
285 tobs->above = (PANELCONS *)0;
294 __override(pan,P_TOUCH);
297 } /* end of __calculate_obscure */
299 /*+-------------------------------------------------------------------------
300 __panel_is_linked(pan) - check to see if panel is in the stack
301 --------------------------------------------------------------------------*/
303 __panel_is_linked(const PANEL *pan)
305 /* This works! The only case where it would fail is, when the list has
306 only one element. But this could only be the pseudo panel at the bottom */
307 return ( ((pan->above!=(PANEL *)0) ||
308 (pan->below!=(PANEL *)0) ||
309 (pan==__bottom_panel)) ? TRUE : FALSE );
310 } /* end of __panel_is_linked */
312 /*+-------------------------------------------------------------------------
313 __panel_link_top(pan) - link panel into stack at top
314 --------------------------------------------------------------------------*/
316 __panel_link_top(PANEL *pan)
319 dStack("<lt%d>",1,pan);
320 if(__panel_is_linked(pan))
324 pan->above = (PANEL *)0;
325 pan->below = (PANEL *)0;
328 __top_panel->above = pan;
329 pan->below = __top_panel;
333 __bottom_panel = pan;
334 __calculate_obscure();
335 dStack("<lt%d>",9,pan);
337 } /* end of __panel_link_top */
339 /*+-------------------------------------------------------------------------
340 __panel_link_bottom(pan) - link panel into stack at bottom
341 --------------------------------------------------------------------------*/
343 __panel_link_bottom(PANEL *pan)
346 dStack("<lb%d>",1,pan);
347 if(__panel_is_linked(pan))
351 pan->above = (PANEL *)0;
352 pan->below = (PANEL *)0;
354 { /* the stdscr pseudo panel always stays real bottom;
355 so we insert after bottom panel*/
356 pan->below = __bottom_panel;
357 pan->above = __bottom_panel->above;
359 pan->above->below = pan;
360 __bottom_panel->above = pan;
363 __bottom_panel = pan;
366 assert(__bottom_panel == &__stdscr_pseudo_panel);
367 __calculate_obscure();
368 dStack("<lb%d>",9,pan);
369 } /* end of __panel_link_bottom */
371 /*+-------------------------------------------------------------------------
372 __panel_unlink(pan) - unlink panel from stack
373 --------------------------------------------------------------------------*/
375 __panel_unlink(PANEL *pan)
381 dStack("<u%d>",1,pan);
382 if(!__panel_is_linked(pan))
386 __override(pan,P_TOUCH);
393 { /* if non-zero, we will not update the list head */
400 if(pan == __bottom_panel)
401 __bottom_panel = next;
402 if(pan == __top_panel)
405 __calculate_obscure();
407 pan->above = (PANEL *)0;
408 pan->below = (PANEL *)0;
409 dStack("<u%d>",9,pan);
410 } /* end of __panel_unlink */
412 /*+-------------------------------------------------------------------------
413 panel_window(pan) - get window associated with panel
414 --------------------------------------------------------------------------*/
416 panel_window(const PANEL *pan)
418 return(pan ? pan->win : (WINDOW *)0);
419 } /* end of panel_window */
421 /*+-------------------------------------------------------------------------
422 update_panels() - wnoutrefresh windows in an orderly fashion
423 --------------------------------------------------------------------------*/
429 dBug(("--> update_panels"));
430 pan = __bottom_panel;
433 __override(pan,P_UPDATE);
437 pan = __bottom_panel;
440 if(is_wintouched(pan->win))
444 } /* end of update_panels */
446 /*+-------------------------------------------------------------------------
447 hide_panel(pan) - remove a panel from stack
448 --------------------------------------------------------------------------*/
450 hide_panel(register PANEL *pan)
455 dBug(("--> hide_panel %s", USER_PTR(pan->user)));
457 if(!__panel_is_linked(pan))
459 pan->above = (PANEL *)0;
460 pan->below = (PANEL *)0;
466 } /* end of hide_panel */
468 /*+-------------------------------------------------------------------------
469 show_panel(pan) - place a panel on top of stack
470 may already be in stack
471 --------------------------------------------------------------------------*/
473 show_panel(register PANEL *pan)
477 if(pan == __top_panel)
479 dBug(("--> show_panel %s", USER_PTR(pan->user)));
480 if(__panel_is_linked(pan))
481 (void)hide_panel(pan);
482 __panel_link_top(pan);
484 } /* end of show_panel */
486 /*+-------------------------------------------------------------------------
487 top_panel(pan) - place a panel on top of stack
488 --------------------------------------------------------------------------*/
490 top_panel(register PANEL *pan)
492 return(show_panel(pan));
493 } /* end of top_panel */
495 /*+-------------------------------------------------------------------------
496 del_panel(pan) - remove a panel from stack, if in it, and free struct
497 --------------------------------------------------------------------------*/
499 del_panel(register PANEL *pan)
503 dBug(("--> del_panel %s", USER_PTR(pan->user)));
504 if(__panel_is_linked(pan))
505 (void)hide_panel(pan);
510 } /* end of del_panel */
512 /*+-------------------------------------------------------------------------
513 bottom_panel(pan) - place a panel on bottom of stack
514 may already be in stack
515 --------------------------------------------------------------------------*/
517 bottom_panel(register PANEL *pan)
521 if(pan == __bottom_panel)
523 dBug(("--> bottom_panel %s", USER_PTR(pan->user)));
524 if(__panel_is_linked(pan))
525 (void)hide_panel(pan);
526 __panel_link_bottom(pan);
528 } /* end of bottom_panel */
530 /*+-------------------------------------------------------------------------
531 new_panel(win) - create a panel and place on top of stack
532 --------------------------------------------------------------------------*/
534 new_panel(WINDOW *win)
536 PANEL *pan = (PANEL *)malloc(sizeof(PANEL));
538 (void)__root_panel();
543 pan->above = (PANEL *)0;
544 pan->below = (PANEL *)0;
545 getbegyx(win, pan->wstarty, pan->wstartx);
546 pan->wendy = pan->wstarty + getmaxy(win);
547 pan->wendx = pan->wstartx + getmaxx(win);
551 pan->user = (char *)0;
553 pan->obscure = (PANELCONS *)0;
554 (void)show_panel(pan);
557 } /* end of new_panel */
559 /*+-------------------------------------------------------------------------
561 --------------------------------------------------------------------------*/
563 panel_above(const PANEL *pan)
567 /* if top and bottom are equal, we have no or only the pseudo panel;
568 if not, we return the panel above the pseudo panel */
569 return(__bottom_panel==__top_panel ? (PANEL*)0 : __bottom_panel->above);
573 } /* end of panel_above */
575 /*+-------------------------------------------------------------------------
577 --------------------------------------------------------------------------*/
579 panel_below(const PANEL *pan)
583 /* if top and bottom are equal, we have no or only the pseudo panel */
584 return(__top_panel==__bottom_panel ? (PANEL*)0 : __top_panel);
588 /* we must not return the pseudo panel */
589 return(pan->below==__bottom_panel ? (PANEL*) 0 : pan->below);
591 } /* end of panel_below */
593 /*+-------------------------------------------------------------------------
594 set_panel_userptr(pan,uptr)
595 --------------------------------------------------------------------------*/
597 set_panel_userptr(PANEL *pan, const void *uptr)
603 } /* end of set_panel_userptr */
605 /*+-------------------------------------------------------------------------
607 --------------------------------------------------------------------------*/
609 panel_userptr(const PANEL *pan)
611 return(pan ? pan->user : (void *)0);
612 } /* end of panel_userptr */
614 /*+-------------------------------------------------------------------------
615 move_panel(pan,starty,startx)
616 --------------------------------------------------------------------------*/
618 move_panel(PANEL *pan, int starty, int startx)
624 if(__panel_is_linked(pan))
625 __override(pan,P_TOUCH);
627 if(mvwin(win,starty,startx))
629 getbegyx(win, pan->wstarty, pan->wstartx);
630 pan->wendy = pan->wstarty + getmaxy(win);
631 pan->wendx = pan->wstartx + getmaxx(win);
632 if(__panel_is_linked(pan))
633 __calculate_obscure();
635 } /* end of move_panel */
637 /*+-------------------------------------------------------------------------
638 replace_panel(pan,win)
639 --------------------------------------------------------------------------*/
641 replace_panel(PANEL *pan, WINDOW *win)
645 if(__panel_is_linked(pan))
646 __override(pan,P_TOUCH);
648 if(__panel_is_linked(pan))
649 __calculate_obscure();
651 } /* end of replace_panel */
653 /*+-------------------------------------------------------------------------
655 --------------------------------------------------------------------------*/
657 panel_hidden(const PANEL *pan)
661 return(__panel_is_linked(pan) ? TRUE : FALSE);
662 } /* end of panel_hidden */