summaryrefslogtreecommitdiff
path: root/clients/vlist.c
diff options
context:
space:
mode:
authorAnders Betts <anders.betts@gmail.com>2026-09-23 09:13:17 +0200
committerAnders Betts <anders.betts@gmail.com>2026-09-23 09:13:17 +0200
commit53071bb69f5d21b35b8a61c2b1dd18832ce781d4 (patch)
treefa76c13cef78925d1b9650e92f64d5115dcdb6e7 /clients/vlist.c
parent2ca284619125af0d5c12e9210ff1bfc8f9122739 (diff)
downloadbokf-53071bb69f5d21b35b8a61c2b1dd18832ce781d4.tar.gz
bokf-53071bb69f5d21b35b8a61c2b1dd18832ce781d4.zip
tui: aligned voucher detail, up/down between vouchers, list sorting
The detail pads every column by display width, blanks zero amounts and shows row texts and a Summa line. Up/Down step to the previous/next voucher in the list order; 's' cycles the list sort (number or date, ascending or descending, saved in tui.conf). The list fetches all pages of voucher.list instead of stopping at 200. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'clients/vlist.c')
-rw-r--r--clients/vlist.c84
1 files changed, 84 insertions, 0 deletions
diff --git a/clients/vlist.c b/clients/vlist.c
new file mode 100644
index 0000000..933b704
--- /dev/null
+++ b/clients/vlist.c
@@ -0,0 +1,84 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "vlist.h"
+
+static const char *const SORT_NAMES[VSORT_COUNT] = {
+ "number", "number-desc", "date", "date-desc",
+};
+
+static const char *const SORT_LABELS[VSORT_COUNT] = {
+ "nummer, stigande", "nummer, fallande", "datum, stigande",
+ "datum, fallande",
+};
+
+static int cmp_i64(int64_t a, int64_t b)
+{
+ return a < b ? -1 : a > b;
+}
+
+static int cmp_number(const struct vlist_item *a, const struct vlist_item *b)
+{
+ int c = strcmp(a->series, b->series);
+ if (c)
+ return c;
+ return cmp_i64(a->number, b->number);
+}
+
+static int g_mode; /* qsort has no context argument in C11 */
+
+static int cmp_items(const void *pa, const void *pb)
+{
+ const struct vlist_item *a = pa, *b = pb;
+ int desc = g_mode == VSORT_NUMBER_DESC || g_mode == VSORT_DATE_DESC;
+ int c = 0;
+ if (g_mode == VSORT_DATE || g_mode == VSORT_DATE_DESC)
+ c = strcmp(a->date, b->date);
+ if (!c)
+ c = cmp_number(a, b);
+ if (!c)
+ c = cmp_i64(a->id, b->id);
+ return desc ? -c : c;
+}
+
+void vlist_sort(struct vlist_item *v, size_t n, int mode)
+{
+ if (!v || n < 2)
+ return;
+ g_mode = mode >= 0 && mode < VSORT_COUNT ? mode : VSORT_NUMBER;
+ qsort(v, n, sizeof *v, cmp_items);
+}
+
+const char *vlist_sort_label(int mode)
+{
+ return SORT_LABELS[mode >= 0 && mode < VSORT_COUNT ? mode : 0];
+}
+
+const char *vlist_sort_name(int mode)
+{
+ return SORT_NAMES[mode >= 0 && mode < VSORT_COUNT ? mode : 0];
+}
+
+int vlist_sort_parse(const char *name)
+{
+ for (int i = 0; name && i < VSORT_COUNT; i++)
+ if (strcmp(name, SORT_NAMES[i]) == 0)
+ return i;
+ return VSORT_NUMBER;
+}
+
+int vlist_index(const struct vlist_item *v, size_t n, int64_t id)
+{
+ for (size_t i = 0; i < n; i++)
+ if (v[i].id == id)
+ return (int)i;
+ return -1;
+}
+
+int vlist_step(size_t n, int idx, int dir)
+{
+ if (idx < 0 || (size_t)idx >= n)
+ return -1;
+ int next = idx + (dir < 0 ? -1 : 1);
+ return next >= 0 && (size_t)next < n ? next : -1;
+}