sdtui: support <b>/<i>/<u> in Pango entries

This commit is contained in:
Přemysl Eric Janouch 2021-10-10 04:41:55 +02:00
parent bc939712cb
commit 16d6eaf012
Signed by: p
GPG Key ID: A0420B94F92B9493
1 changed files with 64 additions and 14 deletions

View File

@ -48,6 +48,10 @@
#define TOP_BAR_CUTOFF 2 ///< How many lines are reserved on top #define TOP_BAR_CUTOFF 2 ///< How many lines are reserved on top
#define APP_TITLE PROJECT_NAME " " ///< Left top corner #define APP_TITLE PROJECT_NAME " " ///< Left top corner
#ifndef A_ITALIC
#define A_ITALIC 0
#endif
// --- Utilities --------------------------------------------------------------- // --- Utilities ---------------------------------------------------------------
static size_t static size_t
@ -269,22 +273,77 @@ app_char_width (Application *app, gunichar c)
/// Splits the entry and adds it to a pointer array. /// Splits the entry and adds it to a pointer array.
static void static void
view_entry_split_add (ViewEntry *ve, const gchar *text) view_entry_split_add (ViewEntry *ve, const gchar *text, const chtype *attrs)
{ {
const gchar *p = text, *nl; const gchar *p = text, *nl;
for (; (nl = strchr (p, '\n')); p = nl + 1) for (; (nl = strchr (p, '\n')); p = nl + 1)
if (nl != p) if (nl != p)
{ {
g_ptr_array_add (ve->definitions, g_strndup (p, nl - p)); g_ptr_array_add (ve->definitions, g_strndup (p, nl - p));
g_ptr_array_add (ve->formatting, NULL); g_ptr_array_add (ve->formatting, !attrs ? NULL
: g_memdup2 (attrs + (p - text), (nl - p) * sizeof *attrs));
} }
if (*p) if (*p)
{ {
g_ptr_array_add (ve->definitions, g_strdup (p)); g_ptr_array_add (ve->definitions, g_strdup (p));
g_ptr_array_add (ve->formatting, NULL); g_ptr_array_add (ve->formatting, !attrs ? NULL
: g_memdup2 (attrs + (p - text), strlen (p) * sizeof *attrs));
} }
} }
static chtype
app_pango_iterator_to_attrs (PangoAttrIterator *iterator)
{
chtype attrs = 0;
PangoAttrInt *attr = NULL;
if ((attr = (PangoAttrInt *) pango_attr_iterator_get (iterator,
PANGO_ATTR_WEIGHT)) && attr->value >= PANGO_WEIGHT_BOLD)
attrs |= A_BOLD;
if ((attr = (PangoAttrInt *) pango_attr_iterator_get (iterator,
PANGO_ATTR_UNDERLINE)) && attr->value == PANGO_UNDERLINE_SINGLE)
attrs |= A_UNDERLINE;
if ((attr = (PangoAttrInt *) pango_attr_iterator_get (iterator,
PANGO_ATTR_STYLE)) && attr->value == PANGO_STYLE_ITALIC)
attrs |= A_ITALIC;
return attrs;
}
static void
view_entry_split_add_pango (ViewEntry *ve, const gchar *markup)
{
// This function skips leading whitespace, but it's the canonical one
gchar *text = NULL;
PangoAttrList *attrs = NULL;
if (!pango_parse_markup (markup, -1, 0, &attrs, &text, NULL, NULL))
{
gchar *replacement = g_strdup_printf ("<%s>", _("error in entry"));
view_entry_split_add (ve, replacement, NULL);
g_free (replacement);
return;
}
PangoAttrIterator *iterator = pango_attr_list_get_iterator (attrs);
chtype *formatting = g_malloc0_n (strlen (text), sizeof *formatting);
do
{
gint start = 0, end = 0;
pango_attr_iterator_range (iterator, &start, &end);
if (end == G_MAXINT)
end = strlen (text);
chtype attrs = app_pango_iterator_to_attrs (iterator);
while (start < end)
formatting[start++] = attrs;
}
while (pango_attr_iterator_next (iterator));
view_entry_split_add (ve, text, formatting);
g_free (formatting);
pango_attr_iterator_destroy (iterator);
pango_attr_list_unref (attrs);
g_free (text);
}
/// Decomposes a dictionary entry into the format we want. /// Decomposes a dictionary entry into the format we want.
static ViewEntry * static ViewEntry *
view_entry_new (StardictIterator *iterator) view_entry_new (StardictIterator *iterator)
@ -306,20 +365,13 @@ view_entry_new (StardictIterator *iterator)
switch (field->type) switch (field->type)
{ {
case STARDICT_FIELD_MEANING: case STARDICT_FIELD_MEANING:
view_entry_split_add (ve, field->data); view_entry_split_add (ve, field->data, NULL);
found_anything_displayable = TRUE; found_anything_displayable = TRUE;
break; break;
case STARDICT_FIELD_PANGO: case STARDICT_FIELD_PANGO:
{ view_entry_split_add_pango (ve, field->data);
gchar *text;
if (!pango_parse_markup (field->data, -1,
0, NULL, &text, NULL, NULL))
text = g_strdup_printf ("<%s>", _("error in entry"));
view_entry_split_add (ve, text);
g_free (text);
found_anything_displayable = TRUE; found_anything_displayable = TRUE;
break; break;
}
case STARDICT_FIELD_PHONETIC: case STARDICT_FIELD_PHONETIC:
g_string_append_printf (word, " /%s/", (const gchar *) field->data); g_string_append_printf (word, " /%s/", (const gchar *) field->data);
break; break;
@ -433,9 +485,7 @@ app_load_color (Application *self, GKeyFile *kf, const gchar *name, int id)
else if (!strcmp (*it, "ul")) attrs.attrs |= A_UNDERLINE; else if (!strcmp (*it, "ul")) attrs.attrs |= A_UNDERLINE;
else if (!strcmp (*it, "blink")) attrs.attrs |= A_BLINK; else if (!strcmp (*it, "blink")) attrs.attrs |= A_BLINK;
else if (!strcmp (*it, "reverse")) attrs.attrs |= A_REVERSE; else if (!strcmp (*it, "reverse")) attrs.attrs |= A_REVERSE;
#ifdef A_ITALIC
else if (!strcmp (*it, "italic")) attrs.attrs |= A_ITALIC; else if (!strcmp (*it, "italic")) attrs.attrs |= A_ITALIC;
#endif // A_ITALIC
} }
g_strfreev (values); g_strfreev (values);