128 lines
3.4 KiB
C
128 lines
3.4 KiB
C
#include <signal.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "_ncurses.h"
|
|
#include "ncrswrap.h"
|
|
#include "ncurses.h"
|
|
#include "node.h"
|
|
#include "tree.h"
|
|
|
|
volatile sig_atomic_t got_winch = 0;
|
|
|
|
void handle_SIGWINCH(int sig) {
|
|
// endwin();
|
|
// Needs to be called after an endwin() so ncurses will initialize
|
|
// itself with the new terminal dimensions.
|
|
got_winch = 1;
|
|
}
|
|
|
|
/*
|
|
* If ncurses is configured to supply its own SIGWINCH handler,
|
|
* - on receipt of a SIGWINCH, the handler sets a flag
|
|
* - which is tested in wgetch(3X), doupdate(3X) and restartterm(3X),
|
|
* - in turn, calling the resizeterm function,
|
|
* - which ungetch's a KEY_RESIZE which will be read on the next call to
|
|
* wgetch. REF: `man resizeterm(3x)`
|
|
*/
|
|
static void bind_SIGWINCH(void) {
|
|
struct sigaction sa;
|
|
memset(&sa, 0, sizeof(sa));
|
|
sa.sa_handler = handle_SIGWINCH;
|
|
sigemptyset(&sa.sa_mask);
|
|
sa.sa_flags = SA_RESTART; /* Restart functions if
|
|
interrupted by handler */
|
|
if (sigaction(SIGWINCH, &sa, NULL) == -1) {
|
|
perror("bind_SIGWINCH");
|
|
exit(2);
|
|
}
|
|
}
|
|
|
|
int ct_init(struct ct_tree **const tree) {
|
|
// bind_SIGWINCH();
|
|
/* Initialise NCurses Library & Root Node */
|
|
init_ncurses();
|
|
init_tree(tree);
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|
|
void ct_redraw(void) {
|
|
/* TODO: hide doupdate() behind some other method */
|
|
/* flush ncurses virtual screen -> physical screen */
|
|
doupdate();
|
|
}
|
|
|
|
/* Recursively search the tree for update requests.
|
|
* Returns:
|
|
* 0 - success (no action required)
|
|
* 1 - success (request: redraw the screen)
|
|
*/
|
|
static int __update_rec(struct ct_node *const node) {
|
|
int result = 0;
|
|
struct ct_dims *dims;
|
|
|
|
if (node->flags & NFLAG_RESIZE) {
|
|
/* TODO: the child has requested a resizing, but resize_node()
|
|
* TODO: wastes CPU time resizing itself!
|
|
*/
|
|
dims = IS_ROOT_NODE(node) ? termdims() : dup_dims(node->surface->dims);
|
|
resize_node(node, dims);
|
|
node->flags &= ~NFLAG_RESIZE;
|
|
result = 1;
|
|
}
|
|
if (node->surface->updatereq) {
|
|
// TODO: is this necessary or does mvresize_win do this for us?
|
|
wnoutrefresh(node->surface->win);
|
|
node->surface->updatereq = 0;
|
|
}
|
|
|
|
for (int i = 0; i < node->cindex; i++) {
|
|
result |= __update_rec(node->child[i]);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void ct_update(struct ct_tree *const tree) {
|
|
// WARNING: update_rec does not flush the screen, wgetch will do that for us
|
|
if (__update_rec(tree->root)) {
|
|
doupdate();
|
|
// redrawwin(curscr);
|
|
// wrefresh(curscr);
|
|
}
|
|
}
|
|
|
|
void ct_process(struct ct_tree *const tree) {
|
|
const int key = wgetch(curscr);
|
|
// int key = -1;
|
|
|
|
/* ncurses binds a SIGWINCH handler if SIGWINCH has SIG_DFL disposition
|
|
* when initscr(3x) is called. This handler emits KEY_RESIZE (decimal 410) to
|
|
* stdin. REF: manpages -> resizeterm(3x) initscr(3x) wgetch(3x)
|
|
*/
|
|
switch (key) {
|
|
case -1:
|
|
// wclear(tree->root->surface->win);
|
|
// mvwprintw(tree->root->surface->win, 0, 0, " \r-1\n");
|
|
// wrefresh(tree->root->surface->win);
|
|
break;
|
|
case KEY_RESIZE:
|
|
// got_winch = 1;
|
|
tree->root->flags |= NFLAG_RESIZE;
|
|
break;
|
|
default:
|
|
// wclear(tree->root->surface->win);
|
|
// mvwprintw(tree->root->surface->win, 0, 0, " \r%d\n", key);
|
|
// wrefresh(tree->root->surface->win);
|
|
break;
|
|
}
|
|
|
|
// if (got_winch == 1) {
|
|
// tree->root->flags |= NFLAG_RESIZE;
|
|
// got_winch = 0;
|
|
// }
|
|
|
|
// if (__update_rec(tree->root)) {
|
|
// ct_redraw();
|
|
// }
|
|
}
|