1 #include <gtk/gtk.h>
2 
3 void
print_attribute(PangoAttribute * attr,GString * string)4 print_attribute (PangoAttribute *attr, GString *string)
5 {
6   GEnumClass *class;
7   GEnumValue *value;
8 
9   g_string_append_printf (string, "[%d,%d]", attr->start_index, attr->end_index);
10 
11   class = g_type_class_ref (pango_attr_type_get_type ());
12   value = g_enum_get_value (class, attr->klass->type);
13   g_string_append_printf (string, "%s=", value->value_nick);
14   g_type_class_unref (class);
15 
16   switch (attr->klass->type)
17     {
18     case PANGO_ATTR_LANGUAGE:
19       g_string_append (string, pango_language_to_string (((PangoAttrLanguage *)attr)->value));
20       break;
21     case PANGO_ATTR_FAMILY:
22     case PANGO_ATTR_FONT_FEATURES:
23       g_string_append (string, ((PangoAttrString *)attr)->value);
24       break;
25     case PANGO_ATTR_STYLE:
26     case PANGO_ATTR_WEIGHT:
27     case PANGO_ATTR_VARIANT:
28     case PANGO_ATTR_STRETCH:
29     case PANGO_ATTR_SIZE:
30     case PANGO_ATTR_ABSOLUTE_SIZE:
31     case PANGO_ATTR_UNDERLINE:
32     case PANGO_ATTR_OVERLINE:
33     case PANGO_ATTR_STRIKETHROUGH:
34     case PANGO_ATTR_RISE:
35     case PANGO_ATTR_FALLBACK:
36     case PANGO_ATTR_LETTER_SPACING:
37     case PANGO_ATTR_GRAVITY:
38     case PANGO_ATTR_GRAVITY_HINT:
39     case PANGO_ATTR_FOREGROUND_ALPHA:
40     case PANGO_ATTR_BACKGROUND_ALPHA:
41     case PANGO_ATTR_ALLOW_BREAKS:
42     case PANGO_ATTR_INSERT_HYPHENS:
43     case PANGO_ATTR_SHOW:
44 #if PANGO_VERSION_CHECK(1, 49, 0)
45     case PANGO_ATTR_ABSOLUTE_LINE_HEIGHT:
46     case PANGO_ATTR_TEXT_TRANSFORM:
47     case PANGO_ATTR_WORD:
48     case PANGO_ATTR_SENTENCE:
49     case PANGO_ATTR_BASELINE_SHIFT:
50     case PANGO_ATTR_FONT_SCALE:
51 #endif
52       g_string_append_printf (string, "%d", ((PangoAttrInt *)attr)->value);
53       break;
54     case PANGO_ATTR_FONT_DESC:
55       {
56         char *text = pango_font_description_to_string (((PangoAttrFontDesc *)attr)->desc);
57         g_string_append (string, text);
58         g_free (text);
59       }
60       break;
61     case PANGO_ATTR_FOREGROUND:
62     case PANGO_ATTR_BACKGROUND:
63     case PANGO_ATTR_UNDERLINE_COLOR:
64     case PANGO_ATTR_OVERLINE_COLOR:
65     case PANGO_ATTR_STRIKETHROUGH_COLOR:
66       {
67         char *text = pango_color_to_string (&((PangoAttrColor *)attr)->color);
68         g_string_append (string, text);
69         g_free (text);
70       }
71       break;
72     case PANGO_ATTR_SHAPE:
73       g_string_append_printf (string, "shape");
74       break;
75     case PANGO_ATTR_SCALE:
76 #if PANGO_VERSION_CHECK(1, 49, 0)
77     case PANGO_ATTR_LINE_HEIGHT:
78 #endif
79       {
80         char val[20];
81 
82         g_ascii_formatd (val, 20, "%f", ((PangoAttrFloat *)attr)->value);
83         g_string_append (string, val);
84      }
85       break;
86     case PANGO_ATTR_INVALID:
87     default:
88       g_assert_not_reached ();
89       break;
90     }
91 }
92 
93 void
print_attr_list(PangoAttrList * attrs,GString * string)94 print_attr_list (PangoAttrList *attrs, GString *string)
95 {
96   PangoAttrIterator *iter;
97 
98   if (!attrs)
99     return;
100 
101   iter = pango_attr_list_get_iterator (attrs);
102   do {
103     int start, end;
104     GSList *list, *l;
105 
106     pango_attr_iterator_range (iter, &start, &end);
107     g_string_append_printf (string, "range %d %d\n", start, end);
108     list = pango_attr_iterator_get_attrs (iter);
109     for (l = list; l; l = l->next)
110       {
111         PangoAttribute *attr = l->data;
112         print_attribute (attr, string);
113         g_string_append (string, "\n");
114       }
115     g_slist_free_full (list, (GDestroyNotify)pango_attribute_destroy);
116   } while (pango_attr_iterator_next (iter));
117 
118   pango_attr_iterator_destroy (iter);
119 }
120 
121 static void
test_label_markup(void)122 test_label_markup (void)
123 {
124   GtkWidget *window;
125   GtkWidget *label;
126   PangoAttrList *attrs;
127   GString *str;
128   const char *text;
129 
130   window = gtk_window_new ();
131   label = gtk_label_new ("");
132 
133   gtk_window_set_child (GTK_WINDOW (window), label);
134   gtk_window_set_mnemonics_visible (GTK_WINDOW (window), TRUE);
135 
136   gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
137   gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
138   gtk_label_set_label (GTK_LABEL (label), "<a href=\"test\"><span font_style=\"italic\">abc</span> _def</a>");
139 
140   g_assert_cmpuint (gtk_label_get_mnemonic_keyval (GTK_LABEL (label)), ==, 'd');
141 
142   text = pango_layout_get_text (gtk_label_get_layout (GTK_LABEL (label)));
143   g_assert_cmpstr (text, ==, "abc def");
144 
145   attrs = pango_layout_get_attributes (gtk_label_get_layout (GTK_LABEL (label)));
146   str = g_string_new ("");
147   print_attr_list (attrs, str);
148 
149   g_assert_cmpstr (str->str, ==,
150     "range 0 3\n"
151     "[0,4]underline=1\n"
152     "[0,8]foreground=#1b1b6a6acbcb\n"
153     "[0,3]style=2\n"
154     "range 3 4\n"
155     "[0,4]underline=1\n"
156     "[0,8]foreground=#1b1b6a6acbcb\n"
157     "range 4 5\n"
158     "[0,8]foreground=#1b1b6a6acbcb\n"
159     "[4,5]underline=3\n"
160     "range 5 8\n"
161     "[0,8]foreground=#1b1b6a6acbcb\n"
162     "[5,8]underline=1\n"
163     "range 8 2147483647\n");
164 
165 
166   gtk_window_set_mnemonics_visible (GTK_WINDOW (window), FALSE);
167 
168   text = pango_layout_get_text (gtk_label_get_layout (GTK_LABEL (label)));
169   g_assert_cmpstr (text, ==, "abc def");
170 
171   attrs = pango_layout_get_attributes (gtk_label_get_layout (GTK_LABEL (label)));
172   g_string_set_size (str, 0);
173   print_attr_list (attrs, str);
174 
175   g_assert_cmpstr (str->str, ==,
176     "range 0 3\n"
177     "[0,7]underline=1\n"
178     "[0,7]foreground=#1b1b6a6acbcb\n"
179     "[0,3]style=2\n"
180     "range 3 7\n"
181     "[0,7]underline=1\n"
182     "[0,7]foreground=#1b1b6a6acbcb\n"
183     "range 7 2147483647\n");
184 
185   gtk_window_set_mnemonics_visible (GTK_WINDOW (window), TRUE);
186   gtk_label_set_use_underline (GTK_LABEL (label), FALSE);
187 
188   text = pango_layout_get_text (gtk_label_get_layout (GTK_LABEL (label)));
189   g_assert_cmpstr (text, ==, "abc _def");
190 
191   attrs = pango_layout_get_attributes (gtk_label_get_layout (GTK_LABEL (label)));
192   g_string_set_size (str, 0);
193   print_attr_list (attrs, str);
194 
195   g_assert_cmpstr (str->str, ==,
196     "range 0 3\n"
197     "[0,8]underline=1\n"
198     "[0,8]foreground=#1b1b6a6acbcb\n"
199     "[0,3]style=2\n"
200     "range 3 8\n"
201     "[0,8]underline=1\n"
202     "[0,8]foreground=#1b1b6a6acbcb\n"
203     "range 8 2147483647\n");
204 
205   g_string_free (str, TRUE);
206 
207   gtk_window_destroy (GTK_WINDOW (window));
208 }
209 
210 static void
test_label_underline(void)211 test_label_underline (void)
212 {
213   GtkWidget *window;
214   GtkWidget *label;
215 
216   window = gtk_window_new ();
217 
218   label = gtk_label_new ("");
219 
220   gtk_window_set_child (GTK_WINDOW (window), label);
221   gtk_window_set_mnemonics_visible (GTK_WINDOW (window), TRUE);
222 
223   gtk_label_set_use_markup (GTK_LABEL (label), FALSE);
224   gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
225   gtk_label_set_label (GTK_LABEL (label), "tes_t & no markup <<");
226 
227   g_assert_cmpint (gtk_label_get_mnemonic_keyval (GTK_LABEL (label)), ==, GDK_KEY_t);
228 
229   gtk_window_destroy (GTK_WINDOW (window));
230 }
231 
232 static void
test_label_parse_more(void)233 test_label_parse_more (void)
234 {
235   struct {
236     const char *input;
237     gboolean use_underline;
238     gboolean use_markup;
239     const char *text;
240     guint accel;
241   } tests[] = {
242     { "tes_t m__e mo_re", TRUE, FALSE, "test m_e more", GDK_KEY_t },
243     { "test m__e mo_re", TRUE, FALSE, "test m_e more", GDK_KEY_r },
244     { "tes_t m__e mo_re", FALSE, FALSE, "tes_t m__e mo_re", GDK_KEY_VoidSymbol },
245     { "<span font='test_font'>test <a href='bla'>w_ith</a> bla</span>", TRUE, TRUE, "test with bla", GDK_KEY_i },
246     { "<span font='test_font'>test <a href='bla'>w_ith</a> bla</span>", FALSE, TRUE, "test w_ith bla", GDK_KEY_VoidSymbol },
247   };
248   GtkWidget *label;
249 
250   label = gtk_label_new ("");
251 
252   for (int i = 0; i < G_N_ELEMENTS (tests); i++)
253     {
254       gtk_label_set_use_underline (GTK_LABEL (label), tests[i].use_underline);
255       gtk_label_set_use_markup (GTK_LABEL (label), tests[i].use_markup);
256       gtk_label_set_label (GTK_LABEL (label), tests[i].input);
257 
258       g_assert_cmpstr (gtk_label_get_label (GTK_LABEL (label)), ==, tests[i].input);
259       g_assert_cmpstr (gtk_label_get_text (GTK_LABEL (label)), ==, tests[i].text);
260       g_assert_cmpuint (gtk_label_get_mnemonic_keyval (GTK_LABEL (label)), ==, tests[i].accel);
261     }
262 
263   g_object_ref_sink (label);
264   g_object_unref (label);
265 }
266 
267 int
main(int argc,char * argv[])268 main (int argc, char *argv[])
269 {
270   gtk_test_init (&argc, &argv);
271 
272   g_test_add_func ("/label/markup-parse", test_label_markup);
273   g_test_add_func ("/label/underline-parse", test_label_underline);
274   g_test_add_func ("/label/parse-more", test_label_parse_more);
275 
276   return g_test_run ();
277 }
278