From bc939712cb0e6511a4cbb0be6488cb202b4763eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emysl=20Eric=20Janouch?= Date: Sun, 10 Oct 2021 03:38:16 +0200 Subject: [PATCH] sdtui: lay the groundwork for formatted entries --- src/sdtui.c | 70 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 54 insertions(+), 16 deletions(-) diff --git a/src/sdtui.c b/src/sdtui.c index 9170b92..2316484 100644 --- a/src/sdtui.c +++ b/src/sdtui.c @@ -194,6 +194,7 @@ struct view_entry { gchar * word; ///< Word GPtrArray * definitions; ///< Word definition entries (gchar *) + GPtrArray * formatting; ///< chtype * or NULL per definition }; struct dictionary @@ -275,10 +276,12 @@ view_entry_split_add (ViewEntry *ve, const gchar *text) if (nl != p) { g_ptr_array_add (ve->definitions, g_strndup (p, nl - p)); + g_ptr_array_add (ve->formatting, NULL); } if (*p) { g_ptr_array_add (ve->definitions, g_strdup (p)); + g_ptr_array_add (ve->formatting, NULL); } } @@ -295,6 +298,7 @@ view_entry_new (StardictIterator *iterator) g_return_val_if_fail (entry != NULL, NULL); ve->definitions = g_ptr_array_new_with_free_func (g_free); + ve->formatting = g_ptr_array_new_with_free_func (g_free); gboolean found_anything_displayable = FALSE; for (const GList *fields = stardict_entry_get_fields (entry); fields; ) { @@ -341,6 +345,7 @@ view_entry_free (ViewEntry *ve) { g_free (ve->word); g_ptr_array_free (ve->definitions, TRUE); + g_ptr_array_free (ve->formatting, TRUE); g_slice_free1 (sizeof *ve, ve); } @@ -777,10 +782,11 @@ row_buffer_init (RowBuffer *self, Application *app) /// Replace invalid chars and push all codepoints to the array w/ attributes. static void -row_buffer_append (RowBuffer *self, const gchar *str, chtype attrs) +row_buffer_append_length (RowBuffer *self, + const gchar *text, glong length, chtype attrs) { glong ucs4_len; - gunichar *ucs4 = g_utf8_to_ucs4_fast (str, -1, &ucs4_len); + gunichar *ucs4 = g_utf8_to_ucs4_fast (text, length, &ucs4_len); for (glong i = 0; i < ucs4_len; i++) { // XXX: this is very crude as it disrespects combining marks @@ -793,6 +799,47 @@ row_buffer_append (RowBuffer *self, const gchar *str, chtype attrs) g_free (ucs4); } +static void +row_buffer_append (RowBuffer *self, const gchar *text, chtype attrs) +{ + row_buffer_append_length (self, text, -1, attrs); +} + +/// Combine attributes, taking care to replace colour bits entirely +static void +row_buffer_merge_attributes (chtype *target, int merged) +{ + if (merged & A_COLOR) + *target = (*target & ~A_COLOR) | merged; + else + *target |= merged; +} + +static void +row_buffer_append_with_formatting (RowBuffer *self, + const gchar *text, const chtype *formatting, chtype default_attrs) +{ + if (!formatting) + { + row_buffer_append (self, text, default_attrs); + return; + } + + while (*text) + { + glong chunk_length = 1; + while (text[chunk_length] && formatting[chunk_length] == *formatting) + chunk_length++; + + chtype merged = default_attrs; + row_buffer_merge_attributes (&merged, *formatting); + row_buffer_append_length (self, text, chunk_length, merged); + + text += chunk_length; + formatting += chunk_length; + } +} + /// Pop as many codepoints as needed to free up "space" character cells. /// Given the suffix nature of combining marks, this should work pretty fine. static gint @@ -995,16 +1042,6 @@ app_show_help (Application *self) app_show_message (self, lines, G_N_ELEMENTS (lines)); } -/// Combine attributes, taking care to replace colour bits entirely -static void -app_merge_attributes (int *target, int merged) -{ - if (merged & A_COLOR) - *target = (*target & ~A_COLOR) | merged; - else - *target |= merged; -} - /// Redraw the dictionary view. static void app_redraw_view (Application *self) @@ -1029,11 +1066,11 @@ app_redraw_view (Application *self) ViewEntry *ve = g_ptr_array_index (self->entries, i); for (; k < ve->definitions->len; k++) { - int attrs = ((self->top_position + i) & 1) + chtype attrs = ((self->top_position + i) & 1) ? APP_ATTR (ODD) : APP_ATTR (EVEN); if (shown == self->selected) - app_merge_attributes (&attrs, self->focused + row_buffer_merge_attributes (&attrs, self->focused ? APP_ATTR (SELECTION) : APP_ATTR (DEFOCUSED)); gboolean last = k + 1 == ve->definitions->len; @@ -1058,8 +1095,9 @@ app_redraw_view (Application *self) row_buffer_init (&buf, self); row_buffer_append (&buf, " ", attrs); - row_buffer_append (&buf, - g_ptr_array_index (ve->definitions, k), attrs); + row_buffer_append_with_formatting (&buf, + g_ptr_array_index (ve->definitions, k), + g_ptr_array_index (ve->formatting, k), attrs); row_buffer_finish (&buf, COLS - left_width, attrs); if ((gint) ++shown == LINES - TOP_BAR_CUTOFF)