Skip to content

Commit 2d96536

Browse files
committed
ui(history): compact short-mode event lines and surface ENC/slot context
1 parent fa7351b commit 2d96536

5 files changed

Lines changed: 161 additions & 12 deletions

File tree

include/dsd-neo/ui/ui_history.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
#pragma once
1515

16+
#include <stddef.h>
17+
1618
#ifdef __cplusplus
1719
extern "C" {
1820
#endif
@@ -26,6 +28,21 @@ void ui_history_set_mode(int mode);
2628
/** @brief Cycle mode Short->Long->Off (mod 3), returning the new mode. */
2729
int ui_history_cycle_mode(void);
2830

31+
/**
32+
* @brief Build display text for event-history lines.
33+
*
34+
* In Short mode, this compacts canonical timestamps from
35+
* `YYYY-MM-DD HH:MM:SS ...` to `HH:MM:SS ...` to reclaim horizontal space.
36+
* Other modes preserve the original string.
37+
*
38+
* @param out Destination buffer.
39+
* @param out_size Destination buffer size in bytes.
40+
* @param event_text Source event string (may be NULL).
41+
* @param mode Event-history mode (normalized internally).
42+
* @return Number of characters written to @p out (excluding NUL).
43+
*/
44+
size_t ui_history_compact_event_text(char* out, size_t out_size, const char* event_text, int mode);
45+
2946
#ifdef __cplusplus
3047
}
3148
#endif

src/ui/terminal/dsd_ncurses_printer.c

Lines changed: 53 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2604,10 +2604,28 @@ ncursesPrinter(dsd_opts* opts, dsd_state* state) {
26042604
attron(COLOR_PAIR(4));
26052605

26062606
if (item->event_string[0] != '\0') {
2607+
char compact_string[2000];
26072608
char text_string[2000];
2608-
memcpy(text_string, item->event_string, (size_t)string_size * sizeof(char));
2609-
text_string[string_size] = 0; //terminate string
2610-
printw("| ");
2609+
ui_history_compact_event_text(compact_string, sizeof compact_string, item->event_string,
2610+
history_mode);
2611+
2612+
const int show_enc_tag = (history_mode == 1 && item->enc != 0);
2613+
const char* line_prefix = show_enc_tag ? "| [ENC] " : "| ";
2614+
const int line_prefix_len = show_enc_tag ? 8 : 2;
2615+
uint16_t line_size = string_size;
2616+
if (history_mode != 2 && cols > 0) {
2617+
int max_text = cols - (line_prefix_len + 2);
2618+
if (max_text < 0) {
2619+
max_text = 0;
2620+
}
2621+
if (max_text < (int)line_size) {
2622+
line_size = (uint16_t)max_text;
2623+
}
2624+
}
2625+
2626+
memcpy(text_string, compact_string, (size_t)line_size * sizeof(char));
2627+
text_string[line_size] = 0; //terminate string
2628+
printw("%s", line_prefix);
26112629
attron(COLOR_PAIR(color_pair)); //this is where the custom color switch occurs for the
26122630
//event_string
26132631
printw("%s\n", text_string);
@@ -2661,13 +2679,13 @@ ncursesPrinter(dsd_opts* opts, dsd_state* state) {
26612679
}
26622680
}
26632681
} else {
2664-
const int prefix_len = 5; // "| S# " (5)
2682+
const int base_prefix_len = 5; // "|[1] " (5)
26652683
uint16_t idx0 = 1;
26662684
uint16_t idx1 = 1;
26672685
uint16_t skip = state->eh_index;
26682686

26692687
if (history_mode != 2 && cols > 0) {
2670-
int max_text = cols - (prefix_len + 2);
2688+
int max_text = cols - (base_prefix_len + 2);
26712689
if (max_text < 0) {
26722690
max_text = 0;
26732691
}
@@ -2737,10 +2755,33 @@ ncursesPrinter(dsd_opts* opts, dsd_state* state) {
27372755
uint8_t color_pair = item->color_pair;
27382756
attron(COLOR_PAIR(4));
27392757

2758+
char compact_string[2000];
27402759
char text_string[2000];
2741-
memcpy(text_string, item->event_string, (size_t)string_size * sizeof(char));
2742-
text_string[string_size] = 0; //terminate string
2743-
printw("| S%d ", slot + 1);
2760+
char line_prefix[16];
2761+
const int show_enc_tag = (history_mode == 1 && item->enc != 0);
2762+
if (show_enc_tag) {
2763+
snprintf(line_prefix, sizeof line_prefix, "|[%d] [ENC] ", slot + 1);
2764+
} else {
2765+
snprintf(line_prefix, sizeof line_prefix, "|[%d] ", slot + 1);
2766+
}
2767+
2768+
ui_history_compact_event_text(compact_string, sizeof compact_string, item->event_string,
2769+
history_mode);
2770+
2771+
uint16_t line_size = string_size;
2772+
if (history_mode != 2 && cols > 0) {
2773+
int max_text = cols - ((int)strlen(line_prefix) + 2);
2774+
if (max_text < 0) {
2775+
max_text = 0;
2776+
}
2777+
if (max_text < (int)line_size) {
2778+
line_size = (uint16_t)max_text;
2779+
}
2780+
}
2781+
2782+
memcpy(text_string, compact_string, (size_t)line_size * sizeof(char));
2783+
text_string[line_size] = 0; //terminate string
2784+
printw("%s", line_prefix);
27442785
attron(COLOR_PAIR(color_pair)); //this is where the custom color switch occurs for the event_string
27452786
printw("%s\n", text_string);
27462787
attron(COLOR_PAIR(4));
@@ -2751,7 +2792,7 @@ ncursesPrinter(dsd_opts* opts, dsd_state* state) {
27512792
break;
27522793
}
27532794
attron(COLOR_PAIR(4)); //feel free to change this to any value you want
2754-
printw("| S%d \\-- %s\n", slot + 1, item->text_message);
2795+
printw("|[%d] \\-- %s\n", slot + 1, item->text_message);
27552796
attron(COLOR_PAIR(4));
27562797
}
27572798

@@ -2761,7 +2802,7 @@ ncursesPrinter(dsd_opts* opts, dsd_state* state) {
27612802
break;
27622803
}
27632804
attron(COLOR_PAIR(4));
2764-
printw("| S%d \\-- Alias: %s \n", slot + 1, item->alias);
2805+
printw("|[%d] \\-- Alias: %s \n", slot + 1, item->alias);
27652806
attron(COLOR_PAIR(4));
27662807
}
27672808

@@ -2771,7 +2812,7 @@ ncursesPrinter(dsd_opts* opts, dsd_state* state) {
27712812
break;
27722813
}
27732814
attron(COLOR_PAIR(4));
2774-
printw("| S%d \\-- GPS: %s \n", slot + 1, item->gps_s);
2815+
printw("|[%d] \\-- GPS: %s \n", slot + 1, item->gps_s);
27752816
attron(COLOR_PAIR(4));
27762817
}
27772818

