1 /* Public Domain Curses */
5 RCSID("$Id: panel.c,v 1.8 2008/07/14 12:35:23 wmcbrine Exp $")
7 /*man-start**************************************************************
12 int bottom_panel(PANEL *pan);
13 int del_panel(PANEL *pan);
14 int hide_panel(PANEL *pan);
15 int move_panel(PANEL *pan, int starty, int startx);
16 PANEL *new_panel(WINDOW *win);
17 PANEL *panel_above(const PANEL *pan);
18 PANEL *panel_below(const PANEL *pan);
19 int panel_hidden(const PANEL *pan);
20 const void *panel_userptr(const PANEL *pan);
21 WINDOW *panel_window(const PANEL *pan);
22 int replace_panel(PANEL *pan, WINDOW *win);
23 int set_panel_userptr(PANEL *pan, const void *uptr);
24 int show_panel(PANEL *pan);
25 int top_panel(PANEL *pan);
26 void update_panels(void);
29 The panel library is built using the curses library, and any
30 program using panels routines must call one of the curses
31 initialization routines such as initscr(). A program using these
32 routines must be linked with the panels and curses libraries.
33 The header <panel.h> includes the header <curses.h>.
35 The panels package gives the applications programmer a way to
36 have depth relationships between curses windows; a curses window
37 is associated with every panel. The panels routines allow curses
38 windows to overlap without making visible the overlapped
39 portions of underlying windows. The initial curses window,
40 stdscr, lies beneath all panels. The set of currently visible
41 panels is the 'deck' of panels.
43 The panels package allows the applications programmer to create
44 panels, fetch and set their associated windows, shuffle panels
45 in the deck, and manipulate panels in other ways.
47 bottom_panel() places pan at the bottom of the deck. The size,
48 location and contents of the panel are unchanged.
50 del_panel() deletes pan, but not its associated winwow.
52 hide_panel() removes a panel from the deck and thus hides it
55 move_panel() moves the curses window associated with pan, so
56 that its upper lefthand corner is at the supplied coordinates.
57 (Do not use mvwin() on the window.)
59 new_panel() creates a new panel associated with win and returns
60 the panel pointer. The new panel is placed at the top of the
63 panel_above() returns a pointer to the panel in the deck above
64 pan, or NULL if pan is the top panel. If the value of pan passed
65 is NULL, this function returns a pointer to the bottom panel in
68 panel_below() returns a pointer to the panel in the deck below
69 pan, or NULL if pan is the bottom panel. If the value of pan
70 passed is NULL, this function returns a pointer to the top panel
73 panel_hidden() returns OK if pan is hidden and ERR if it is not.
75 panel_userptr() - Each panel has a user pointer available for
76 maintaining relevant information. This function returns a
77 pointer to that information previously set up by
80 panel_window() returns a pointer to the curses window associated
83 replace_panel() replaces the current window of pan with win.
85 set_panel_userptr() - Each panel has a user pointer available
86 for maintaining relevant information. This function sets the
87 value of that information.
89 show_panel() makes a previously hidden panel visible and places
90 it back in the deck on top.
92 top_panel() places pan on the top of the deck. The size,
93 location and contents of the panel are unchanged.
95 update_panels() refreshes the virtual screen to reflect the
96 depth relationships between the panels in the deck. The user
97 must use doupdate() to refresh the physical screen.
100 Each routine that returns a pointer to an object returns NULL if
101 an error occurs. Each panel routine that returns an integer,
102 returns OK if it executes successfully and ERR if it does not.
104 Portability X/Open BSD SYS V
116 set_panel_userptr - - Y
122 Original Author - Warren Tucker <wht@n4hgf.mt-park.ga.us>
124 **man-end****************************************************************/
129 PANEL
*_bottom_panel
= (PANEL
*)0;
130 PANEL
*_top_panel
= (PANEL
*)0;
131 PANEL _stdscr_pseudo_panel
= { (WINDOW
*)0 };
135 static void dPanel(char *text
, PANEL
*pan
)
137 PDC_LOG(("%s id=%s b=%s a=%s y=%d x=%d", text
, pan
->user
,
138 pan
->below
? pan
->below
->user
: "--",
139 pan
->above
? pan
->above
->user
: "--",
140 pan
->wstarty
, pan
->wstartx
));
143 static void dStack(char *fmt
, int num
, PANEL
*pan
)
147 sprintf(s80
, fmt
, num
, pan
);
148 PDC_LOG(("%s b=%s t=%s", s80
, _bottom_panel
? _bottom_panel
->user
: "--",
149 _top_panel
? _top_panel
->user
: "--"));
152 PDC_LOG(("pan id=%s", pan
->user
));
163 /* debugging hook for wnoutrefresh */
165 static void Wnoutrefresh(PANEL
*pan
)
167 dPanel("wnoutrefresh", pan
);
168 wnoutrefresh(pan
->win
);
171 static void Touchpan(PANEL
*pan
)
173 dPanel("Touchpan", pan
);
177 static void Touchline(PANEL
*pan
, int start
, int count
)
181 sprintf(s80
, "Touchline s=%d c=%d", start
, count
);
183 touchline(pan
->win
, start
, count
);
186 #else /* PANEL_DEBUG */
188 #define dPanel(text, pan)
189 #define dStack(fmt, num, pan)
190 #define Wnoutrefresh(pan) wnoutrefresh((pan)->win)
191 #define Touchpan(pan) touchwin((pan)->win)
192 #define Touchline(pan, start, count) touchline((pan)->win, start, count)
194 #endif /* PANEL_DEBUG */
196 static bool _panels_overlapped(PANEL
*pan1
, PANEL
*pan2
)
201 return ((pan1
->wstarty
>= pan2
->wstarty
&& pan1
->wstarty
< pan2
->wendy
)
202 || (pan2
->wstarty
>= pan1
->wstarty
&& pan2
->wstarty
< pan1
->wendy
))
203 && ((pan1
->wstartx
>= pan2
->wstartx
&& pan1
->wstartx
< pan2
->wendx
)
204 || (pan2
->wstartx
>= pan1
->wstartx
&& pan2
->wstartx
< pan1
->wendx
));
207 static void _free_obscure(PANEL
*pan
)
209 PANELOBS
*tobs
= pan
->obscure
; /* "this" one */
210 PANELOBS
*nobs
; /* "next" one */
218 pan
->obscure
= (PANELOBS
*)0;
221 static void _override(PANEL
*pan
, int show
)
225 PANELOBS
*tobs
= pan
->obscure
; /* "this" one */
232 Touchpan(&_stdscr_pseudo_panel
);
235 while (tobs
&& (tobs
->pan
!= pan
))
240 if ((pan2
= tobs
->pan
) != pan
)
241 for (y
= pan
->wstarty
; y
< pan
->wendy
; y
++)
242 if ((y
>= pan2
->wstarty
) && (y
< pan2
->wendy
) &&
243 ((is_linetouched(pan
->win
, y
- pan
->wstarty
)) ||
244 (is_linetouched(stdscr
, y
))))
245 Touchline(pan2
, y
- pan2
->wstarty
, 1);
251 static void _calculate_obscure(void)
254 PANELOBS
*tobs
; /* "this" one */
255 PANELOBS
*lobs
; /* last one */
264 lobs
= (PANELOBS
*)0;
265 pan2
= _bottom_panel
;
269 if (_panels_overlapped(pan
, pan2
))
271 if ((tobs
= malloc(sizeof(PANELOBS
))) == NULL
)
275 dPanel("obscured", pan2
);
276 tobs
->above
= (PANELOBS
*)0;
294 /* check to see if panel is in the stack */
296 static bool _panel_is_linked(const PANEL
*pan
)
298 PANEL
*pan2
= _bottom_panel
;
311 /* link panel into stack at top */
313 static void _panel_link_top(PANEL
*pan
)
316 dStack("<lt%d>", 1, pan
);
317 if (_panel_is_linked(pan
))
320 pan
->above
= (PANEL
*)0;
321 pan
->below
= (PANEL
*)0;
325 _top_panel
->above
= pan
;
326 pan
->below
= _top_panel
;
334 _calculate_obscure();
335 dStack("<lt%d>", 9, pan
);
338 /* link panel into stack at bottom */
340 static void _panel_link_bottom(PANEL
*pan
)
343 dStack("<lb%d>", 1, pan
);
344 if (_panel_is_linked(pan
))
347 pan
->above
= (PANEL
*)0;
348 pan
->below
= (PANEL
*)0;
352 _bottom_panel
->below
= pan
;
353 pan
->above
= _bottom_panel
;
361 _calculate_obscure();
362 dStack("<lb%d>", 9, pan
);
365 static void _panel_unlink(PANEL
*pan
)
371 dStack("<u%d>", 1, pan
);
372 if (!_panel_is_linked(pan
))
381 /* if non-zero, we will not update the list head */
392 if (pan
== _bottom_panel
)
393 _bottom_panel
= next
;
395 if (pan
== _top_panel
)
398 _calculate_obscure();
400 pan
->above
= (PANEL
*)0;
401 pan
->below
= (PANEL
*)0;
402 dStack("<u%d>", 9, pan
);
406 /************************************************************************
407 * The following are the public functions for the panels library. *
408 ************************************************************************/
410 int bottom_panel(PANEL
*pan
)
415 if (pan
== _bottom_panel
)
418 if (_panel_is_linked(pan
))
421 _panel_link_bottom(pan
);
426 int del_panel(PANEL
*pan
)
430 if (_panel_is_linked(pan
))
440 int hide_panel(PANEL
*pan
)
445 if (!_panel_is_linked(pan
))
447 pan
->above
= (PANEL
*)0;
448 pan
->below
= (PANEL
*)0;
457 int move_panel(PANEL
*pan
, int starty
, int startx
)
465 if (_panel_is_linked(pan
))
470 if (mvwin(win
, starty
, startx
) == ERR
)
473 getbegyx(win
, pan
->wstarty
, pan
->wstartx
);
474 getmaxyx(win
, maxy
, maxx
);
475 pan
->wendy
= pan
->wstarty
+ maxy
;
476 pan
->wendx
= pan
->wstartx
+ maxx
;
478 if (_panel_is_linked(pan
))
479 _calculate_obscure();
484 PANEL
*new_panel(WINDOW
*win
)
486 PANEL
*pan
= malloc(sizeof(PANEL
));
488 if (!_stdscr_pseudo_panel
.win
)
490 _stdscr_pseudo_panel
.win
= stdscr
;
491 _stdscr_pseudo_panel
.wstarty
= 0;
492 _stdscr_pseudo_panel
.wstartx
= 0;
493 _stdscr_pseudo_panel
.wendy
= LINES
;
494 _stdscr_pseudo_panel
.wendx
= COLS
;
495 _stdscr_pseudo_panel
.user
= "stdscr";
496 _stdscr_pseudo_panel
.obscure
= (PANELOBS
*)0;
504 pan
->above
= (PANEL
*)0;
505 pan
->below
= (PANEL
*)0;
506 getbegyx(win
, pan
->wstarty
, pan
->wstartx
);
507 getmaxyx(win
, maxy
, maxx
);
508 pan
->wendy
= pan
->wstarty
+ maxy
;
509 pan
->wendx
= pan
->wstartx
+ maxx
;
513 pan
->user
= (char *)0;
515 pan
->obscure
= (PANELOBS
*)0;
522 PANEL
*panel_above(const PANEL
*pan
)
524 return pan
? pan
->above
: _bottom_panel
;
527 PANEL
*panel_below(const PANEL
*pan
)
529 return pan
? pan
->below
: _top_panel
;
532 int panel_hidden(const PANEL
*pan
)
537 return _panel_is_linked(pan
) ? ERR
: OK
;
540 const void *panel_userptr(const PANEL
*pan
)
542 return pan
? pan
->user
: NULL
;
545 WINDOW
*panel_window(const PANEL
*pan
)
547 PDC_LOG(("panel_window() - called\n"));
552 int replace_panel(PANEL
*pan
, WINDOW
*win
)
559 if (_panel_is_linked(pan
))
563 getbegyx(win
, pan
->wstarty
, pan
->wstartx
);
564 getmaxyx(win
, maxy
, maxx
);
565 pan
->wendy
= pan
->wstarty
+ maxy
;
566 pan
->wendx
= pan
->wstartx
+ maxx
;
568 if (_panel_is_linked(pan
))
569 _calculate_obscure();
574 int set_panel_userptr(PANEL
*pan
, const void *uptr
)
583 int show_panel(PANEL
*pan
)
588 if (pan
== _top_panel
)
591 if (_panel_is_linked(pan
))
594 _panel_link_top(pan
);
599 int top_panel(PANEL
*pan
)
601 return show_panel(pan
);
604 void update_panels(void)
608 PDC_LOG(("update_panels() - called\n"));
618 if (is_wintouched(stdscr
))
619 Wnoutrefresh(&_stdscr_pseudo_panel
);
625 if (is_wintouched(pan
->win
) || !pan
->above
)