Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Kitware
GitHub Repository: Kitware/CMake
Path: blob/master/Utilities/cmpdcurses/pdcurses/panel.c
3153 views
1
/* PDCurses */
2
3
#include <curspriv.h>
4
5
/*man-start**************************************************************
6
7
panel
8
-----
9
10
### Synopsis
11
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
30
For historic reasons, and for compatibility with other versions of
31
curses, the panel functions are prototyped in a separate header,
32
panel.h. In many implementations, they're also in a separate library,
33
but PDCurses incorporates them.
34
35
The panel functions provide a way to have depth relationships between
36
curses windows. Panels can overlap without making visible the
37
overlapped portions of underlying windows. The initial curses window,
38
stdscr, lies beneath all panels. The set of currently visible panels
39
is the 'deck' of panels.
40
41
You can create panels, fetch and set their associated windows,
42
shuffle panels in the deck, and manipulate them in other ways.
43
44
bottom_panel() places pan at the bottom of the deck. The size,
45
location and contents of the panel are unchanged.
46
47
del_panel() deletes pan, but not its associated winwow.
48
49
hide_panel() removes a panel from the deck and thus hides it from
50
view.
51
52
move_panel() moves the curses window associated with pan, so that its
53
upper lefthand corner is at the supplied coordinates. (Don't use
54
mvwin() on the window.)
55
56
new_panel() creates a new panel associated with win and returns the
57
panel pointer. The new panel is placed at the top of the deck.
58
59
panel_above() returns a pointer to the panel in the deck above pan,
60
or NULL if pan is the top panel. If the value of pan passed is NULL,
61
this function returns a pointer to the bottom panel in the deck.
62
63
panel_below() returns a pointer to the panel in the deck below pan,
64
or NULL if pan is the bottom panel. If the value of pan passed is
65
NULL, this function returns a pointer to the top panel in the deck.
66
67
panel_hidden() returns OK if pan is hidden and ERR if it is not.
68
69
panel_userptr() - Each panel has a user pointer available for
70
maintaining relevant information. This function returns a pointer to
71
that information previously set up by set_panel_userptr().
72
73
panel_window() returns a pointer to the curses window associated with
74
the panel.
75
76
replace_panel() replaces the current window of pan with win.
77
78
set_panel_userptr() - Each panel has a user pointer available for
79
maintaining relevant information. This function sets the value of
80
that information.
81
82
show_panel() makes a previously hidden panel visible and places it
83
back in the deck on top.
84
85
top_panel() places pan on the top of the deck. The size, location and
86
contents of the panel are unchanged.
87
88
update_panels() refreshes the virtual screen to reflect the depth
89
relationships between the panels in the deck. The user must use
90
doupdate() to refresh the physical screen.
91
92
### Return Value
93
94
Each routine that returns a pointer to an object returns NULL if an
95
error occurs. Each panel routine that returns an integer, returns OK
96
if it executes successfully and ERR if it does not.
97
98
### Portability
99
X/Open ncurses NetBSD
100
bottom_panel - Y Y
101
del_panel - Y Y
102
hide_panel - Y Y
103
move_panel - Y Y
104
new_panel - Y Y
105
panel_above - Y Y
106
panel_below - Y Y
107
panel_hidden - Y Y
108
panel_userptr - Y Y
109
panel_window - Y Y
110
replace_panel - Y Y
111
set_panel_userptr - Y Y
112
show_panel - Y Y
113
top_panel - Y Y
114
update_panels - Y Y
115
116
Credits:
117
Original Author - Warren Tucker <[email protected]>
118
119
**man-end****************************************************************/
120
121
#include <panel.h>
122
#include <stdlib.h>
123
124
PANEL *_bottom_panel = (PANEL *)0;
125
PANEL *_top_panel = (PANEL *)0;
126
PANEL _stdscr_pseudo_panel = { (WINDOW *)0 };
127
128
#ifdef PANEL_DEBUG
129
130
static void dPanel(char *text, PANEL *pan)
131
{
132
PDC_LOG(("%s id=%s b=%s a=%s y=%d x=%d", text, pan->user,
133
pan->below ? pan->below->user : "--",
134
pan->above ? pan->above->user : "--",
135
pan->wstarty, pan->wstartx));
136
}
137
138
static void dStack(char *fmt, int num, PANEL *pan)
139
{
140
char s80[80];
141
142
sprintf(s80, fmt, num, pan);
143
PDC_LOG(("%s b=%s t=%s", s80, _bottom_panel ? _bottom_panel->user : "--",
144
_top_panel ? _top_panel->user : "--"));
145
146
if (pan)
147
PDC_LOG(("pan id=%s", pan->user));
148
149
pan = _bottom_panel;
150
151
while (pan)
152
{
153
dPanel("stk", pan);
154
pan = pan->above;
155
}
156
}
157
158
/* debugging hook for wnoutrefresh */
159
160
static void Wnoutrefresh(PANEL *pan)
161
{
162
dPanel("wnoutrefresh", pan);
163
wnoutrefresh(pan->win);
164
}
165
166
static void Touchpan(PANEL *pan)
167
{
168
dPanel("Touchpan", pan);
169
touchwin(pan->win);
170
}
171
172
static void Touchline(PANEL *pan, int start, int count)
173
{
174
char s80[80];
175
176
sprintf(s80, "Touchline s=%d c=%d", start, count);
177
dPanel(s80, pan);
178
touchline(pan->win, start, count);
179
}
180
181
#else /* PANEL_DEBUG */
182
183
#define dPanel(text, pan)
184
#define dStack(fmt, num, pan)
185
#define Wnoutrefresh(pan) wnoutrefresh((pan)->win)
186
#define Touchpan(pan) touchwin((pan)->win)
187
#define Touchline(pan, start, count) touchline((pan)->win, start, count)
188
189
#endif /* PANEL_DEBUG */
190
191
static bool _panels_overlapped(PANEL *pan1, PANEL *pan2)
192
{
193
if (!pan1 || !pan2)
194
return FALSE;
195
196
return ((pan1->wstarty >= pan2->wstarty && pan1->wstarty < pan2->wendy)
197
|| (pan2->wstarty >= pan1->wstarty && pan2->wstarty < pan1->wendy))
198
&& ((pan1->wstartx >= pan2->wstartx && pan1->wstartx < pan2->wendx)
199
|| (pan2->wstartx >= pan1->wstartx && pan2->wstartx < pan1->wendx));
200
}
201
202
static void _free_obscure(PANEL *pan)
203
{
204
PANELOBS *tobs = pan->obscure; /* "this" one */
205
PANELOBS *nobs; /* "next" one */
206
207
while (tobs)
208
{
209
nobs = tobs->above;
210
free((char *)tobs);
211
tobs = nobs;
212
}
213
pan->obscure = (PANELOBS *)0;
214
}
215
216
static void _override(PANEL *pan, int show)
217
{
218
int y;
219
PANEL *pan2;
220
PANELOBS *tobs = pan->obscure; /* "this" one */
221
222
if (show == 1)
223
Touchpan(pan);
224
else if (!show)
225
{
226
Touchpan(pan);
227
Touchpan(&_stdscr_pseudo_panel);
228
}
229
else if (show == -1)
230
while (tobs && (tobs->pan != pan))
231
tobs = tobs->above;
232
233
while (tobs)
234
{
235
if ((pan2 = tobs->pan) != pan)
236
for (y = pan->wstarty; y < pan->wendy; y++)
237
if ((y >= pan2->wstarty) && (y < pan2->wendy) &&
238
((is_linetouched(pan->win, y - pan->wstarty)) ||
239
(is_linetouched(stdscr, y))))
240
Touchline(pan2, y - pan2->wstarty, 1);
241
242
tobs = tobs->above;
243
}
244
}
245
246
static void _calculate_obscure(void)
247
{
248
PANEL *pan, *pan2;
249
PANELOBS *tobs; /* "this" one */
250
PANELOBS *lobs; /* last one */
251
252
pan = _bottom_panel;
253
254
while (pan)
255
{
256
if (pan->obscure)
257
_free_obscure(pan);
258
259
lobs = (PANELOBS *)0;
260
pan2 = _bottom_panel;
261
262
while (pan2)
263
{
264
if (_panels_overlapped(pan, pan2))
265
{
266
if ((tobs = malloc(sizeof(PANELOBS))) == NULL)
267
return;
268
269
tobs->pan = pan2;
270
dPanel("obscured", pan2);
271
tobs->above = (PANELOBS *)0;
272
273
if (lobs)
274
lobs->above = tobs;
275
else
276
pan->obscure = tobs;
277
278
lobs = tobs;
279
}
280
281
pan2 = pan2->above;
282
}
283
284
_override(pan, 1);
285
pan = pan->above;
286
}
287
}
288
289
/* check to see if panel is in the stack */
290
291
static bool _panel_is_linked(const PANEL *pan)
292
{
293
PANEL *pan2 = _bottom_panel;
294
295
while (pan2)
296
{
297
if (pan2 == pan)
298
return TRUE;
299
300
pan2 = pan2->above;
301
}
302
303
return FALSE;
304
}
305
306
/* link panel into stack at top */
307
308
static void _panel_link_top(PANEL *pan)
309
{
310
#ifdef PANEL_DEBUG
311
dStack("<lt%d>", 1, pan);
312
if (_panel_is_linked(pan))
313
return;
314
#endif
315
pan->above = (PANEL *)0;
316
pan->below = (PANEL *)0;
317
318
if (_top_panel)
319
{
320
_top_panel->above = pan;
321
pan->below = _top_panel;
322
}
323
324
_top_panel = pan;
325
326
if (!_bottom_panel)
327
_bottom_panel = pan;
328
329
_calculate_obscure();
330
dStack("<lt%d>", 9, pan);
331
}
332
333
/* link panel into stack at bottom */
334
335
static void _panel_link_bottom(PANEL *pan)
336
{
337
#ifdef PANEL_DEBUG
338
dStack("<lb%d>", 1, pan);
339
if (_panel_is_linked(pan))
340
return;
341
#endif
342
pan->above = (PANEL *)0;
343
pan->below = (PANEL *)0;
344
345
if (_bottom_panel)
346
{
347
_bottom_panel->below = pan;
348
pan->above = _bottom_panel;
349
}
350
351
_bottom_panel = pan;
352
353
if (!_top_panel)
354
_top_panel = pan;
355
356
_calculate_obscure();
357
dStack("<lb%d>", 9, pan);
358
}
359
360
static void _panel_unlink(PANEL *pan)
361
{
362
PANEL *prev;
363
PANEL *next;
364
365
#ifdef PANEL_DEBUG
366
dStack("<u%d>", 1, pan);
367
if (!_panel_is_linked(pan))
368
return;
369
#endif
370
_override(pan, 0);
371
_free_obscure(pan);
372
373
prev = pan->below;
374
next = pan->above;
375
376
/* if non-zero, we will not update the list head */
377
378
if (prev)
379
{
380
prev->above = next;
381
if(next)
382
next->below = prev;
383
}
384
else if (next)
385
next->below = prev;
386
387
if (pan == _bottom_panel)
388
_bottom_panel = next;
389
390
if (pan == _top_panel)
391
_top_panel = prev;
392
393
_calculate_obscure();
394
395
pan->above = (PANEL *)0;
396
pan->below = (PANEL *)0;
397
dStack("<u%d>", 9, pan);
398
399
}
400
401
/************************************************************************
402
* The following are the public functions for the panels library. *
403
************************************************************************/
404
405
int bottom_panel(PANEL *pan)
406
{
407
if (!pan)
408
return ERR;
409
410
if (pan == _bottom_panel)
411
return OK;
412
413
if (_panel_is_linked(pan))
414
hide_panel(pan);
415
416
_panel_link_bottom(pan);
417
418
return OK;
419
}
420
421
int del_panel(PANEL *pan)
422
{
423
if (pan)
424
{
425
if (_panel_is_linked(pan))
426
hide_panel(pan);
427
428
free((char *)pan);
429
return OK;
430
}
431
432
return ERR;
433
}
434
435
int hide_panel(PANEL *pan)
436
{
437
if (!pan)
438
return ERR;
439
440
if (!_panel_is_linked(pan))
441
{
442
pan->above = (PANEL *)0;
443
pan->below = (PANEL *)0;
444
return ERR;
445
}
446
447
_panel_unlink(pan);
448
449
return OK;
450
}
451
452
int move_panel(PANEL *pan, int starty, int startx)
453
{
454
WINDOW *win;
455
int maxy, maxx;
456
457
if (!pan)
458
return ERR;
459
460
if (_panel_is_linked(pan))
461
_override(pan, 0);
462
463
win = pan->win;
464
465
if (mvwin(win, starty, startx) == ERR)
466
return ERR;
467
468
getbegyx(win, pan->wstarty, pan->wstartx);
469
getmaxyx(win, maxy, maxx);
470
pan->wendy = pan->wstarty + maxy;
471
pan->wendx = pan->wstartx + maxx;
472
473
if (_panel_is_linked(pan))
474
_calculate_obscure();
475
476
return OK;
477
}
478
479
PANEL *new_panel(WINDOW *win)
480
{
481
PANEL *pan;
482
483
if (!win)
484
return (PANEL *)NULL;
485
486
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
if (!pan)
550
return (WINDOW *)NULL;
551
552
return pan->win;
553
}
554
555
int replace_panel(PANEL *pan, WINDOW *win)
556
{
557
int maxy, maxx;
558
559
if (!pan)
560
return ERR;
561
562
if (_panel_is_linked(pan))
563
_override(pan, 0);
564
565
pan->win = win;
566
getbegyx(win, pan->wstarty, pan->wstartx);
567
getmaxyx(win, maxy, maxx);
568
pan->wendy = pan->wstarty + maxy;
569
pan->wendx = pan->wstartx + maxx;
570
571
if (_panel_is_linked(pan))
572
_calculate_obscure();
573
574
return OK;
575
}
576
577
int set_panel_userptr(PANEL *pan, const void *uptr)
578
{
579
if (!pan)
580
return ERR;
581
582
pan->user = uptr;
583
return OK;
584
}
585
586
int show_panel(PANEL *pan)
587
{
588
if (!pan)
589
return ERR;
590
591
if (pan == _top_panel)
592
return OK;
593
594
if (_panel_is_linked(pan))
595
hide_panel(pan);
596
597
_panel_link_top(pan);
598
599
return OK;
600
}
601
602
int top_panel(PANEL *pan)
603
{
604
return show_panel(pan);
605
}
606
607
void update_panels(void)
608
{
609
PANEL *pan;
610
611
PDC_LOG(("update_panels() - called\n"));
612
613
pan = _bottom_panel;
614
615
while (pan)
616
{
617
_override(pan, -1);
618
pan = pan->above;
619
}
620
621
if (is_wintouched(stdscr))
622
Wnoutrefresh(&_stdscr_pseudo_panel);
623
624
pan = _bottom_panel;
625
626
while (pan)
627
{
628
if (is_wintouched(pan->win) || !pan->above)
629
Wnoutrefresh(pan);
630
631
pan = pan->above;
632
}
633
}
634
635