GtkLabel with markup and mnemonic shouldn't strip underscores from Pango markup tags
Hi again! I hope everyone is doing OK out there. IRL has gotten in the way for me.
This might also occur (probably does?) in GTK4, but I'm a bit away from being able to test it.
This code should produce a GtkLabel
whose text looks like Mnemonic
with a red strike through it, and whose :mnemonic-keyval
is m
as given by the underline at _M
.
#include <gtk/gtk.h>
static void
on_application_activate (GApplication *application)
{
GtkLabel *label = GTK_LABEL (gtk_label_new (NULL));
gtk_label_set_use_markup (label, TRUE);
gtk_label_set_use_underline (label, TRUE);
gtk_label_set_label (label,
"<span strikethrough='true' strikethrough_color='red'>_Mnemonic</span>");
GtkWindow *window = GTK_WINDOW (gtk_window_new (GTK_WINDOW_TOPLEVEL));
gtk_container_add (GTK_CONTAINER (window), GTK_WIDGET (label));
gtk_widget_show_all (GTK_WIDGET (window));
gtk_application_add_window (GTK_APPLICATION (application), window);
}
int
main(int argc, char **argv)
{
GtkApplication *application = gtk_application_new ("org.djb.test", G_APPLICATION_FLAGS_NONE);
g_signal_connect (application, "activate", G_CALLBACK(on_application_activate), NULL);
int result = g_application_run (G_APPLICATION (application), argc, argv);
g_object_unref (application);
return result;
}
However, we actually get this with a visible underline instead of a 'hidden' one,
and we get this warning in the terminal:
(a.out:52169): Gtk-WARNING **: 17:58:55.364: Failed to set text '<markup><span strikethrough="true" strikethroughcolor="red">Mnemonic</span></markup>' from markup due to error parsing markup: Attribute 'strikethroughcolor' is not allowed on the <span> tag on line 1 char 69
See that the attribute complained about is strikethroughcolor
, instead of the correct strikethrough_color
. It seems like this half works, in that some other stage does apply the markup, but then the code in question here barfs on it and doesn't finish the job right.
Based on the following backtrace, it seems that separate_uline_pattern()
is not smart enough, and it removes all underscores from the string - even those that are part of Pango markup, such as my strikethrough_color
, i.e. are between <>
.
Surely this should not happen, and we should not strip any underscores between <
and >
if the Label:use-markup
, so we don't mangle markup and cause warnings?
i.e. if we find a <
in the raw text, skip to the matching >
(or end of string) without trying to do any separation or otherwise of underscores between.
I found this when I was trying to test my own code to determine the :mnemonic-keyval
, since we don't provide public API for that, and my tests got broken by it.
#0 _g_log_abort (breakpoint=1) at ../../../../jhbuild/checkout/gnome/glib/glib/gmessages.c:557
#1 0x00007ffff70bbfd8 in g_log_writer_default (log_level=18, fields=0x7fffffffc080, n_fields=6, user_data=0x0)
at ../../../../jhbuild/checkout/gnome/glib/glib/gmessages.c:2694
#2 0x00007ffff70badf3 in g_log_structured_array (log_level=G_LOG_LEVEL_WARNING, fields=0x7fffffffc080, n_fields=6)
at ../../../../jhbuild/checkout/gnome/glib/glib/gmessages.c:1925
#3 0x00007ffff70bb05b in g_log_structured_standard (log_domain=0x7ffff7d10610 "Gtk", log_level=G_LOG_LEVEL_WARNING,
file=0x7ffff7d10f30 "../../../../jhbuild/checkout/gnome/gtk+-3/gtk/gtklabel.c", line=0x7ffff7d11286 "2723",
func=0x7ffff7d116b0 <__func__.72052> "gtk_label_set_markup_internal",
message_format=0x7ffff7d11228 "Failed to set text '%s' from markup due to error parsing markup: %s")
at ../../../../jhbuild/checkout/gnome/glib/glib/gmessages.c:1982
#4 0x00007ffff79b9448 in gtk_label_set_markup_internal (label=0x5555555aa810,
str=0x5555556bdec0 "<span strikethrough='true' strikethrough_color='red'>_Mnemonic</span>", with_uline=1)
at ../../../../jhbuild/checkout/gnome/gtk+-3/gtk/gtklabel.c:2723
#5 0x00007ffff79b82c0 in gtk_label_recalculate (label=0x5555555aa810) at ../../../../jhbuild/checkout/gnome/gtk+-3/gtk/gtklabel.c:2220
#6 0x00007ffff79b7991 in mnemonics_visible_apply (widget=0x5555555aa810, mnemonics_visible=0)
at ../../../../jhbuild/checkout/gnome/gtk+-3/gtk/gtklabel.c:1963
#7 0x00007ffff79b7a43 in _gtk_label_mnemonics_visible_apply_recursively (widget=0x5555555aa810, mnemonics_visible=0)
at ../../../../jhbuild/checkout/gnome/gtk+-3/gtk/gtklabel.c:1981
#8 0x00007ffff79b79bc in label_mnemonics_visible_traverse_container (widget=0x5555555aa810, data=0x0)
at ../../../../jhbuild/checkout/gnome/gtk+-3/gtk/gtklabel.c:1973
#9 0x00007ffff7bd9a0c in gtk_window_forall (container=0x55555585e2a0, include_internals=1,
callback=0x7ffff79b7994 <label_mnemonics_visible_traverse_container>, callback_data=0x0)
at ../../../../jhbuild/checkout/gnome/gtk+-3/gtk/gtkwindow.c:8590
#10 0x00007ffff78af251 in gtk_container_forall (container=0x55555585e2a0,
callback=0x7ffff79b7994 <label_mnemonics_visible_traverse_container>, callback_data=0x0)
at ../../../../jhbuild/checkout/gnome/gtk+-3/gtk/gtkcontainer.c:2444
#11 0x00007ffff79b7b4b in label_mnemonics_visible_changed (window=0x55555585e2a0, pspec=0x5555555eb2e0, data=0x5555555aa810)
at ../../../../jhbuild/checkout/gnome/gtk+-3/gtk/gtklabel.c:1997
#12 0x00007ffff74fd04f in g_cclosure_marshal_VOID__PARAM (closure=0x5555556c6f90, return_value=0x0, n_param_values=2,
param_values=0x7fffffffc6f0, invocation_hint=0x7fffffffc630, marshal_data=0x0)
at ../../../../jhbuild/checkout/gnome/glib/gobject/gmarshal.c:1516
#13 0x00007ffff74f856f in g_closure_invoke (closure=0x5555556c6f90, return_value=0x0, n_param_values=2, param_values=0x7fffffffc6f0,
invocation_hint=0x7fffffffc630) at ../../../../jhbuild/checkout/gnome/glib/gobject/gclosure.c:810
#14 0x00007ffff7516594 in signal_emit_unlocked_R (node=0x555555564300, detail=648, instance=0x55555585e2a0, emission_return=0x0,
instance_and_params=0x7fffffffc6f0) at ../../../../jhbuild/checkout/gnome/glib/gobject/gsignal.c:3738
#15 0x00007ffff751589d in g_signal_emit_valist (instance=0x55555585e2a0, signal_id=1, detail=648, var_args=0x7fffffffc9b8)
at ../../../../jhbuild/checkout/gnome/glib/gobject/gsignal.c:3494
#16 0x00007ffff7515e20 in g_signal_emit (instance=0x55555585e2a0, signal_id=1, detail=648)
at ../../../../jhbuild/checkout/gnome/glib/gobject/gsignal.c:3550
#17 0x00007ffff74ffd2a in g_object_dispatch_properties_changed (object=0x55555585e2a0, n_pspecs=1, pspecs=0x7fffffffcaf0)
at ../../../../jhbuild/checkout/gnome/glib/gobject/gobject.c:1206
#18 0x00007ffff74fff2b in g_object_notify_by_spec_internal (object=0x55555585e2a0, pspec=0x5555555eb2e0)
at ../../../../jhbuild/checkout/gnome/glib/gobject/gobject.c:1299
#19 0x00007ffff75000f4 in g_object_notify_by_pspec (object=0x55555585e2a0, pspec=0x5555555eb2e0)
at ../../../../jhbuild/checkout/gnome/glib/gobject/gobject.c:1409
#20 0x00007ffff7be085b in gtk_window_set_mnemonics_visible (window=0x55555585e2a0, setting=0)
at ../../../../jhbuild/checkout/gnome/gtk+-3/gtk/gtkwindow.c:12324
#21 0x00007ffff7bd4955 in gtk_window_map (widget=0x55555585e2a0) at ../../../../jhbuild/checkout/gnome/gtk+-3/gtk/gtkwindow.c:6349
#22 0x00007ffff74fba34 in g_cclosure_marshal_VOID__VOIDv (closure=0x5555555865a0, return_value=0x0, instance=0x55555585e2a0,
args=0x7fffffffd038, marshal_data=0x7ffff7bd4591 <gtk_window_map>, n_params=0, param_types=0x0)
at ../../../../jhbuild/checkout/gnome/glib/gobject/gmarshal.c:165
#23 0x00007ffff74f8cdd in g_type_class_meta_marshalv (closure=0x5555555865a0, return_value=0x0, instance=0x55555585e2a0,
args=0x7fffffffd038, marshal_data=0xb8, n_params=0, param_types=0x0)
at ../../../../jhbuild/checkout/gnome/glib/gobject/gclosure.c:1034
#24 0x00007ffff74f8860 in _g_closure_invoke_va (closure=0x5555555865a0, return_value=0x0, instance=0x55555585e2a0,
args=0x7fffffffd038, n_params=0, param_types=0x0) at ../../../../jhbuild/checkout/gnome/glib/gobject/gclosure.c:873
#25 0x00007ffff7514bd6 in g_signal_emit_valist (instance=0x55555585e2a0, signal_id=60, detail=0, var_args=0x7fffffffd038)
at ../../../../jhbuild/checkout/gnome/glib/gobject/gsignal.c:3403
#26 0x00007ffff7515e20 in g_signal_emit (instance=0x55555585e2a0, signal_id=60, detail=0)
at ../../../../jhbuild/checkout/gnome/glib/gobject/gsignal.c:3550
#27 0x00007ffff7bacfe2 in gtk_widget_map (widget=0x55555585e2a0) at ../../../../jhbuild/checkout/gnome/gtk+-3/gtk/gtkwidget.c:5047
#28 0x00007ffff7bd4292 in gtk_window_show (widget=0x55555585e2a0) at ../../../../jhbuild/checkout/gnome/gtk+-3/gtk/gtkwindow.c:6179
#29 0x00007ffff74fb9a1 in g_cclosure_marshal_VOID__VOID (closure=0x5555555863e0, return_value=0x0, n_param_values=1,
param_values=0x7fffffffd460, invocation_hint=0x7fffffffd3a0, marshal_data=0x7ffff7bd41a9 <gtk_window_show>)
at ../../../../jhbuild/checkout/gnome/glib/gobject/gmarshal.c:117
#30 0x00007ffff74f8c51 in g_type_class_meta_marshal (closure=0x5555555863e0, return_value=0x0, n_param_values=1,
param_values=0x7fffffffd460, invocation_hint=0x7fffffffd3a0, marshal_data=0xa0)
(ins)--Type <RET> for more, q to quit, c to continue without paging--
at ../../../../jhbuild/checkout/gnome/glib/gobject/gclosure.c:1007
#31 0x00007ffff74f856f in g_closure_invoke (closure=0x5555555863e0, return_value=0x0, n_param_values=1, param_values=0x7fffffffd460,
invocation_hint=0x7fffffffd3a0) at ../../../../jhbuild/checkout/gnome/glib/gobject/gclosure.c:810
#32 0x00007ffff75162a3 in signal_emit_unlocked_R (node=0x555555586430, detail=0, instance=0x55555585e2a0, emission_return=0x0,
instance_and_params=0x7fffffffd460) at ../../../../jhbuild/checkout/gnome/glib/gobject/gsignal.c:3668
#33 0x00007ffff751589d in g_signal_emit_valist (instance=0x55555585e2a0, signal_id=58, detail=0, var_args=0x7fffffffd708)
at ../../../../jhbuild/checkout/gnome/glib/gobject/gsignal.c:3494
#34 0x00007ffff7515e20 in g_signal_emit (instance=0x55555585e2a0, signal_id=58, detail=0)
at ../../../../jhbuild/checkout/gnome/glib/gobject/gsignal.c:3550
#35 0x00007ffff7bac8df in gtk_widget_show (widget=0x55555585e2a0) at ../../../../jhbuild/checkout/gnome/gtk+-3/gtk/gtkwidget.c:4848
#36 0x00007ffff78b17b9 in gtk_container_show_all (widget=0x55555585e2a0)
at ../../../../jhbuild/checkout/gnome/gtk+-3/gtk/gtkcontainer.c:3600
#37 0x00007ffff7bace9b in gtk_widget_show_all (widget=0x55555585e2a0) at ../../../../jhbuild/checkout/gnome/gtk+-3/gtk/gtkwidget.c:5019
#38 0x0000555555555334 in on_application_activate ()
#39 0x00007ffff74fb9a1 in g_cclosure_marshal_VOID__VOID (closure=0x5555555755c0, return_value=0x0, n_param_values=1,
param_values=0x7fffffffdb30, invocation_hint=0x7fffffffda70, marshal_data=0x0)
at ../../../../jhbuild/checkout/gnome/glib/gobject/gmarshal.c:117
#40 0x00007ffff74f856f in g_closure_invoke (closure=0x5555555755c0, return_value=0x0, n_param_values=1, param_values=0x7fffffffdb30,
invocation_hint=0x7fffffffda70) at ../../../../jhbuild/checkout/gnome/glib/gobject/gclosure.c:810
#41 0x00007ffff7516594 in signal_emit_unlocked_R (node=0x555555570210, detail=0, instance=0x5555555740f0, emission_return=0x0,
instance_and_params=0x7fffffffdb30) at ../../../../jhbuild/checkout/gnome/glib/gobject/gsignal.c:3738
#42 0x00007ffff751589d in g_signal_emit_valist (instance=0x5555555740f0, signal_id=8, detail=0, var_args=0x7fffffffddd8)
at ../../../../jhbuild/checkout/gnome/glib/gobject/gsignal.c:3494
#43 0x00007ffff7515e20 in g_signal_emit (instance=0x5555555740f0, signal_id=8, detail=0)
at ../../../../jhbuild/checkout/gnome/glib/gobject/gsignal.c:3550
#44 0x00007ffff76504f4 in g_application_activate (application=0x5555555740f0)
at ../../../../jhbuild/checkout/gnome/glib/gio/gapplication.c:2303
#45 0x00007ffff764e359 in g_application_real_local_command_line (application=0x5555555740f0, arguments=0x7fffffffdfc8,
exit_status=0x7fffffffdfc4) at ../../../../jhbuild/checkout/gnome/glib/gio/gapplication.c:1139
#46 0x00007ffff782c6c0 in gtk_application_local_command_line (application=0x5555555740f0, arguments=0x7fffffffdfc8,
exit_status=0x7fffffffdfc4) at ../../../../jhbuild/checkout/gnome/gtk+-3/gtk/gtkapplication.c:343
#47 0x00007ffff7650888 in g_application_run (application=0x5555555740f0, argc=1, argv=0x7fffffffe138)
at ../../../../jhbuild/checkout/gnome/glib/gio/gapplication.c:2528
#48 0x00005555555553de in main ()