@@ -2781,7 +2822,7 @@ ncursesPrinter(dsd_opts* opts, dsd_state* state) {
27812822
break;
27822823
}
27832824
attron(COLOR_PAIR(4));
2784-
printw("| S%d \\-- DSD-neo: %s \n", slot + 1, item->internal_str);
2825+
printw("|[%d] \\-- DSD-neo: %s \n", slot + 1, item->internal_str);
27852826
attron(COLOR_PAIR(4));
27862827
}
27872828
}

src/ui/terminal/ui_history.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
* Copyright (C) 2026 by arancormonk <180709949+arancormonk@users.noreply.github.com>
44
*/
55

6+
#include <ctype.h>
67
#include <dsd-neo/platform/atomic_compat.h>
78
#include <dsd-neo/ui/ui_history.h>
9+
#include <string.h>
810

911
static atomic_int g_ui_history_mode = 1;
1012

@@ -17,6 +19,27 @@ ui_history_normalize_mode(int mode) {
1719
return m;
1820
}
1921

22+
static int
23+
ui_history_has_full_datetime_prefix(const char* s) {
24+
if (s == NULL) {
25+
return 0;
26+
}
27+
28+
const size_t min_len = 20; // "YYYY-MM-DD HH:MM:SS "
29+
if (strlen(s) < min_len) {
30+
return 0;
31+
}
32+
33+
// Canonical prefix check produced by watchdog_event_current/datacall.
34+
return isdigit((unsigned char)s[0]) && isdigit((unsigned char)s[1]) && isdigit((unsigned char)s[2])
35+
&& isdigit((unsigned char)s[3]) && s[4] == '-' && isdigit((unsigned char)s[5])
36+
&& isdigit((unsigned char)s[6]) && s[7] == '-' && isdigit((unsigned char)s[8])
37+
&& isdigit((unsigned char)s[9]) && s[10] == ' ' && isdigit((unsigned char)s[11])
38+
&& isdigit((unsigned char)s[12]) && s[13] == ':' && isdigit((unsigned char)s[14])
39+
&& isdigit((unsigned char)s[15]) && s[16] == ':' && isdigit((unsigned char)s[17])
40+
&& isdigit((unsigned char)s[18]) && s[19] == ' ';
41+
}
42+
2043
int
2144
ui_history_get_mode(void) {
2245
return ui_history_normalize_mode(atomic_load(&g_ui_history_mode));
@@ -37,3 +60,23 @@ ui_history_cycle_mode(void) {
3760
}
3861
}
3962
}
63+
64+
size_t
65+
ui_history_compact_event_text(char* out, size_t out_size, const char* event_text, int mode) {
66+
if (out == NULL || out_size == 0) {
67+
return 0;
68+
}
69+
70+
const char* src = event_text ? event_text : "";
71+
if (ui_history_normalize_mode(mode) == 1 && ui_history_has_full_datetime_prefix(src)) {
72+
src += 11; // drop "YYYY-MM-DD " while keeping time and payload
73+
}
74+
75+
size_t n = strlen(src);
76+
if (n >= out_size) {
77+
n = out_size - 1;
78+
}
79+
memcpy(out, src, n);
80+
out[n] = '\0';
81+
return n;
82+
}

