1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
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.
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.
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.
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/.
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>
36 #include "gtkmenuitem.h"
37 #include "gtknotebook.h"
39 struct _GtkLabelSelectionInfo
42 gint selection_anchor;
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,
67 static void gtk_label_get_property (GObject *object,
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,
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);
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);
98 static void gtk_label_set_text_internal (GtkLabel *label,
100 static void gtk_label_set_label_internal (GtkLabel *label,
102 static void gtk_label_set_use_markup_internal (GtkLabel *label,
104 static void gtk_label_set_use_underline_internal (GtkLabel *label,
106 static void gtk_label_set_attributes_internal (GtkLabel *label,
107 PangoAttrList *attrs);
108 static void gtk_label_set_uline_text_internal (GtkLabel *label,
110 static void gtk_label_set_pattern_internal (GtkLabel *label,
111 const gchar *pattern);
112 static void set_markup (GtkLabel *label,
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);
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,
125 static void gtk_label_select_region_index (GtkLabel *label,
129 static gboolean gtk_label_mnemonic_activate (GtkWidget *widget,
130 gboolean group_cycling);
131 static void gtk_label_setup_mnemonic (GtkLabel *label,
135 static GtkMiscClass *parent_class = NULL;
139 gtk_label_get_type (void)
141 static GtkType label_type = 0;
145 static const GTypeInfo label_info =
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 */
154 32, /* n_preallocs */
155 (GInstanceInitFunc) gtk_label_init,
158 label_type = g_type_register_static (GTK_TYPE_MISC, "GtkLabel", &label_info, 0);
165 gtk_label_class_init (GtkLabelClass *class)
167 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
168 GtkObjectClass *object_class = GTK_OBJECT_CLASS (class);
169 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
171 parent_class = gtk_type_class (GTK_TYPE_MISC);
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;
177 object_class->destroy = gtk_label_destroy;
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;
195 g_object_class_install_property (G_OBJECT_CLASS(object_class),
197 g_param_spec_string ("label",
199 _("The text of the label."),
202 g_object_class_install_property (gobject_class,
204 g_param_spec_boxed ("attributes",
206 _("A list of style attributes to apply to the text of the label."),
207 PANGO_TYPE_ATTR_LIST,
209 g_object_class_install_property (gobject_class,
211 g_param_spec_boolean ("use_markup",
213 _("The text of the label includes XML markup. See pango_parse_markup()."),
216 g_object_class_install_property (gobject_class,
218 g_param_spec_boolean ("use_underline",
220 _("If set, an underline in the text indicates the next character should be used for the mnemonic accelerator key"),
224 g_object_class_install_property (gobject_class,
226 g_param_spec_enum ("justify",
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,
233 g_object_class_install_property (gobject_class,
235 g_param_spec_string ("pattern",
237 _("A string with _ characters in positions correspond to characters in the text to underline."),
241 g_object_class_install_property (gobject_class,
243 g_param_spec_boolean ("wrap",
245 _("If set, wrap lines if the text becomes too wide."),
248 g_object_class_install_property (gobject_class,
250 g_param_spec_boolean ("selectable",
252 _("Whether the label text can be selected with the mouse."),
255 g_object_class_install_property (gobject_class,
256 PROP_MNEMONIC_KEYVAL,
257 g_param_spec_uint ("mnemonic_keyval",
259 _("The mnemonic accelerator key for this label."),
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 "
275 gtk_label_set_property (GObject *object,
283 label = GTK_LABEL (object);
284 last_keyval = label->mnemonic_keyval;
289 gtk_label_set_label (label, g_value_get_string (value));
291 case PROP_ATTRIBUTES:
292 gtk_label_set_attributes (label, g_value_get_boxed (value));
294 case PROP_USE_MARKUP:
295 gtk_label_set_use_markup (label, g_value_get_boolean (value));
297 case PROP_USE_UNDERLINE:
298 gtk_label_set_use_underline (label, g_value_get_boolean (value));
301 gtk_label_set_justify (label, g_value_get_enum (value));
304 gtk_label_set_pattern (label, g_value_get_string (value));
307 gtk_label_set_line_wrap (label, g_value_get_boolean (value));
309 case PROP_SELECTABLE:
310 gtk_label_set_selectable (label, g_value_get_boolean (value));
312 case PROP_MNEMONIC_WIDGET:
313 gtk_label_set_mnemonic_widget (label, (GtkWidget*) g_value_get_object (value));
316 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
322 gtk_label_get_property (GObject *object,
329 label = GTK_LABEL (object);
334 g_value_set_string (value, label->label);
336 case PROP_ATTRIBUTES:
337 g_value_set_boxed (value, label->attrs);
339 case PROP_USE_MARKUP:
340 g_value_set_boolean (value, label->use_markup);
342 case PROP_USE_UNDERLINE:
343 g_value_set_boolean (value, label->use_underline);
346 g_value_set_enum (value, label->jtype);
349 g_value_set_boolean (value, label->wrap);
351 case PROP_SELECTABLE:
352 g_value_set_boolean (value, gtk_label_get_selectable (label));
354 case PROP_MNEMONIC_KEYVAL:
355 g_value_set_uint (value, label->mnemonic_keyval);
357 case PROP_MNEMONIC_WIDGET:
358 g_value_set_object (value, (GObject*) label->mnemonic_widget);
362 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
368 gtk_label_init (GtkLabel *label)
370 GTK_WIDGET_SET_FLAGS (label, GTK_NO_WINDOW);
374 label->jtype = GTK_JUSTIFY_CENTER;
377 label->use_underline = FALSE;
378 label->use_markup = FALSE;
380 label->mnemonic_keyval = GDK_VoidSymbol;
381 label->layout = NULL;
385 label->mnemonic_widget = NULL;
386 label->mnemonic_window = NULL;
388 gtk_label_set_text (label, "");
393 * @str: The text of the label
395 * Creates a new #GtkLabel, containing the text in @str.
397 * Return value: the new #GtkLabel
400 gtk_label_new (const gchar *str)
404 label = gtk_type_new (GTK_TYPE_LABEL);
407 gtk_label_set_text (label, str);
409 return GTK_WIDGET (label);
413 * gtk_label_new_with_mnemonic:
414 * @str: The text of the label, with an underscore in front of the
417 * Creates a new #GtkLabel, containing the text in @str.
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().
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
432 * Return value: the new #GtkLabel
435 gtk_label_new_with_mnemonic (const gchar *str)
439 label = gtk_type_new (GTK_TYPE_LABEL);
442 gtk_label_set_text_with_mnemonic (label, str);
444 return GTK_WIDGET (label);
448 gtk_label_mnemonic_activate (GtkWidget *widget,
449 gboolean group_cycling)
453 if (GTK_LABEL (widget)->mnemonic_widget)
454 return gtk_widget_mnemonic_activate (GTK_LABEL (widget)->mnemonic_widget, group_cycling);
456 /* Try to find the widget to activate by traversing the
459 parent = widget->parent;
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;
470 /* barf if there was nothing to activate */
471 g_warning ("Couldn't find a target for a mnemonic activation.");
478 gtk_label_setup_mnemonic (GtkLabel *label,
483 if (last_key != GDK_VoidSymbol && label->mnemonic_window)
485 gtk_window_remove_mnemonic (label->mnemonic_window,
488 label->mnemonic_window = NULL;
491 if (label->mnemonic_keyval == GDK_VoidSymbol)
494 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (label));
495 if (GTK_WIDGET_TOPLEVEL (toplevel))
497 gtk_window_add_mnemonic (GTK_WINDOW (toplevel),
498 label->mnemonic_keyval,
500 label->mnemonic_window = GTK_WINDOW (toplevel);
505 gtk_label_hierarchy_changed (GtkWidget *widget,
506 GtkWidget *old_toplevel)
508 GtkLabel *label = GTK_LABEL (widget);
510 gtk_label_setup_mnemonic (label, label->mnemonic_keyval);
515 * gtk_label_set_mnemonic_widget:
516 * @label: a #GtkLabel
517 * @widget: the target #GtkWidget
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.
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.
534 gtk_label_set_mnemonic_widget (GtkLabel *label,
537 g_return_if_fail (GTK_IS_LABEL (label));
539 g_return_if_fail (GTK_IS_WIDGET (widget));
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);
549 * gtk_label_get_mnemonic_widget:
550 * @label: a #GtkLabel
552 * Retrieves the target of the mnemonic (keyboard shortcut) of this
553 * label. See gtk_label_set_mnemonic_widget ().
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.
559 gtk_label_get_mnemonic_widget (GtkLabel *label)
561 g_return_val_if_fail (GTK_IS_LABEL (label), NULL);
563 return label->mnemonic_widget;
567 * gtk_label_get_mnemonic_keyval:
568 * @label: a #GtkLabel
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.
574 * Returns: GDK keyval usable for accelerators, or GDK_VoidSymbol
577 gtk_label_get_mnemonic_keyval (GtkLabel *label)
579 g_return_val_if_fail (GTK_IS_LABEL (label), GDK_VoidSymbol);
581 return label->mnemonic_keyval;
585 gtk_label_set_text_internal (GtkLabel *label,
588 g_free (label->text);
592 gtk_label_select_region_index (label, 0, 0);
596 gtk_label_set_label_internal (GtkLabel *label,
599 g_free (label->label);
603 g_object_notify (G_OBJECT (label), "label");
607 gtk_label_set_use_markup_internal (GtkLabel *label,
611 if (label->use_markup != val)
613 g_object_notify (G_OBJECT (label), "use_markup");
614 label->use_markup = val;
619 gtk_label_set_use_underline_internal (GtkLabel *label,
623 if (label->use_underline != val)
625 g_object_notify (G_OBJECT (label), "use_underline");
626 label->use_underline = val;
631 gtk_label_set_attributes_internal (GtkLabel *label,
632 PangoAttrList *attrs)
635 pango_attr_list_ref (attrs);
638 pango_attr_list_unref (label->attrs);
640 if (!label->use_markup && !label->use_underline)
642 pango_attr_list_ref (attrs);
643 if (label->effective_attrs)
644 pango_attr_list_unref (label->effective_attrs);
645 label->effective_attrs = attrs;
648 label->attrs = attrs;
649 g_object_notify (G_OBJECT (label), "attributes");
653 /* Calculates text, attrs and mnemonic_keyval from
654 * label, use_underline and use_markup
657 gtk_label_recalculate (GtkLabel *label)
659 if (label->use_markup)
660 set_markup (label, label->label, label->use_underline);
663 if (label->use_underline)
664 gtk_label_set_uline_text_internal (label, label->label);
667 gtk_label_set_text_internal (label, g_strdup (label->label));
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;
676 if (!label->use_underline)
678 guint keyval = label->mnemonic_keyval;
680 label->mnemonic_keyval = GDK_VoidSymbol;
681 gtk_label_setup_mnemonic (label, keyval);
684 gtk_label_clear_layout (label);
685 gtk_widget_queue_resize (GTK_WIDGET (label));
689 * gtk_label_set_text:
690 * @label: a #GtkLabel
693 * Sets the text of the label to @str.
695 * This will also clear any previously set mnemonic accelerators.
698 gtk_label_set_text (GtkLabel *label,
701 g_return_if_fail (GTK_IS_LABEL (label));
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);
707 gtk_label_recalculate (label);
711 * gtk_label_set_attributes:
712 * @label: a #GtkLabel
713 * @attrs: a #PangoAttrList
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.
720 gtk_label_set_attributes (GtkLabel *label,
721 PangoAttrList *attrs)
723 g_return_if_fail (GTK_IS_LABEL (label));
725 gtk_label_set_attributes_internal (label, attrs);
727 gtk_label_clear_layout (label);
728 gtk_widget_queue_resize (GTK_WIDGET (label));
732 * gtk_label_get_attributes:
733 * @label: a #GtkLabel
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)).
742 * Return value: the attribute list, or %NULL if none was set.
745 gtk_label_get_attributes (GtkLabel *label)
747 g_return_val_if_fail (GTK_IS_LABEL (label), NULL);
753 * gtk_label_set_label:
754 * @label: a #GtkLabel
755 * @str: the new text to set for the label
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.
762 gtk_label_set_label (GtkLabel *label,
767 g_return_if_fail (GTK_IS_LABEL (label));
768 g_return_if_fail (str != NULL);
770 last_keyval = label->mnemonic_keyval;
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);
779 * gtk_label_get_label:
780 * @label: a #GtkLabel
782 * Fetches the text from a label widget including any embedded
783 * underlines indicating mnemonics and Pango markup. (See
784 * gtk_label_get_text ()).
786 * Return value: the text of the label widget. This string is
787 * owned by the widget and must not be modified or freed.
789 G_CONST_RETURN gchar *
790 gtk_label_get_label (GtkLabel *label)
792 g_return_val_if_fail (GTK_IS_LABEL (label), NULL);
798 set_markup (GtkLabel *label,
803 GError *error = NULL;
804 PangoAttrList *attrs = NULL;
805 gunichar accel_char = 0;
807 if (!pango_parse_markup (str,
809 with_uline ? '_' : 0,
812 with_uline ? &accel_char : NULL,
815 g_warning ("Failed to set label from markup due to error parsing markup: %s",
817 g_error_free (error);
822 gtk_label_set_text_internal (label, text);
826 if (label->effective_attrs)
827 pango_attr_list_unref (label->effective_attrs);
828 label->effective_attrs = attrs;
832 label->mnemonic_keyval = gdk_keyval_to_lower (gdk_unicode_to_keyval (accel_char));
834 label->mnemonic_keyval = GDK_VoidSymbol;
838 * gtk_label_set_markup:
839 * @label: a #GtkLabel
840 * @str: a markup string (see <link linkend="PangoMarkupFormat">Pango markup format</link>)
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.
846 gtk_label_set_markup (GtkLabel *label,
849 g_return_if_fail (GTK_IS_LABEL (label));
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);
855 gtk_label_recalculate (label);
859 * gtk_label_set_markup_with_mnemonic:
860 * @label: a #GtkLabel
861 * @str: a markup string (see <link linkend="PangoMarkupFormat">Pango markup format</link>)
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.
868 * The mnemonic key can be used to activate another widget, chosen automatically,
869 * or explicitly using gtk_label_set_mnemonic_widget().
872 gtk_label_set_markup_with_mnemonic (GtkLabel *label,
876 g_return_if_fail (GTK_IS_LABEL (label));
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);
883 gtk_label_recalculate (label);
884 gtk_label_setup_mnemonic (label, last_keyval);
888 * gtk_label_get_text:
889 * @label: a #GtkLabel
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())
895 * Return value: the text in the label widget. This is the internal
896 * string used by the label, and must not be modified.
898 G_CONST_RETURN gchar *
899 gtk_label_get_text (GtkLabel *label)
901 g_return_val_if_fail (GTK_IS_LABEL (label), NULL);
906 static PangoAttrList *
907 gtk_label_pattern_to_attrs (GtkLabel *label,
908 const gchar *pattern)
911 const char *p = label->text;
912 const char *q = pattern;
913 PangoAttrList *attrs;
915 attrs = pango_attr_list_new ();
919 while (*p && *q && *q != '_')
921 p = g_utf8_next_char (p);
925 while (*p && *q && *q == '_')
927 p = g_utf8_next_char (p);
933 PangoAttribute *attr = pango_attr_underline_new (PANGO_UNDERLINE_LOW);
934 attr->start_index = start - label->text;
935 attr->end_index = p - label->text;
937 pango_attr_list_insert (attrs, attr);
947 gtk_label_set_pattern_internal (GtkLabel *label,
948 const gchar *pattern)
950 PangoAttrList *attrs;
951 g_return_if_fail (GTK_IS_LABEL (label));
953 attrs = gtk_label_pattern_to_attrs (label, pattern);
955 if (label->effective_attrs)
956 pango_attr_list_unref (label->effective_attrs);
957 label->effective_attrs = attrs;
961 gtk_label_set_pattern (GtkLabel *label,
962 const gchar *pattern)
964 g_return_if_fail (GTK_IS_LABEL (label));
966 gtk_label_set_pattern_internal (label, pattern);
968 gtk_label_clear_layout (label);
969 gtk_widget_queue_resize (GTK_WIDGET (label));
974 * gtk_label_set_justify:
975 * @label: a #GtkLabel
976 * @jtype: a #GtkJustification
978 * Sets the alignment of the lines in the text of the label relative to
982 gtk_label_set_justify (GtkLabel *label,
983 GtkJustification jtype)
985 g_return_if_fail (GTK_IS_LABEL (label));
986 g_return_if_fail (jtype >= GTK_JUSTIFY_LEFT && jtype <= GTK_JUSTIFY_FILL);
988 if ((GtkJustification) label->jtype != jtype)
990 label->jtype = jtype;
992 /* No real need to be this drastic, but easier than duplicating the code */
993 gtk_label_clear_layout (label);
995 g_object_notify (G_OBJECT (label), "justify");
996 gtk_widget_queue_resize (GTK_WIDGET (label));
1001 * gtk_label_get_justify:
1002 * @label: a #GtkLabel
1004 * Returns the justification of the label. See gtk_label_set_justification ().
1006 * Return value: GtkJustification
1009 gtk_label_get_justify (GtkLabel *label)
1011 g_return_val_if_fail (GTK_IS_LABEL (label), 0);
1013 return label->jtype;
1017 * gtk_label_set_line_wrap:
1018 * @label: a #GtkLabel
1019 * @wrap: the setting
1021 * If true, the lines will be wrapped if the text becomes too wide.
1024 gtk_label_set_line_wrap (GtkLabel *label,
1027 g_return_if_fail (GTK_IS_LABEL (label));
1029 wrap = wrap != FALSE;
1031 if (label->wrap != wrap)
1034 g_object_notify (G_OBJECT (label), "wrap");
1036 gtk_widget_queue_resize (GTK_WIDGET (label));
1041 * gtk_label_get_line_wrap:
1042 * @label: a #GtkLabel
1044 * Returns whether lines in the label are automatically wrapped. See gtk_label_set_line_wrap ().
1046 * Return value: %TRUE if the lines of the label are automatically wrapped.
1049 gtk_label_get_line_wrap (GtkLabel *label)
1051 g_return_val_if_fail (GTK_IS_LABEL (label), FALSE);
1057 gtk_label_get (GtkLabel *label,
1060 g_return_if_fail (GTK_IS_LABEL (label));
1061 g_return_if_fail (str != NULL);
1067 gtk_label_destroy (GtkObject *object)
1069 GtkLabel *label = GTK_LABEL (object);
1071 gtk_label_set_mnemonic_widget (label, NULL);
1073 GTK_OBJECT_CLASS (parent_class)->destroy (object);
1077 gtk_label_finalize (GObject *object)
1081 g_return_if_fail (GTK_IS_LABEL (object));
1083 label = GTK_LABEL (object);
1085 g_free (label->label);
1086 g_free (label->text);
1089 g_object_unref (G_OBJECT (label->layout));
1092 pango_attr_list_unref (label->attrs);
1094 if (label->effective_attrs)
1095 pango_attr_list_unref (label->effective_attrs);
1097 g_free (label->select_info);
1099 G_OBJECT_CLASS (parent_class)->finalize (object);
1103 gtk_label_clear_layout (GtkLabel *label)
1107 g_object_unref (G_OBJECT (label->layout));
1108 label->layout = NULL;
1113 gtk_label_ensure_layout (GtkLabel *label,
1118 PangoRectangle logical_rect;
1119 gint rwidth, rheight;
1121 widget = GTK_WIDGET (label);
1124 * There are a number of conditions which will necessitate re-filling
1128 * 2. justification changed either from to to GTK_JUSTIFY_FILL.
1131 * These have been detected elsewhere, and label->words will be zero,
1132 * if one of the above has occured.
1134 * Additionally, though, if GTK_JUSTIFY_FILL, we need to re-fill if:
1136 * 4. gtk_widget_set_usize has changed the requested width.
1137 * 5. gtk_misc_set_padding has changed xpad.
1138 * 6. maybe others?...
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.
1144 rwidth = label->misc.xpad * 2;
1145 rheight = label->misc.ypad * 2;
1149 PangoAlignment align = PANGO_ALIGN_LEFT; /* Quiet gcc */
1151 label->layout = gtk_widget_create_pango_layout (widget, label->text);
1153 if (label->effective_attrs)
1154 pango_layout_set_attributes (label->layout, label->effective_attrs);
1156 switch (label->jtype)
1158 case GTK_JUSTIFY_LEFT:
1159 align = PANGO_ALIGN_LEFT;
1161 case GTK_JUSTIFY_RIGHT:
1162 align = PANGO_ALIGN_RIGHT;
1164 case GTK_JUSTIFY_CENTER:
1165 align = PANGO_ALIGN_LEFT;
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);
1173 g_assert_not_reached();
1176 pango_layout_set_alignment (label->layout, align);
1181 GtkWidgetAuxInfo *aux_info;
1182 gint longest_paragraph;
1186 aux_info = _gtk_widget_get_aux_info (widget, FALSE);
1187 if (aux_info && aux_info->width > 0)
1189 pango_layout_set_width (label->layout, aux_info->width * PANGO_SCALE);
1190 pango_layout_get_extents (label->layout, NULL, &logical_rect);
1192 rwidth += aux_info->width;
1193 rheight += PANGO_PIXELS (logical_rect.height);
1197 pango_layout_set_width (label->layout, -1);
1198 pango_layout_get_extents (label->layout, NULL, &logical_rect);
1200 width = logical_rect.width;
1201 height = logical_rect.height;
1203 /* Try to guess a reasonable maximum width
1205 longest_paragraph = 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."));
1211 PANGO_SCALE * (gdk_screen_width () + 1) / 2);
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;
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
1221 if (longest_paragraph > 0)
1223 gint nlines, perfect_width;
1225 nlines = pango_layout_get_line_count (label->layout);
1226 perfect_width = (longest_paragraph + nlines - 1) / nlines;
1228 if (perfect_width < width)
1230 pango_layout_set_width (label->layout, perfect_width);
1231 pango_layout_get_extents (label->layout, NULL, &logical_rect);
1233 if (logical_rect.height <= height)
1235 width = perfect_width;
1236 real_width = logical_rect.width;
1237 height = logical_rect.height;
1241 gint mid_width = (perfect_width + width) / 2;
1243 if (mid_width > perfect_width)
1245 pango_layout_set_width (label->layout, mid_width);
1246 pango_layout_get_extents (label->layout, NULL, &logical_rect);
1248 if (logical_rect.height <= height)
1251 real_width = logical_rect.width;
1252 height = logical_rect.height;
1258 pango_layout_set_width (label->layout, width);
1260 rwidth += PANGO_PIXELS (real_width);
1261 rheight += PANGO_PIXELS (height);
1264 else /* !label->wrap */
1266 pango_layout_set_width (label->layout, -1);
1267 pango_layout_get_extents (label->layout, NULL, &logical_rect);
1269 rwidth += PANGO_PIXELS (logical_rect.width);
1270 rheight += PANGO_PIXELS (logical_rect.height);
1281 gtk_label_size_request (GtkWidget *widget,
1282 GtkRequisition *requisition)
1287 g_return_if_fail (GTK_IS_LABEL (widget));
1288 g_return_if_fail (requisition != NULL);
1290 label = GTK_LABEL (widget);
1292 gtk_label_ensure_layout (label, &width, &height);
1294 requisition->width = width;
1295 requisition->height = height;
1299 gtk_label_size_allocate (GtkWidget *widget,
1300 GtkAllocation *allocation)
1304 label = GTK_LABEL (widget);
1306 (* GTK_WIDGET_CLASS (parent_class)->size_allocate) (widget, allocation);
1308 if (label->select_info && label->select_info->window)
1310 gdk_window_move_resize (label->select_info->window,
1314 allocation->height);
1319 gtk_label_state_changed (GtkWidget *widget,
1320 GtkStateType prev_state)
1324 label = GTK_LABEL (widget);
1326 if (label->select_info)
1327 gtk_label_select_region (label, 0, 0);
1329 if (GTK_WIDGET_CLASS (parent_class)->state_changed)
1330 GTK_WIDGET_CLASS (parent_class)->state_changed (widget, prev_state);
1334 gtk_label_style_set (GtkWidget *widget,
1335 GtkStyle *previous_style)
1339 g_return_if_fail (GTK_IS_LABEL (widget));
1341 label = GTK_LABEL (widget);
1343 /* We have to clear the layout, fonts etc. may have changed */
1344 gtk_label_clear_layout (label);
1348 gtk_label_direction_changed (GtkWidget *widget,
1349 GtkTextDirection previous_dir)
1351 GtkLabel *label = GTK_LABEL (widget);
1354 pango_layout_context_changed (label->layout);
1356 GTK_WIDGET_CLASS (parent_class)->direction_changed (widget, previous_dir);
1361 gtk_label_paint_word (GtkLabel *label,
1367 GtkWidget *widget = GTK_WIDGET (label);
1368 GtkLabelULine *uline;
1371 tmp_str = gdk_wcstombs (word->beginning);
1374 gtk_paint_string (widget->style, widget->window, widget->state,
1375 area, widget, "label",
1382 for (uline = word->uline; uline; uline = uline->next)
1383 gtk_paint_hline (widget->style, widget->window,
1384 widget->state, area,
1386 x + uline->x1, x + uline->x2, y + uline->y);
1391 get_layout_location (GtkLabel *label,
1400 misc = GTK_MISC (label);
1401 widget = GTK_WIDGET (label);
1403 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
1404 xalign = misc->xalign;
1406 xalign = 1.0 - misc->xalign;
1408 x = floor (widget->allocation.x + (gint)misc->xpad
1409 + ((widget->allocation.width - widget->requisition.width) * xalign)
1412 y = floor (widget->allocation.y + (gint)misc->ypad
1413 + ((widget->allocation.height - widget->requisition.height) * misc->yalign)
1425 gtk_label_expose (GtkWidget *widget,
1426 GdkEventExpose *event)
1431 g_return_val_if_fail (GTK_IS_LABEL (widget), FALSE);
1432 g_return_val_if_fail (event != NULL, FALSE);
1434 label = GTK_LABEL (widget);
1436 gtk_label_ensure_layout (label, NULL, NULL);
1438 if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget) &&
1439 label->text && (*label->text != '\0'))
1441 get_layout_location (label, &x, &y);
1443 gtk_paint_layout (widget->style,
1445 GTK_WIDGET_STATE (widget),
1453 if (label->select_info &&
1454 (label->select_info->selection_anchor !=
1455 label->select_info->selection_end))
1460 range[0] = label->select_info->selection_anchor;
1461 range[1] = label->select_info->selection_end;
1463 if (range[0] > range[1])
1465 gint tmp = range[0];
1466 range[0] = range[1];
1470 clip = gdk_pango_layout_get_clip_region (label->layout,
1475 /* FIXME should use gtk_paint, but it can't use a clip
1479 gdk_gc_set_clip_region (widget->style->white_gc, clip);
1481 gdk_draw_layout_with_colors (widget->window,
1482 widget->style->white_gc,
1485 &widget->style->fg[GTK_STATE_SELECTED],
1486 &widget->style->bg[GTK_STATE_SELECTED]);
1488 gdk_gc_set_clip_region (widget->style->white_gc, NULL);
1489 gdk_region_destroy (clip);
1497 gtk_label_set_uline_text_internal (GtkLabel *label,
1500 guint accel_key = GDK_VoidSymbol;
1505 gchar *dest, *pattern_dest;
1506 gboolean underscore;
1508 g_return_if_fail (GTK_IS_LABEL (label));
1509 g_return_if_fail (str != NULL);
1511 /* Convert text to wide characters */
1513 new_str = g_new (gchar, strlen (str) + 1);
1514 pattern = g_new (gchar, g_utf8_strlen (str, -1) + 1);
1523 pattern_dest = pattern;
1530 c = g_utf8_get_char (src);
1531 if (c == (gunichar)-1)
1533 g_warning ("Invalid input string");
1538 next_src = g_utf8_next_char (src);
1543 *pattern_dest++ = ' ';
1546 *pattern_dest++ = '_';
1547 if (accel_key == GDK_VoidSymbol)
1548 accel_key = gdk_keyval_to_lower (c);
1551 while (src < next_src)
1565 while (src < next_src)
1568 *pattern_dest++ = ' ';
1575 gtk_label_set_text_internal (label, new_str);
1576 gtk_label_set_pattern_internal (label, pattern);
1580 label->mnemonic_keyval = accel_key;
1584 gtk_label_parse_uline (GtkLabel *label,
1590 g_return_val_if_fail (GTK_IS_LABEL (label), GDK_VoidSymbol);
1591 g_return_val_if_fail (str != NULL, GDK_VoidSymbol);
1593 orig_keyval = label->mnemonic_keyval;
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);
1599 gtk_label_recalculate (label);
1601 keyval = label->mnemonic_keyval;
1602 label->mnemonic_keyval = GDK_VoidSymbol;
1604 gtk_label_setup_mnemonic (label, orig_keyval);
1610 * gtk_label_set_text_with_mnemonic:
1611 * @label: a #GtkLabel
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().
1621 gtk_label_set_text_with_mnemonic (GtkLabel *label,
1626 g_return_if_fail (GTK_IS_LABEL (label));
1627 g_return_if_fail (str != NULL);
1629 last_keyval = label->mnemonic_keyval;
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);
1635 gtk_label_recalculate (label);
1637 gtk_label_setup_mnemonic (label, last_keyval);
1642 gtk_label_realize (GtkWidget *widget)
1646 label = GTK_LABEL (widget);
1648 (* GTK_WIDGET_CLASS (parent_class)->realize) (widget);
1650 if (label->select_info)
1651 gtk_label_create_window (label);
1655 gtk_label_unrealize (GtkWidget *widget)
1659 label = GTK_LABEL (widget);
1661 if (label->select_info)
1662 gtk_label_destroy_window (label);
1664 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
1668 gtk_label_map (GtkWidget *widget)
1672 label = GTK_LABEL (widget);
1674 (* GTK_WIDGET_CLASS (parent_class)->map) (widget);
1676 if (label->select_info)
1677 gdk_window_show (label->select_info->window);
1681 gtk_label_unmap (GtkWidget *widget)
1685 label = GTK_LABEL (widget);
1687 if (label->select_info)
1688 gdk_window_hide (label->select_info->window);
1690 (* GTK_WIDGET_CLASS (parent_class)->unmap) (widget);
1694 window_to_layout_coords (GtkLabel *label,
1701 widget = GTK_WIDGET (label);
1703 /* get layout location in widget->window coords */
1704 get_layout_location (label, &lx, &ly);
1708 *x += widget->allocation.x; /* go to widget->window */
1709 *x -= lx; /* go to layout */
1714 *y += widget->allocation.y; /* go to widget->window */
1715 *y -= ly; /* go to layout */
1721 layout_to_window_coords (GtkLabel *label,
1728 widget = GTK_WIDGET (label);
1730 /* get layout location in widget->window coords */
1731 get_layout_location (label, &lx, &ly);
1735 *x += lx; /* go to widget->window */
1736 *x -= widget->allocation.x; /* go to selection window */
1741 *y += ly; /* go to widget->window */
1742 *y -= widget->allocation.y; /* go to selection window */
1748 get_layout_index (GtkLabel *label,
1754 const gchar *cluster;
1755 const gchar *cluster_end;
1759 gtk_label_ensure_layout (label, NULL, NULL);
1761 window_to_layout_coords (label, &x, &y);
1766 pango_layout_xy_to_index (label->layout,
1771 cluster = label->text + *index;
1772 cluster_end = cluster;
1775 cluster_end = g_utf8_next_char (cluster_end);
1779 *index += (cluster_end - cluster);
1783 gtk_label_button_press (GtkWidget *widget,
1784 GdkEventButton *event)
1789 label = GTK_LABEL (widget);
1791 if (label->select_info == NULL)
1794 if (event->button != 1)
1797 get_layout_index (label, event->x, event->y, &index);
1799 if ((label->select_info->selection_anchor !=
1800 label->select_info->selection_end) &&
1801 (event->state & GDK_SHIFT_MASK))
1803 /* extend (same as motion) */
1804 if (index < label->select_info->selection_end)
1805 gtk_label_select_region_index (label,
1807 label->select_info->selection_end);
1809 gtk_label_select_region_index (label,
1810 label->select_info->selection_anchor,
1813 /* ensure the anchor is opposite index */
1814 if (index == label->select_info->selection_anchor)
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;
1823 /* start a replacement */
1824 gtk_label_select_region_index (label, index, index);
1831 gtk_label_button_release (GtkWidget *widget,
1832 GdkEventButton *event)
1837 label = GTK_LABEL (widget);
1839 if (label->select_info == NULL)
1842 if (event->button != 1)
1845 /* The goal here is to return TRUE iff we ate the
1846 * button press to start selecting.
1853 gtk_label_motion (GtkWidget *widget,
1854 GdkEventMotion *event)
1860 label = GTK_LABEL (widget);
1862 if (label->select_info == NULL)
1865 if ((event->state & GDK_BUTTON1_MASK) == 0)
1868 gdk_window_get_pointer (label->select_info->window,
1871 get_layout_index (label, x, y, &index);
1873 gtk_label_select_region_index (label,
1874 label->select_info->selection_anchor,
1881 gtk_label_create_window (GtkLabel *label)
1884 GdkWindowAttr attributes;
1885 gint attributes_mask;
1887 g_assert (label->select_info);
1888 g_assert (GTK_WIDGET_REALIZED (label));
1890 if (label->select_info->window)
1893 widget = GTK_WIDGET (label);
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;
1907 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_NOREDIR;
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);
1915 gtk_label_destroy_window (GtkLabel *label)
1917 g_assert (label->select_info);
1919 if (label->select_info->window == NULL)
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;
1928 * gtk_label_set_selectable:
1929 * @label: a #GtkLabel
1930 * @setting: %TRUE to allow selecting text in the label
1932 * Selectable labels allow the user to select text from the label, for
1937 gtk_label_set_selectable (GtkLabel *label,
1940 gboolean old_setting;
1942 g_return_if_fail (GTK_IS_LABEL (label));
1944 setting = setting != FALSE;
1945 old_setting = label->select_info != NULL;
1949 if (label->select_info == NULL)
1951 label->select_info = g_new (GtkLabelSelectionInfo, 1);
1953 label->select_info->window = NULL;
1954 label->select_info->selection_anchor = 0;
1955 label->select_info->selection_end = 0;
1957 if (GTK_WIDGET_REALIZED (label))
1958 gtk_label_create_window (label);
1960 if (GTK_WIDGET_MAPPED (label))
1961 gdk_window_show (label->select_info->window);
1966 if (label->select_info)
1968 /* unselect, to give up the selection */
1969 gtk_label_select_region (label, 0, 0);
1971 if (label->select_info->window)
1972 gtk_label_destroy_window (label);
1974 g_free (label->select_info);
1976 label->select_info = NULL;
1979 if (setting != old_setting)
1981 g_object_notify (G_OBJECT (label), "selectable");
1982 gtk_widget_queue_draw (GTK_WIDGET (label));
1987 * gtk_label_get_selectable:
1988 * @label: a #GtkLabel
1990 * Gets the value set by gtk_label_set_selectable().
1992 * Return value: %TRUE if the user can copy text from the label
1995 gtk_label_get_selectable (GtkLabel *label)
1997 g_return_val_if_fail (GTK_IS_LABEL (label), FALSE);
1999 return label->select_info != NULL;
2003 get_text_callback (GtkClipboard *clipboard,
2004 GtkSelectionData *selection_data,
2006 gpointer user_data_or_owner)
2011 label = GTK_LABEL (user_data_or_owner);
2013 if ((label->select_info->selection_anchor !=
2014 label->select_info->selection_end) &&
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);
2025 len = strlen (label->text);
2033 str = g_strndup (label->text + start,
2036 gtk_selection_data_set_text (selection_data,
2044 clear_text_callback (GtkClipboard *clipboard,
2045 gpointer user_data_or_owner)
2049 label = GTK_LABEL (user_data_or_owner);
2051 if (label->select_info)
2053 label->select_info->selection_anchor = 0;
2054 label->select_info->selection_end = 0;
2056 gtk_label_clear_layout (label);
2057 gtk_widget_queue_draw (GTK_WIDGET (label));
2062 gtk_label_select_region_index (GtkLabel *label,
2066 static const GtkTargetEntry targets[] = {
2069 { "COMPOUND_TEXT", 0, 0 },
2070 { "UTF8_STRING", 0, 0 }
2073 g_return_if_fail (GTK_IS_LABEL (label));
2075 if (label->select_info)
2077 GtkClipboard *clipboard;
2079 label->select_info->selection_anchor = anchor_index;
2080 label->select_info->selection_end = end_index;
2082 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
2084 if (anchor_index != end_index)
2086 gtk_clipboard_set_with_owner (clipboard,
2088 G_N_ELEMENTS (targets),
2090 clear_text_callback,
2095 if (gtk_clipboard_get_owner (clipboard) == G_OBJECT (label))
2096 gtk_clipboard_clear (clipboard);
2099 gtk_label_clear_layout (label);
2100 gtk_widget_queue_draw (GTK_WIDGET (label));
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)
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.
2117 gtk_label_select_region (GtkLabel *label,
2121 g_return_if_fail (GTK_IS_LABEL (label));
2123 if (label->text && label->select_info)
2125 if (start_offset < 0)
2126 start_offset = g_utf8_strlen (label->text, -1);
2129 end_offset = g_utf8_strlen (label->text, -1);
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);
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
2143 * Gets the selected range of characters in the label, returning %TRUE
2144 * if there's a selection.
2146 * Return value: %TRUE if selection is non-empty
2149 gtk_label_get_selection_bounds (GtkLabel *label,
2153 g_return_val_if_fail (GTK_IS_LABEL (label), FALSE);
2155 if (label->select_info == NULL)
2157 /* not a selectable label */
2167 gint start_index, end_index;
2168 gint start_offset, end_offset;
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);
2176 len = strlen (label->text);
2178 if (end_index > len)
2181 if (start_index > len)
2184 start_offset = g_utf8_strlen (label->text, start_index);
2185 end_offset = g_utf8_strlen (label->text, end_index);
2187 if (start_offset > end_offset)
2189 gint tmp = start_offset;
2190 start_offset = end_offset;
2195 *start = start_offset;
2200 return start_offset != end_offset;
2206 * gtk_label_get_layout:
2207 * @label: a #GtkLabel
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.
2215 * Return value: the #PangoLayout for this label
2218 gtk_label_get_layout (GtkLabel *label)
2220 g_return_val_if_fail (GTK_IS_LABEL (label), NULL);
2222 gtk_label_ensure_layout (label, NULL, NULL);
2224 return label->layout;
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
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.
2244 gtk_label_get_layout_offsets (GtkLabel *label,
2248 g_return_if_fail (GTK_IS_LABEL (label));
2250 get_layout_location (label, x, y);
2254 * gtk_label_set_use_markup:
2255 * @label: a #GtkLabel
2256 * @setting: %TRUE if the label's text should be parsed for markup.
2258 * Sets whether the text of the label contains markup in Pango's
2259 * text markup lango. See gtk_label_set_markup().
2262 gtk_label_set_use_markup (GtkLabel *label,
2265 g_return_if_fail (GTK_IS_LABEL (label));
2267 gtk_label_set_use_markup_internal (label, setting);
2268 gtk_label_recalculate (label);
2272 * gtk_label_get_use_markup:
2273 * @label: a #GtkLabel
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 ().
2278 * Return value: %TRUE if the label's text will be parsed for markup.
2281 gtk_label_get_use_markup (GtkLabel *label)
2283 g_return_val_if_fail (GTK_IS_LABEL (label), FALSE);
2285 return label->use_markup;
2289 * gtk_label_set_use_underline:
2290 * @label: a #GtkLabel
2291 * @setting: %TRUE if underlines in the text indicate mnemonics
2293 * If true, an underline in the text indicates the next character should be
2294 * used for the mnemonic accelerator key.
2297 gtk_label_set_use_underline (GtkLabel *label,
2300 g_return_if_fail (GTK_IS_LABEL (label));
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);
2309 * gtk_label_get_use_underline:
2310 * @label: a #GtkLabel
2312 * Returns whether an embedded underline in the label indicates a
2313 * mnemonic. See gtk_label_set_use_underline ().
2315 * Return value: %TRUE whether an embedded underline in the label indicates
2316 * the mnemonic accelerator keys.
2319 gtk_label_get_use_underline (GtkLabel *label)
2321 g_return_val_if_fail (GTK_IS_LABEL (label), FALSE);
2323 return label->use_underline;