diff options
| author | Anders Betts <anders.betts@gmail.com> | 2026-09-20 10:24:18 +0200 |
|---|---|---|
| committer | Anders Betts <anders.betts@gmail.com> | 2026-09-20 10:24:18 +0200 |
| commit | ae60b7d2c87cc9ed6878faa57cd4233f77f6f7c3 (patch) | |
| tree | 918e717a5d226dcd54890901682a980c41d7e1d0 /clients/tui.c | |
| parent | 5097941fa96ce0c309e5f1af034993781a70fc66 (diff) | |
| download | bokf-0.1.48.tar.gz bokf-0.1.48.zip | |
tui: pinned report headers, voucher detail headers, clamped pagingv0.1.48
Diffstat (limited to 'clients/tui.c')
| -rw-r--r-- | clients/tui.c | 116 |
1 files changed, 87 insertions, 29 deletions
diff --git a/clients/tui.c b/clients/tui.c index 06740d3..031fad0 100644 --- a/clients/tui.c +++ b/clients/tui.c @@ -126,6 +126,8 @@ const char *tui_markup(const char *line, int *style) { const char *p = line ? line : ""; int st = -1; + if (*p == TUI_MARK_STICKY) + p++; if (*p == TUI_MARK_HEADING) { st = TUI_HEADING; p++; @@ -141,6 +143,20 @@ const char *tui_markup(const char *line, int *style) return p; } +int tui_sticky_split(char **lines, int n, char **head, int *nhead) +{ + int h = 0, b = 0; + for (int i = 0; i < n; i++) { + if (lines[i][0] == TUI_MARK_STICKY) + head[h++] = lines[i]; + else + lines[b++] = lines[i]; + } + if (nhead) + *nhead = h; + return b; +} + void tui_keys_setup(void) { /* ^Enter has no control code; enable xterm modifyOtherKeys and bind the @@ -1210,6 +1226,28 @@ int tui_pager(const char *title, const char *text, const char *action_hint) action_hint ? TUI_PAGER_SAVE : 0, NULL, NULL); } +static void pager_line(int row, const char *line) +{ + move(row, 2); + clrtoeol(); + if (!line) + return; + int st = -1; + const char *s = tui_markup(line, &st); + if (st == TUI_RULE) { + attrset(tui_style_attrs(TUI_RULE, g_colours, 0)); + for (int x = 2; x < COLS - 1; x++) + mvaddch(row, x, ACS_HLINE); + attrset(A_NORMAL); + } else if (st >= 0) { + attrset(tui_style_attrs((enum tui_style)st, g_colours, 0)); + mvaddnstr(row, 2, s, COLS - 4); + attrset(A_NORMAL); + } else { + mvaddnstr(row, 2, s, COLS - 4); + } +} + int tui_pager_hook(const char *title, const char *text, const char *extra_hint, unsigned flags, int (*key)(void *ud, int ch), void *ud) @@ -1232,29 +1270,24 @@ int tui_pager_hook(const char *title, const char *text, break; p = nl + 1; } + char **head = xcalloc(nlines ? nlines : 1, sizeof(char *)); + int nhead = 0; + int nb = tui_sticky_split(lines, n, head, &nhead); int top = 0; int view = LINES - 4; + int vbody = view - nhead; + if (vbody < 1) + vbody = 1; for (;;) { tui_frame(title); - for (int i = 0; i < view; i++) { - move(2 + i, 2); - clrtoeol(); - if (top + i >= n) - continue; - int st = -1; - const char *s = tui_markup(lines[top + i], &st); - if (st == TUI_RULE) { - attrset(tui_style_attrs(TUI_RULE, g_colours, 0)); - for (int x = 2; x < COLS - 1; x++) - mvaddch(2 + i, x, ACS_HLINE); - attrset(A_NORMAL); - } else if (st >= 0) { - attrset(tui_style_attrs((enum tui_style)st, g_colours, 0)); - mvaddnstr(2 + i, 2, s, COLS - 4); - attrset(A_NORMAL); - } else { - mvaddnstr(2 + i, 2, s, COLS - 4); - } + int row = 0; + for (int i = 0; i < nhead && row < view; i++, row++) + pager_line(2 + row, head[i]); + for (int i = 0; i < vbody && row < view; i++, row++) { + if (top + i < nb) + pager_line(2 + row, lines[top + i]); + else + pager_line(2 + row, NULL); } char hint[512]; if (extra_hint && *extra_hint) @@ -1290,23 +1323,24 @@ int tui_pager_hook(const char *title, const char *text, if (h == TUI_HOOK_STAY) continue; } - if (ch == KEY_DOWN && top + view < n) + if (ch == KEY_DOWN && top + vbody < nb) top++; else if (ch == KEY_UP && top > 0) top--; else if (ch == KEY_NPAGE) - top += view; + top += vbody; else if (ch == KEY_PPAGE) - top -= view; + top -= vbody; else if (ch == KEY_HOME) top = 0; else if (ch == KEY_END) - top = n > view ? n - view : 0; - if (top + view > n) - top = n > view ? n - view : 0; + top = nb > vbody ? nb - vbody : 0; + if (top + vbody > nb) + top = nb > vbody ? nb - vbody : 0; if (top < 0) top = 0; } + free(head); free(copy); free(lines); return ret; @@ -1410,6 +1444,33 @@ int tui_form_act_first(int nf, const struct tui_form_action *acts, int na) return -1; } +int tui_form_act_page(int focus, int nf, const struct tui_form_action *acts, + int na, int dir) +{ + if (nf < 0) + nf = 0; + if (na < 0) + na = 0; + int n = nf + na; + if (n <= 0) + return -1; + int pos = focus >= 0 && focus < n ? focus : 0; + for (int i = 0; i < TUI_FORM_PAGE; i++) { + int next = -1; + for (int p = pos + (dir >= 0 ? 1 : -1); p >= 0 && p < n; + p += (dir >= 0 ? 1 : -1)) { + if (p < nf || act_selectable(acts, p - nf, na)) { + next = p; + break; + } + } + if (next < 0) + break; + pos = next; + } + return pos; +} + int tui_form_act_key(int sel, int nf, const struct tui_form_action *acts, int na, int ch) { @@ -1429,10 +1490,7 @@ int tui_form_act_key(int sel, int nf, const struct tui_form_action *acts, } if (ch == KEY_NPAGE || ch == KEY_PPAGE) { int dir = ch == KEY_NPAGE ? 1 : -1; - int pos = sel; - for (int i = 0; i < TUI_FORM_PAGE; i++) - pos = tui_form_act_step(pos, nf, acts, na, dir); - return pos; + return tui_form_act_page(sel, nf, acts, na, dir); } return tui_form_next(sel, nf, ch); } |
