]> Pileus Git - ~andy/gtk/blob - gtk/gtklabel.c
Add properties for labels, mnemonics and stock items. Added C accessor
[~andy/gtk] / gtk / gtklabel.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free
16  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18
19 /*
20  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
21  * file for a list of people on the GTK+ Team.  See the ChangeLog
22  * files for a list of changes.  These files are distributed with
23  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
24  */
25
26 #include <math.h>
27 #include <string.h>
28 #include "gtklabel.h"
29 #include "gtksignal.h"
30 #include "gtkwindow.h"
31 #include "gdk/gdkkeysyms.h"
32 #include "gtkclipboard.h"
33 #include "gdk/gdki18n.h"
34 #include <pango/pango.h>
35 #include "gtkintl.h"
36 #include "gtkmenuitem.h"
37 #include "gtknotebook.h"
38
39 struct _GtkLabelSelectionInfo
40 {
41   GdkWindow *window;
42   gint selection_anchor;
43   gint selection_end;
44 };
45
46
47 enum {
48   PROP_0,
49   PROP_LABEL,
50   PROP_ATTRIBUTES,
51   PROP_USE_MARKUP,
52   PROP_USE_UNDERLINE,
53   PROP_JUSTIFY,
54   PROP_PATTERN,
55   PROP_WRAP,
56   PROP_SELECTABLE,
57   PROP_MNEMONIC_KEYVAL,
58   PROP_MNEMONIC_WIDGET
59 };
60
61 static void gtk_label_class_init        (GtkLabelClass    *klass);
62 static void gtk_label_init              (GtkLabel         *label);
63 static void gtk_label_set_property      (GObject          *object,
64                                          guint             prop_id,
65                                          const GValue     *value,
66                                          GParamSpec       *pspec);
67 static void gtk_label_get_property      (GObject          *object,
68                                          guint             prop_id,
69                                          GValue           *value,
70                                          GParamSpec       *pspec);
71 static void gtk_label_destroy           (GtkObject        *object);
72 static void gtk_label_finalize          (GObject          *object);
73 static void gtk_label_size_request      (GtkWidget        *widget,
74                                          GtkRequisition   *requisition);
75 static void gtk_label_size_allocate     (GtkWidget        *widget,
76                                          GtkAllocation    *allocation);
77 static void gtk_label_state_changed     (GtkWidget        *widget,
78                                          GtkStateType      state);
79 static void gtk_label_style_set         (GtkWidget        *widget,
80                                          GtkStyle         *previous_style);
81 static void gtk_label_direction_changed (GtkWidget        *widget,
82                                          GtkTextDirection  previous_dir);
83 static gint gtk_label_expose            (GtkWidget        *widget,
84                                          GdkEventExpose   *event);
85
86 static void gtk_label_realize           (GtkWidget        *widget);
87 static void gtk_label_unrealize         (GtkWidget        *widget);
88 static void gtk_label_map               (GtkWidget        *widget);
89 static void gtk_label_unmap             (GtkWidget        *widget);
90 static gint gtk_label_button_press      (GtkWidget        *widget,
91                                          GdkEventButton   *event);
92 static gint gtk_label_button_release    (GtkWidget        *widget,
93                                          GdkEventButton   *event);
94 static gint gtk_label_motion            (GtkWidget        *widget,
95                                          GdkEventMotion   *event);
96
97
98 static void gtk_label_set_text_internal          (GtkLabel      *label,
99                                                   gchar         *str);
100 static void gtk_label_set_label_internal         (GtkLabel      *label,
101                                                   gchar         *str);
102 static void gtk_label_set_use_markup_internal    (GtkLabel      *label,
103                                                   gboolean       val);
104 static void gtk_label_set_use_underline_internal (GtkLabel      *label,
105                                                   gboolean       val);
106 static void gtk_label_set_attributes_internal    (GtkLabel      *label,
107                                                   PangoAttrList *attrs);
108 static void gtk_label_set_uline_text_internal    (GtkLabel      *label,
109                                                   const gchar   *str);
110 static void gtk_label_set_pattern_internal       (GtkLabel      *label,
111                                                   const gchar   *pattern);
112 static void set_markup                           (GtkLabel      *label,
113                                                   const gchar   *str,
114                                                   gboolean       with_uline);
115 static void gtk_label_recalculate                (GtkLabel      *label);
116 static void gtk_label_hierarchy_changed          (GtkWidget     *widget,
117                                                   GtkWidget     *old_toplevel);
118
119 static void gtk_label_create_window       (GtkLabel *label);
120 static void gtk_label_destroy_window      (GtkLabel *label);
121 static void gtk_label_clear_layout        (GtkLabel *label);
122 static void gtk_label_ensure_layout       (GtkLabel *label,
123                                            gint     *widthp,
124                                            gint     *heightp);
125 static void gtk_label_select_region_index (GtkLabel *label,
126                                            gint      anchor_index,
127                                            gint      end_index);
128
129 static gboolean gtk_label_mnemonic_activate (GtkWidget *widget,
130                                              gboolean   group_cycling);
131 static void     gtk_label_setup_mnemonic    (GtkLabel  *label,
132                                              guint      last_key);
133
134
135 static GtkMiscClass *parent_class = NULL;
136
137
138 GtkType
139 gtk_label_get_type (void)
140 {
141   static GtkType label_type = 0;
142   
143   if (!label_type)
144     {
145       static const GTypeInfo label_info =
146       {
147         sizeof (GtkLabelClass),
148         NULL,           /* base_init */
149         NULL,           /* base_finalize */
150         (GClassInitFunc) gtk_label_class_init,
151         NULL,           /* class_finalize */
152         NULL,           /* class_data */
153         sizeof (GtkLabel),
154         32,             /* n_preallocs */
155         (GInstanceInitFunc) gtk_label_init,
156       };
157
158       label_type = g_type_register_static (GTK_TYPE_MISC, "GtkLabel", &label_info, 0);
159     }
160   
161   return label_type;
162 }
163
164 static void
165 gtk_label_class_init (GtkLabelClass *class)
166 {
167   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
168   GtkObjectClass *object_class = GTK_OBJECT_CLASS (class);
169   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
170
171   parent_class = gtk_type_class (GTK_TYPE_MISC);
172   
173   gobject_class->set_property = gtk_label_set_property;
174   gobject_class->get_property = gtk_label_get_property;
175   gobject_class->finalize = gtk_label_finalize;
176
177   object_class->destroy = gtk_label_destroy;
178   
179   widget_class->size_request = gtk_label_size_request;
180   widget_class->size_allocate = gtk_label_size_allocate;
181   widget_class->state_changed = gtk_label_state_changed;
182   widget_class->style_set = gtk_label_style_set;
183   widget_class->direction_changed = gtk_label_direction_changed;
184   widget_class->expose_event = gtk_label_expose;
185   widget_class->realize = gtk_label_realize;
186   widget_class->unrealize = gtk_label_unrealize;
187   widget_class->map = gtk_label_map;
188   widget_class->unmap = gtk_label_unmap;
189   widget_class->button_press_event = gtk_label_button_press;
190   widget_class->button_release_event = gtk_label_button_release;
191   widget_class->motion_notify_event = gtk_label_motion;
192   widget_class->hierarchy_changed = gtk_label_hierarchy_changed;
193   widget_class->mnemonic_activate = gtk_label_mnemonic_activate;
194
195   g_object_class_install_property (G_OBJECT_CLASS(object_class),
196                                    PROP_LABEL,
197                                    g_param_spec_string ("label",
198                                                         _("Label"),
199                                                         _("The text of the label."),
200                                                         NULL,
201                                                         G_PARAM_READWRITE));
202   g_object_class_install_property (gobject_class,
203                                    PROP_ATTRIBUTES,
204                                    g_param_spec_boxed ("attributes",
205                                                        _("Attributes"),
206                                                        _("A list of style attributes to apply to the text of the label."),
207                                                        PANGO_TYPE_ATTR_LIST,
208                                                        G_PARAM_READWRITE));
209   g_object_class_install_property (gobject_class,
210                                    PROP_USE_MARKUP,
211                                    g_param_spec_boolean ("use_markup",
212                                                          _("Use markup"),
213                                                          _("The text of the label includes XML markup. See pango_parse_markup()."),
214                                                         FALSE,
215                                                         G_PARAM_READWRITE));
216   g_object_class_install_property (gobject_class,
217                                    PROP_USE_UNDERLINE,
218                                    g_param_spec_boolean ("use_underline",
219                                                          _("Use underline"),
220                                                          _("If set, an underline in the text indicates the next character should be used for the mnemonic accelerator key"),
221                                                         FALSE,
222                                                         G_PARAM_READWRITE));
223
224   g_object_class_install_property (gobject_class,
225                                    PROP_JUSTIFY,
226                                    g_param_spec_enum ("justify",
227                                                       _("Justification"),
228                                                       _("The alignment of the lines in the text of the label relative to each other. This does NOT affect the alignment of the label within its allocation. See GtkMisc::xalign for that."),
229                                                       GTK_TYPE_JUSTIFICATION,
230                                                       GTK_JUSTIFY_LEFT,
231                                                       G_PARAM_READWRITE));
232
233   g_object_class_install_property (gobject_class,
234                                    PROP_PATTERN,
235                                    g_param_spec_string ("pattern",
236                                                         _("Pattern"),
237                                                         _("A string with _ characters in positions correspond to characters in the text to underline."),
238                                                         NULL,
239                                                         G_PARAM_WRITABLE));
240
241   g_object_class_install_property (gobject_class,
242                                    PROP_WRAP,
243                                    g_param_spec_boolean ("wrap",
244                                                         _("Line wrap"),
245                                                         _("If set, wrap lines if the text becomes too wide."),
246                                                         TRUE,
247                                                         G_PARAM_READWRITE));
248   g_object_class_install_property (gobject_class,
249                                    PROP_SELECTABLE,
250                                    g_param_spec_boolean ("selectable",
251                                                         _("Selectable"),
252                                                         _("Whether the label text can be selected with the mouse."),
253                                                         FALSE,
254                                                         G_PARAM_READWRITE));
255   g_object_class_install_property (gobject_class,
256                                    PROP_MNEMONIC_KEYVAL,
257                                    g_param_spec_uint ("mnemonic_keyval",
258                                                       _("Mnemonic key"),
259                                                       _("The mnemonic accelerator key for this label."),
260                                                       0,
261                                                       G_MAXUINT,
262                                                       GDK_VoidSymbol,
263                                                       G_PARAM_READABLE));
264   g_object_class_install_property (gobject_class,
265                                    PROP_MNEMONIC_WIDGET,
266                                    g_param_spec_object ("mnemonic_widget",
267                                                         _("Mnemonic widget"),
268                                                         _("The widget to be activated when the label's mnemonic "
269                                                           "key is pressed."),
270                                                         GTK_TYPE_WIDGET,
271                                                         G_PARAM_READWRITE));
272 }
273
274 static void 
275 gtk_label_set_property (GObject      *object,
276                         guint         prop_id,
277                         const GValue *value,
278                         GParamSpec   *pspec)
279 {
280   GtkLabel *label;
281   guint last_keyval;
282
283   label = GTK_LABEL (object);
284   last_keyval = label->mnemonic_keyval;
285   
286   switch (prop_id)
287     {
288     case PROP_LABEL:
289       gtk_label_set_label (label, g_value_get_string (value));
290       break;
291     case PROP_ATTRIBUTES:
292       gtk_label_set_attributes (label, g_value_get_boxed (value));
293       break;
294     case PROP_USE_MARKUP:
295       gtk_label_set_use_markup (label, g_value_get_boolean (value));
296       break;
297     case PROP_USE_UNDERLINE:
298       gtk_label_set_use_underline (label, g_value_get_boolean (value));
299       break;
300     case PROP_JUSTIFY:
301       gtk_label_set_justify (label, g_value_get_enum (value));
302       break;
303     case PROP_PATTERN:
304       gtk_label_set_pattern (label, g_value_get_string (value));
305       break;
306     case PROP_WRAP:
307       gtk_label_set_line_wrap (label, g_value_get_boolean (value));
308       break;      
309     case PROP_SELECTABLE:
310       gtk_label_set_selectable (label, g_value_get_boolean (value));
311       break;      
312     case PROP_MNEMONIC_WIDGET:
313       gtk_label_set_mnemonic_widget (label, (GtkWidget*) g_value_get_object (value));
314       break;
315     default:
316       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
317       break;
318     }
319 }
320
321 static void 
322 gtk_label_get_property (GObject     *object,
323                         guint        prop_id,
324                         GValue      *value,
325                         GParamSpec  *pspec)
326 {
327   GtkLabel *label;
328   
329   label = GTK_LABEL (object);
330   
331   switch (prop_id)
332     {
333     case PROP_LABEL:
334       g_value_set_string (value, label->label);
335       break;
336     case PROP_ATTRIBUTES:
337       g_value_set_boxed (value, label->attrs);
338       break;
339     case PROP_USE_MARKUP:
340       g_value_set_boolean (value, label->use_markup);
341       break;
342     case PROP_USE_UNDERLINE:
343       g_value_set_boolean (value, label->use_underline);
344       break;
345     case PROP_JUSTIFY:
346       g_value_set_enum (value, label->jtype);
347       break;
348     case PROP_WRAP:
349       g_value_set_boolean (value, label->wrap);
350       break;
351     case PROP_SELECTABLE:
352       g_value_set_boolean (value, gtk_label_get_selectable (label));
353       break;
354     case PROP_MNEMONIC_KEYVAL:
355       g_value_set_uint (value, label->mnemonic_keyval);
356       break;
357     case PROP_MNEMONIC_WIDGET:
358       g_value_set_object (value, (GObject*) label->mnemonic_widget);
359       break;
360
361     default:
362       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
363       break;
364     }
365 }
366
367 static void
368 gtk_label_init (GtkLabel *label)
369 {
370   GTK_WIDGET_SET_FLAGS (label, GTK_NO_WINDOW);
371   
372   label->label = NULL;
373
374   label->jtype = GTK_JUSTIFY_CENTER;
375   label->wrap = FALSE;
376
377   label->use_underline = FALSE;
378   label->use_markup = FALSE;
379   
380   label->mnemonic_keyval = GDK_VoidSymbol;
381   label->layout = NULL;
382   label->text = NULL;
383   label->attrs = NULL;
384
385   label->mnemonic_widget = NULL;
386   label->mnemonic_window = NULL;
387   
388   gtk_label_set_text (label, "");
389 }
390
391 /**
392  * gtk_label_new:
393  * @str: The text of the label
394  *
395  * Creates a new #GtkLabel, containing the text in @str.
396  *
397  * Return value: the new #GtkLabel
398  **/
399 GtkWidget*
400 gtk_label_new (const gchar *str)
401 {
402   GtkLabel *label;
403   
404   label = gtk_type_new (GTK_TYPE_LABEL);
405
406   if (str && *str)
407     gtk_label_set_text (label, str);
408   
409   return GTK_WIDGET (label);
410 }
411
412 /**
413  * gtk_label_new_with_mnemonic:
414  * @str: The text of the label, with an underscore in front of the
415  *       mnemonic character
416  *
417  * Creates a new #GtkLabel, containing the text in @str.
418  *
419  * If characters in @str are preceded by an underscore, they are
420  * underlined indicating that they represent a keyboard accelerator
421  * called a mnemonic.  The mnemonic key can be used to activate
422  * another widget, chosen automatically, or explicitly using
423  * gtk_label_set_mnemonic_widget().
424  * 
425  * If gtk_label_set_mnemonic_widget()
426  * is not called, then the first activatable ancestor of the #GtkLabel
427  * will be chosen as the mnemonic widget. For instance, if the
428  * label is inside a button or menu item, the button or menu item will
429  * automatically become the mnemonic widget and be activated by
430  * the mnemonic.
431  *
432  * Return value: the new #GtkLabel
433  **/
434 GtkWidget*
435 gtk_label_new_with_mnemonic (const gchar *str)
436 {
437   GtkLabel *label;
438   
439   label = gtk_type_new (GTK_TYPE_LABEL);
440
441   if (str && *str)
442     gtk_label_set_text_with_mnemonic (label, str);
443   
444   return GTK_WIDGET (label);
445 }
446
447 static gboolean
448 gtk_label_mnemonic_activate (GtkWidget *widget,
449                              gboolean   group_cycling)
450 {
451   GtkWidget *parent;
452
453   if (GTK_LABEL (widget)->mnemonic_widget)
454     return gtk_widget_mnemonic_activate (GTK_LABEL (widget)->mnemonic_widget, group_cycling);
455
456   /* Try to find the widget to activate by traversing the
457    * widget's ancestry.
458    */
459   parent = widget->parent;
460   while (parent)
461     {
462       if (GTK_WIDGET_CAN_FOCUS (parent) ||
463           (!group_cycling && GTK_WIDGET_GET_CLASS (parent)->activate_signal) ||
464           (parent->parent && GTK_IS_NOTEBOOK (parent->parent)) ||
465           (GTK_IS_MENU_ITEM (parent)))
466         return gtk_widget_mnemonic_activate (parent, group_cycling);
467       parent = parent->parent;
468     }
469
470   /* barf if there was nothing to activate */
471   g_warning ("Couldn't find a target for a mnemonic activation.");
472   gdk_beep ();
473   
474   return FALSE;
475 }
476
477 static void
478 gtk_label_setup_mnemonic (GtkLabel *label,
479                           guint     last_key)
480 {
481   GtkWidget *toplevel;
482
483   if (last_key != GDK_VoidSymbol && label->mnemonic_window)
484     {
485       gtk_window_remove_mnemonic  (label->mnemonic_window,
486                                    last_key,
487                                    GTK_WIDGET (label));
488       label->mnemonic_window = NULL;
489     }
490   
491   if (label->mnemonic_keyval == GDK_VoidSymbol)
492     return;
493   
494   toplevel = gtk_widget_get_toplevel (GTK_WIDGET (label));
495   if (GTK_WIDGET_TOPLEVEL (toplevel))
496     {
497       gtk_window_add_mnemonic (GTK_WINDOW (toplevel),
498                                label->mnemonic_keyval,
499                                GTK_WIDGET (label));
500       label->mnemonic_window = GTK_WINDOW (toplevel);
501     }
502 }
503
504 static void
505 gtk_label_hierarchy_changed (GtkWidget *widget,
506                              GtkWidget *old_toplevel)
507 {
508   GtkLabel *label = GTK_LABEL (widget);
509   
510   gtk_label_setup_mnemonic (label, label->mnemonic_keyval);
511 }
512
513
514 /**
515  * gtk_label_set_mnemonic_widget:
516  * @label: a #GtkLabel
517  * @widget: the target #GtkWidget 
518  *
519  * If the label has been set so that it has an mnemonic key (using
520  * i.e.  gtk_label_set_markup_with_mnemonic(),
521  * gtk_label_set_text_with_mnemonic(), gtk_label_new_with_mnemonic()
522  * or the "use_underline" property) the label can be associated with a
523  * widget that is the target of the mnemonic. When the label is inside
524  * a widget (like a #GtkButton or a #GtkNotebook tab) it is
525  * automatically associated with the correct widget, but sometimes
526  * (i.e. when the target is a #GtkEntry next to the label) you need to
527  * set it explicitly using this function.
528  *
529  * The target widget will be accelerated by emitting "mnemonic_activate" on it.
530  * The default handler for this signal will activate the widget if there are no
531  * mnemonic collisions and toggle focus between the colliding widgets otherwise.
532  **/
533 void
534 gtk_label_set_mnemonic_widget (GtkLabel  *label,
535                                GtkWidget *widget)
536 {
537   g_return_if_fail (GTK_IS_LABEL (label));
538   if (widget)
539     g_return_if_fail (GTK_IS_WIDGET (widget));
540
541   if (label->mnemonic_widget)
542     gtk_widget_unref (label->mnemonic_widget);
543   label->mnemonic_widget = widget;
544   if (label->mnemonic_widget)
545     gtk_widget_ref (label->mnemonic_widget);
546 }
547
548 /**
549  * gtk_label_get_mnemonic_widget:
550  * @label: a #GtkLabel
551  *
552  * Retrieves the target of the mnemonic (keyboard shortcut) of this
553  * label. See gtk_label_set_mnemonic_widget ().
554  *
555  * Return value: the target of the label's mnemonic, or %NULL if none
556  *               has been set and the default algorithm will be used.
557  **/
558 GtkWidget *
559 gtk_label_get_mnemonic_widget (GtkLabel *label)
560 {
561   g_return_val_if_fail (GTK_IS_LABEL (label), NULL);
562
563   return label->mnemonic_widget;
564 }
565
566 /**
567  * gtk_label_get_mnemonic_keyval:
568  * @label: a #GtkLabel
569  *
570  * If the label has been set so that it has an mnemonic key this function
571  * returns the keyval used for the mnemonic accelerator. If there is no
572  * mnemonic set up it returns #GDK_VoidSymbol.
573  *
574  * Returns: GDK keyval usable for accelerators, or GDK_VoidSymbol
575  **/
576 guint
577 gtk_label_get_mnemonic_keyval (GtkLabel *label)
578 {
579   g_return_val_if_fail (GTK_IS_LABEL (label), GDK_VoidSymbol);
580
581   return label->mnemonic_keyval;
582 }
583
584 static void
585 gtk_label_set_text_internal (GtkLabel *label,
586                              gchar    *str)
587 {
588   g_free (label->text);
589   
590   label->text = str;
591
592   gtk_label_select_region_index (label, 0, 0);
593 }
594
595 static void
596 gtk_label_set_label_internal (GtkLabel *label,
597                               gchar    *str)
598 {
599   g_free (label->label);
600   
601   label->label = str;
602
603   g_object_notify (G_OBJECT (label), "label");
604 }
605
606 static void
607 gtk_label_set_use_markup_internal (GtkLabel *label,
608                                    gboolean  val)
609 {
610   val = val != FALSE;
611   if (label->use_markup != val)
612     {
613       g_object_notify (G_OBJECT (label), "use_markup");
614       label->use_markup = val;
615     }
616 }
617
618 static void
619 gtk_label_set_use_underline_internal (GtkLabel *label,
620                                       gboolean val)
621 {
622   val = val != FALSE;
623   if (label->use_underline != val)
624     {
625       g_object_notify (G_OBJECT (label), "use_underline");
626       label->use_underline = val;
627     }
628 }
629
630 static void
631 gtk_label_set_attributes_internal (GtkLabel      *label,
632                                    PangoAttrList *attrs)
633 {
634   if (attrs)
635     pango_attr_list_ref (attrs);
636   
637   if (label->attrs)
638     pango_attr_list_unref (label->attrs);
639
640   if (!label->use_markup && !label->use_underline)
641     {
642       pango_attr_list_ref (attrs);
643       if (label->effective_attrs)
644         pango_attr_list_unref (label->effective_attrs);
645       label->effective_attrs = attrs;
646     }
647
648   label->attrs = attrs;
649   g_object_notify (G_OBJECT (label), "attributes");
650 }
651
652
653 /* Calculates text, attrs and mnemonic_keyval from
654  * label, use_underline and use_markup
655  */
656 static void
657 gtk_label_recalculate (GtkLabel *label)
658 {
659   if (label->use_markup)
660     set_markup (label, label->label, label->use_underline);
661   else
662     {
663       if (label->use_underline)
664         gtk_label_set_uline_text_internal (label, label->label);
665       else
666         {
667           gtk_label_set_text_internal (label, g_strdup (label->label));
668           if (label->attrs)
669             pango_attr_list_ref (label->attrs);
670           if (label->effective_attrs)
671             pango_attr_list_unref (label->effective_attrs);
672           label->effective_attrs = label->attrs;
673         }
674     }
675
676   if (!label->use_underline)
677     {
678       guint keyval = label->mnemonic_keyval;
679
680       label->mnemonic_keyval = GDK_VoidSymbol;
681       gtk_label_setup_mnemonic (label, keyval);
682     }
683
684   gtk_label_clear_layout (label);  
685   gtk_widget_queue_resize (GTK_WIDGET (label));
686 }
687
688 /**
689  * gtk_label_set_text:
690  * @label: a #GtkLabel
691  * @str: a string
692  *
693  * Sets the text of the label to @str.
694  *
695  * This will also clear any previously set mnemonic accelerators.
696  **/
697 void
698 gtk_label_set_text (GtkLabel    *label,
699                     const gchar *str)
700 {
701   g_return_if_fail (GTK_IS_LABEL (label));
702   
703   gtk_label_set_label_internal (label, g_strdup (str ? str : ""));
704   gtk_label_set_use_markup_internal (label, FALSE);
705   gtk_label_set_use_underline_internal (label, FALSE);
706   
707   gtk_label_recalculate (label);
708 }
709
710 /**
711  * gtk_label_set_attributes:
712  * @label: a #GtkLabel
713  * @attrs: a #PangoAttrList
714  * 
715  * Sets a #PangoAttrList; the attributes in the list are applied to the
716  * label text. The attributes set with this function will be ignored
717  * if label->use_underline or label->use_markup is %TRUE.
718  **/
719 void
720 gtk_label_set_attributes (GtkLabel         *label,
721                           PangoAttrList    *attrs)
722 {
723   g_return_if_fail (GTK_IS_LABEL (label));
724
725   gtk_label_set_attributes_internal (label, attrs);
726   
727   gtk_label_clear_layout (label);  
728   gtk_widget_queue_resize (GTK_WIDGET (label));
729 }
730
731 /**
732  * gtk_label_get_attributes:
733  * @label: a #GtkLabel
734  *
735  * Gets the attribute list that was set on the label using
736  * gtk_label_set_attributes(), if any. This function does
737  * not reflect attributes that come from the labels markup
738  * (see gtk_label_set_markup()). If you want to get the
739  * effective attributes for the label, use
740  * pango_layout_get_attribute (gtk_label_get_layout (label)).
741  *
742  * Return value: the attribute list, or %NULL if none was set.
743  **/
744 PangoAttrList *
745 gtk_label_get_attributes (GtkLabel *label)
746 {
747   g_return_val_if_fail (GTK_IS_LABEL (label), NULL);
748
749   return label->attrs;
750 }
751
752 /**
753  * gtk_label_set_label:
754  * @label: a #GtkLabel
755  * @str: the new text to set for the label
756  *
757  * Sets the text of the label. The label is interpreted as
758  * including embedded underlines and/or Pango markup depending
759  * on the values of label->use_underline and label->use_markup.
760  **/
761 void
762 gtk_label_set_label (GtkLabel    *label,
763                      const gchar *str)
764 {
765   guint last_keyval;
766
767   g_return_if_fail (GTK_IS_LABEL (label));
768   g_return_if_fail (str != NULL);
769
770   last_keyval = label->mnemonic_keyval;
771
772   gtk_label_set_label_internal (label, g_strdup (str));
773   gtk_label_recalculate (label);
774   if (last_keyval != label->mnemonic_keyval)
775     gtk_label_setup_mnemonic (label, last_keyval);
776 }
777
778 /**
779  * gtk_label_get_label:
780  * @label: a #GtkLabel
781  *
782  * Fetches the text from a label widget including any embedded
783  * underlines indicating mnemonics and Pango markup. (See
784  * gtk_label_get_text ()).
785  *
786  * Return value: the text of the label widget. This string is
787  *   owned by the widget and must not be modified or freed.
788  **/
789 G_CONST_RETURN gchar *
790 gtk_label_get_label (GtkLabel *label)
791 {
792   g_return_val_if_fail (GTK_IS_LABEL (label), NULL);
793
794   return label->label;
795 }
796
797 static void
798 set_markup (GtkLabel    *label,
799             const gchar *str,
800             gboolean     with_uline)
801 {
802   gchar *text = NULL;
803   GError *error = NULL;
804   PangoAttrList *attrs = NULL;
805   gunichar accel_char = 0;
806
807   if (!pango_parse_markup (str,
808                            -1,
809                            with_uline ? '_' : 0,
810                            &attrs,
811                            &text,
812                            with_uline ? &accel_char : NULL,
813                            &error))
814     {
815       g_warning ("Failed to set label from markup due to error parsing markup: %s",
816                  error->message);
817       g_error_free (error);
818       return;
819     }
820
821   if (text)
822     gtk_label_set_text_internal (label, text);
823
824   if (attrs)
825     {
826       if (label->effective_attrs)
827         pango_attr_list_unref (label->effective_attrs);
828       label->effective_attrs = attrs;
829     }
830
831   if (accel_char != 0)
832     label->mnemonic_keyval = gdk_keyval_to_lower (gdk_unicode_to_keyval (accel_char));
833   else
834     label->mnemonic_keyval = GDK_VoidSymbol;
835 }
836
837 /**
838  * gtk_label_set_markup:
839  * @label: a #GtkLabel
840  * @str: a markup string (see <link linkend="PangoMarkupFormat">Pango markup format</link>)
841  * 
842  * Parses @str which is marked up with the Pango text markup language,
843  * setting the label's text and attribute list based on the parse results.
844  **/
845 void
846 gtk_label_set_markup (GtkLabel    *label,
847                       const gchar *str)
848 {  
849   g_return_if_fail (GTK_IS_LABEL (label));
850
851   gtk_label_set_label_internal (label, g_strdup (str ? str : ""));
852   gtk_label_set_use_markup_internal (label, TRUE);
853   gtk_label_set_use_underline_internal (label, FALSE);
854   
855   gtk_label_recalculate (label);
856 }
857
858 /**
859  * gtk_label_set_markup_with_mnemonic:
860  * @label: a #GtkLabel
861  * @str: a markup string (see <link linkend="PangoMarkupFormat">Pango markup format</link>)
862  * 
863  * Parses @str which is marked up with the Pango text markup language,
864  * setting the label's text and attribute list based on the parse results.
865  * If characters in @str are preceded by an underscore, they are underlined
866  * indicating that they represent a keyboard accelerator called a mnemonic.
867  *
868  * The mnemonic key can be used to activate another widget, chosen automatically,
869  * or explicitly using gtk_label_set_mnemonic_widget().
870  **/
871 void
872 gtk_label_set_markup_with_mnemonic (GtkLabel    *label,
873                                     const gchar *str)
874 {
875   guint last_keyval;
876   g_return_if_fail (GTK_IS_LABEL (label));
877
878   last_keyval = label->mnemonic_keyval;
879   gtk_label_set_label_internal (label, g_strdup (str ? str : ""));
880   gtk_label_set_use_markup_internal (label, TRUE);
881   gtk_label_set_use_underline_internal (label, TRUE);
882   
883   gtk_label_recalculate (label);
884   gtk_label_setup_mnemonic (label, last_keyval);
885 }
886
887 /**
888  * gtk_label_get_text:
889  * @label: a #GtkLabel
890  * 
891  * Fetches the text from a label widget, as displayed on the
892  * screen. This does not include any embedded underlines
893  * indicating mnemonics or Pango markup. (See gtk_label_get_label())
894  * 
895  * Return value: the text in the label widget. This is the internal
896  *   string used by the label, and must not be modified.
897  **/
898 G_CONST_RETURN gchar *
899 gtk_label_get_text (GtkLabel *label)
900 {
901   g_return_val_if_fail (GTK_IS_LABEL (label), NULL);
902
903   return label->text;
904 }
905
906 static PangoAttrList *
907 gtk_label_pattern_to_attrs (GtkLabel      *label,
908                             const gchar   *pattern)
909 {
910   const char *start;
911   const char *p = label->text;
912   const char *q = pattern;
913   PangoAttrList *attrs;
914
915   attrs = pango_attr_list_new ();
916
917   while (1)
918     {
919       while (*p && *q && *q != '_')
920         {
921           p = g_utf8_next_char (p);
922           q++;
923         }
924       start = p;
925       while (*p && *q && *q == '_')
926         {
927           p = g_utf8_next_char (p);
928           q++;
929         }
930       
931       if (p > start)
932         {
933           PangoAttribute *attr = pango_attr_underline_new (PANGO_UNDERLINE_LOW);
934           attr->start_index = start - label->text;
935           attr->end_index = p - label->text;
936           
937           pango_attr_list_insert (attrs, attr);
938         }
939       else
940         break;
941     }
942
943   return attrs;
944 }
945
946 static void
947 gtk_label_set_pattern_internal (GtkLabel    *label,
948                                 const gchar *pattern)
949 {
950   PangoAttrList *attrs;
951   g_return_if_fail (GTK_IS_LABEL (label));
952   
953   attrs = gtk_label_pattern_to_attrs (label, pattern);
954
955   if (label->effective_attrs)
956     pango_attr_list_unref (label->effective_attrs);
957   label->effective_attrs = attrs;
958 }
959
960 void
961 gtk_label_set_pattern (GtkLabel    *label,
962                        const gchar *pattern)
963 {
964   g_return_if_fail (GTK_IS_LABEL (label));
965   
966   gtk_label_set_pattern_internal (label, pattern);
967
968   gtk_label_clear_layout (label);  
969   gtk_widget_queue_resize (GTK_WIDGET (label));
970 }
971
972
973 /**
974  * gtk_label_set_justify:
975  * @label: a #GtkLabel
976  * @jtype: a #GtkJustification
977  *
978  * Sets the alignment of the lines in the text of the label relative to
979  * each other.
980  **/
981 void
982 gtk_label_set_justify (GtkLabel        *label,
983                        GtkJustification jtype)
984 {
985   g_return_if_fail (GTK_IS_LABEL (label));
986   g_return_if_fail (jtype >= GTK_JUSTIFY_LEFT && jtype <= GTK_JUSTIFY_FILL);
987   
988   if ((GtkJustification) label->jtype != jtype)
989     {
990       label->jtype = jtype;
991
992       /* No real need to be this drastic, but easier than duplicating the code */
993       gtk_label_clear_layout (label);
994       
995       g_object_notify (G_OBJECT (label), "justify");
996       gtk_widget_queue_resize (GTK_WIDGET (label));
997     }
998 }
999
1000 /**
1001  * gtk_label_get_justify:
1002  * @label: a #GtkLabel
1003  *
1004  * Returns the justification of the label. See gtk_label_set_justification ().
1005  *
1006  * Return value: GtkJustification
1007  **/
1008 GtkJustification
1009 gtk_label_get_justify (GtkLabel *label)
1010 {
1011   g_return_val_if_fail (GTK_IS_LABEL (label), 0);
1012
1013   return label->jtype;
1014 }
1015
1016 /**
1017  * gtk_label_set_line_wrap:
1018  * @label: a #GtkLabel
1019  * @wrap: the setting
1020  *
1021  * If true, the lines will be wrapped if the text becomes too wide.
1022  */
1023 void
1024 gtk_label_set_line_wrap (GtkLabel *label,
1025                          gboolean  wrap)
1026 {
1027   g_return_if_fail (GTK_IS_LABEL (label));
1028   
1029   wrap = wrap != FALSE;
1030   
1031   if (label->wrap != wrap)
1032     {
1033       label->wrap = wrap;
1034       g_object_notify (G_OBJECT (label), "wrap");
1035       
1036       gtk_widget_queue_resize (GTK_WIDGET (label));
1037     }
1038 }
1039
1040 /**
1041  * gtk_label_get_line_wrap:
1042  * @label: a #GtkLabel
1043  *
1044  * Returns whether lines in the label are automatically wrapped. See gtk_label_set_line_wrap ().
1045  *
1046  * Return value: %TRUE if the lines of the label are automatically wrapped.
1047  */
1048 gboolean
1049 gtk_label_get_line_wrap (GtkLabel *label)
1050 {
1051   g_return_val_if_fail (GTK_IS_LABEL (label), FALSE);
1052
1053   return label->wrap;
1054 }
1055
1056 void
1057 gtk_label_get (GtkLabel *label,
1058                gchar   **str)
1059 {
1060   g_return_if_fail (GTK_IS_LABEL (label));
1061   g_return_if_fail (str != NULL);
1062   
1063   *str = label->text;
1064 }
1065
1066 static void
1067 gtk_label_destroy (GtkObject *object)
1068 {
1069   GtkLabel *label = GTK_LABEL (object);
1070
1071   gtk_label_set_mnemonic_widget (label, NULL);
1072
1073   GTK_OBJECT_CLASS (parent_class)->destroy (object);
1074 }
1075
1076 static void
1077 gtk_label_finalize (GObject *object)
1078 {
1079   GtkLabel *label;
1080   
1081   g_return_if_fail (GTK_IS_LABEL (object));
1082   
1083   label = GTK_LABEL (object);
1084   
1085   g_free (label->label);
1086   g_free (label->text);
1087
1088   if (label->layout)
1089     g_object_unref (G_OBJECT (label->layout));
1090
1091   if (label->attrs)
1092     pango_attr_list_unref (label->attrs);
1093
1094   if (label->effective_attrs)
1095     pango_attr_list_unref (label->effective_attrs);
1096
1097   g_free (label->select_info);
1098
1099   G_OBJECT_CLASS (parent_class)->finalize (object);
1100 }
1101
1102 static void
1103 gtk_label_clear_layout (GtkLabel *label)
1104 {
1105   if (label->layout)
1106     {
1107       g_object_unref (G_OBJECT (label->layout));
1108       label->layout = NULL;
1109     }
1110 }
1111
1112 static void
1113 gtk_label_ensure_layout (GtkLabel *label,
1114                          gint     *widthp,
1115                          gint     *heightp)
1116 {
1117   GtkWidget *widget;
1118   PangoRectangle logical_rect;
1119   gint rwidth, rheight;
1120
1121   widget = GTK_WIDGET (label);
1122
1123   /*
1124    * There are a number of conditions which will necessitate re-filling
1125    * our text:
1126    *
1127    *     1. text changed.
1128    *     2. justification changed either from to to GTK_JUSTIFY_FILL.
1129    *     3. font changed.
1130    *
1131    * These have been detected elsewhere, and label->words will be zero,
1132    * if one of the above has occured.
1133    *
1134    * Additionally, though, if GTK_JUSTIFY_FILL, we need to re-fill if:
1135    *
1136    *     4. gtk_widget_set_usize has changed the requested width.
1137    *     5. gtk_misc_set_padding has changed xpad.
1138    *     6.  maybe others?...
1139    *
1140    * Too much of a pain to detect all these case, so always re-fill.  I
1141    * don't think it's really that slow.
1142    */
1143
1144   rwidth = label->misc.xpad * 2;
1145   rheight = label->misc.ypad * 2;
1146
1147   if (!label->layout)
1148     {
1149       PangoAlignment align = PANGO_ALIGN_LEFT; /* Quiet gcc */
1150
1151       label->layout = gtk_widget_create_pango_layout (widget, label->text);
1152
1153       if (label->effective_attrs)
1154         pango_layout_set_attributes (label->layout, label->effective_attrs);
1155       
1156       switch (label->jtype)
1157         {
1158         case GTK_JUSTIFY_LEFT:
1159           align = PANGO_ALIGN_LEFT;
1160           break;
1161         case GTK_JUSTIFY_RIGHT:
1162           align = PANGO_ALIGN_RIGHT;
1163           break;
1164         case GTK_JUSTIFY_CENTER:
1165           align = PANGO_ALIGN_LEFT;
1166           break;
1167         case GTK_JUSTIFY_FILL:
1168           /* FIXME: This just doesn't work to do this */
1169           align = PANGO_ALIGN_LEFT;
1170           pango_layout_set_justify (label->layout, TRUE);
1171           break;
1172         default:
1173           g_assert_not_reached();
1174         }
1175
1176       pango_layout_set_alignment (label->layout, align);
1177     }
1178
1179   if (label->wrap)
1180     {
1181       GtkWidgetAuxInfo *aux_info;
1182       gint longest_paragraph;
1183       gint width, height;
1184       gint real_width;
1185
1186       aux_info = _gtk_widget_get_aux_info (widget, FALSE);
1187       if (aux_info && aux_info->width > 0)
1188         {
1189           pango_layout_set_width (label->layout, aux_info->width * PANGO_SCALE);
1190           pango_layout_get_extents (label->layout, NULL, &logical_rect);
1191
1192           rwidth += aux_info->width;
1193           rheight += PANGO_PIXELS (logical_rect.height);
1194         }
1195       else
1196         {
1197           pango_layout_set_width (label->layout, -1);
1198           pango_layout_get_extents (label->layout, NULL, &logical_rect);
1199       
1200           width = logical_rect.width;
1201           height = logical_rect.height;
1202           
1203           /* Try to guess a reasonable maximum width
1204            */
1205           longest_paragraph = width;
1206
1207           width = MIN (width,
1208                        PANGO_SCALE * gdk_string_width (GTK_WIDGET (label)->style->font,
1209                                                 "This long string gives a good enough length for any line to have."));
1210           width = MIN (width,
1211                        PANGO_SCALE * (gdk_screen_width () + 1) / 2);
1212
1213           pango_layout_set_width (label->layout, width);
1214           pango_layout_get_extents (label->layout, NULL, &logical_rect);
1215           real_width = logical_rect.width;
1216           height = logical_rect.height;
1217           
1218           /* Unfortunately, the above may leave us with a very unbalanced looking paragraph,
1219            * so we try short search for a narrower width that leaves us with the same height
1220            */
1221           if (longest_paragraph > 0)
1222             {
1223               gint nlines, perfect_width;
1224
1225               nlines = pango_layout_get_line_count (label->layout);
1226               perfect_width = (longest_paragraph + nlines - 1) / nlines;
1227               
1228               if (perfect_width < width)
1229                 {
1230                   pango_layout_set_width (label->layout, perfect_width);
1231                   pango_layout_get_extents (label->layout, NULL, &logical_rect);
1232                   
1233                   if (logical_rect.height <= height)
1234                     {
1235                       width = perfect_width;
1236                       real_width = logical_rect.width;
1237                       height = logical_rect.height;
1238                     }
1239                   else
1240                     {
1241                       gint mid_width = (perfect_width + width) / 2;
1242
1243                       if (mid_width > perfect_width)
1244                         {
1245                           pango_layout_set_width (label->layout, mid_width);
1246                           pango_layout_get_extents (label->layout, NULL, &logical_rect);
1247
1248                           if (logical_rect.height <= height)
1249                             {
1250                               width = mid_width;
1251                               real_width = logical_rect.width;
1252                               height = logical_rect.height;
1253                             }
1254                         }
1255                     }
1256                 }
1257             }
1258           pango_layout_set_width (label->layout, width);
1259
1260           rwidth += PANGO_PIXELS (real_width);
1261           rheight += PANGO_PIXELS (height);
1262         }
1263     }
1264   else                          /* !label->wrap */
1265     {
1266       pango_layout_set_width (label->layout, -1);
1267       pango_layout_get_extents (label->layout, NULL, &logical_rect);
1268
1269       rwidth += PANGO_PIXELS (logical_rect.width);
1270       rheight += PANGO_PIXELS (logical_rect.height);
1271     }
1272
1273   if (widthp)
1274     *widthp = rwidth;
1275
1276   if (heightp)
1277     *heightp = rheight;
1278 }
1279
1280 static void
1281 gtk_label_size_request (GtkWidget      *widget,
1282                         GtkRequisition *requisition)
1283 {
1284   GtkLabel *label;
1285   gint width, height;
1286   
1287   g_return_if_fail (GTK_IS_LABEL (widget));
1288   g_return_if_fail (requisition != NULL);
1289   
1290   label = GTK_LABEL (widget);
1291
1292   gtk_label_ensure_layout (label, &width, &height);
1293
1294   requisition->width = width;
1295   requisition->height = height;
1296 }
1297
1298 static void
1299 gtk_label_size_allocate (GtkWidget     *widget,
1300                          GtkAllocation *allocation)
1301 {
1302   GtkLabel *label;
1303
1304   label = GTK_LABEL (widget);
1305   
1306   (* GTK_WIDGET_CLASS (parent_class)->size_allocate) (widget, allocation);
1307
1308   if (label->select_info && label->select_info->window)
1309     {
1310       gdk_window_move_resize (label->select_info->window,
1311                               allocation->x,
1312                               allocation->y,
1313                               allocation->width,
1314                               allocation->height);
1315     }
1316 }
1317
1318 static void
1319 gtk_label_state_changed (GtkWidget   *widget,
1320                          GtkStateType prev_state)
1321 {
1322   GtkLabel *label;
1323   
1324   label = GTK_LABEL (widget);
1325
1326   if (label->select_info)
1327     gtk_label_select_region (label, 0, 0);
1328
1329   if (GTK_WIDGET_CLASS (parent_class)->state_changed)
1330     GTK_WIDGET_CLASS (parent_class)->state_changed (widget, prev_state);
1331 }
1332
1333 static void 
1334 gtk_label_style_set (GtkWidget *widget,
1335                      GtkStyle  *previous_style)
1336 {
1337   GtkLabel *label;
1338   
1339   g_return_if_fail (GTK_IS_LABEL (widget));
1340   
1341   label = GTK_LABEL (widget);
1342
1343   /* We have to clear the layout, fonts etc. may have changed */
1344   gtk_label_clear_layout (label);
1345 }
1346
1347 static void 
1348 gtk_label_direction_changed (GtkWidget        *widget,
1349                              GtkTextDirection previous_dir)
1350 {
1351   GtkLabel *label = GTK_LABEL (widget);
1352
1353   if (label->layout)
1354     pango_layout_context_changed (label->layout);
1355
1356   GTK_WIDGET_CLASS (parent_class)->direction_changed (widget, previous_dir);
1357 }
1358
1359 #if 0
1360 static void
1361 gtk_label_paint_word (GtkLabel     *label,
1362                       gint          x,
1363                       gint          y,
1364                       GtkLabelWord *word,
1365                       GdkRectangle *area)
1366 {
1367   GtkWidget *widget = GTK_WIDGET (label);
1368   GtkLabelULine *uline;
1369   gchar *tmp_str;
1370   
1371   tmp_str = gdk_wcstombs (word->beginning);
1372   if (tmp_str)
1373     {
1374       gtk_paint_string (widget->style, widget->window, widget->state,
1375                         area, widget, "label", 
1376                         x + word->x,
1377                         y + word->y,
1378                         tmp_str);
1379       g_free (tmp_str);
1380     }
1381   
1382   for (uline = word->uline; uline; uline = uline->next)
1383     gtk_paint_hline (widget->style, widget->window, 
1384                      widget->state, area,
1385                      widget, "label", 
1386                      x + uline->x1, x + uline->x2, y + uline->y);
1387 }
1388 #endif
1389
1390 static void
1391 get_layout_location (GtkLabel  *label,
1392                      gint      *xp,
1393                      gint      *yp)
1394 {
1395   GtkMisc *misc;
1396   GtkWidget *widget;
1397   gfloat xalign;
1398   gint x, y;
1399   
1400   misc = GTK_MISC (label);
1401   widget = GTK_WIDGET (label);
1402   
1403   if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
1404     xalign = misc->xalign;
1405   else
1406     xalign = 1.0 - misc->xalign;
1407   
1408   x = floor (widget->allocation.x + (gint)misc->xpad
1409              + ((widget->allocation.width - widget->requisition.width) * xalign)
1410              + 0.5);
1411   
1412   y = floor (widget->allocation.y + (gint)misc->ypad 
1413              + ((widget->allocation.height - widget->requisition.height) * misc->yalign)
1414              + 0.5);
1415   
1416
1417   if (xp)
1418     *xp = x;
1419
1420   if (yp)
1421     *yp = y;
1422 }
1423
1424 static gint
1425 gtk_label_expose (GtkWidget      *widget,
1426                   GdkEventExpose *event)
1427 {
1428   GtkLabel *label;
1429   gint x, y;
1430   
1431   g_return_val_if_fail (GTK_IS_LABEL (widget), FALSE);
1432   g_return_val_if_fail (event != NULL, FALSE);
1433   
1434   label = GTK_LABEL (widget);
1435
1436   gtk_label_ensure_layout (label, NULL, NULL);
1437   
1438   if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget) &&
1439       label->text && (*label->text != '\0'))
1440     {
1441       get_layout_location (label, &x, &y);
1442       
1443       gtk_paint_layout (widget->style,
1444                         widget->window,
1445                         GTK_WIDGET_STATE (widget),
1446                         FALSE,
1447                         &event->area,
1448                         widget,
1449                         "label",
1450                         x, y,
1451                         label->layout);
1452       
1453       if (label->select_info &&
1454           (label->select_info->selection_anchor !=
1455            label->select_info->selection_end))
1456         {
1457           gint range[2];
1458           GdkRegion *clip;
1459           
1460           range[0] = label->select_info->selection_anchor;
1461           range[1] = label->select_info->selection_end;
1462
1463           if (range[0] > range[1])
1464             {
1465               gint tmp = range[0];
1466               range[0] = range[1];
1467               range[1] = tmp;
1468             }
1469
1470           clip = gdk_pango_layout_get_clip_region (label->layout,
1471                                                    x, y,
1472                                                    range,
1473                                                    1);
1474
1475           /* FIXME should use gtk_paint, but it can't use a clip
1476            * region
1477            */
1478
1479           gdk_gc_set_clip_region (widget->style->white_gc, clip);
1480           
1481           gdk_draw_layout_with_colors (widget->window,
1482                                        widget->style->white_gc,
1483                                        x, y,
1484                                        label->layout,
1485                                        &widget->style->fg[GTK_STATE_SELECTED],
1486                                        &widget->style->bg[GTK_STATE_SELECTED]);
1487
1488           gdk_gc_set_clip_region (widget->style->white_gc, NULL);
1489           gdk_region_destroy (clip);
1490         }
1491     }
1492
1493   return TRUE;
1494 }
1495
1496 void
1497 gtk_label_set_uline_text_internal (GtkLabel    *label,
1498                                    const gchar *str)
1499 {
1500   guint accel_key = GDK_VoidSymbol;
1501
1502   gchar *new_str;
1503   gchar *pattern;
1504   const gchar *src;
1505   gchar *dest, *pattern_dest;
1506   gboolean underscore;
1507       
1508   g_return_if_fail (GTK_IS_LABEL (label));
1509   g_return_if_fail (str != NULL);
1510
1511   /* Convert text to wide characters */
1512
1513   new_str = g_new (gchar, strlen (str) + 1);
1514   pattern = g_new (gchar, g_utf8_strlen (str, -1) + 1);
1515   
1516   underscore = FALSE;
1517
1518   if (str == NULL)
1519     str = "";
1520   
1521   src = str;
1522   dest = new_str;
1523   pattern_dest = pattern;
1524   
1525   while (*src)
1526     {
1527       gunichar c;
1528       gchar *next_src;
1529
1530       c = g_utf8_get_char (src);
1531       if (c == (gunichar)-1)
1532         {
1533           g_warning ("Invalid input string");
1534           g_free (new_str);
1535           g_free (pattern);
1536           return;
1537         }
1538       next_src = g_utf8_next_char (src);
1539       
1540       if (underscore)
1541         {
1542           if (c == '_')
1543             *pattern_dest++ = ' ';
1544           else
1545             {
1546               *pattern_dest++ = '_';
1547               if (accel_key == GDK_VoidSymbol)
1548                 accel_key = gdk_keyval_to_lower (c);
1549             }
1550
1551           while (src < next_src)
1552             *dest++ = *src++;
1553           
1554           underscore = FALSE;
1555         }
1556       else
1557         {
1558           if (c == '_')
1559             {
1560               underscore = TRUE;
1561               src = next_src;
1562             }
1563           else
1564             {
1565               while (src < next_src)
1566                 *dest++ = *src++;
1567           
1568               *pattern_dest++ = ' ';
1569             }
1570         }
1571     }
1572   *dest = 0;
1573   *pattern_dest = 0;
1574   
1575   gtk_label_set_text_internal (label, new_str);
1576   gtk_label_set_pattern_internal (label, pattern);
1577   
1578   g_free (pattern);
1579
1580   label->mnemonic_keyval = accel_key;
1581 }
1582
1583 guint      
1584 gtk_label_parse_uline (GtkLabel    *label,
1585                        const gchar *str)
1586 {
1587   guint keyval;
1588   guint orig_keyval;
1589   
1590   g_return_val_if_fail (GTK_IS_LABEL (label), GDK_VoidSymbol);
1591   g_return_val_if_fail (str != NULL, GDK_VoidSymbol);
1592
1593   orig_keyval = label->mnemonic_keyval;
1594   
1595   gtk_label_set_label_internal (label, g_strdup (str ? str : ""));
1596   gtk_label_set_use_markup_internal (label, FALSE);
1597   gtk_label_set_use_underline_internal (label, TRUE);
1598   
1599   gtk_label_recalculate (label);
1600
1601   keyval = label->mnemonic_keyval;
1602   label->mnemonic_keyval = GDK_VoidSymbol;
1603   
1604   gtk_label_setup_mnemonic (label, orig_keyval);
1605   
1606   return keyval;
1607 }
1608
1609 /**
1610  * gtk_label_set_text_with_mnemonic:
1611  * @label: a #GtkLabel
1612  * @str: a string
1613  * 
1614  * Sets the label's text from the string @str.
1615  * If characters in @str are preceded by an underscore, they are underlined
1616  * indicating that they represent a keyboard accelerator called a mnemonic.
1617  * The mnemonic key can be used to activate another widget, chosen automatically,
1618  * or explicitly using gtk_label_set_mnemonic_widget().
1619  **/
1620 void
1621 gtk_label_set_text_with_mnemonic (GtkLabel    *label,
1622                                   const gchar *str)
1623 {
1624   guint last_keyval;
1625   
1626   g_return_if_fail (GTK_IS_LABEL (label));
1627   g_return_if_fail (str != NULL);
1628
1629   last_keyval = label->mnemonic_keyval;
1630   
1631   gtk_label_set_label_internal (label, g_strdup (str ? str : ""));
1632   gtk_label_set_use_markup_internal (label, FALSE);
1633   gtk_label_set_use_underline_internal (label, TRUE);
1634   
1635   gtk_label_recalculate (label);
1636
1637   gtk_label_setup_mnemonic (label, last_keyval);
1638 }
1639
1640
1641 static void
1642 gtk_label_realize (GtkWidget *widget)
1643 {
1644   GtkLabel *label;
1645
1646   label = GTK_LABEL (widget);
1647   
1648   (* GTK_WIDGET_CLASS (parent_class)->realize) (widget);
1649
1650   if (label->select_info)
1651     gtk_label_create_window (label);
1652 }
1653
1654 static void
1655 gtk_label_unrealize (GtkWidget *widget)
1656 {
1657   GtkLabel *label;
1658
1659   label = GTK_LABEL (widget);
1660
1661   if (label->select_info)
1662     gtk_label_destroy_window (label);
1663   
1664   (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
1665 }
1666
1667 static void
1668 gtk_label_map (GtkWidget *widget)
1669 {
1670   GtkLabel *label;
1671
1672   label = GTK_LABEL (widget);
1673   
1674   (* GTK_WIDGET_CLASS (parent_class)->map) (widget);
1675   
1676   if (label->select_info)
1677     gdk_window_show (label->select_info->window);
1678 }
1679
1680 static void
1681 gtk_label_unmap (GtkWidget *widget)
1682 {
1683   GtkLabel *label;
1684
1685   label = GTK_LABEL (widget);
1686
1687   if (label->select_info)
1688     gdk_window_hide (label->select_info->window);
1689   
1690   (* GTK_WIDGET_CLASS (parent_class)->unmap) (widget);
1691 }
1692
1693 static void
1694 window_to_layout_coords (GtkLabel *label,
1695                          gint     *x,
1696                          gint     *y)
1697 {
1698   gint lx, ly;
1699   GtkWidget *widget;
1700
1701   widget = GTK_WIDGET (label);
1702   
1703   /* get layout location in widget->window coords */
1704   get_layout_location (label, &lx, &ly);
1705   
1706   if (x)
1707     {
1708       *x += widget->allocation.x; /* go to widget->window */
1709       *x -= lx;                   /* go to layout */
1710     }
1711
1712   if (y)
1713     {
1714       *y += widget->allocation.y; /* go to widget->window */
1715       *y -= ly;                   /* go to layout */
1716     }
1717 }
1718
1719 #if 0
1720 static void
1721 layout_to_window_coords (GtkLabel *label,
1722                          gint     *x,
1723                          gint     *y)
1724 {
1725   gint lx, ly;
1726   GtkWidget *widget;
1727
1728   widget = GTK_WIDGET (label);
1729   
1730   /* get layout location in widget->window coords */
1731   get_layout_location (label, &lx, &ly);
1732   
1733   if (x)
1734     {
1735       *x += lx;                   /* go to widget->window */
1736       *x -= widget->allocation.x; /* go to selection window */
1737     }
1738
1739   if (y)
1740     {
1741       *y += ly;                   /* go to widget->window */
1742       *y -= widget->allocation.y; /* go to selection window */
1743     }
1744 }
1745 #endif
1746
1747 static void
1748 get_layout_index (GtkLabel *label,
1749                   gint      x,
1750                   gint      y,
1751                   gint     *index)
1752 {
1753   gint trailing = 0;
1754   const gchar *cluster;
1755   const gchar *cluster_end;
1756
1757   *index = 0;
1758   
1759   gtk_label_ensure_layout (label, NULL, NULL);
1760   
1761   window_to_layout_coords (label, &x, &y);
1762
1763   x *= PANGO_SCALE;
1764   y *= PANGO_SCALE;
1765   
1766   pango_layout_xy_to_index (label->layout,
1767                             x, y,
1768                             index, &trailing);
1769
1770   
1771   cluster = label->text + *index;
1772   cluster_end = cluster;
1773   while (trailing)
1774     {
1775       cluster_end = g_utf8_next_char (cluster_end);
1776       --trailing;
1777     }
1778
1779   *index += (cluster_end - cluster);
1780 }
1781
1782 static gint
1783 gtk_label_button_press (GtkWidget      *widget,
1784                         GdkEventButton *event)
1785 {
1786   GtkLabel *label;
1787   gint index = 0;
1788   
1789   label = GTK_LABEL (widget);
1790
1791   if (label->select_info == NULL)
1792     return FALSE;
1793
1794   if (event->button != 1)
1795     return FALSE;
1796
1797   get_layout_index (label, event->x, event->y, &index);
1798   
1799   if ((label->select_info->selection_anchor !=
1800        label->select_info->selection_end) &&
1801       (event->state & GDK_SHIFT_MASK))
1802     {
1803       /* extend (same as motion) */
1804       if (index < label->select_info->selection_end)
1805         gtk_label_select_region_index (label,
1806                                        index,
1807                                        label->select_info->selection_end);
1808       else
1809         gtk_label_select_region_index (label,
1810                                        label->select_info->selection_anchor,
1811                                        index);
1812
1813       /* ensure the anchor is opposite index */
1814       if (index == label->select_info->selection_anchor)
1815         {
1816           gint tmp = label->select_info->selection_end;
1817           label->select_info->selection_end = label->select_info->selection_anchor;
1818           label->select_info->selection_anchor = tmp;
1819         }
1820     }
1821   else
1822     {
1823       /* start a replacement */
1824       gtk_label_select_region_index (label, index, index);
1825     }
1826   
1827   return TRUE;
1828 }
1829
1830 static gint
1831 gtk_label_button_release (GtkWidget      *widget,
1832                           GdkEventButton *event)
1833
1834 {
1835   GtkLabel *label;
1836
1837   label = GTK_LABEL (widget);
1838   
1839   if (label->select_info == NULL)
1840     return FALSE;
1841   
1842   if (event->button != 1)
1843     return FALSE;
1844   
1845   /* The goal here is to return TRUE iff we ate the
1846    * button press to start selecting.
1847    */
1848   
1849   return TRUE;
1850 }
1851
1852 static gint
1853 gtk_label_motion (GtkWidget      *widget,
1854                   GdkEventMotion *event)
1855 {
1856   GtkLabel *label;
1857   gint index;
1858   gint x, y;
1859   
1860   label = GTK_LABEL (widget);
1861   
1862   if (label->select_info == NULL)
1863     return FALSE;  
1864
1865   if ((event->state & GDK_BUTTON1_MASK) == 0)
1866     return FALSE;
1867
1868   gdk_window_get_pointer (label->select_info->window,
1869                           &x, &y, NULL);
1870   
1871   get_layout_index (label, x, y, &index);
1872
1873   gtk_label_select_region_index (label,
1874                                  label->select_info->selection_anchor,
1875                                  index);
1876   
1877   return TRUE;
1878 }
1879
1880 static void
1881 gtk_label_create_window (GtkLabel *label)
1882 {
1883   GtkWidget *widget;
1884   GdkWindowAttr attributes;
1885   gint attributes_mask;
1886   
1887   g_assert (label->select_info);
1888   g_assert (GTK_WIDGET_REALIZED (label));
1889   
1890   if (label->select_info->window)
1891     return;
1892   
1893   widget = GTK_WIDGET (label);
1894
1895   attributes.x = widget->allocation.x;
1896   attributes.y = widget->allocation.y;
1897   attributes.width = widget->allocation.width;
1898   attributes.height = widget->allocation.height;
1899   attributes.window_type = GDK_WINDOW_TEMP;
1900   attributes.wclass = GDK_INPUT_ONLY;
1901   attributes.override_redirect = TRUE;
1902   attributes.event_mask = gtk_widget_get_events (widget) |
1903     GDK_BUTTON_PRESS_MASK        |
1904     GDK_BUTTON_RELEASE_MASK      |
1905     GDK_BUTTON_MOTION_MASK;
1906
1907   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_NOREDIR;
1908
1909   label->select_info->window = gdk_window_new (widget->window,
1910                                                &attributes, attributes_mask);
1911   gdk_window_set_user_data (label->select_info->window, widget);  
1912 }
1913
1914 static void
1915 gtk_label_destroy_window (GtkLabel *label)
1916 {
1917   g_assert (label->select_info);
1918
1919   if (label->select_info->window == NULL)
1920     return;
1921   
1922   gdk_window_set_user_data (label->select_info->window, NULL);
1923   gdk_window_destroy (label->select_info->window);
1924   label->select_info->window = NULL;
1925 }
1926
1927 /**
1928  * gtk_label_set_selectable:
1929  * @label: a #GtkLabel
1930  * @setting: %TRUE to allow selecting text in the label
1931  *
1932  * Selectable labels allow the user to select text from the label, for
1933  * copy-and-paste.
1934  * 
1935  **/
1936 void
1937 gtk_label_set_selectable (GtkLabel *label,
1938                           gboolean  setting)
1939 {
1940   gboolean old_setting;
1941   
1942   g_return_if_fail (GTK_IS_LABEL (label));
1943   
1944   setting = setting != FALSE;
1945   old_setting = label->select_info != NULL;
1946   
1947   if (setting)
1948     {
1949       if (label->select_info == NULL)
1950         {
1951           label->select_info = g_new (GtkLabelSelectionInfo, 1);
1952
1953           label->select_info->window = NULL;
1954           label->select_info->selection_anchor = 0;
1955           label->select_info->selection_end = 0;
1956
1957           if (GTK_WIDGET_REALIZED (label))
1958             gtk_label_create_window (label);
1959
1960           if (GTK_WIDGET_MAPPED (label))
1961             gdk_window_show (label->select_info->window);
1962         }
1963     }
1964   else
1965     {
1966       if (label->select_info)
1967         {
1968           /* unselect, to give up the selection */
1969           gtk_label_select_region (label, 0, 0);
1970           
1971           if (label->select_info->window)
1972             gtk_label_destroy_window (label);
1973
1974           g_free (label->select_info);
1975
1976           label->select_info = NULL;
1977         }
1978     }
1979   if (setting != old_setting)
1980     {
1981        g_object_notify (G_OBJECT (label), "selectable");
1982        gtk_widget_queue_draw (GTK_WIDGET (label));
1983     }
1984 }
1985
1986 /**
1987  * gtk_label_get_selectable:
1988  * @label: a #GtkLabel
1989  * 
1990  * Gets the value set by gtk_label_set_selectable().
1991  * 
1992  * Return value: %TRUE if the user can copy text from the label
1993  **/
1994 gboolean
1995 gtk_label_get_selectable (GtkLabel *label)
1996 {
1997   g_return_val_if_fail (GTK_IS_LABEL (label), FALSE);
1998
1999   return label->select_info != NULL;
2000 }
2001
2002 static void
2003 get_text_callback (GtkClipboard     *clipboard,
2004                    GtkSelectionData *selection_data,
2005                    guint             info,
2006                    gpointer          user_data_or_owner)
2007 {
2008   GtkLabel *label;
2009   gchar *str;
2010   
2011   label = GTK_LABEL (user_data_or_owner);
2012   
2013   if ((label->select_info->selection_anchor !=
2014        label->select_info->selection_end) &&
2015       label->text)
2016     {
2017       gint start, end;
2018       gint len;
2019       
2020       start = MIN (label->select_info->selection_anchor,
2021                    label->select_info->selection_end);
2022       end = MAX (label->select_info->selection_anchor,
2023                  label->select_info->selection_end);
2024
2025       len = strlen (label->text);
2026
2027       if (end > len)
2028         end = len;
2029
2030       if (start > len)
2031         start = len;
2032
2033       str = g_strndup (label->text + start,
2034                        end - start);
2035       
2036       gtk_selection_data_set_text (selection_data, 
2037                                    str);
2038
2039       g_free (str);
2040     }
2041 }
2042
2043 static void
2044 clear_text_callback (GtkClipboard     *clipboard,
2045                      gpointer          user_data_or_owner)
2046 {
2047   GtkLabel *label;
2048
2049   label = GTK_LABEL (user_data_or_owner);
2050
2051   if (label->select_info)
2052     {
2053       label->select_info->selection_anchor = 0;
2054       label->select_info->selection_end = 0;
2055       
2056       gtk_label_clear_layout (label);
2057       gtk_widget_queue_draw (GTK_WIDGET (label));
2058     }
2059 }
2060
2061 static void
2062 gtk_label_select_region_index (GtkLabel *label,
2063                                gint      anchor_index,
2064                                gint      end_index)
2065 {
2066   static const GtkTargetEntry targets[] = {
2067     { "STRING", 0, 0 },
2068     { "TEXT",   0, 0 }, 
2069     { "COMPOUND_TEXT", 0, 0 },
2070     { "UTF8_STRING", 0, 0 }
2071   };
2072   
2073   g_return_if_fail (GTK_IS_LABEL (label));
2074   
2075   if (label->select_info)
2076     {
2077       GtkClipboard *clipboard;
2078
2079       label->select_info->selection_anchor = anchor_index;
2080       label->select_info->selection_end = end_index;
2081
2082       clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);      
2083       
2084       if (anchor_index != end_index)
2085         {
2086           gtk_clipboard_set_with_owner (clipboard,
2087                                         targets,
2088                                         G_N_ELEMENTS (targets),
2089                                         get_text_callback,
2090                                         clear_text_callback,
2091                                         G_OBJECT (label));
2092         }
2093       else
2094         {
2095           if (gtk_clipboard_get_owner (clipboard) == G_OBJECT (label))
2096             gtk_clipboard_clear (clipboard);
2097         }
2098
2099       gtk_label_clear_layout (label);
2100       gtk_widget_queue_draw (GTK_WIDGET (label));
2101     }
2102 }
2103
2104 /**
2105  * gtk_label_select_region:
2106  * @label: a #GtkLabel
2107  * @start_offset: start offset (in characters not bytes)
2108  * @end_offset: end offset (in characters not bytes)
2109  *
2110  * Selects a range of characters in the label, if the label is selectable.
2111  * See gtk_label_set_selectable(). If the label is not selectable,
2112  * this function has no effect. If @start_offset or
2113  * @end_offset are -1, then the end of the label will be substituted.
2114  * 
2115  **/
2116 void
2117 gtk_label_select_region  (GtkLabel *label,
2118                           gint      start_offset,
2119                           gint      end_offset)
2120 {
2121   g_return_if_fail (GTK_IS_LABEL (label));
2122   
2123   if (label->text && label->select_info)
2124     {
2125       if (start_offset < 0)
2126         start_offset = g_utf8_strlen (label->text, -1);
2127       
2128       if (end_offset < 0)
2129         end_offset = g_utf8_strlen (label->text, -1);
2130       
2131       gtk_label_select_region_index (label,
2132                                      g_utf8_offset_to_pointer (label->text, start_offset) - label->text,
2133                                      g_utf8_offset_to_pointer (label->text, end_offset) - label->text);
2134     }
2135 }
2136
2137 /**
2138  * gtk_label_get_selection_bounds:
2139  * @label: a #GtkLabel
2140  * @start: return location for start of selection, as a character offset
2141  * @end: return location for end of selection, as a character offset
2142  * 
2143  * Gets the selected range of characters in the label, returning %TRUE
2144  * if there's a selection.
2145  * 
2146  * Return value: %TRUE if selection is non-empty
2147  **/
2148 gboolean
2149 gtk_label_get_selection_bounds (GtkLabel  *label,
2150                                 gint      *start,
2151                                 gint      *end)
2152 {
2153   g_return_val_if_fail (GTK_IS_LABEL (label), FALSE);
2154
2155   if (label->select_info == NULL)
2156     {
2157       /* not a selectable label */
2158       if (start)
2159         *start = 0;
2160       if (end)
2161         *end = 0;
2162
2163       return FALSE;
2164     }
2165   else
2166     {
2167       gint start_index, end_index;
2168       gint start_offset, end_offset;
2169       gint len;
2170       
2171       start_index = MIN (label->select_info->selection_anchor,
2172                    label->select_info->selection_end);
2173       end_index = MAX (label->select_info->selection_anchor,
2174                  label->select_info->selection_end);
2175
2176       len = strlen (label->text);
2177
2178       if (end_index > len)
2179         end_index = len;
2180
2181       if (start_index > len)
2182         start_index = len;
2183       
2184       start_offset = g_utf8_strlen (label->text, start_index);
2185       end_offset = g_utf8_strlen (label->text, end_index);
2186
2187       if (start_offset > end_offset)
2188         {
2189           gint tmp = start_offset;
2190           start_offset = end_offset;
2191           end_offset = tmp;
2192         }
2193       
2194       if (start)
2195         *start = start_offset;
2196
2197       if (end)
2198         *end = end_offset;
2199
2200       return start_offset != end_offset;
2201     }
2202 }
2203
2204
2205 /**
2206  * gtk_label_get_layout:
2207  * @label: a #GtkLabel
2208  * 
2209  * Gets the #PangoLayout used to display the label.
2210  * The layout is useful to e.g. convert text positions to
2211  * pixel positions, in combination with gtk_label_get_layout_offsets().
2212  * The returned layout is owned by the label so need not be
2213  * freed by the caller.
2214  * 
2215  * Return value: the #PangoLayout for this label
2216  **/
2217 PangoLayout*
2218 gtk_label_get_layout (GtkLabel *label)
2219 {
2220   g_return_val_if_fail (GTK_IS_LABEL (label), NULL);
2221
2222   gtk_label_ensure_layout (label, NULL, NULL);
2223
2224   return label->layout;
2225 }
2226
2227 /**
2228  * gtk_label_get_layout_offsets:
2229  * @label: a #GtkLabel
2230  * @x: location to store X offset of layout, or %NULL
2231  * @y: location to store Y offset of layout, or %NULL
2232  *
2233  * Obtains the coordinates where the label will draw the #PangoLayout
2234  * representing the text in the label; useful to convert mouse events
2235  * into coordinates inside the #PangoLayout, e.g. to take some action
2236  * if some part of the label is clicked. Of course you will need to
2237  * create a #GtkEventBox to receive the events, and pack the label
2238  * inside it, since labels are a #GTK_NO_WINDOW widget. Remember
2239  * when using the #PangoLayout functions you need to convert to
2240  * and from pixels using PANGO_PIXELS() or #PANGO_SCALE.
2241  * 
2242  **/
2243 void
2244 gtk_label_get_layout_offsets (GtkLabel *label,
2245                               gint     *x,
2246                               gint     *y)
2247 {
2248   g_return_if_fail (GTK_IS_LABEL (label));
2249   
2250   get_layout_location (label, x, y);
2251 }
2252
2253 /**
2254  * gtk_label_set_use_markup:
2255  * @label: a #GtkLabel
2256  * @setting: %TRUE if the label's text should be parsed for markup.
2257  *
2258  * Sets whether the text of the label contains markup in Pango's
2259  * text markup lango. See gtk_label_set_markup().
2260  **/
2261 void
2262 gtk_label_set_use_markup (GtkLabel *label,
2263                           gboolean  setting)
2264 {
2265   g_return_if_fail (GTK_IS_LABEL (label));
2266
2267   gtk_label_set_use_markup_internal (label, setting);
2268   gtk_label_recalculate (label);
2269 }
2270
2271 /**
2272  * gtk_label_get_use_markup:
2273  * @label: a #GtkLabel
2274  *
2275  * Returns whether the label's text is interpreted as marked up with the
2276  * Pango text markup language. See gtk_label_set_use_markup ().
2277  *
2278  * Return value: %TRUE if the label's text will be parsed for markup.
2279  **/
2280 gboolean
2281 gtk_label_get_use_markup (GtkLabel *label)
2282 {
2283   g_return_val_if_fail (GTK_IS_LABEL (label), FALSE);
2284   
2285   return label->use_markup;
2286 }
2287
2288 /**
2289  * gtk_label_set_use_underline:
2290  * @label: a #GtkLabel
2291  * @setting: %TRUE if underlines in the text indicate mnemonics
2292  *
2293  * If true, an underline in the text indicates the next character should be
2294  * used for the mnemonic accelerator key.
2295  */
2296 void
2297 gtk_label_set_use_underline (GtkLabel *label,
2298                              gboolean  setting)
2299 {
2300   g_return_if_fail (GTK_IS_LABEL (label));
2301
2302   gtk_label_set_use_underline_internal (label, setting);
2303   gtk_label_recalculate (label);
2304   if (label->use_underline)
2305     gtk_label_setup_mnemonic (label, label->mnemonic_keyval);
2306 }
2307
2308 /**
2309  * gtk_label_get_use_underline:
2310  * @label: a #GtkLabel
2311  *
2312  * Returns whether an embedded underline in the label indicates a
2313  * mnemonic. See gtk_label_set_use_underline ().
2314  *
2315  * Return value: %TRUE whether an embedded underline in the label indicates
2316  *               the mnemonic accelerator keys.
2317  **/
2318 gboolean
2319 gtk_label_get_use_underline (GtkLabel *label)
2320 {
2321   g_return_val_if_fail (GTK_IS_LABEL (label), FALSE);
2322   
2323   return label->use_underline;
2324 }