aboutsummaryrefslogtreecommitdiff
path: root/clients/tui.c
diff options
context:
space:
mode:
Diffstat (limited to 'clients/tui.c')
-rw-r--r--clients/tui.c193
1 files changed, 191 insertions, 2 deletions
diff --git a/clients/tui.c b/clients/tui.c
index 30761a8..13da593 100644
--- a/clients/tui.c
+++ b/clients/tui.c
@@ -17,6 +17,12 @@ static int (*g_in)(void) = getch;
static void (*g_frame)(const char *title);
static void (*g_hints)(const char *hints);
static void (*g_quit)(void);
+static const char *g_list_hint_extra;
+
+void tui_list_hint_extra(const char *extra)
+{
+ g_list_hint_extra = extra;
+}
void tui_set_input(int (*fn)(void))
{
@@ -1082,6 +1088,10 @@ int tui_select_list_hook(const char *title, char **items, int n, int start,
allow_refresh ? " F5 = uppdatera" : "",
allow_new ? " ^N = ny" : "", dbuf,
allow_toggle ? " ^A = öppna/stäng" : "");
+ if (g_list_hint_extra && *g_list_hint_extra) {
+ size_t hl = strlen(hint);
+ snprintf(hint + hl, sizeof hint - hl, " %s", g_list_hint_extra);
+ }
list_draw(title, items, n, &v, hint);
int ch = in_key();
int r = tui_nav_key(&v, ch, allow_new, archive_action != NULL,
@@ -1190,6 +1200,7 @@ int tui_menu(const char *title, const char *const *items, int n,
/* ------------------------------------------------------------------ */
static const char *g_form_hint;
+static const char *g_form_hint_extra;
static char g_status[512];
static char g_right[160];
@@ -1198,6 +1209,11 @@ void tui_form_hint(const char *hint)
g_form_hint = hint;
}
+void tui_form_hint_extra(const char *extra)
+{
+ g_form_hint_extra = extra;
+}
+
void tui_set_status(const char *status, const char *right)
{
snprintf(g_status, sizeof g_status, "%s", status ? status : "");
@@ -1531,6 +1547,174 @@ void tui_form_act_label(const struct tui_form_action *a, char *buf, size_t n)
}
}
+static void action_key_name(int key, char *buf, size_t n)
+{
+ if (key >= KEY_F(1) && key <= KEY_F(12))
+ snprintf(buf, n, "F%d", key - KEY_F(0));
+ else if (key == TUI_KEY_CTRL_N)
+ snprintf(buf, n, "^N");
+ else if (key == TUI_KEY_CTRL_X)
+ snprintf(buf, n, "^X");
+ else if (key == 27)
+ snprintf(buf, n, "Esc");
+ else if (key == '\n' || key == '\r' || key == KEY_ENTER)
+ snprintf(buf, n, "Enter");
+ else if (key > 0 && key < 27)
+ snprintf(buf, n, "^%c", 'A' + key - 1);
+ else
+ snprintf(buf, n, "?");
+}
+
+void tui_action_label(const struct tui_action *a, char *buf, size_t n)
+{
+ const char *label = a && a->label ? a->label : "";
+
+ if (a && a->enabled == 0) {
+ const char *reason =
+ a->reason && *a->reason ? a->reason : "otillgänglig";
+ snprintf(buf, n, "%s (%s)", label, reason);
+ } else {
+ snprintf(buf, n, "%s", label);
+ }
+}
+
+void tui_action_hint(const struct tui_action *acts, int n, int max, char *buf,
+ size_t cap)
+{
+ size_t o = 0;
+ int shown = 0;
+
+ if (!buf || cap == 0)
+ return;
+ buf[0] = '\0';
+ for (int i = 0; i < n && (max <= 0 || shown < max); i++) {
+ char key[16], item[200];
+ size_t len;
+
+ if (acts[i].enabled != 1 || !acts[i].key)
+ continue;
+ action_key_name(acts[i].key, key, sizeof key);
+ snprintf(item, sizeof item, "%s%s = %s", shown ? " " : "", key,
+ acts[i].label ? acts[i].label : "");
+ len = strlen(item);
+ if (o + len + 1 > cap)
+ break;
+ memcpy(buf + o, item, len + 1);
+ o += len;
+ shown++;
+ }
+ const char *more = "F2 = fler";
+ size_t ml = strlen(more);
+ if (o + ml + (o ? 3 : 0) + 1 <= cap)
+ snprintf(buf + o, cap - o, "%s%s", o ? " " : "", more);
+}
+
+int tui_action_menu(const char *title, const struct tui_action *acts, int n,
+ int *focus)
+{
+ struct tui_list_nav v;
+ unsigned char *ok;
+ char **items;
+ int ret = -1;
+
+ if (!acts || n <= 0)
+ return -1;
+ memset(&v, 0, sizeof v);
+ v.n = n;
+ ok = xcalloc((size_t)n, 1);
+ items = xcalloc((size_t)n, sizeof(char *));
+ for (int i = 0; i < n; i++) {
+ char line[192];
+
+ tui_action_label(&acts[i], line, sizeof line);
+ items[i] = xstrdup(line);
+ ok[i] = acts[i].enabled != -1;
+ }
+ v.selectable = ok;
+ v.sel = focus && *focus >= 0 && *focus < n ? *focus : 0;
+ if (!ok[v.sel])
+ v.sel = nav_snap(&v, v.sel, 1);
+ v.numw = tui_num_width(n);
+ if (v.numw < 2)
+ v.numw = 2;
+ v.view = LINES - 4;
+ snprintf(v.gotolabel, sizeof v.gotolabel, "Gå till nummer: ");
+ for (;;) {
+ int num = 0;
+
+ if (v.sel < 0 || v.sel >= n) {
+ v.sel = nav_snap(&v, 0, 1);
+ if (v.sel < 0)
+ break;
+ }
+ if (focus)
+ *focus = v.sel;
+ list_view_sync(&v);
+ if (g_frame)
+ g_frame(title);
+ for (int i = 0; i < v.top && i < n; i++)
+ if (ok[i])
+ num++;
+ for (int idx = v.top; idx < n && idx < v.top + v.view; idx++) {
+ char line[832];
+ if (!ok[idx]) {
+ snprintf(line, sizeof line, "%*s %s", v.numw, "",
+ items[idx]);
+ attron(tui_style_attrs(TUI_DIM, g_colours, 0));
+ mvaddnstr(3 + (idx - v.top), 4, line, COLS - 6);
+ attroff(tui_style_attrs(TUI_DIM, g_colours, 0));
+ continue;
+ }
+ num++;
+ snprintf(line, sizeof line, "%*d. %s", v.numw, num, items[idx]);
+ if (acts[idx].enabled != 1)
+ attron(tui_style_attrs(TUI_DIM, g_colours, 0));
+ if (idx == v.sel)
+ attron(A_REVERSE);
+ mvaddnstr(3 + (idx - v.top), 4, line, COLS - 6);
+ if (idx == v.sel)
+ attroff(A_REVERSE);
+ if (acts[idx].enabled != 1)
+ attroff(tui_style_attrs(TUI_DIM, g_colours, 0));
+ }
+ if (v.goto_active) {
+ move(LINES - 2, 2);
+ tui_style(TUI_ACCENT);
+ printw("%s%s", v.gotolabel, v.gotobuf);
+ tui_style_reset();
+ clrtoeol();
+ } else {
+ move(LINES - 2, 2);
+ clrtoeol();
+ }
+ if (g_hints)
+ g_hints("upp/ned, 1-9 = hoppa, g = gå till, PgUp/PgDn, Home/End,"
+ " Enter = utför Esc/q = avbryt");
+ refresh();
+ int ch = in_key();
+ if (ch == '\n' || ch == '\r' || ch == KEY_ENTER) {
+ if (!ok[v.sel])
+ continue;
+ if (acts[v.sel].enabled != 1) {
+ tui_message(title, "%s",
+ acts[v.sel].reason && *acts[v.sel].reason
+ ? acts[v.sel].reason
+ : "Otillgänglig.");
+ continue;
+ }
+ ret = v.sel;
+ break;
+ }
+ if (tui_nav_key(&v, ch, 0, 0, 0, 0) == -1)
+ break;
+ }
+ for (int i = 0; i < n; i++)
+ free(items[i]);
+ free(items);
+ free(ok);
+ return ret;
+}
+
/* Action rows sit under the fields, one blank line below them. */
static void form_draw_actions(const struct tui_form_action *acts, int na,
int nf, int sel)
@@ -1615,7 +1799,7 @@ static int form_run(const char *title, struct tui_form_field *f, int nf,
h = na > 0
? (can_edit
? "upp/ned/Tab = flytta Enter = ändra/utför"
- " F5 = uppdatera ^Enter/F9 = spara"
+ " F5 = uppdatera F9 = spara"
" Esc/q = tillbaka ^C = avsluta"
: "upp/ned/Tab = flytta Enter = utför"
" F5 = uppdatera Esc/q = tillbaka"
@@ -1623,11 +1807,16 @@ static int form_run(const char *title, struct tui_form_field *f, int nf,
" (endast behöriga kan ändra)")
: (can_edit
? "upp/ned/Home/End Enter = ändra"
- " F5 = uppdatera ^Enter/F9 = spara"
+ " F5 = uppdatera F9 = spara"
" Esc/q = tillbaka ^C = avsluta"
: "upp/ned/Home/End F5 = uppdatera"
" Esc/q = tillbaka ^C = avsluta"
" (endast behöriga kan ändra)");
+ char hbuf[640];
+ if (g_form_hint_extra && *g_form_hint_extra &&
+ snprintf(hbuf, sizeof hbuf, "%s %s", h, g_form_hint_extra) <
+ (int)sizeof hbuf)
+ h = hbuf;
tui_hints(h);
g_form_hint = NULL;
refresh();