aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/macros.h2
-rw-r--r--src/ui/base.c91
-rw-r--r--src/ui/debug.c14
-rw-r--r--src/ui/dock.c96
-rw-r--r--src/ui/root.c50
-rw-r--r--src/ui/ui.internal.h20
6 files changed, 157 insertions, 116 deletions
diff --git a/src/macros.h b/src/macros.h
index 8523a42..ef862d8 100644
--- a/src/macros.h
+++ b/src/macros.h
@@ -1,6 +1,8 @@
#ifndef UMPS_MACROS_H_INCLUDED
#define UMPS_MACROS_H_INCLUDED
+#define umps_unused(_v) ((void)(_v))
+
/* define handy macros (unreachable and trap) */
#ifdef __GNUC__ /* gcc and clang */
diff --git a/src/ui/base.c b/src/ui/base.c
index 50e6944..dd454ec 100644
--- a/src/ui/base.c
+++ b/src/ui/base.c
@@ -4,23 +4,61 @@
#include "ui.internal.h"
#include "ui/uimenu.internal.h"
+#include "../macros.h"
struct ui_window_root *ui_root = NULL;
void ui__default_draw_proc(struct ui_window_base *base)
{
- wnoutrefresh(base->cwindow); /* root window calls doupdate */
+ umps_unused(base);
+}
+
+void ui__leaf_draw_proc(struct ui_window_base *base)
+{
+ WINDOW *mywin = ((struct ui_window_leaf *)base)->cwindow;
+ int maxy, maxx;
+ getmaxyx(mywin, maxy, maxx);
+
+ box(mywin, 0, 0);
+ mvwaddstr(mywin, 0, 2, "Traces");
+ for (int i = 1; i < maxy-1; ++i) {
+ mvwhline(mywin, i, 1, '.', maxx - 2);
+ }
+
+ wnoutrefresh(mywin);
+}
+
+void ui__leaf_layout_proc(struct ui_window_base *base)
+{
+ struct ui_window_leaf *leaf = (struct ui_window_leaf *)base;
+ if (leaf->cwindow) delwin(leaf->cwindow);
+ leaf->cwindow = newwin(leaf->super.dims.maxy, leaf->super.dims.maxx, leaf->super.dims.begy, leaf->super.dims.begx);
}
void ui__init_window_base(struct ui_window_base *base)
{
base->type = UI__WINDOW_TYPE_BASE;
base->parent = NULL;
- base->cwindow = NULL;
+
+ base->dims.begy = 0;
+ base->dims.begx = 0;
+ base->dims.maxy = 0;
+ base->dims.maxx = 0;
+
base->draw_proc = &ui__default_draw_proc;
base->layout_proc = NULL;
}
+void ui__init_window_leaf(struct ui_window_leaf *leaf)
+{
+ ui__init_window_base(&leaf->super);
+ leaf->super.type = UI__WINDOW_TYPE_LEAF;
+ leaf->super.draw_proc = &ui__leaf_draw_proc;
+ leaf->super.layout_proc = &ui__leaf_layout_proc;
+
+ leaf->cwindow = NULL;
+}
+
void ui__init_window_dock(struct ui_window_dock *dock)
{
ui__init_window_base(&dock->super);
@@ -40,11 +78,14 @@ void ui__init_window_dock(struct ui_window_dock *dock)
void ui__init_window_root(struct ui_window_root *root, WINDOW *cwindow)
{
ui__init_window_base(&root->super);
- root->super.cwindow = cwindow;
root->super.type = UI__WINDOW_TYPE_ROOT;
root->super.draw_proc = &ui__root_draw_proc;
root->super.layout_proc = &ui__root_layout_proc;
+ root->cwindow = cwindow;
+ getmaxyx(cwindow, root->super.dims.maxy, root->super.dims.maxx);
+ getbegyx(cwindow, root->super.dims.begy, root->super.dims.begx);
+
root->undersize_scr = false;
root->content = NULL;
root->floating = NULL;
@@ -55,6 +96,7 @@ void ui__init_window_root(struct ui_window_root *root, WINDOW *cwindow)
/* type-specific destructors */
void ui__destroy_window_base(struct ui_window_base *base);
+void ui__destroy_window_leaf(struct ui_window_leaf *leaf);
void ui__destroy_window_dock(struct ui_window_dock *dock);
void ui__window_destroy_root(struct ui_window_root *root)
@@ -67,6 +109,8 @@ void ui__window_destroy_root(struct ui_window_root *root)
uimenu_menu_free(root->menu_root);
+ if (root->cwindow) delwin(root->cwindow);
+
ui__destroy_window_base(&root->super);
}
@@ -81,9 +125,14 @@ void ui__destroy_window_dock(struct ui_window_dock *dock)
ui__destroy_window_base(&dock->super);
}
+void ui__destroy_window_leaf(struct ui_window_leaf *leaf)
+{
+ if (leaf->cwindow) delwin(leaf->cwindow);
+ ui__destroy_window_base(&leaf->super);
+}
+
void ui__destroy_window_base(struct ui_window_base *base)
{
- delwin(base->cwindow);
free(base);
}
@@ -99,14 +148,17 @@ void ui__destroy_window(struct ui_window_base *base)
case UI__WINDOW_TYPE_DOCK:
ui__destroy_window_dock(ui__cast(dock, base));
break;
+ case UI__WINDOW_TYPE_LEAF:
+ ui__destroy_window_leaf(ui__cast(leaf, base));
+ break;
case UI__WINDOW_TYPE_BASE:
ui__destroy_window_base(base);
}
}
/* the focused window MUST be a leaf window, or the screen will get clobbered.
- * This is because the focused window will have methods like getch() called on it,
- * which brings it to the "foreground", squashing whatever is behind it. */
+ * This is because the focused window will have wgetch() called for it, which
+ * calls wrefresh() sometimes. This will clobber windows inside of it. */
struct ui_window_base *ui__find_focused(void)
{
struct ui_window_base *window = ui__cast(base, ui_root);
@@ -171,20 +223,6 @@ void ui__call_layout_proc(struct ui_window_base *base)
}
}
-void ui__traces_draw_proc(struct ui_window_base *base)
-{
- box(base->cwindow, 0, 0);
- int maxy, maxx;
-
- mvwaddstr(base->cwindow, 0, 2, "Traces");
- getmaxyx(base->cwindow, maxy, maxx);
- for (int i = 1; i < maxy-1; ++i)
- {
- mvwhline(base->cwindow, i, 1, '.', maxx-2);
- }
- wnoutrefresh(base->cwindow);
-}
-
void ui_init(void)
{
ui_root = malloc(sizeof(struct ui_window_root)); /* TODO: check */
@@ -216,12 +254,12 @@ void ui_init(void)
for (unsigned i = 0; i < UI__WINDOW_DOCK_MAX; ++i)
{
if (i == UI__WINDOW_DOCK_LEFT) continue;
- struct ui_window_base *win_traces = malloc(sizeof(struct ui_window_base));
- ui__init_window_base(win_traces);
- ui__dock_add_child(maindock, win_traces, i, 1./5);
- win_traces->draw_proc = &ui__traces_draw_proc;
+ struct ui_window_leaf *win_traces = malloc(sizeof(struct ui_window_leaf));
+ ui__init_window_leaf(win_traces);
+ ui__dock_add_child(maindock, ui__cast(base, win_traces), i, 1./5);
}
+ /* ui__call_layout_proc(ui__cast(base, ui_root)); */
ui__call_draw_proc(ui__cast(base, ui_root));
}
@@ -233,7 +271,8 @@ void ui_handle(void)
#ifdef NCURSES_WIDE
wint_t inp;
- wget_wch(window->cwindow, &inp);
+ /* FIXME: find a better way of circumnavigating this annoying implied-wrefresh business */
+ wget_wch(ui__cast(leaf, window)->cwindow, &inp);
#else
int inp = wgetch(window->cwindow);
#endif
@@ -244,6 +283,8 @@ void ui_handle(void)
}
else if (inp == KEY_RESIZE)
{
+ getmaxyx(ui_root->cwindow, ui_root->super.dims.maxy, ui_root->super.dims.maxx);
+ getbegyx(ui_root->cwindow, ui_root->super.dims.begy, ui_root->super.dims.begx);
ui__call_layout_proc(ui__cast(base, ui_root));
ui__call_draw_proc(ui__cast(base, ui_root));
} else if (inp == NS('h')) {
diff --git a/src/ui/debug.c b/src/ui/debug.c
index f30c12c..6d3ea5d 100644
--- a/src/ui/debug.c
+++ b/src/ui/debug.c
@@ -1,7 +1,6 @@
#ifndef NDEBUG
-#include <assert.h>
-
+#include "../macros.h"
#include "ui.internal.h"
struct ui_window_base *ui__check_cast_to_base(void *obj)
@@ -9,17 +8,24 @@ struct ui_window_base *ui__check_cast_to_base(void *obj)
return obj; /* this cast always succeeds */
}
+struct ui_window_leaf *ui__check_cast_to_leaf(void *obj)
+{
+ struct ui_window_base *base = obj;
+ umps_assert(base->type == UI__WINDOW_TYPE_LEAF);
+ return obj;
+}
+
struct ui_window_dock *ui__check_cast_to_dock(void *obj)
{
struct ui_window_base *base = obj;
- assert(base->type == UI__WINDOW_TYPE_DOCK);
+ umps_assert(base->type == UI__WINDOW_TYPE_DOCK);
return obj;
}
struct ui_window_root *ui__check_cast_to_root(void *obj)
{
struct ui_window_base *base = obj;
- assert(base->type == UI__WINDOW_TYPE_ROOT);
+ umps_assert(base->type == UI__WINDOW_TYPE_ROOT);
return obj;
}
diff --git a/src/ui/dock.c b/src/ui/dock.c
index fd895c2..82f6728 100644
--- a/src/ui/dock.c
+++ b/src/ui/dock.c
@@ -21,21 +21,21 @@ unsigned ui__dock_position_opposite(unsigned position)
}
}
-void ui__dock_adjust(struct ui_window_dock *dock, unsigned flags, int *maxy, int *maxx, int *begy, int *begx)
+void ui__dock_adjust(struct ui_window_dock *dock, unsigned flags, struct ui_dims *dims)
{
if (flags & 1)
{
if (dock->children[UI__WINDOW_DOCK_TOP])
{
- unsigned top_maxy = getmaxy(dock->children[UI__WINDOW_DOCK_TOP]->cwindow);
- *maxy -= top_maxy;
- *begy += top_maxy;
+ unsigned top_maxy = dock->children[UI__WINDOW_DOCK_TOP]->dims.maxy;
+ dims->maxy -= top_maxy;
+ dims->begy += top_maxy;
}
if (dock->children[UI__WINDOW_DOCK_BOTTOM])
{
- unsigned bottom_maxy = getmaxy(dock->children[UI__WINDOW_DOCK_BOTTOM]->cwindow);
- *maxy -= bottom_maxy;
+ unsigned bottom_maxy = dock->children[UI__WINDOW_DOCK_BOTTOM]->dims.maxy;
+ dims->maxy -= bottom_maxy;
}
}
@@ -43,15 +43,15 @@ void ui__dock_adjust(struct ui_window_dock *dock, unsigned flags, int *maxy, int
{
if (dock->children[UI__WINDOW_DOCK_LEFT])
{
- unsigned left_maxx = getmaxx(dock->children[UI__WINDOW_DOCK_LEFT]->cwindow);
- *maxx -= left_maxx;
- *begx += left_maxx;
+ unsigned left_maxx = dock->children[UI__WINDOW_DOCK_LEFT]->dims.maxx;
+ dims->maxx -= left_maxx;
+ dims->begx += left_maxx;
}
if (dock->children[UI__WINDOW_DOCK_RIGHT])
{
- unsigned right_maxx = getmaxx(dock->children[UI__WINDOW_DOCK_RIGHT]->cwindow);
- *maxx -= right_maxx;
+ unsigned right_maxx = dock->children[UI__WINDOW_DOCK_RIGHT]->dims.maxx;
+ dims->maxx -= right_maxx;
}
}
}
@@ -62,64 +62,54 @@ void ui__dock_adjust(struct ui_window_dock *dock, unsigned flags, int *maxy, int
* - Center
*
* Note that other methods (layout proc namely) require this same order to be present in the values of the dock constants. */
-WINDOW *ui__dock_place_window(struct ui_window_dock *dock, unsigned position, float size)
+void ui__dock_place_window(struct ui_window_dock *dock, unsigned position, float size, struct ui_dims *dims)
{
- int maxy, maxx;
- int begy, begx;
-
- int out_lines, out_cols;
- int out_y, out_x;
-
- getmaxyx(dock->super.cwindow, maxy, maxx);
- getbegyx(dock->super.cwindow, begy, begx);
+ struct ui_dims mydims = dock->super.dims;
switch (position)
{
case UI__WINDOW_DOCK_TOP:
- out_lines = maxy * size;
- out_y = begy;
- out_cols = maxx;
- out_x = begx;
+ dims->maxy = mydims.maxy * size;
+ dims->begy = mydims.begy;
+ dims->maxx = mydims.maxx;
+ dims->begx = mydims.begx;
break;
case UI__WINDOW_DOCK_BOTTOM:
- out_lines = maxy * size;
- out_y = maxy - out_lines + begy;
- out_cols = maxx;
- out_x = begx;
+ dims->maxy = mydims.maxy * size;
+ dims->begy = mydims.maxy - dims->maxy + mydims.begy;
+ dims->maxx = mydims.maxx;
+ dims->begx = mydims.begx;
break;
case UI__WINDOW_DOCK_LEFT:
- ui__dock_adjust(dock, 1, &maxy, &maxx, &begy, &begx);
- out_lines = maxy;
- out_y = begy;
- out_cols = maxx * size;
- out_x = begx;
+ ui__dock_adjust(dock, 1, &mydims);
+ dims->maxy = mydims.maxy;
+ dims->begy = mydims.begy;
+ dims->maxx = mydims.maxx * size;
+ dims->begx = mydims.begx;
break;
case UI__WINDOW_DOCK_RIGHT:
- ui__dock_adjust(dock, 1, &maxy, &maxx, &begy, &begx);
- out_lines = maxy;
- out_y = begy;
- out_cols = maxx * size;
- out_x = maxx - out_cols + begx;
+ ui__dock_adjust(dock, 1, &mydims);
+ dims->maxy = mydims.maxy;
+ dims->begy = mydims.begy;
+ dims->maxx = mydims.maxx * size;
+ dims->begx = mydims.maxx - dims->maxx + mydims.begx;
break;
case UI__WINDOW_DOCK_CENTER:
- ui__dock_adjust(dock, 3, &maxy, &maxx, &begy, &begx);
- out_lines = maxy;
- out_y = begy;
- out_cols = maxx;
- out_x = begx;
+ ui__dock_adjust(dock, 3, &mydims);
+ dims->maxy = mydims.maxy;
+ dims->begy = mydims.begy;
+ dims->maxx = mydims.maxx;
+ dims->begx = mydims.begx;
break;
default:
umps_trap;
}
-
- return newwin(out_lines, out_cols, out_y, out_x);
}
void ui__dock_add_child(struct ui_window_dock *dock, struct ui_window_base *child, unsigned position, float size)
{
umps_assert_s(!dock->children[position], "child present"); /* TODO: handle gracefully (technically invalid usage) */
umps_assert_s(!child->parent, "child parent present"); /* TODO: take this window from its current parent */
- umps_assert_s(!child->cwindow, "child already initialized");
child->parent = (struct ui_window_base *)dock;
dock->children[position] = child;
@@ -135,20 +125,13 @@ void ui__dock_add_child(struct ui_window_dock *dock, struct ui_window_base *chil
}
/* now set up the window for this child */
- child->cwindow = ui__dock_place_window(dock, position, size);
+ ui__dock_place_window(dock, position, size, &child->dims);
+ ui__call_layout_proc(child);
}
void ui__dock_default_draw_proc(struct ui_window_base *base)
{
struct ui_window_dock *dock = ui__cast(dock, base);
- int maxy, maxx;
- getmaxyx(base->cwindow, maxy, maxx);
-
- for (int i = 0; i < maxy; ++i) {
- mvwhline(base->cwindow, i, 0, '.', maxx);
- }
-
- wnoutrefresh(dock->super.cwindow);
for (unsigned i = 0; i < UI__WINDOW_DOCK_MAX; ++i)
{
if (dock->children[i])
@@ -166,8 +149,7 @@ void ui__dock_default_layout_proc(struct ui_window_base *base)
struct ui_window_base *child = dock->children[i];
if (!child) continue;
- delwin(child->cwindow);
- child->cwindow = ui__dock_place_window(dock, i, dock->childsizes[i]);
+ ui__dock_place_window(dock, i, dock->childsizes[i], &child->dims);
ui__call_layout_proc(child);
}
}
diff --git a/src/ui/root.c b/src/ui/root.c
index 3877359..00eda14 100644
--- a/src/ui/root.c
+++ b/src/ui/root.c
@@ -1,7 +1,7 @@
#include "ui.internal.h"
#include "macros.h"
#include "ui/uimenu.internal.h"
-#include <curses.h>
+#include <string.h>
#define UI__ROOT_MIN_Y (24)
#define UI__ROOT_MIN_X (80)
@@ -17,20 +17,15 @@
const char *ui__status_text = "Ready";
-WINDOW *ui__root_place_content_window(struct ui_window_root *root)
+void ui__root_place_content_window(struct ui_window_root *root, struct ui_dims *dims)
{
- int maxy, maxx;
- int begy, begx;
- getmaxyx(root->super.cwindow, maxy, maxx);
- getbegyx(root->super.cwindow, begy, begx);
-
- begy += UI__ROOT_MARGIN_TOP;
- maxy -= UI__ROOT_MARGIN_TOP + UI__ROOT_MARGIN_BOTTOM;
+ memcpy(dims, &root->super.dims, sizeof(struct ui_dims));
- begx += UI__ROOT_MARGIN_LEFT;
- begx -= UI__ROOT_MARGIN_LEFT + UI__ROOT_MARGIN_RIGHT;
+ dims->begy += UI__ROOT_MARGIN_TOP;
+ dims->maxy -= UI__ROOT_MARGIN_TOP + UI__ROOT_MARGIN_BOTTOM;
- return newwin(maxy, maxx, begy, begx);
+ dims->begx += UI__ROOT_MARGIN_LEFT;
+ dims->maxx -= UI__ROOT_MARGIN_LEFT + UI__ROOT_MARGIN_RIGHT;
}
void ui__root_draw_menu(struct ui_window_root *root);
@@ -41,21 +36,21 @@ void ui__root_draw_proc(struct ui_window_base *base)
struct ui_window_root *root = ui__cast(root, base);
int maxy, maxx;
- getmaxyx(base->cwindow, maxy, maxx);
+ getmaxyx(root->cwindow, maxy, maxx);
if (root->undersize_scr) {
for (int y = 0; y < maxy; ++y)
- mvwhline(base->cwindow, y, 0, y < 3 ? ' ' : '/', maxx);
+ mvwhline(root->cwindow, y, 0, y < 3 ? ' ' : '/', maxx);
- mvwprintw(base->cwindow, 0, 0, "Your terminal is too small! It must be at least %dx%d.", UI__ROOT_MIN_X, UI__ROOT_MIN_Y);
+ mvwprintw(root->cwindow, 0, 0, "Your terminal is too small! It must be at least %dx%d.", UI__ROOT_MIN_X, UI__ROOT_MIN_Y);
- wrefresh(base->cwindow);
+ wrefresh(root->cwindow);
return;
}
ui__root_draw_menu(root);
ui__root_draw_status(root);
- wnoutrefresh(base->cwindow);
+ wnoutrefresh(root->cwindow);
if (root->content) {
ui__call_draw_proc(root->content);
@@ -70,7 +65,7 @@ void ui__root_draw_proc(struct ui_window_base *base)
void ui__root_draw_menu(struct ui_window_root *root)
{
- WINDOW *mywin = root->super.cwindow;
+ WINDOW *mywin = root->cwindow;
attron(A_REVERSE);
mvwhline(mywin, 0, 0, ' ', getmaxx(mywin));
mvwaddstr(mywin, 0, 0, " UMPS v0.1.0-dev");
@@ -101,7 +96,7 @@ void ui__root_draw_menu(struct ui_window_root *root)
void ui__root_draw_status(struct ui_window_root *root)
{
- WINDOW *mywin = root->super.cwindow;
+ WINDOW *mywin = root->cwindow;
attron(A_REVERSE);
mvwhline(mywin, getmaxy(mywin)-1, 0, ' ', getmaxx(mywin));
@@ -117,10 +112,12 @@ void ui__root_layout_proc(struct ui_window_base *base)
{
struct ui_window_root *root = ui__cast(root, base);
- int maxy, maxx;
- getmaxyx(base->cwindow, maxy, maxx);
+ if (root->cwindow != stdscr) {
+ if (root->cwindow) delwin(root->cwindow);
+ root->cwindow = newwin(root->super.dims.maxy, root->super.dims.maxx, root->super.dims.begy, root->super.dims.begx);
+ }
- if (maxy < UI__ROOT_MIN_Y || maxx < UI__ROOT_MIN_X) {
+ if (root->super.dims.maxy < UI__ROOT_MIN_Y || root->super.dims.maxx < UI__ROOT_MIN_X) {
root->undersize_scr = true;
return;
}
@@ -128,8 +125,7 @@ void ui__root_layout_proc(struct ui_window_base *base)
root->undersize_scr = false;
if (root->content) {
- delwin(root->content->cwindow);
- root->content->cwindow = ui__root_place_content_window(root);
+ ui__root_place_content_window(root, &root->content->dims);
ui__call_layout_proc(root->content);
}
}
@@ -137,18 +133,18 @@ void ui__root_layout_proc(struct ui_window_base *base)
void ui__root_set_content(struct ui_window_root *root, struct ui_window_base *window)
{
umps_assert(!window->parent);
- umps_assert(!window->cwindow);
umps_assert(!root->content);
- window->cwindow = ui__root_place_content_window(root);
+ ui__root_place_content_window(root, &window->dims);
root->content = window;
window->parent = ui__cast(base, root);
+
+ ui__call_layout_proc(window);
}
void ui__root_set_floating(struct ui_window_root *root, struct ui_window_base *window)
{
umps_assert(!window->parent);
- umps_assert(!window->cwindow);
umps_assert(!root->floating);
diff --git a/src/ui/ui.internal.h b/src/ui/ui.internal.h
index 161391f..946d57a 100644
--- a/src/ui/ui.internal.h
+++ b/src/ui/ui.internal.h
@@ -17,8 +17,9 @@
#define UI__WINDOW_FOCUS_NONE (999u)
#define UI__WINDOW_TYPE_BASE (0u)
-#define UI__WINDOW_TYPE_DOCK (1u)
-#define UI__WINDOW_TYPE_ROOT (2u)
+#define UI__WINDOW_TYPE_LEAF (1u)
+#define UI__WINDOW_TYPE_DOCK (2u)
+#define UI__WINDOW_TYPE_ROOT (3u)
#define UI__WINDOW_DOCK_MAX UI__WINDOW_DOCK_CENTER+1
@@ -28,6 +29,7 @@
#define ui__cast(_t, _v) (ui__check_cast_to_ ## _t(_v))
struct ui_window_base *ui__check_cast_to_base(void *);
+struct ui_window_leaf *ui__check_cast_to_leaf(void *);
struct ui_window_dock *ui__check_cast_to_dock(void *);
struct ui_window_root *ui__check_cast_to_root(void *);
#endif
@@ -43,12 +45,21 @@ typedef void (ui__layout_proc)(struct ui_window_base *);
struct ui_window_base {
unsigned type;
struct ui_window_base *parent; /* the parent of a window manages its memory */
- WINDOW *cwindow; /* ncurses window */
+ struct ui_dims {
+ int maxy, maxx;
+ int begy, begx;
+ } dims;
ui__draw_proc *draw_proc;
ui__layout_proc *layout_proc;
};
+struct ui_window_leaf {
+ struct ui_window_base super;
+
+ WINDOW *cwindow;
+};
+
struct ui_window_dock {
struct ui_window_base super;
@@ -60,6 +71,8 @@ struct ui_window_dock {
struct ui_window_root {
struct ui_window_base super;
+ WINDOW *cwindow;
+
bool undersize_scr;
struct ui_window_base *content;
@@ -72,6 +85,7 @@ struct ui_window_root {
/* in-place constructors */
void ui__init_window_base(struct ui_window_base *);
+void ui__init_window_leaf(struct ui_window_leaf *);
void ui__init_window_dock(struct ui_window_dock *);
void ui__init_window_root(struct ui_window_root *, WINDOW *);