tests/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,13 @@ target_include_directories(dsd-neo_test_ui_history_state PRIVATE ${PROJECT_SOURC
325325
target_link_libraries(dsd-neo_test_ui_history_state PRIVATE dsd-neo_platform)
326326
add_test(NAME UI_HISTORY_STATE COMMAND dsd-neo_test_ui_history_state)
327327

328+
add_executable(dsd-neo_test_ui_history_compact
329+
ui/test_ui_history_compact.c
330+
${PROJECT_SOURCE_DIR}/src/ui/terminal/ui_history.c)
331+
target_include_directories(dsd-neo_test_ui_history_compact PRIVATE ${PROJECT_SOURCE_DIR}/include)
332+
target_link_libraries(dsd-neo_test_ui_history_compact PRIVATE dsd-neo_platform)
333+
add_test(NAME UI_HISTORY_COMPACT COMMAND dsd-neo_test_ui_history_compact)
334+
328335
add_executable(dsd-neo_test_ui_snapshot_event_history
329336
ui/test_ui_snapshot_event_history.c
330337
${PROJECT_SOURCE_DIR}/src/ui/terminal/ui_snapshot.c)

tests/ui/test_ui_history_compact.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// SPDX-License-Identifier: GPL-3.0-or-later
2+
/*
3+
* Copyright (C) 2026 by arancormonk <180709949+arancormonk@users.noreply.github.com>
4+
*/
5+
6+
#include <assert.h>
7+
#include <stdio.h>
8+
#include <string.h>
9+
10+
#include <dsd-neo/ui/ui_history.h>
11+
12+
int
13+
main(void) {
14+
char out[256];
15+
16+
const char* canonical = "2026-01-21 02:05:13 DMR TGT: 00000014; SRC: 00300010; CC: 01; Group; TXI;";
17+
size_t n = ui_history_compact_event_text(out, sizeof out, canonical, 1);
18+
assert(n == strlen(out));
19+
assert(strcmp(out, "02:05:13 DMR TGT: 00000014; SRC: 00300010; CC: 01; Group; TXI;") == 0);
20+
21+
n = ui_history_compact_event_text(out, sizeof out, canonical, 2);
22+
assert(n == strlen(out));
23+
assert(strcmp(out, canonical) == 0);
24+
25+
const char* noncanonical = "DMR TGT: 00000014; SRC: 00300010; CC: 01;";
26+
n = ui_history_compact_event_text(out, sizeof out, noncanonical, 1);
27+
assert(n == strlen(out));
28+
assert(strcmp(out, noncanonical) == 0);
29+
30+
n = ui_history_compact_event_text(out, sizeof out, NULL, 1);
31+
assert(n == 0);
32+
assert(out[0] == '\0');
33+
34+
char tiny[5];
35+
n = ui_history_compact_event_text(tiny, sizeof tiny, canonical, 1);
36+
assert(n == 4);
37+
assert(strcmp(tiny, "02:0") == 0);
38+
39+
printf("UI_HISTORY_COMPACT: OK\n");
40+
return 0;
41+
}

0 commit comments

Comments
 (0)