aboutsummaryrefslogtreecommitdiffstats
path: root/src/ui
diff options
context:
space:
mode:
authorLibravatar bigfoot547 <[email protected]>2023-11-27 23:50:21 -0600
committerLibravatar bigfoot547 <[email protected]>2023-11-27 23:50:21 -0600
commitfdfa8f9ba55edb798cc6ae820b8c732b96f31808 (patch)
tree7e489d43851be8872c687022d7362c97128b725a /src/ui
parentadd key handling and some other stuff (diff)
add some scrolling code and debug stuf
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/base.c17
-rw-r--r--src/ui/debug.c22
-rw-r--r--src/ui/root.c123
-rw-r--r--src/ui/ui.internal.h17
4 files changed, 150 insertions, 29 deletions
diff --git a/src/ui/base.c b/src/ui/base.c
index 0db31b3..f1aa217 100644
--- a/src/ui/base.c
+++ b/src/ui/base.c
@@ -5,6 +5,7 @@
#include "ui.internal.h"
#include "ui/uimenu.internal.h"
#include "../macros.h"
+#include "config.h"
struct ui_window_root *ui_root = NULL;
@@ -31,8 +32,8 @@ void ui__leaf_draw_proc(struct ui_window_base *base)
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);
+ if (leaf->cwindow) NCCI(delwin(leaf->cwindow));
+ leaf->cwindow = NCCP(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)
@@ -89,8 +90,12 @@ void ui__init_window_root(struct ui_window_root *root, WINDOW *cwindow)
getmaxyx(cwindow, root->super.dims.maxy, root->super.dims.maxx);
getbegyx(cwindow, root->super.dims.begy, root->super.dims.begx);
+ root->menu_prefix = "";
+ root->menu_prefix_len = 0;
+
root->menu_cwindow = newwin(1, root->super.dims.maxx, 0, 0);
root->menu_selected = NULL;
+ root->menu_scroll = 0;
root->undersize_scr = false;
root->content = NULL;
@@ -303,14 +308,18 @@ void ui_init(void)
curs_set(0);
ui__init_window_root(ui_root, stdscr);
+ ui__call_layout_proc(ui__cast(base, ui_root));
/* set up UI */
+ ui_root->menu_prefix = " " UMPS_NAME " " UMPS_VERSION " ";
+ ui_root->menu_prefix_len = strlen(ui_root->menu_prefix);
+
struct ui_window_dock *maindock = malloc(sizeof(struct ui_window_dock));
ui__init_window_dock(maindock);
ui__root_set_content(ui_root, ui__cast(base, maindock));
- const char *menu_names[] = { "File", "View", "Tools", "Filters", "Help", NULL };
+ const char *menu_names[] = { "File", "View", "Tools", "Filters", "Help", "1", "22", "333", "4444", "55555", "666666", "7777777", "88888888", "999999999", "0000000000", NULL };
for (int i = 0; menu_names[i]; ++i) {
struct uimenu_item_menu *menu = malloc(sizeof(struct uimenu_item_menu));
uimenu_item_menu_init(menu, menu_names[i]);
@@ -325,7 +334,7 @@ void ui_init(void)
ui__dock_add_child(maindock, ui__cast(base, win_traces), i, 1./5);
}
- /* ui__call_layout_proc(ui__cast(base, ui_root)); */
+ ui__call_layout_proc(ui__cast(base, ui_root)); /* should call layout proc to check for undersize at least */
ui__call_draw_proc(ui__cast(base, ui_root));
}
diff --git a/src/ui/debug.c b/src/ui/debug.c
index 6e404a3..5623b97 100644
--- a/src/ui/debug.c
+++ b/src/ui/debug.c
@@ -51,6 +51,28 @@ struct ui_window_root *ui__check_cast_to_root(void *obj, const char *file, const
UMPS__DEBUG_DO_ERROR(obj, file, func, line, UI__WINDOW_TYPE_ROOT);
}
+int ui__debug_nc_check_int(int in, const char *call, const char *file, const char *func, int line)
+{
+ if (in == ERR) {
+ fprintf(stderr, "!!!!!\n!!!!!\n!!!!! UMPS checked ncurses call \"%s\" failed (returned ERR) at %s:%d %s !!!!!\n!!!!!\n!!!!!\n",
+ call, file, line, func);
+ umps_trap;
+ }
+
+ return in;
+}
+
+WINDOW *ui__debug_nc_check_ptr(WINDOW *ptr, const char *call, const char *file, const char *func, int line)
+{
+ if (ptr == NULL) {
+ fprintf(stderr, "!!!!!\n!!!!!\n!!!!! UMPS checked ncurses call \"%s\" failed (returned NULL) at %s:%d %s !!!!!\n!!!!!\n!!!!!\n",
+ call, file, line, func);
+ umps_trap;
+ }
+
+ return ptr;
+}
+
#else
/* the file must have a declaration */
diff --git a/src/ui/root.c b/src/ui/root.c
index 6846d45..fd82ea6 100644
--- a/src/ui/root.c
+++ b/src/ui/root.c
@@ -1,7 +1,6 @@
#include "ui.internal.h"
#include "macros.h"
#include "ui/uimenu.internal.h"
-#include <curses.h>
#include <string.h>
#define UI__ROOT_MIN_Y (24)
@@ -65,40 +64,108 @@ void ui__root_draw_proc(struct ui_window_base *base)
doupdate();
}
+const char *ui__root_get_menu_text(struct uimenu_item_header *item)
+{
+ const char *text = NULL;
+ switch (item->type) {
+ case UMPS__MENU_TYPE_SPACER:
+ return "--";
+ case UMPS__MENU_TYPE_BUTTON:
+ text = ((struct uimenu_item_button *)item)->text;
+ break;
+ case UMPS__MENU_TYPE_MENU:
+ text = ((struct uimenu_item_menu *)item)->text;
+ break;
+ default:
+ umps_trap;
+ }
+
+ return text ? text : "???";
+}
+
+void ui__update_scroll(struct ui_window_root *root)
+{
+ unsigned cursor = 0, prevcursor = 0;
+ unsigned menu_len = getmaxx(root->menu_cwindow) - root->menu_prefix_len - 2;
+
+ for (struct uimenu_item_header *item = root->menu_root->head; item; item = item->next, prevcursor = cursor) {
+ if (item == root->menu_selected) { /* we have found the item :) */
+ if (root->menu_scroll > cursor) { /* we are scrolled too far to the right */
+ root->menu_scroll = cursor;
+ return;
+ }
+ }
+
+ cursor += 2;
+
+ cursor += strlen(ui__root_get_menu_text(item));
+
+ if (item == root->menu_selected) {
+ if (cursor > root->menu_scroll + menu_len) {
+ root->menu_scroll = cursor - menu_len;
+ }
+
+ return;
+ }
+ }
+}
+
+void ui__root_scroll_text(struct ui_window_root *root, unsigned cursor, const char *text, size_t tlen)
+{
+ if (cursor < root->menu_scroll) {
+ size_t strend = cursor + tlen;
+ if (strend > root->menu_scroll) {
+ size_t desired_length = strend - root->menu_scroll;
+ waddnstr(root->menu_cwindow, text + (tlen - desired_length), desired_length);
+ }
+ return;
+ }
+
+ waddnstr(root->menu_cwindow, text, tlen);
+}
+
void ui__root_draw_menu(struct ui_window_root *root)
{
wattron(root->menu_cwindow, A_REVERSE);
mvwhline(root->menu_cwindow, 0, 0, ' ', getmaxx(root->menu_cwindow));
- mvwaddstr(root->menu_cwindow, 0, 0, " UMPS v0.1.0-dev");
+ mvwaddnstr(root->menu_cwindow, 0, 0, root->menu_prefix, root->menu_prefix_len);
+
+ ui__update_scroll(root);
+
+ if (root->menu_scroll > 2) {
+ waddch(root->menu_cwindow, ACS_LARROW);
+ } else {
+ waddch(root->menu_cwindow, ' ');
+ }
- char *text;
+ unsigned cursor = 0;
+ const char *text;
int idx = 0;
- for (struct uimenu_item_header *item = root->menu_root->head; item; item = item->next, ++idx) {
- waddstr(root->menu_cwindow, " ");
-
- switch (item->type) {
- case UMPS__MENU_TYPE_SPACER:
- waddstr(root->menu_cwindow, "--");
- continue;
- case UMPS__MENU_TYPE_BUTTON:
- text = ((struct uimenu_item_button *)item)->text;
- break;
- case UMPS__MENU_TYPE_MENU:
- text = ((struct uimenu_item_menu *)item)->text;
- break;
- default:
- umps_trap;
+ unsigned menu_len = getmaxx(root->menu_cwindow) - root->menu_prefix_len - 2;
+ struct uimenu_item_header *item;
+ for (item = root->menu_root->head; item; item = item->next, ++idx) {
+ if (cursor > root->menu_scroll) {
+ waddstr(root->menu_cwindow, " ");
}
+ cursor += 2;
+ text = ui__root_get_menu_text(item);
+ size_t tlen = strlen(text);
if (item == root->menu_selected)
wattroff(root->menu_cwindow, A_REVERSE);
- if (text) waddstr(root->menu_cwindow, text);
- else waddstr(root->menu_cwindow, "???");
+ ui__root_scroll_text(root, cursor, text, tlen);
wattron(root->menu_cwindow, A_REVERSE);
+ cursor += tlen;
+
+ if (cursor >= root->menu_scroll + menu_len) {
+ break;
+ }
}
+ mvwaddch(root->menu_cwindow, 0, getmaxx(root->menu_cwindow)-1, (cursor > root->menu_scroll + menu_len || (item && item->next)) ? ACS_RARROW : ' ');
+
wattroff(root->menu_cwindow, A_REVERSE);
}
@@ -128,12 +195,12 @@ void ui__root_layout_proc(struct ui_window_base *base)
struct ui_window_root *root = ui__cast(root, base);
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 (root->cwindow) NCCI(delwin(root->cwindow));
+ root->cwindow = NCCP(newwin(root->super.dims.maxy, root->super.dims.maxx, root->super.dims.begy, root->super.dims.begx));
}
- delwin(root->menu_cwindow);
- root->menu_cwindow = newwin(1, root->super.dims.maxx, 0, 0);
+ NCCI(delwin(root->menu_cwindow));
+ root->menu_cwindow = NCCP(newwin(1, root->super.dims.maxx, 0, 0));
if (root->super.dims.maxy < UI__ROOT_MIN_Y || root->super.dims.maxx < UI__ROOT_MIN_X) {
root->undersize_scr = true;
@@ -171,6 +238,14 @@ struct ui_window_base *ui__root_control_proc(struct ui_window_base *base, ui_con
}
ui__root_redraw_menu(root);
return NULL;
+ case NS('a'):
+ --root->menu_scroll;
+ ui__root_redraw_menu(root);
+ break;
+ case NS('d'):
+ ++root->menu_scroll;
+ ui__root_redraw_menu(root);
+ break;
case KEY_LEFT:
case KEY_RIGHT:
if (root->menu_selected) {
diff --git a/src/ui/ui.internal.h b/src/ui/ui.internal.h
index 763f9a7..863d9b2 100644
--- a/src/ui/ui.internal.h
+++ b/src/ui/ui.internal.h
@@ -6,6 +6,7 @@
#include "config.h"
#include NCURSES_INCLUDE
+#include <stddef.h> /* for size_t */
#include <stdbool.h>
#define UI__WINDOW_DOCK_TOP (0u)
@@ -36,6 +37,10 @@ enum {
#ifdef NDEBUG
#define ui__cast(_t, _v) ((struct ui_window_ ## _t *)(_v))
+
+/* ncurses auto-checkers no-op in release */
+#define NCCI(_call) _call
+#define NCCP(_call) _call
#else
#define ui__cast(_t, _v) (ui__check_cast_to_ ## _t(_v, __FILE__, __func__, __LINE__))
@@ -43,6 +48,12 @@ struct ui_window_base *ui__check_cast_to_base(void *, const char *, const char *
struct ui_window_leaf *ui__check_cast_to_leaf(void *, const char *, const char *, int);
struct ui_window_dock *ui__check_cast_to_dock(void *, const char *, const char *, int);
struct ui_window_root *ui__check_cast_to_root(void *, const char *, const char *, int);
+
+#define NCCI(_call) ui__debug_nc_check_int(_call, #_call, __FILE__, __func__, __LINE__)
+#define NCCP(_call) ui__debug_nc_check_ptr(_call, #_call, __FILE__, __func__, __LINE__)
+
+int ui__debug_nc_check_int(int in, const char *call, const char *file, const char *func, int line);
+WINDOW *ui__debug_nc_check_ptr(WINDOW *ptr, const char *call, const char *file, const char *func, int line);
#endif
/* concrete type definitions */
@@ -93,9 +104,13 @@ struct ui_window_root {
struct ui_window_base super;
WINDOW *cwindow, *menu_cwindow;
+ const char *menu_prefix;
+ size_t menu_prefix_len;
+
struct uimenu_item_header *menu_selected;
+ unsigned menu_scroll;
- bool undersize_scr;
+ bool undersize_scr; /* true if the screen was found to be undersize (set in layout proc) */
struct ui_window_base *content; /* content of the editor */
struct ui_window_base *floating; /* floating menu layer */