libpayload: remove trailing whitespace and run dos2unix
[coreboot.git] / payloads / libpayload / curses / PDCurses-3.4 / pdcurses / panel.c
1 /* Public Domain Curses */
2
3 #include <curspriv.h>
4
5 RCSID("$Id: panel.c,v 1.8 2008/07/14 12:35:23 wmcbrine Exp $")
6
7 /*man-start**************************************************************
8
9   Name:                                                         panel
10
11   Synopsis:
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);
27
28   Description:
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>.
34
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.
42
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.
46
47         bottom_panel() places pan at the bottom of the deck. The size,
48         location and contents of the panel are unchanged.
49
50         del_panel() deletes pan, but not its associated winwow.
51
52         hide_panel() removes a panel from the deck and thus hides it
53         from view.
54
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.)
58
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
61         deck.
62
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
66         the deck.
67
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
71         in the deck.
72
73         panel_hidden() returns OK if pan is hidden and ERR if it is not.
74
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
78         set_panel_userptr().
79
80         panel_window() returns a pointer to the curses window associated
81         with the panel.
82
83         replace_panel() replaces the current window of pan with win.
84
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.
88
89         show_panel() makes a previously hidden panel visible and places
90         it back in the deck on top.
91
92         top_panel() places pan on the top of the deck. The size,
93         location and contents of the panel are unchanged.
94
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.
98
99   Return Value:
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.
103
104   Portability                                X/Open    BSD    SYS V
105         bottom_panel                            -       -       Y
106         del_panel                               -       -       Y
107         hide_panel                              -       -       Y
108         move_panel                              -       -       Y
109         new_panel                               -       -       Y
110         panel_above                             -       -       Y
111         panel_below                             -       -       Y
112         panel_hidden                            -       -       Y
113         panel_userptr                           -       -       Y
114         panel_window                            -       -       Y
115         replace_panel                           -       -       Y
116         set_panel_userptr                       -       -       Y
117         show_panel                              -       -       Y
118         top_panel                               -       -       Y
119         update_panels                           -       -       Y
120
121   Credits:
122         Original Author - Warren Tucker <wht@n4hgf.mt-park.ga.us>
123
124 **man-end****************************************************************/
125
126 #include <panel.h>
127 #include <stdlib.h>
128
129 PANEL *_bottom_panel = (PANEL *)0;
130 PANEL *_top_panel = (PANEL *)0;
131 PANEL _stdscr_pseudo_panel = { (WINDOW *)0 };
132
133 #ifdef PANEL_DEBUG
134
135 static void dPanel(char *text, PANEL *pan)
136 {
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));
141 }
142
143 static void dStack(char *fmt, int num, PANEL *pan)
144 {
145     char s80[80];
146
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    : "--"));
150
151     if (pan)
152         PDC_LOG(("pan id=%s", pan->user));
153
154     pan = _bottom_panel;
155
156     while (pan)
157     {
158         dPanel("stk", pan);
159         pan = pan->above;
160     }
161 }
162
163 /* debugging hook for wnoutrefresh */
164
165 static void Wnoutrefresh(PANEL *pan)
166 {
167     dPanel("wnoutrefresh", pan);
168     wnoutrefresh(pan->win);
169 }
170
171 static void Touchpan(PANEL *pan)
172 {
173     dPanel("Touchpan", pan);
174     touchwin(pan->win);
175 }
176
177 static void Touchline(PANEL *pan, int start, int count)
178 {
179     char s80[80];
180
181     sprintf(s80, "Touchline s=%d c=%d", start, count);
182     dPanel(s80, pan);
183     touchline(pan->win, start, count);
184 }
185
186 #else   /* PANEL_DEBUG */
187
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)
193
194 #endif  /* PANEL_DEBUG */
195
196 static bool _panels_overlapped(PANEL *pan1, PANEL *pan2)
197 {
198     if (!pan1 || !pan2)
199         return FALSE;
200
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));
205 }
206
207 static void _free_obscure(PANEL *pan)
208 {
209     PANELOBS *tobs = pan->obscure;  /* "this" one */
210     PANELOBS *nobs;                 /* "next" one */
211
212     while (tobs)
213     {
214         nobs = tobs->above;
215         free((char *)tobs);
216         tobs = nobs;
217     }
218     pan->obscure = (PANELOBS *)0;
219 }
220
221 static void _override(PANEL *pan, int show)
222 {
223     int y;
224     PANEL *pan2;
225     PANELOBS *tobs = pan->obscure;      /* "this" one */
226
227     if (show == 1)
228         Touchpan(pan);
229     else if (!show)
230     {
231         Touchpan(pan);
232         Touchpan(&_stdscr_pseudo_panel);
233     }
234     else if (show == -1)
235         while (tobs && (tobs->pan != pan))
236             tobs = tobs->above;
237
238     while (tobs)
239     {
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);
246
247         tobs = tobs->above;
248     }
249 }
250
251 static void _calculate_obscure(void)
252 {
253     PANEL *pan, *pan2;
254     PANELOBS *tobs;     /* "this" one */
255     PANELOBS *lobs;     /* last one */
256
257     pan = _bottom_panel;
258
259     while (pan)
260     {
261         if (pan->obscure)
262             _free_obscure(pan);
263
264         lobs = (PANELOBS *)0;
265         pan2 = _bottom_panel;
266
267         while (pan2)
268         {
269             if (_panels_overlapped(pan, pan2))
270             {
271                 if ((tobs = malloc(sizeof(PANELOBS))) == NULL)
272                     return;
273
274                 tobs->pan = pan2;
275                 dPanel("obscured", pan2);
276                 tobs->above = (PANELOBS *)0;
277
278                 if (lobs)
279                     lobs->above = tobs;
280                 else
281                     pan->obscure = tobs;
282
283                 lobs  = tobs;
284             }
285
286             pan2 = pan2->above;
287         }
288
289         _override(pan, 1);
290         pan = pan->above;
291     }
292 }
293
294 /* check to see if panel is in the stack */
295
296 static bool _panel_is_linked(const PANEL *pan)
297 {
298     PANEL *pan2 = _bottom_panel;
299
300     while (pan2)
301     {
302         if (pan2 == pan)
303             return TRUE;
304
305         pan2 = pan2->above;
306     }
307
308     return FALSE;
309 }
310
311 /* link panel into stack at top */
312
313 static void _panel_link_top(PANEL *pan)
314 {
315 #ifdef PANEL_DEBUG
316     dStack("<lt%d>", 1, pan);
317     if (_panel_is_linked(pan))
318         return;
319 #endif
320     pan->above = (PANEL *)0;
321     pan->below = (PANEL *)0;
322
323     if (_top_panel)
324     {
325         _top_panel->above = pan;
326         pan->below = _top_panel;
327     }
328
329     _top_panel = pan;
330
331     if (!_bottom_panel)
332         _bottom_panel = pan;
333
334     _calculate_obscure();
335     dStack("<lt%d>", 9, pan);
336 }
337
338 /* link panel into stack at bottom */
339
340 static void _panel_link_bottom(PANEL *pan)
341 {
342 #ifdef PANEL_DEBUG
343     dStack("<lb%d>", 1, pan);
344     if (_panel_is_linked(pan))
345         return;
346 #endif
347     pan->above = (PANEL *)0;
348     pan->below = (PANEL *)0;
349
350     if (_bottom_panel)
351     {
352         _bottom_panel->below = pan;
353         pan->above = _bottom_panel;
354     }
355
356     _bottom_panel = pan;
357
358     if (!_top_panel)
359         _top_panel = pan;
360
361     _calculate_obscure();
362     dStack("<lb%d>", 9, pan);
363 }
364
365 static void _panel_unlink(PANEL *pan)
366 {
367     PANEL *prev;
368     PANEL *next;
369
370 #ifdef PANEL_DEBUG
371     dStack("<u%d>", 1, pan);
372     if (!_panel_is_linked(pan))
373         return;
374 #endif
375     _override(pan, 0);
376     _free_obscure(pan);
377
378     prev = pan->below;
379     next = pan->above;
380
381     /* if non-zero, we will not update the list head */
382
383     if (prev)
384     {
385         prev->above = next;
386         if(next)
387             next->below = prev;
388     }
389     else if (next)
390         next->below = prev;
391
392     if (pan == _bottom_panel)
393         _bottom_panel = next;
394
395     if (pan == _top_panel)
396         _top_panel = prev;
397
398     _calculate_obscure();
399
400     pan->above = (PANEL *)0;
401     pan->below = (PANEL *)0;
402     dStack("<u%d>", 9, pan);
403
404 }
405
406 /************************************************************************
407  *   The following are the public functions for the panels library.     *
408  ************************************************************************/
409
410 int bottom_panel(PANEL *pan)
411 {
412     if (!pan)
413         return ERR;
414
415     if (pan == _bottom_panel)
416         return OK;
417
418     if (_panel_is_linked(pan))
419         hide_panel(pan);
420
421     _panel_link_bottom(pan);
422
423     return OK;
424 }
425
426 int del_panel(PANEL *pan)
427 {
428     if (pan)
429     {
430         if (_panel_is_linked(pan))
431             hide_panel(pan);
432
433         free((char *)pan);
434         return OK;
435     }
436
437     return ERR;
438 }
439
440 int hide_panel(PANEL *pan)
441 {
442     if (!pan)
443         return ERR;
444
445     if (!_panel_is_linked(pan))
446     {
447         pan->above = (PANEL *)0;
448         pan->below = (PANEL *)0;
449         return ERR;
450     }
451
452     _panel_unlink(pan);
453
454     return OK;
455 }
456
457 int move_panel(PANEL *pan, int starty, int startx)
458 {
459     WINDOW *win;
460     int maxy, maxx;
461
462     if (!pan)
463         return ERR;
464
465     if (_panel_is_linked(pan))
466         _override(pan, 0);
467
468     win = pan->win;
469
470     if (mvwin(win, starty, startx) == ERR)
471         return ERR;
472
473     getbegyx(win, pan->wstarty, pan->wstartx);
474     getmaxyx(win, maxy, maxx);
475     pan->wendy = pan->wstarty + maxy;
476     pan->wendx = pan->wstartx + maxx;
477
478     if (_panel_is_linked(pan))
479         _calculate_obscure();
480
481     return OK;
482 }
483
484 PANEL *new_panel(WINDOW *win)
485 {
486     PANEL *pan = malloc(sizeof(PANEL));
487
488     if (!_stdscr_pseudo_panel.win)
489     {
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;
497     }
498
499     if (pan)
500     {
501         int maxy, maxx;
502
503         pan->win = win;
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;
510 #ifdef PANEL_DEBUG
511         pan->user = "new";
512 #else
513         pan->user = (char *)0;
514 #endif
515         pan->obscure = (PANELOBS *)0;
516         show_panel(pan);
517     }
518
519     return pan;
520 }
521
522 PANEL *panel_above(const PANEL *pan)
523 {
524     return pan ? pan->above : _bottom_panel;
525 }
526
527 PANEL *panel_below(const PANEL *pan)
528 {
529     return pan ? pan->below : _top_panel;
530 }
531
532 int panel_hidden(const PANEL *pan)
533 {
534     if (!pan)
535         return ERR;
536
537     return _panel_is_linked(pan) ? ERR : OK;
538 }
539
540 const void *panel_userptr(const PANEL *pan)
541 {
542     return pan ? pan->user : NULL;
543 }
544
545 WINDOW *panel_window(const PANEL *pan)
546 {
547     PDC_LOG(("panel_window() - called\n"));
548
549     return pan->win;
550 }
551
552 int replace_panel(PANEL *pan, WINDOW *win)
553 {
554     int maxy, maxx;
555
556     if (!pan)
557         return ERR;
558
559     if (_panel_is_linked(pan))
560         _override(pan, 0);
561
562     pan->win = win;
563     getbegyx(win, pan->wstarty, pan->wstartx);
564     getmaxyx(win, maxy, maxx);
565     pan->wendy = pan->wstarty + maxy;
566     pan->wendx = pan->wstartx + maxx;
567
568     if (_panel_is_linked(pan))
569         _calculate_obscure();
570
571     return OK;
572 }
573
574 int set_panel_userptr(PANEL *pan, const void *uptr)
575 {
576     if (!pan)
577         return ERR;
578
579     pan->user = uptr;
580     return OK;
581 }
582
583 int show_panel(PANEL *pan)
584 {
585     if (!pan)
586         return ERR;
587
588     if (pan == _top_panel)
589         return OK;
590
591     if (_panel_is_linked(pan))
592         hide_panel(pan);
593
594     _panel_link_top(pan);
595
596     return OK;
597 }
598
599 int top_panel(PANEL *pan)
600 {
601     return show_panel(pan);
602 }
603
604 void update_panels(void)
605 {
606     PANEL *pan;
607
608     PDC_LOG(("update_panels() - called\n"));
609
610     pan = _bottom_panel;
611
612     while (pan)
613     {
614         _override(pan, -1);
615         pan = pan->above;
616     }
617
618     if (is_wintouched(stdscr))
619         Wnoutrefresh(&_stdscr_pseudo_panel);
620
621     pan = _bottom_panel;
622
623     while (pan)
624     {
625         if (is_wintouched(pan->win) || !pan->above)
626             Wnoutrefresh(pan);
627
628         pan = pan->above;
629     }
630 }