diff options
| author | Přemysl Eric Janouch <p@janouch.name> | 2021-10-10 04:41:55 +0200 | 
|---|---|---|
| committer | Přemysl Eric Janouch <p@janouch.name> | 2021-10-10 06:13:49 +0200 | 
| commit | 16d6eaf012da1bac5d34fce41fd30b0f53aa8f65 (patch) | |
| tree | bfd695f620efb50bd0482c8606a0accc6649642b | |
| parent | bc939712cb0e6511a4cbb0be6488cb202b4763eb (diff) | |
| download | tdv-16d6eaf012da1bac5d34fce41fd30b0f53aa8f65.tar.gz tdv-16d6eaf012da1bac5d34fce41fd30b0f53aa8f65.tar.xz tdv-16d6eaf012da1bac5d34fce41fd30b0f53aa8f65.zip | |
sdtui: support <b>/<i>/<u> in Pango entries
| -rw-r--r-- | src/sdtui.c | 78 | 
1 files changed, 64 insertions, 14 deletions
| diff --git a/src/sdtui.c b/src/sdtui.c index 2316484..d823f43 100644 --- a/src/sdtui.c +++ b/src/sdtui.c @@ -48,6 +48,10 @@  #define TOP_BAR_CUTOFF  2               ///< How many lines are reserved on top  #define APP_TITLE  PROJECT_NAME " "     ///< Left top corner +#ifndef A_ITALIC +#define A_ITALIC 0 +#endif +  // --- Utilities ---------------------------------------------------------------  static size_t @@ -269,20 +273,75 @@ app_char_width (Application *app, gunichar c)  /// Splits the entry and adds it to a pointer array.  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;  	for (; (nl = strchr (p, '\n')); p = nl + 1)  		if (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)  	{  		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. @@ -306,20 +365,13 @@ view_entry_new (StardictIterator *iterator)  		switch (field->type)  		{  		case STARDICT_FIELD_MEANING: -			view_entry_split_add (ve, field->data); +			view_entry_split_add (ve, field->data, NULL);  			found_anything_displayable = TRUE;  			break;  		case STARDICT_FIELD_PANGO: -		{ -			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); +			view_entry_split_add_pango (ve, field->data);  			found_anything_displayable = TRUE;  			break; -		}  		case STARDICT_FIELD_PHONETIC:  			g_string_append_printf (word, " /%s/", (const gchar *) field->data);  			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, "blink"))   attrs.attrs |= A_BLINK;  		else if (!strcmp (*it, "reverse")) attrs.attrs |= A_REVERSE; -#ifdef A_ITALIC  		else if (!strcmp (*it, "italic"))  attrs.attrs |= A_ITALIC; -#endif  // A_ITALIC  	}  	g_strfreev (values); | 
