From 6b1697412e7dea42f87ac6de506628112cb53307 Mon Sep 17 00:00:00 2001 From: Jacob Komissar Date: Fri, 26 Sep 2025 17:09:40 -0400 Subject: [PATCH 01/12] Add option to display alternate characters in tiling mode --- src/config.c | 3 +- src/config.h | 1 + src/label.c | 170 +++++++++++++++++++++++++++++++++++------------ src/label.h | 20 ++++-- src/mode_tile.c | 6 +- src/test_label.c | 34 +++++++++- 6 files changed, 180 insertions(+), 54 deletions(-) diff --git a/src/config.c b/src/config.c index 0c02ea1..f145a9f 100644 --- a/src/config.c +++ b/src/config.c @@ -372,7 +372,8 @@ static struct section_def section_defs[] = { MT_FIELD(label_font_size, "8 50% 100", parse_relative_font_size, noop), MT_FIELD( label_symbols, "abcdefghijklmnopqrstuvwxyz", parse_str, free_str - ) + ), + MT_FIELD(label_display, "", parse_str, free_str) ), SECTION( mode_floating, diff --git a/src/config.h b/src/config.h index 1b9c7d0..7bc37a4 100644 --- a/src/config.h +++ b/src/config.h @@ -26,6 +26,7 @@ struct mode_tile_config { char *label_font_family; struct relative_font_size label_font_size; char *label_symbols; + char *label_display; }; enum floating_mode_source { diff --git a/src/label.c b/src/label.c index 26dc9f3..fbf77b0 100644 --- a/src/label.c +++ b/src/label.c @@ -7,46 +7,52 @@ #include #include -label_symbols_t *label_symbols_from_str(char *s) { +// Measure the length and number of symbols in s. +// Output is written to len and num_symbols. +// Returns true for errors. +static bool measure_label_symbols(char *s, int *len, int *num_symbols) { char *c = s; uint32_t r; int c_len; - int len = sizeof(label_symbols_t); - int num_symbols = 0; - while ((c_len = str_to_rune(c, &r)) > 0) { // One byte for the indices and one of the end of string (`\0`). - c += c_len; - len += c_len + 2; - num_symbols += 1; + c += c_len; + *len += c_len + 2; + *num_symbols += 1; } if (c_len < 0) { LOG_ERR("Invalid UTF-8 input."); - return NULL; + return true; } - if (num_symbols < 2) { + if (*num_symbols < 2) { LOG_ERR( - "Not enough characters (%d). Must have at least 2.", num_symbols + "Not enough characters (%d). Must have at least 2.", *num_symbols ); - return NULL; + return true; } - if (num_symbols >= 255) { - LOG_ERR("Too many characters (%d).", num_symbols); - return NULL; + if (*num_symbols >= 255) { + LOG_ERR("Too many characters (%d).", *num_symbols); + return true; } - label_symbols_t *label_symbols = malloc(len); + return false; +} + +// Given a label symbol string and number of symbols, populate the +// provided data array as label_symbols_t.data. +static void fill_label_symbols_data(char *s, int num_symbols, char *data) { + unsigned char *indices = (unsigned char *)data; + char *str = &data[num_symbols]; - label_symbols->num_symbols = num_symbols; - unsigned char *indices = (unsigned char *)label_symbols->data; - char *str = &label_symbols->data[num_symbols]; + uint32_t r; + int c_len; - c = s; + char *c = s; int str_offset = 0; for (int i = 0; i < num_symbols; i++) { c_len = str_to_rune(c, &r); @@ -57,11 +63,54 @@ label_symbols_t *label_symbols_from_str(char *s) { str_offset += c_len + 1; c += c_len; } +} + +label_symbols_t *label_symbols_from_str(char *s) { + return label_symbols_from_strs(s, s); +} + +label_symbols_t *label_symbols_from_strs(char *s, char *display_s) { + int len = sizeof(label_symbols_t); + int num_symbols = 0; + + if (measure_label_symbols(s, &len, &num_symbols)) { + return NULL; + } + + label_symbols_t *label_symbols = malloc(len); + + label_symbols->num_symbols = num_symbols; + label_symbols->display_data = NULL; + + fill_label_symbols_data(s, num_symbols, label_symbols->data); + + if (s == display_s || display_s[0] == '\0' || strcmp(s, display_s) == 0) { + label_symbols->display_data = label_symbols->data; + } else { + int disp_len = 0; + int num_display = 0; + + if (measure_label_symbols(display_s, &disp_len, &num_display)) { + return NULL; + } + + if (num_display != num_symbols) { + LOG_ERR("Label display symbols must be empty or same length as label symbols."); + return NULL; + } + + label_symbols->display_data = malloc(disp_len); + + fill_label_symbols_data(display_s, num_display, label_symbols->display_data); + } return label_symbols; } void label_symbols_free(label_symbols_t *ls) { + if (ls != NULL && ls->display_data != ls->data) { + free(ls->display_data); + } free(ls); } @@ -75,6 +124,16 @@ char *label_symbols_idx_to_ptr(label_symbols_t *label_symbols, int idx) { ((unsigned char *)label_symbols->data)[idx]; } +char *label_symbols_idx_to_display_ptr(label_symbols_t *label_symbols, int idx) { + if (idx < 0 || idx >= label_symbols->num_symbols) { + LOG_ERR("Label symbols index (%d) out of bound.", idx); + return NULL; + } + + return label_symbols->display_data + label_symbols->num_symbols + + ((unsigned char *)label_symbols->display_data)[idx]; +} + int label_symbols_find_idx(label_symbols_t *label_symbols, char *s) { for (int i = 0; i < label_symbols->num_symbols; i++) { if (strcmp(label_symbols_idx_to_ptr(label_symbols, i), s) == 0) { @@ -106,6 +165,7 @@ void label_selection_clear(label_selection_t *label_selection) { label_selection->next = 0; } +// Convert label selection to 1-dimensional index static int label_selection_to_partial_idx(label_selection_t *label_selection) { int idx = 0; int factor = 1; @@ -170,6 +230,7 @@ int label_selection_to_idx(label_selection_t *label_selection) { return label_selection_to_partial_idx(label_selection); } +// Fill a label selection's input array to correspond to the given index int label_selection_set_from_idx(label_selection_t *label_selection, int idx) { int num_symbols = label_selection->label_symbols->num_symbols; @@ -199,25 +260,48 @@ int label_selection_incr(label_selection_t *label_selection) { return 0; } -static int label_symbols_max_str_len(label_symbols_t *label_symbols) { - unsigned char *indices = (unsigned char *)label_symbols->data; - int i; - - int max_len = 0; +// Given an array of the start indices of the elements of a +// contiguous, heterogenous array, return the length of the longest +// element, excluding the last. The length of the last may be provided +// separately. +static int index_array_max_len( + unsigned char *indices, int num_symbols, int last_len +) { + int max_len = last_len; int curr_len = 0; - for (i = 1; i < label_symbols->num_symbols; i++) { + for (int i = 1; i < num_symbols; i++) { + // Compute length of symbol at index i - 1 curr_len = indices[i] - indices[i - 1] - 1; if (curr_len > max_len) { max_len = curr_len; } } - curr_len = strlen( - label_symbols_idx_to_ptr(label_symbols, label_symbols->num_symbols - 1) + return max_len; +} + +// Gets max str len for both symbols and display symbols +static int label_symbols_max_str_len(label_symbols_t *label_symbols) { + int num_symbols = label_symbols->num_symbols; + + int max_len = index_array_max_len( + (unsigned char *)label_symbols->data, + num_symbols, + strlen(label_symbols_idx_to_ptr(label_symbols, num_symbols - 1)) ); - if (curr_len > max_len) { - max_len = curr_len; + + // Measure display symbols as well, if they are present + if (label_symbols->display_data != label_symbols->data) { + int max_disp_len = index_array_max_len( + (unsigned char *)label_symbols->display_data, + num_symbols, + strlen(label_symbols_idx_to_display_ptr(label_symbols, num_symbols - 1)) + ); + + if (max_disp_len > max_len) { + max_len = max_disp_len; + } } return max_len; @@ -228,13 +312,20 @@ int label_selection_str_max_len(label_selection_t *label_selection) { label_selection->len; } -void label_selection_str(label_selection_t *label_selection, char *out) { - label_symbols_t *label_symbols = label_selection->label_symbols; - for (int i = 0; i < label_selection->next; i++) { - out = stpcpy( +static char *label_selection_stpcpy_idx( + char *out, label_selection_t *label_selection, int i +) { + return stpcpy( out, - label_symbols_idx_to_ptr(label_symbols, label_selection->input[i]) + label_symbols_idx_to_display_ptr( + label_selection->label_symbols, label_selection->input[i] + ) ); +} + +void label_selection_str(label_selection_t *label_selection, char *out) { + for (int i = 0; i < label_selection->next; i++) { + out = label_selection_stpcpy_idx(out, label_selection, i); } *out = '\0'; @@ -249,20 +340,13 @@ void label_selection_str_split( cut = label_selection->next; } - label_symbols_t *label_symbols = label_selection->label_symbols; for (int i = 0; i < cut; i++) { - prefix = stpcpy( - prefix, - label_symbols_idx_to_ptr(label_symbols, label_selection->input[i]) - ); + prefix = label_selection_stpcpy_idx(prefix, label_selection, i); } *prefix = '\0'; for (int i = cut; i < label_selection->next; i++) { - suffix = stpcpy( - suffix, - label_symbols_idx_to_ptr(label_symbols, label_selection->input[i]) - ); + suffix = label_selection_stpcpy_idx(suffix, label_selection, i); } *suffix = '\0'; } diff --git a/src/label.h b/src/label.h index 676eb29..4d2b74b 100644 --- a/src/label.h +++ b/src/label.h @@ -4,15 +4,18 @@ #include typedef struct { - /* data data[num_symbols] - * | | - * | 4 || 0 | 2 | 4 | 6 ||`a`| 0 |`b`| 0 |`c`| 0 |`d`| 0 | - * ^ ^-----------^ ^---------------------------^ - * | offsets strings - * | + /* data data[num_symbols] + * | | + * | 4 ||xxxx|| 0 | 2 | 4 | 6 ||`a`| 0 |`b`| 0 |`c`| 0 |`d`| 0 | + * ^ ^ ^-----------^ ^---------------------------^ + * | | offsets strings + * | pointer to display data * number of symbols + * + * The display data is identical in structure to the data. */ unsigned char num_symbols; + char *display_data; char data[]; } label_symbols_t; @@ -27,6 +30,11 @@ typedef struct { // Create a `label_symbols_t` from a string of characters. // Returns `NULL` upon error. label_symbols_t *label_symbols_from_str(char *s); +// Create a `label_symbols_t` from a string of key characters and a +// possibly-empty string of label characters. +// Returns `NULL` upon error. +label_symbols_t *label_symbols_from_strs(char *s, char *display_s); + // Free memory of a `label_symbols_t`. void label_symbols_free(label_symbols_t *ls); diff --git a/src/mode_tile.c b/src/mode_tile.c index 2e3af52..6a144bf 100644 --- a/src/mode_tile.c +++ b/src/mode_tile.c @@ -38,8 +38,10 @@ void *tile_mode_enter(struct state *state, struct rect area) { ms->sub_area_width_off = ms->area.w % ms->sub_area_columns; ms->sub_area_width = ms->area.w / ms->sub_area_columns; - ms->label_symbols = - label_symbols_from_str(state->config.mode_tile.label_symbols); + ms->label_symbols = label_symbols_from_strs( + state->config.mode_tile.label_symbols, + state->config.mode_tile.label_display + ); if (ms->label_symbols == NULL) { ms->label_selection = NULL; state->running = false; diff --git a/src/test_label.c b/src/test_label.c index 401b1e5..404633b 100644 --- a/src/test_label.c +++ b/src/test_label.c @@ -5,8 +5,8 @@ int main() { label_symbols_t *label_symbols = label_symbols_from_str("abcdé"); - if (!label_symbols) { - LOG_ERR("`label_symbolss_from_str` should not have returned null."); + if (label_symbols == NULL) { + LOG_ERR("`label_symbols_from_str` should not have returned null."); return 1; } @@ -136,6 +136,36 @@ int main() { } } + // These have the same number of code points and different byte lenths. + label_symbols_t *display = label_symbols_from_strs("abcde", "ABCDÉ"); + label_symbols_t *display2 = label_symbols_from_strs("abcdé", "ABCDE"); + if (display == NULL || display2 == NULL) { + LOG_ERR("`label_symbols_from_strs` should not have returned null."); + return 15; + } + label_symbols_free(display2); + + LOG_WARN("A 'Label display symbols must be empty...' error is expected below."); + label_symbols_t *display3 = label_symbols_from_strs("abcd", "abcde"); + if (display3 != NULL) { + LOG_ERR("`label_symbols_from_strs` should return null for different-length strings."); + return 16; + } + label_symbols_free(display3); + + // Make sure the unicode measured in the second string + label_selection_t *display_selection = + label_selection_new(display, 100); + int display_selection_buf_size = + label_selection_str_max_len(display_selection) + 1; + if (display_selection_buf_size != 7) { + LOG_ERR( + "Wrong label_selection_str_buffer_size = %d", + display_selection_buf_size + ); + return 17; + } + label_selection_free(label_selection); label_symbols_free(label_symbols); return 0; From 8fbdd9cbcad417ac4a3b1bb565766be221f8df2a Mon Sep 17 00:00:00 2001 From: Jacob Komissar Date: Fri, 26 Sep 2025 17:20:51 -0400 Subject: [PATCH 02/12] Make label_symbols_from_strs less repetitive --- src/label.c | 53 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/src/label.c b/src/label.c index fbf77b0..538de77 100644 --- a/src/label.c +++ b/src/label.c @@ -69,39 +69,50 @@ label_symbols_t *label_symbols_from_str(char *s) { return label_symbols_from_strs(s, s); } -label_symbols_t *label_symbols_from_strs(char *s, char *display_s) { - int len = sizeof(label_symbols_t); - int num_symbols = 0; - +// Set up label symbols from source string. Return NULL for errors. +// If label_symbols is NULL, allocate one. Else, only fill its display_data. +static label_symbols_t *label_symbols_init( + char *s, label_symbols_t *label_symbols +) { + int num_symbols = 0; + int len = 0; if (measure_label_symbols(s, &len, &num_symbols)) { return NULL; } - label_symbols_t *label_symbols = malloc(len); + char *data; - label_symbols->num_symbols = num_symbols; - label_symbols->display_data = NULL; + if (label_symbols == NULL) { + label_symbols = malloc(len + sizeof(label_symbols_t)); + label_symbols->num_symbols = num_symbols; + label_symbols->display_data = NULL; + data = label_symbols->data; + } else { + data = label_symbols->display_data = malloc(len); + if (num_symbols != label_symbols->num_symbols) { + LOG_ERR("Label display symbols must be empty or same length as label symbols."); + return NULL; + } + } - fill_label_symbols_data(s, num_symbols, label_symbols->data); + fill_label_symbols_data(s, num_symbols, data); + return label_symbols; +} + +label_symbols_t *label_symbols_from_strs(char *s, char *display_s) { + label_symbols_t *label_symbols = label_symbols_init(s, NULL); + if (label_symbols == NULL) { + return NULL; + } if (s == display_s || display_s[0] == '\0' || strcmp(s, display_s) == 0) { + // When possible, don't use a second array. label_symbols->display_data = label_symbols->data; } else { - int disp_len = 0; - int num_display = 0; - - if (measure_label_symbols(display_s, &disp_len, &num_display)) { - return NULL; - } - - if (num_display != num_symbols) { - LOG_ERR("Label display symbols must be empty or same length as label symbols."); + void *result = label_symbols_init(display_s, label_symbols); + if (result == NULL) { return NULL; } - - label_symbols->display_data = malloc(disp_len); - - fill_label_symbols_data(display_s, num_display, label_symbols->display_data); } return label_symbols; From ececb0847346d62816a860f98a074416f1a9fc31 Mon Sep 17 00:00:00 2001 From: Jacob Komissar Date: Fri, 26 Sep 2025 19:47:43 -0400 Subject: [PATCH 03/12] Free label symbols after failure to initialize --- src/label.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/label.c b/src/label.c index 538de77..ddf1b12 100644 --- a/src/label.c +++ b/src/label.c @@ -111,6 +111,7 @@ label_symbols_t *label_symbols_from_strs(char *s, char *display_s) { } else { void *result = label_symbols_init(display_s, label_symbols); if (result == NULL) { + label_symbols_free(label_symbols); return NULL; } } From 8d870b232ce23605b092fcda71910cb68c4a6a56 Mon Sep 17 00:00:00 2001 From: Jacob Komissar Date: Fri, 26 Sep 2025 20:07:55 -0400 Subject: [PATCH 04/12] Rename label_symbols_find_idx to label_symbols_find_key_idx --- src/label.c | 2 +- src/label.h | 4 ++-- src/mode_floating.c | 2 +- src/mode_tile.c | 2 +- src/test_label.c | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/label.c b/src/label.c index ddf1b12..86d6d59 100644 --- a/src/label.c +++ b/src/label.c @@ -146,7 +146,7 @@ char *label_symbols_idx_to_display_ptr(label_symbols_t *label_symbols, int idx) ((unsigned char *)label_symbols->display_data)[idx]; } -int label_symbols_find_idx(label_symbols_t *label_symbols, char *s) { +int label_symbols_find_key_idx(label_symbols_t *label_symbols, char *s) { for (int i = 0; i < label_symbols->num_symbols; i++) { if (strcmp(label_symbols_idx_to_ptr(label_symbols, i), s) == 0) { return i; diff --git a/src/label.h b/src/label.h index 4d2b74b..f4109fb 100644 --- a/src/label.h +++ b/src/label.h @@ -43,9 +43,9 @@ void label_symbols_free(label_symbols_t *ls); // Returns value <0 upon error. char *label_symbols_idx_to_ptr(label_symbols_t *label_symbols, int idx); -// Find symbol index from given string. +// Find key index from given string. // Returns value <0 upon error. -int label_symbols_find_idx(label_symbols_t *label_symbols, char *s); +int label_symbols_find_key_idx(label_symbols_t *label_symbols, char *s); // Create a `label_selection_t`. label_selection_t * diff --git a/src/mode_floating.c b/src/mode_floating.c index 4d927d0..d62b0a1 100644 --- a/src/mode_floating.c +++ b/src/mode_floating.c @@ -131,7 +131,7 @@ static bool floating_mode_key( state->running = false; break; default:; - int symbol_idx = label_symbols_find_idx(ms->label_symbols, text); + int symbol_idx = label_symbols_find_key_idx(ms->label_symbols, text); if (symbol_idx < 0) { return false; } diff --git a/src/mode_tile.c b/src/mode_tile.c index 6a144bf..589b70c 100644 --- a/src/mode_tile.c +++ b/src/mode_tile.c @@ -104,7 +104,7 @@ static bool tile_mode_key( state->running = false; break; default:; - int symbol_idx = label_symbols_find_idx(ms->label_symbols, text); + int symbol_idx = label_symbols_find_key_idx(ms->label_symbols, text); if (symbol_idx < 0) { return false; } diff --git a/src/test_label.c b/src/test_label.c index 404633b..a3e3f89 100644 --- a/src/test_label.c +++ b/src/test_label.c @@ -27,7 +27,7 @@ int main() { }; for (int i = 0; i < sizeof(symbols) / sizeof(symbols[0]); i++) { - int symbol_idx = label_symbols_find_idx(label_symbols, symbols[i]); + int symbol_idx = label_symbols_find_key_idx(label_symbols, symbols[i]); if (symbol_idx != i) { LOG_ERR( "Wrong index %d (expected %d) for symbol '%s'", symbol_idx, i, @@ -126,7 +126,7 @@ int main() { for (int i = 0; i < 9; i++) { int symbol_idx = - label_symbols_find_idx(alt_label_symbols, alt_symbols[i]); + label_symbols_find_key_idx(alt_label_symbols, alt_symbols[i]); if (symbol_idx != i) { LOG_ERR( "Wrong index %d (expected %d) for symbol '%s'", symbol_idx, i, From c303ef7b89e1dfa761a5b9f0e871fc8568076d17 Mon Sep 17 00:00:00 2001 From: Jacob Komissar Date: Fri, 26 Sep 2025 20:05:34 -0400 Subject: [PATCH 05/12] Make label_symbols_max_str_len only consider symbols, not keys This fails tests because we still use the field now called key_data to store display data. --- src/label.c | 42 ++++++++---------------------------------- 1 file changed, 8 insertions(+), 34 deletions(-) diff --git a/src/label.c b/src/label.c index 86d6d59..0286b54 100644 --- a/src/label.c +++ b/src/label.c @@ -272,15 +272,15 @@ int label_selection_incr(label_selection_t *label_selection) { return 0; } -// Given an array of the start indices of the elements of a -// contiguous, heterogenous array, return the length of the longest -// element, excluding the last. The length of the last may be provided -// separately. -static int index_array_max_len( - unsigned char *indices, int num_symbols, int last_len -) { - int max_len = last_len; +// Max string length for a single symbol in a label +static int label_symbols_max_str_len(label_symbols_t *label_symbols) { + int num_symbols = label_symbols->num_symbols; + unsigned char *indices = (unsigned char *)label_symbols->data; + int curr_len = 0; + int max_len = strlen( + label_symbols_idx_to_display_ptr(label_symbols, num_symbols - 1) + ); for (int i = 1; i < num_symbols; i++) { // Compute length of symbol at index i - 1 @@ -293,32 +293,6 @@ static int index_array_max_len( return max_len; } -// Gets max str len for both symbols and display symbols -static int label_symbols_max_str_len(label_symbols_t *label_symbols) { - int num_symbols = label_symbols->num_symbols; - - int max_len = index_array_max_len( - (unsigned char *)label_symbols->data, - num_symbols, - strlen(label_symbols_idx_to_ptr(label_symbols, num_symbols - 1)) - ); - - // Measure display symbols as well, if they are present - if (label_symbols->display_data != label_symbols->data) { - int max_disp_len = index_array_max_len( - (unsigned char *)label_symbols->display_data, - num_symbols, - strlen(label_symbols_idx_to_display_ptr(label_symbols, num_symbols - 1)) - ); - - if (max_disp_len > max_len) { - max_len = max_disp_len; - } - } - - return max_len; -} - int label_selection_str_max_len(label_selection_t *label_selection) { return label_symbols_max_str_len(label_selection->label_symbols) * label_selection->len; From 3e06a9abad374e9cf036ed5a4290f2e896dc7ea0 Mon Sep 17 00:00:00 2001 From: Jacob Komissar Date: Fri, 26 Sep 2025 20:33:01 -0400 Subject: [PATCH 06/12] Rename label_symbols_idx_to_ptr to label_symbols_idx_to_key_ptr --- src/label.c | 4 ++-- src/label.h | 4 ++-- src/test_label.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/label.c b/src/label.c index 0286b54..a1797ad 100644 --- a/src/label.c +++ b/src/label.c @@ -126,7 +126,7 @@ void label_symbols_free(label_symbols_t *ls) { free(ls); } -char *label_symbols_idx_to_ptr(label_symbols_t *label_symbols, int idx) { +char *label_symbols_idx_to_key_ptr(label_symbols_t *label_symbols, int idx) { if (idx < 0 || idx >= label_symbols->num_symbols) { LOG_ERR("Label symbols index (%d) out of bound.", idx); return NULL; @@ -148,7 +148,7 @@ char *label_symbols_idx_to_display_ptr(label_symbols_t *label_symbols, int idx) int label_symbols_find_key_idx(label_symbols_t *label_symbols, char *s) { for (int i = 0; i < label_symbols->num_symbols; i++) { - if (strcmp(label_symbols_idx_to_ptr(label_symbols, i), s) == 0) { + if (strcmp(label_symbols_idx_to_key_ptr(label_symbols, i), s) == 0) { return i; } } diff --git a/src/label.h b/src/label.h index f4109fb..26d56ef 100644 --- a/src/label.h +++ b/src/label.h @@ -39,9 +39,9 @@ label_symbols_t *label_symbols_from_strs(char *s, char *display_s); // Free memory of a `label_symbols_t`. void label_symbols_free(label_symbols_t *ls); -// Get pointer to string of the symbol at given index. +// Get pointer to string of the key at given index. // Returns value <0 upon error. -char *label_symbols_idx_to_ptr(label_symbols_t *label_symbols, int idx); +char *label_symbols_idx_to_key_ptr(label_symbols_t *label_symbols, int idx); // Find key index from given string. // Returns value <0 upon error. diff --git a/src/test_label.c b/src/test_label.c index a3e3f89..bd14e55 100644 --- a/src/test_label.c +++ b/src/test_label.c @@ -15,7 +15,7 @@ int main() { return 2; } - char *s = label_symbols_idx_to_ptr(label_symbols, 0); + char *s = label_symbols_idx_to_key_ptr(label_symbols, 0); if (strcmp(s, "a")) { LOG_ERR("No match"); LOG_ERR("Given string: '%s'", s); From b9f54ad1a0b5259a9d76995801dff5d101b69357 Mon Sep 17 00:00:00 2001 From: Jacob Komissar Date: Fri, 26 Sep 2025 20:55:22 -0400 Subject: [PATCH 07/12] [1/3] Swap the roles of the arguments to label_symbols_from_strs --- src/label.c | 10 +++++++--- src/test_label.c | 4 ++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/label.c b/src/label.c index a1797ad..52ea854 100644 --- a/src/label.c +++ b/src/label.c @@ -100,16 +100,20 @@ static label_symbols_t *label_symbols_init( } label_symbols_t *label_symbols_from_strs(char *s, char *display_s) { - label_symbols_t *label_symbols = label_symbols_init(s, NULL); + if (display_s[0] == '\0') { + display_s = s; + } + + label_symbols_t *label_symbols = label_symbols_init(display_s, NULL); if (label_symbols == NULL) { return NULL; } - if (s == display_s || display_s[0] == '\0' || strcmp(s, display_s) == 0) { + if (s == display_s || strcmp(s, display_s) == 0) { // When possible, don't use a second array. label_symbols->display_data = label_symbols->data; } else { - void *result = label_symbols_init(display_s, label_symbols); + void *result = label_symbols_init(s, label_symbols); if (result == NULL) { label_symbols_free(label_symbols); return NULL; diff --git a/src/test_label.c b/src/test_label.c index bd14e55..687e0f3 100644 --- a/src/test_label.c +++ b/src/test_label.c @@ -137,8 +137,8 @@ int main() { } // These have the same number of code points and different byte lenths. - label_symbols_t *display = label_symbols_from_strs("abcde", "ABCDÉ"); - label_symbols_t *display2 = label_symbols_from_strs("abcdé", "ABCDE"); + label_symbols_t *display = label_symbols_from_strs("ABCDÉ", "abcde"); + label_symbols_t *display2 = label_symbols_from_strs("ABCDE", "abcdé"); if (display == NULL || display2 == NULL) { LOG_ERR("`label_symbols_from_strs` should not have returned null."); return 15; From d352a9ceb5fa4ed5d251717dcf8e04abf0dc0ce3 Mon Sep 17 00:00:00 2001 From: Jacob Komissar Date: Fri, 26 Sep 2025 20:56:38 -0400 Subject: [PATCH 08/12] [2/3] Update names and comments to match swapped parameters --- src/label.c | 12 ++++++------ src/label.h | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/label.c b/src/label.c index 52ea854..92a8123 100644 --- a/src/label.c +++ b/src/label.c @@ -99,21 +99,21 @@ static label_symbols_t *label_symbols_init( return label_symbols; } -label_symbols_t *label_symbols_from_strs(char *s, char *display_s) { - if (display_s[0] == '\0') { - display_s = s; +label_symbols_t *label_symbols_from_strs(char *symbols, char *keys) { + if (keys[0] == '\0') { + keys = symbols; } - label_symbols_t *label_symbols = label_symbols_init(display_s, NULL); + label_symbols_t *label_symbols = label_symbols_init(keys, NULL); if (label_symbols == NULL) { return NULL; } - if (s == display_s || strcmp(s, display_s) == 0) { + if (symbols == keys || strcmp(symbols, keys) == 0) { // When possible, don't use a second array. label_symbols->display_data = label_symbols->data; } else { - void *result = label_symbols_init(s, label_symbols); + void *result = label_symbols_init(symbols, label_symbols); if (result == NULL) { label_symbols_free(label_symbols); return NULL; diff --git a/src/label.h b/src/label.h index 26d56ef..a4f20ae 100644 --- a/src/label.h +++ b/src/label.h @@ -30,10 +30,10 @@ typedef struct { // Create a `label_symbols_t` from a string of characters. // Returns `NULL` upon error. label_symbols_t *label_symbols_from_str(char *s); -// Create a `label_symbols_t` from a string of key characters and a -// possibly-empty string of label characters. +// Create a `label_symbols_t` from a string of label characters and a +// possibly-empty string of key characters. // Returns `NULL` upon error. -label_symbols_t *label_symbols_from_strs(char *s, char *display_s); +label_symbols_t *label_symbols_from_strs(char *symbols, char *keys); // Free memory of a `label_symbols_t`. From fe1fb212cfb97538f9ad8ad735b49b7e78e73e9f Mon Sep 17 00:00:00 2001 From: Jacob Komissar Date: Fri, 26 Sep 2025 20:58:34 -0400 Subject: [PATCH 09/12] [3/3] Update config option name to match swapped parameters --- src/config.c | 2 +- src/config.h | 2 +- src/mode_tile.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/config.c b/src/config.c index f145a9f..460df37 100644 --- a/src/config.c +++ b/src/config.c @@ -373,7 +373,7 @@ static struct section_def section_defs[] = { MT_FIELD( label_symbols, "abcdefghijklmnopqrstuvwxyz", parse_str, free_str ), - MT_FIELD(label_display, "", parse_str, free_str) + MT_FIELD(keys, "", parse_str, free_str) ), SECTION( mode_floating, diff --git a/src/config.h b/src/config.h index 7bc37a4..fecf328 100644 --- a/src/config.h +++ b/src/config.h @@ -26,7 +26,7 @@ struct mode_tile_config { char *label_font_family; struct relative_font_size label_font_size; char *label_symbols; - char *label_display; + char *keys; }; enum floating_mode_source { diff --git a/src/mode_tile.c b/src/mode_tile.c index 589b70c..7c4fbd8 100644 --- a/src/mode_tile.c +++ b/src/mode_tile.c @@ -40,7 +40,7 @@ void *tile_mode_enter(struct state *state, struct rect area) { ms->label_symbols = label_symbols_from_strs( state->config.mode_tile.label_symbols, - state->config.mode_tile.label_display + state->config.mode_tile.keys ); if (ms->label_symbols == NULL) { ms->label_selection = NULL; From bd11a15ae658a8f7ba1569d225b373d2fabe853e Mon Sep 17 00:00:00 2001 From: Jacob Komissar Date: Fri, 26 Sep 2025 21:01:59 -0400 Subject: [PATCH 10/12] Update label_symbols_t field names --- src/label.c | 26 +++++++++++++------------- src/label.h | 10 +++++----- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/label.c b/src/label.c index 92a8123..a7d0d5c 100644 --- a/src/label.c +++ b/src/label.c @@ -83,12 +83,12 @@ static label_symbols_t *label_symbols_init( char *data; if (label_symbols == NULL) { - label_symbols = malloc(len + sizeof(label_symbols_t)); - label_symbols->num_symbols = num_symbols; - label_symbols->display_data = NULL; - data = label_symbols->data; + label_symbols = malloc(len + sizeof(label_symbols_t)); + label_symbols->num_symbols = num_symbols; + label_symbols->symbols = NULL; + data = label_symbols->keys; } else { - data = label_symbols->display_data = malloc(len); + data = label_symbols->symbols = malloc(len); if (num_symbols != label_symbols->num_symbols) { LOG_ERR("Label display symbols must be empty or same length as label symbols."); return NULL; @@ -111,7 +111,7 @@ label_symbols_t *label_symbols_from_strs(char *symbols, char *keys) { if (symbols == keys || strcmp(symbols, keys) == 0) { // When possible, don't use a second array. - label_symbols->display_data = label_symbols->data; + label_symbols->symbols = label_symbols->keys; } else { void *result = label_symbols_init(symbols, label_symbols); if (result == NULL) { @@ -124,8 +124,8 @@ label_symbols_t *label_symbols_from_strs(char *symbols, char *keys) { } void label_symbols_free(label_symbols_t *ls) { - if (ls != NULL && ls->display_data != ls->data) { - free(ls->display_data); + if (ls != NULL && ls->symbols != ls->keys) { + free(ls->symbols); } free(ls); } @@ -136,8 +136,8 @@ char *label_symbols_idx_to_key_ptr(label_symbols_t *label_symbols, int idx) { return NULL; } - return ((char *)label_symbols->data) + label_symbols->num_symbols + - ((unsigned char *)label_symbols->data)[idx]; + return ((char *)label_symbols->keys) + label_symbols->num_symbols + + ((unsigned char *)label_symbols->keys)[idx]; } char *label_symbols_idx_to_display_ptr(label_symbols_t *label_symbols, int idx) { @@ -146,8 +146,8 @@ char *label_symbols_idx_to_display_ptr(label_symbols_t *label_symbols, int idx) return NULL; } - return label_symbols->display_data + label_symbols->num_symbols + - ((unsigned char *)label_symbols->display_data)[idx]; + return label_symbols->symbols + label_symbols->num_symbols + + ((unsigned char *)label_symbols->symbols)[idx]; } int label_symbols_find_key_idx(label_symbols_t *label_symbols, char *s) { @@ -279,7 +279,7 @@ int label_selection_incr(label_selection_t *label_selection) { // Max string length for a single symbol in a label static int label_symbols_max_str_len(label_symbols_t *label_symbols) { int num_symbols = label_symbols->num_symbols; - unsigned char *indices = (unsigned char *)label_symbols->data; + unsigned char *indices = (unsigned char *)label_symbols->keys; int curr_len = 0; int max_len = strlen( diff --git a/src/label.h b/src/label.h index a4f20ae..2499928 100644 --- a/src/label.h +++ b/src/label.h @@ -4,19 +4,19 @@ #include typedef struct { - /* data data[num_symbols] + /* keys keys[num_symbols] * | | * | 4 ||xxxx|| 0 | 2 | 4 | 6 ||`a`| 0 |`b`| 0 |`c`| 0 |`d`| 0 | * ^ ^ ^-----------^ ^---------------------------^ * | | offsets strings - * | pointer to display data + * | pointer to symbol data * number of symbols * - * The display data is identical in structure to the data. + * The symbol field's data is identical in structure to the keys field. */ unsigned char num_symbols; - char *display_data; - char data[]; + char *symbols; + char keys[]; } label_symbols_t; typedef struct { From ebf01b295f6e7d9bf36d940bf1160f1fe09e641c Mon Sep 17 00:00:00 2001 From: Jacob Komissar Date: Fri, 26 Sep 2025 21:06:13 -0400 Subject: [PATCH 11/12] Swap data fields in label_symbols_t struct --- src/label.c | 20 ++++++++------------ src/label.h | 10 +++++----- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/src/label.c b/src/label.c index a7d0d5c..47f5494 100644 --- a/src/label.c +++ b/src/label.c @@ -85,10 +85,10 @@ static label_symbols_t *label_symbols_init( if (label_symbols == NULL) { label_symbols = malloc(len + sizeof(label_symbols_t)); label_symbols->num_symbols = num_symbols; - label_symbols->symbols = NULL; - data = label_symbols->keys; + label_symbols->keys = NULL; + data = label_symbols->symbols; } else { - data = label_symbols->symbols = malloc(len); + data = label_symbols->keys = malloc(len); if (num_symbols != label_symbols->num_symbols) { LOG_ERR("Label display symbols must be empty or same length as label symbols."); return NULL; @@ -100,20 +100,16 @@ static label_symbols_t *label_symbols_init( } label_symbols_t *label_symbols_from_strs(char *symbols, char *keys) { - if (keys[0] == '\0') { - keys = symbols; - } - - label_symbols_t *label_symbols = label_symbols_init(keys, NULL); + label_symbols_t *label_symbols = label_symbols_init(symbols, NULL); if (label_symbols == NULL) { return NULL; } - if (symbols == keys || strcmp(symbols, keys) == 0) { + if (symbols == keys || keys[0] == '\0' || strcmp(symbols, keys) == 0) { // When possible, don't use a second array. - label_symbols->symbols = label_symbols->keys; + label_symbols->keys = label_symbols->symbols; } else { - void *result = label_symbols_init(symbols, label_symbols); + void *result = label_symbols_init(keys, label_symbols); if (result == NULL) { label_symbols_free(label_symbols); return NULL; @@ -125,7 +121,7 @@ label_symbols_t *label_symbols_from_strs(char *symbols, char *keys) { void label_symbols_free(label_symbols_t *ls) { if (ls != NULL && ls->symbols != ls->keys) { - free(ls->symbols); + free(ls->keys); } free(ls); } diff --git a/src/label.h b/src/label.h index 2499928..c87e150 100644 --- a/src/label.h +++ b/src/label.h @@ -4,19 +4,19 @@ #include typedef struct { - /* keys keys[num_symbols] + /* symbols symbols[num_symbols] * | | * | 4 ||xxxx|| 0 | 2 | 4 | 6 ||`a`| 0 |`b`| 0 |`c`| 0 |`d`| 0 | * ^ ^ ^-----------^ ^---------------------------^ * | | offsets strings - * | pointer to symbol data + * | pointer to key data * number of symbols * - * The symbol field's data is identical in structure to the keys field. + * The keys field's data is identical in structure to the symbols field. */ unsigned char num_symbols; - char *symbols; - char keys[]; + char *keys; + char symbols[]; } label_symbols_t; typedef struct { From 33aa039dd3e51cc7c6dfcc45eb19df3c8c08bda0 Mon Sep 17 00:00:00 2001 From: Jacob Komissar Date: Fri, 26 Sep 2025 21:34:30 -0400 Subject: [PATCH 12/12] Add label-keys option to floating mode --- src/config.c | 3 ++- src/config.h | 1 + src/mode_floating.c | 6 ++++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/config.c b/src/config.c index 460df37..8170d9c 100644 --- a/src/config.c +++ b/src/config.c @@ -387,7 +387,8 @@ static struct section_def section_defs[] = { MF_FIELD(label_font_size, "12 50% 100", parse_relative_font_size, noop), MF_FIELD( label_symbols, "abcdefghijklmnopqrstuvwxyz", parse_str, free_str - ) + ), + MF_FIELD(keys, "", parse_str, free_str) ), SECTION( mode_bisect, MB_FIELD(label_color, "#fffd", parse_color, noop), diff --git a/src/config.h b/src/config.h index fecf328..b69d622 100644 --- a/src/config.h +++ b/src/config.h @@ -44,6 +44,7 @@ struct mode_floating_config { char *label_font_family; struct relative_font_size label_font_size; char *label_symbols; + char *keys; }; struct mode_bisect_config { diff --git a/src/mode_floating.c b/src/mode_floating.c index d62b0a1..2ceb1d2 100644 --- a/src/mode_floating.c +++ b/src/mode_floating.c @@ -77,8 +77,10 @@ static void get_area_from_screenshot( void *floating_mode_enter(struct state *state, struct rect area) { struct floating_mode_state *ms = malloc(sizeof(*ms)); - ms->label_symbols = - label_symbols_from_str(state->config.mode_floating.label_symbols); + ms->label_symbols = label_symbols_from_strs( + state->config.mode_floating.label_symbols, + state->config.mode_floating.keys + ); if (ms->label_symbols == NULL) { ms->areas = NULL;