diff options
| author | Anders Betts <anders.betts@gmail.com> | 2026-09-20 00:05:51 +0200 |
|---|---|---|
| committer | Anders Betts <anders.betts@gmail.com> | 2026-09-20 00:05:51 +0200 |
| commit | a61cfeefb0599e74fc9189b189b16dd0b6d36f0f (patch) | |
| tree | 83e0934e190744605e91e69cd032e91c85eecf57 /clients | |
| parent | 1f2d7a8190876e3d1c541251e079a11a2cc637f2 (diff) | |
| download | bokf-a61cfeefb0599e74fc9189b189b16dd0b6d36f0f.tar.gz bokf-a61cfeefb0599e74fc9189b189b16dd0b6d36f0f.zip | |
tui: remember the focused row in forms and the bokslut hubv0.1.44
Diffstat (limited to 'clients')
| -rw-r--r-- | clients/bokftui.c | 15 | ||||
| -rw-r--r-- | clients/tui.c | 71 | ||||
| -rw-r--r-- | clients/tui.h | 17 |
3 files changed, 76 insertions, 27 deletions
diff --git a/clients/bokftui.c b/clients/bokftui.c index 3258f22..f7500bf 100644 --- a/clients/bokftui.c +++ b/clients/bokftui.c @@ -320,6 +320,7 @@ static void update_status(struct app *a) /* Create a new fiscal year. Returns the new id (>0) or 0. */ static int64_t fy_new_form(struct app *a) { + static int sel = 0; char label[32] = "", start[16] = "", end[16] = ""; char *resp = client_rpc(&a->conn, "fiscal_year.list", a->session, a->org, "{}"); @@ -372,7 +373,7 @@ static int64_t fy_new_form(struct app *a) ff[2].value = end; ff[2].cap = sizeof end; ff[2].kind = TUI_F_DATE; - int r = tui_form_run("Nytt räkenskapsår", ff, 3, 1); + int r = tui_form_run("Nytt räkenskapsår", ff, 3, 1, &sel); if (r == TUI_FORM_BACK) return 0; if (r != TUI_FORM_REFRESH && r != TUI_FORM_SUBMIT) @@ -4130,6 +4131,7 @@ static void board_screen(struct app *a) static void company_screen(struct app *a) { + static int sel = 0; const int nf = (int)(sizeof COMPANY_FIELDS / sizeof COMPANY_FIELDS[0]); int owner = a->role[0] && strcmp(a->role, "owner") == 0; for (;;) { @@ -4164,7 +4166,7 @@ static void company_screen(struct app *a) free(resp); ff[nf].label = "Styrelseledamöter"; ff[nf].kind = TUI_F_ACTION; - int r = tui_form_run("Företagsuppgifter", ff, nf + 1, owner); + int r = tui_form_run("Företagsuppgifter", ff, nf + 1, owner, &sel); if (r >= 0 && r < nf) { if (!company_field_valid(&COMPANY_FIELDS[r], vals[r])) { tui_message("Ogiltigt värde", "%s", COMPANY_FIELDS[r].label); @@ -4204,6 +4206,7 @@ static const char *const SETTING_LABELS[] = { "Standardserie", static void settings_screen(struct app *a) { + static int sel = 0; const int nset = (int)(sizeof SETTING_KEYS / sizeof SETTING_KEYS[0]); for (;;) { if (g_quit) @@ -4231,7 +4234,7 @@ static void settings_screen(struct app *a) ff[i].kind = TUI_F_TEXT; } free(resp); - int r = tui_form_run("Inställningar", ff, nset, 1); + int r = tui_form_run("Inställningar", ff, nset, 1, &sel); if (r >= 0) { yyjson_mut_doc *d = yyjson_mut_doc_new(NULL); yyjson_mut_val *o = yyjson_mut_obj(d); @@ -4472,6 +4475,7 @@ static void bokslut_plan(struct app *a, const char *fond, const char *rate, view. New years inherit the stable fields. */ static void bokslut_screen(struct app *a) { + static int sel = 0; static const char *const labels[6] = { "Väsentliga händelser", "Årsstämma (YYYY-MM-DD)", @@ -4574,7 +4578,7 @@ static void bokslut_screen(struct app *a) " bokslutsplan ^Enter = bokför planen (frågar" " först) Esc/q = tillbaka ^C = avsluta"); int r = tui_form_run_actions("Bokslut", ff, nf + 2, can_edit, acts, 5, - NULL); + NULL, &sel); if (r >= 0 && r < nf) { yyjson_mut_doc *d = yyjson_mut_doc_new(NULL); yyjson_mut_val *o = yyjson_mut_obj(d); @@ -5606,6 +5610,7 @@ static int try_login(struct app *a, const char *user, const char *pass, static int login_screen(struct app *a) { + static int sel = 0; char socket_path[256], user[64], pass[128]; snprintf(socket_path, sizeof socket_path, "%s", a->socket); const char *env_pass = getenv("BOKFD_PASSWORD"); @@ -5631,7 +5636,7 @@ static int login_screen(struct app *a) ff[3].kind = TUI_F_ACTION; for (;;) { - int r = tui_form_run("bokf — inloggning", ff, 4, 1); + int r = tui_form_run("bokf — inloggning", ff, 4, 1, &sel); if (r == TUI_FORM_BACK) { if (g_quit) { endwin(); diff --git a/clients/tui.c b/clients/tui.c index a5b0cd2..c52538c 100644 --- a/clients/tui.c +++ b/clients/tui.c @@ -1346,6 +1346,36 @@ static int act_selectable(const struct tui_form_action *acts, int i, int na) return acts && i >= 0 && i < na && acts[i].enabled != -1; } +int tui_form_focus_clamp(int focus, int nf, + const struct tui_form_action *acts, int na) +{ + if (nf < 0) + nf = 0; + if (na < 0) + na = 0; + int n = nf + na; + if (n <= 0) + return -1; + int pos = focus; + if (pos < 0) + pos = 0; + if (pos >= n) + pos = n - 1; + for (int i = 0; i < n; i++) { + if (pos < nf || act_selectable(acts, pos - nf, na)) + return pos; + pos = (pos + 1) % n; + } + return -1; +} + +int tui_form_focus_store(int *focus, int sel, int ret) +{ + if (focus) + *focus = sel; + return ret; +} + int tui_form_act_step(int focus, int nf, const struct tui_form_action *acts, int na, int dir) { @@ -1440,13 +1470,14 @@ static void form_draw_actions(const struct tui_form_action *acts, int na, static int form_run(const char *title, struct tui_form_field *f, int nf, int can_edit, const struct tui_form_action *acts, int na, - const char *hint, int (*key)(void *ud, int ch), void *ud) + const char *hint, int (*key)(void *ud, int ch), void *ud, + int *focus) { - int sel = nf > 0 ? 0 : tui_form_act_first(0, acts, na); + int sel = tui_form_focus_clamp(focus ? *focus : -1, nf, acts, na); for (;;) { int ntot = nf + (na > 0 ? na : 0); if (ntot <= 0) - return TUI_FORM_BACK; + return tui_form_focus_store(focus, sel, TUI_FORM_BACK); if (sel < 0) sel = tui_form_act_first(nf, acts, na); if (sel >= ntot) @@ -1523,15 +1554,15 @@ static int form_run(const char *title, struct tui_form_field *f, int nf, } if (nxt == TUI_FORM_REFRESH || nxt == TUI_FORM_SUBMIT || nxt == TUI_FORM_BACK) - return nxt; + return tui_form_focus_store(focus, sel, nxt); if (key) { int hk = key(ud, ch); if (hk == TUI_HOOK_BACK) - return TUI_FORM_BACK; + return tui_form_focus_store(focus, sel, TUI_FORM_BACK); if (hk == TUI_HOOK_REFRESH) - return TUI_FORM_REFRESH; + return tui_form_focus_store(focus, sel, TUI_FORM_REFRESH); if (hk == TUI_HOOK_SUBMIT) - return TUI_FORM_SUBMIT; + return tui_form_focus_store(focus, sel, TUI_FORM_SUBMIT); if (hk != TUI_HOOK_NONE) continue; } @@ -1550,7 +1581,8 @@ static int form_run(const char *title, struct tui_form_field *f, int nf, } if (act->enabled == -1) continue; - return TUI_FORM_ACTION + (sel - nf); + return tui_form_focus_store(focus, sel, + TUI_FORM_ACTION + (sel - nf)); } if (!can_edit) { tui_message(title, "Endast behöriga kan ändra."); @@ -1558,49 +1590,50 @@ static int form_run(const char *title, struct tui_form_field *f, int nf, } struct tui_form_field *fl = &f[sel]; if (fl->kind == TUI_F_ACTION) - return sel; + return tui_form_focus_store(focus, sel, sel); char label[192]; snprintf(label, sizeof label, "%s: ", fl->label); if (fl->kind == TUI_F_TEXT) { if (fl->value && tui_prompt_into(fl->value, fl->cap, label, fl->value, fl->mask)) - return sel; + return tui_form_focus_store(focus, sel, sel); } else if (fl->kind == TUI_F_DATE) { if (fl->value && tui_date_prompt_into(fl->value, fl->cap, label, fl->value)) - return sel; + return tui_form_focus_store(focus, sel, sel); } else if (fl->kind == TUI_F_AMOUNT) { if (fl->ore && tui_amount_prompt_into(fl->ore, label, *fl->ore)) - return sel; + return tui_form_focus_store(focus, sel, sel); } else if (fl->kind == TUI_F_CHOICE && fl->choice) { int c = tui_choice_prompt(label, fl->choices, fl->nchoices, *fl->choice); if (c >= 0) { *fl->choice = c; - return sel; + return tui_form_focus_store(focus, sel, sel); } } } } int tui_form_run(const char *title, struct tui_form_field *f, int n, - int can_edit) + int can_edit, int *focus) { - return form_run(title, f, n, can_edit, NULL, 0, NULL, NULL, NULL); + return form_run(title, f, n, can_edit, NULL, 0, NULL, NULL, NULL, focus); } int tui_form_run_hook(const char *title, struct tui_form_field *f, int n, - int can_edit, int (*key)(void *ud, int ch), void *ud) + int can_edit, int (*key)(void *ud, int ch), void *ud, + int *focus) { - return form_run(title, f, n, can_edit, NULL, 0, NULL, key, ud); + return form_run(title, f, n, can_edit, NULL, 0, NULL, key, ud, focus); } int tui_form_run_actions(const char *title, struct tui_form_field *f, int nf, int can_edit, const struct tui_form_action *acts, - int na, const char *hint) + int na, const char *hint, int *focus) { - return form_run(title, f, nf, can_edit, acts, na, hint, NULL, NULL); + return form_run(title, f, nf, can_edit, acts, na, hint, NULL, NULL, focus); } /* ------------------------------------------------------------------ */ diff --git a/clients/tui.h b/clients/tui.h index d0656da..7250c0b 100644 --- a/clients/tui.h +++ b/clients/tui.h @@ -179,11 +179,13 @@ struct tui_form_field { }; 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); + int can_edit, int *focus); void tui_form_hint(const char *hint); /* overrides the footer for the next run */ int tui_form_run_hook(const char *title, struct tui_form_field *f, int n, - int can_edit, int (*key)(void *ud, int ch), void *ud); + int can_edit, int (*key)(void *ud, int ch), void *ud, + int *focus); /* --- action list in a form (tui_form_run_actions) --- */ /* enabled: 1 = selectable and runs; 0 = dimmed but selectable (Enter shows @@ -197,6 +199,15 @@ struct tui_form_action { #define TUI_FORM_ACTION 1000 /* action i is returned as TUI_FORM_ACTION + i */ +/* Focus memory: the screen owns an int and passes its address to + tui_form_run*; on entry *focus is clamped to a selectable row — out of + range snaps to the nearest end and a heading row snaps forward, wrapping + — and on every return the row the form stopped on is written back. + Passing NULL starts at the first focusable row and stores nothing. */ +int tui_form_focus_clamp(int focus, int nf, + const struct tui_form_action *acts, int na); +int tui_form_focus_store(int *focus, int sel, int ret); + /* Focus ring over fields (0..nf-1) and actions (nf..nf+na-1); heading rows are skipped and the ring wraps. dir +1 = Tab/Down, -1 = Shift-Tab/Up. */ int tui_form_act_step(int focus, int nf, const struct tui_form_action *acts, @@ -218,7 +229,7 @@ void tui_form_act_label(const struct tui_form_action *a, char *buf, size_t n); footer; tui_form_hint() still takes precedence. */ int tui_form_run_actions(const char *title, struct tui_form_field *f, int nf, int can_edit, const struct tui_form_action *acts, - int na, const char *hint); + int na, const char *hint, int *focus); /* --- row table --- */ enum { TUI_RT_EDIT = 0, TUI_RT_INFO, TUI_RT_DATE }; |
