diff options
| author | Anders Betts <anders.betts@gmail.com> | 2026-09-19 21:58:58 +0200 |
|---|---|---|
| committer | Anders Betts <anders.betts@gmail.com> | 2026-09-19 21:58:58 +0200 |
| commit | 4329ffb98d7eeffe2b3874d2b31cb0857d33d944 (patch) | |
| tree | 16e777dc90fa334ce3f436a3b5d3a7a9efdbd8b9 /clients/tui.h | |
| parent | 34fc2b1dce788fbb093e70c2124630167e7980ef (diff) | |
| download | bokf-0.1.36.tar.gz bokf-0.1.36.zip | |
tui: shared widget layer (fields, prompts, lists, forms, pager) + testsv0.1.36
Diffstat (limited to 'clients/tui.h')
| -rw-r--r-- | clients/tui.h | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/clients/tui.h b/clients/tui.h new file mode 100644 index 0000000..0bda359 --- /dev/null +++ b/clients/tui.h @@ -0,0 +1,131 @@ +#ifndef BOKF_TUI_H +#define BOKF_TUI_H + +#include <stddef.h> +#include <stdint.h> + +#include <ncursesw/ncurses.h> + +/* Shared TUI widgets: the only place that touches ncurses (screens compose + these; see docs/TUI-GUIDELINES.md). Everything with logic of its own is + unit-tested in tests/test_tui.c, which links only the pure parts. */ + +/* Universal keys that have no control code or need a stable name. */ +#define TUI_KEY_CTRL_N 0x0e +#define TUI_KEY_CTRL_ENTER (KEY_MAX + 1) + +/* The application supplies input, frame/hints drawing and a quit hook so + this module stays free of app state (and testable). */ +void tui_set_input(int (*fn)(void)); +void tui_set_screen(void (*frame)(const char *), void (*hints)(const char *)); +void tui_set_quit(void (*fn)(void)); +void tui_keys_setup(void); + +/* --- text measure and formatting --- */ +int tui_disp_width(const char *s); +int tui_disp_width_n(const char *s, size_t n); +void tui_pad_field(char *buf, size_t cap, int width); +void tui_pad_label(char *buf, size_t n, const char *text, int width); +void tui_pad_hdr(char *buf, size_t n, int width, const char *text); +void tui_amt_col(char *buf, size_t n, int width, int64_t ore); +void tui_kr_format(int64_t ore, char *buf, size_t n); +void tui_kr0_format(int64_t ore, char *buf, size_t n); +int tui_parse_kr(const char *s, int64_t *out); + +/* --- line editor (pure) --- */ +struct tui_ledit { + char *buf; + size_t cap; + size_t len; + size_t pos; /* caret in bytes */ +}; + +void tui_le_init(struct tui_ledit *e, char *buf, size_t cap); +void tui_le_clear(struct tui_ledit *e); +int tui_le_key(struct tui_ledit *e, int ch); + +/* Applies one key to a form field. *pos is the caret ((size_t)-1 = end); + *fresh replaces the content on the first editing key. Returns whether + the key was consumed. */ +int tui_field_edit(char *buf, size_t cap, size_t *pos, int ch, int *fresh); + +/* Date field: digits only, dashes inserted ("20260215" -> "2026-02-15"), + caret tracked in digit space. */ +int tui_date_field_edit(char *buf, size_t cap, size_t *pos, int ch, + int *fresh); + +/* Line editor at (y,x) with the label already drawn. Returns 1 on Enter, + 2 on Tab, 3 on Shift-Tab, 0 on Esc. */ +int tui_edit_field(int y, int x, char *buf, size_t cap, int mask); + +/* --- modal dialogs --- */ +void tui_message(const char *title, const char *fmt, ...) + __attribute__((format(printf, 2, 3))); +int tui_confirm(const char *title, const char *fmt, ...) + __attribute__((format(printf, 2, 3))); + +/* --- prompts: write into the caller's buffer, return 0 on Esc --- */ +int tui_prompt_into(char *buf, size_t cap, const char *label, + const char *def, int mask); +int tui_date_prompt_into(char *buf, size_t cap, const char *label, + const char *def); +int tui_amount_prompt_into(int64_t *out, const char *label, int64_t def_ore); +int tui_choice_prompt(const char *label, const char *const *opts, int n, + int cur); + +/* --- lists --- */ +#define TUI_NAV_NONE (-3) + +struct tui_list_nav { + int n, sel, top, view, numw; + char gotobuf[12]; + char gotolabel[32]; + int goto_active; +}; + +/* Returns the selected index, or -1 back, -2 refresh, -4 new, -6 remove, + -7 toggle, TUI_NAV_NONE when nothing happened. */ +int tui_nav_key(struct tui_list_nav *v, int ch, int allow_new, + int allow_remove, int allow_toggle, int menu_mode); + +int tui_select_list(const char *title, char **items, int n, int start, + int allow_refresh, int *cursor, int allow_new, + const char *archive_action, int allow_toggle); +int tui_menu(const char *title, const char *const *items, int n, + int allow_new, int *cursor); + +/* --- frame, status, hints, pager --- */ +void tui_set_status(const char *status, const char *right); +void tui_frame(const char *title); +void tui_hints(const char *s); +int tui_pager(const char *title, const char *text, const char *action_hint); + +/* --- forms --- */ +enum { + TUI_F_TEXT = 0, + TUI_F_DATE, + TUI_F_AMOUNT, + TUI_F_CHOICE, + TUI_F_ACTION, +}; + +#define TUI_FORM_BACK (-1) +#define TUI_FORM_REFRESH (-2) +#define TUI_FORM_SUBMIT (-3) + +struct tui_form_field { + const char *label; + char *value; /* text storage for TEXT/DATE (also CHOICE labels) */ + size_t cap; + int kind; + int64_t *ore; /* TUI_F_AMOUNT */ + const char *const *choices; /* TUI_F_CHOICE */ + int nchoices; + int *choice; /* TUI_F_CHOICE: current index */ +}; + +int tui_form_next(int sel, int n, int ch); +int tui_form_run(const char *title, struct tui_form_field *f, int n, + int can_edit); + +#endif |
