gint wrap_width;
gint width_chars;
gint max_width_chars;
+
+ gboolean mnemonics_visible;
} GtkLabelPrivate;
/* Notes about the handling of links:
COPY_CLIPBOARD,
POPULATE_POPUP,
ACTIVATE_LINK,
+ ACTIVATE_CURRENT_LINK,
LAST_SIGNAL
};
PROP_WIDTH_CHARS,
PROP_SINGLE_LINE_MODE,
PROP_ANGLE,
- PROP_MAX_WIDTH_CHARS
+ PROP_MAX_WIDTH_CHARS,
+ PROP_TRACK_VISITED_LINKS
};
static guint signals[LAST_SIGNAL] = { 0 };
static void gtk_label_set_uline_text_internal (GtkLabel *label,
const gchar *str);
static void gtk_label_set_pattern_internal (GtkLabel *label,
- const gchar *pattern);
+ const gchar *pattern,
+ gboolean is_mnemonic);
static void gtk_label_set_markup_internal (GtkLabel *label,
const gchar *str,
gboolean with_uline);
gpointer user_data);
+static void connect_mnemonics_visible_notify (GtkLabel *label);
+static gboolean separate_uline_pattern (const gchar *str,
+ guint *accel_key,
+ gchar **new_str,
+ gchar **pattern);
+
+
/* For selectable labels: */
static void gtk_label_move_cursor (GtkLabel *label,
GtkMovementStep step,
/* For links: */
static void gtk_label_rescan_links (GtkLabel *label);
static void gtk_label_clear_links (GtkLabel *label);
-static gboolean gtk_label_activate_link (GtkLabel *label);
+static gboolean gtk_label_activate_link (GtkLabel *label,
+ const gchar *uri);
+static void gtk_label_activate_current_link (GtkLabel *label);
static GtkLabelLink *gtk_label_get_current_link (GtkLabel *label);
static void gtk_label_get_link_colors (GtkWidget *widget,
GdkColor **link_color,
GdkColor **visited_link_color);
+static void emit_activate_link (GtkLabel *label,
+ GtkLabelLink *link);
static GQuark quark_angle = 0;
GTK_TYPE_MENU);
/**
- * GtkLabel::activate-link:
- * @label: The label on which the signal was emitted.
+ * GtkLabel::activate-current-link:
+ * @label: The label on which the signal was emitted
*
- * A <link linkend="keybinding-signals">keybinding signal</link>
+ * A <link linkend="keybinding-signals">keybinding signal</link>
* which gets emitted when the user activates a link in the label.
*
- * Applications may connect to it to override the default behaviour,
- * which is to call gtk_show_uri(). To obtain the URI that is being
- * activated, use gtk_label_get_current_uri().
- *
* Applications may also emit the signal with g_signal_emit_by_name()
* if they need to control activation of URIs programmatically.
*
* The default bindings for this signal are all forms of the Enter key.
*
+ * Since: 2.18
+ */
+ signals[ACTIVATE_CURRENT_LINK] =
+ g_signal_new_class_handler ("activate-current-link",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_CALLBACK (gtk_label_activate_current_link),
+ NULL, NULL,
+ _gtk_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ /**
+ * GtkLabel::activate-link:
+ * @label: The label on which the signal was emitted
+ * @uri: the URI that is activated
+ *
+ * The signal which gets emitted to activate a URI.
+ * Applications may connect to it to override the default behaviour,
+ * which is to call gtk_show_uri().
+ *
* Returns: %TRUE if the link has been activated
*
* Since: 2.18
signals[ACTIVATE_LINK] =
g_signal_new ("activate-link",
G_TYPE_FROM_CLASS (object_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkLabelClass, activate_link),
_gtk_boolean_handled_accumulator, NULL,
- _gtk_marshal_BOOLEAN__VOID,
- G_TYPE_BOOLEAN, 0);
+ _gtk_marshal_BOOLEAN__STRING,
+ G_TYPE_BOOLEAN, 1, G_TYPE_STRING);
g_object_class_install_property (gobject_class,
PROP_LABEL,
G_MAXINT,
-1,
GTK_PARAM_READWRITE));
+
+ /**
+ * GtkLabel:track-visited-links:
+ *
+ * Set this property to %TRUE to make the label track which links
+ * have been clicked. It will then apply the ::visited-link-color
+ * color, instead of ::link-color.
+ *
+ * Since: 2.18
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_TRACK_VISITED_LINKS,
+ g_param_spec_boolean ("track-visited-links",
+ P_("Track visited links"),
+ P_("Whether visited links should be tracked"),
+ TRUE,
+ GTK_PARAM_READWRITE));
/*
* Key bindings
*/
"copy-clipboard", 0);
gtk_binding_entry_add_signal (binding_set, GDK_Return, 0,
- "activate-link", 0);
+ "activate-current-link", 0);
gtk_binding_entry_add_signal (binding_set, GDK_ISO_Enter, 0,
- "activate-link", 0);
+ "activate-current-link", 0);
gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
- "activate-link", 0);
+ "activate-current-link", 0);
gtk_settings_install_property (g_param_spec_boolean ("gtk-label-select-on-focus",
P_("Select on focus"),
case PROP_MAX_WIDTH_CHARS:
gtk_label_set_max_width_chars (label, g_value_get_int (value));
break;
+ case PROP_TRACK_VISITED_LINKS:
+ gtk_label_set_track_visited_links (label, g_value_get_boolean (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
case PROP_MAX_WIDTH_CHARS:
g_value_set_int (value, gtk_label_get_max_width_chars (label));
break;
-
+ case PROP_TRACK_VISITED_LINKS:
+ g_value_set_boolean (value, gtk_label_get_track_visited_links (label));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
label->use_underline = FALSE;
label->use_markup = FALSE;
label->pattern_set = FALSE;
-
+ label->track_links = TRUE;
+
label->mnemonic_keyval = GDK_VoidSymbol;
label->layout = NULL;
label->text = NULL;
label->mnemonic_widget = NULL;
label->mnemonic_window = NULL;
-
+
+ priv->mnemonics_visible = TRUE;
+
gtk_label_set_text (label, "");
}
}
if (label->mnemonic_keyval == GDK_VoidSymbol)
- goto done;
+ goto done;
+
+ connect_mnemonics_visible_notify (GTK_LABEL (widget));
toplevel = gtk_widget_get_toplevel (widget);
- if (GTK_WIDGET_TOPLEVEL (toplevel))
+ if (gtk_widget_is_toplevel (toplevel))
{
GtkWidget *menu_shell;
g_list_free (list);
}
+static void
+mnemonics_visible_apply (GtkWidget *widget,
+ gboolean mnemonics_visible)
+{
+ GtkLabel *label;
+ GtkLabelPrivate *priv;
+
+ label = GTK_LABEL (widget);
+
+ priv = GTK_LABEL_GET_PRIVATE (label);
+
+ mnemonics_visible = mnemonics_visible != FALSE;
+
+ if (priv->mnemonics_visible != mnemonics_visible)
+ {
+ priv->mnemonics_visible = mnemonics_visible;
+
+ gtk_label_recalculate (label);
+ }
+}
+
+static void
+label_mnemonics_visible_traverse_container (GtkWidget *widget,
+ gpointer data)
+{
+ gboolean mnemonics_visible = GPOINTER_TO_INT (data);
+
+ _gtk_label_mnemonics_visible_apply_recursively (widget, mnemonics_visible);
+}
+
+void
+_gtk_label_mnemonics_visible_apply_recursively (GtkWidget *widget,
+ gboolean mnemonics_visible)
+{
+ if (GTK_IS_LABEL (widget))
+ mnemonics_visible_apply (widget, mnemonics_visible);
+ else if (GTK_IS_CONTAINER (widget))
+ gtk_container_forall (GTK_CONTAINER (widget),
+ label_mnemonics_visible_traverse_container,
+ GINT_TO_POINTER (mnemonics_visible));
+}
+
+static void
+label_mnemonics_visible_changed (GtkWindow *window,
+ GParamSpec *pspec,
+ gpointer data)
+{
+ gboolean mnemonics_visible;
+
+ g_object_get (window, "mnemonics-visible", &mnemonics_visible, NULL);
+
+ gtk_container_forall (GTK_CONTAINER (window),
+ label_mnemonics_visible_traverse_container,
+ GINT_TO_POINTER (mnemonics_visible));
+}
+
static void
gtk_label_screen_changed (GtkWidget *widget,
GdkScreen *old_screen)
/**
* gtk_label_set_mnemonic_widget:
* @label: a #GtkLabel
- * @widget: the target #GtkWidget
+ * @widget: (allow-none): the target #GtkWidget
*
* If the label has been set so that it has an mnemonic key (using
* i.e. gtk_label_set_markup_with_mnemonic(),
if (label->effective_attrs)
{
if ((iter = pango_attr_list_get_iterator (label->attrs)))
- do
- {
- iter_attrs = pango_attr_iterator_get_attrs (iter);
- for (l = iter_attrs; l; l = l->next)
- {
- attr = l->data;
- pango_attr_list_insert (label->effective_attrs, attr);
- }
- g_slist_free (iter_attrs);
- }
- while (pango_attr_iterator_next (iter));
+ {
+ do
+ {
+ iter_attrs = pango_attr_iterator_get_attrs (iter);
+ for (l = iter_attrs; l; l = l->next)
+ {
+ attr = l->data;
+ pango_attr_list_insert (label->effective_attrs, attr);
+ }
+ g_slist_free (iter_attrs);
+ }
+ while (pango_attr_iterator_next (iter));
+ pango_attr_iterator_destroy (iter);
+ }
}
else
- label->effective_attrs =
+ label->effective_attrs =
pango_attr_list_ref (label->attrs);
}
}
else
{
gtk_label_set_text_internal (label, g_strdup (label->label));
- if (label->attrs)
- pango_attr_list_ref (label->attrs);
- if (label->effective_attrs)
- pango_attr_list_unref (label->effective_attrs);
- label->effective_attrs = label->attrs;
+ gtk_label_compose_effective_attrs (label);
}
}
return;
}
- if (pdata->label->select_info)
+ visited = FALSE;
+ if (pdata->label->track_links && pdata->label->select_info)
{
GList *l;
for (l = pdata->label->select_info->links; l; l = l->next)
const gchar *str,
gboolean with_uline)
{
+ GtkLabelPrivate *priv = GTK_LABEL_GET_PRIVATE (label);
gchar *text = NULL;
GError *error = NULL;
PangoAttrList *attrs = NULL;
gtk_label_ensure_has_tooltip (label);
}
+ if (with_uline)
+ {
+ gboolean enable_mnemonics;
+ gboolean auto_mnemonics;
+
+ g_object_get (gtk_widget_get_settings (GTK_WIDGET (label)),
+ "gtk-enable-mnemonics", &enable_mnemonics,
+ "gtk-auto-mnemonics", &auto_mnemonics,
+ NULL);
+
+ if (!(enable_mnemonics && priv->mnemonics_visible &&
+ (!auto_mnemonics ||
+ (GTK_WIDGET_IS_SENSITIVE (label) &&
+ (!label->mnemonic_widget ||
+ GTK_WIDGET_IS_SENSITIVE (label->mnemonic_widget))))))
+ {
+ gchar *tmp;
+ gchar *pattern;
+ guint key;
+
+ if (separate_uline_pattern (new_str, &key, &tmp, &pattern))
+ {
+ g_free (new_str);
+ new_str = tmp;
+ g_free (pattern);
+ }
+ }
+ }
+
if (!pango_parse_markup (new_str,
-1,
with_uline ? '_' : 0,
static void
gtk_label_set_pattern_internal (GtkLabel *label,
- const gchar *pattern)
+ const gchar *pattern,
+ gboolean is_mnemonic)
{
+ GtkLabelPrivate *priv = GTK_LABEL_GET_PRIVATE (label);
PangoAttrList *attrs;
gboolean enable_mnemonics;
+ gboolean auto_mnemonics;
g_return_if_fail (GTK_IS_LABEL (label));
if (label->pattern_set)
return;
- g_object_get (gtk_widget_get_settings (GTK_WIDGET (label)),
- "gtk-enable-mnemonics", &enable_mnemonics,
- NULL);
+ if (is_mnemonic)
+ {
+ g_object_get (gtk_widget_get_settings (GTK_WIDGET (label)),
+ "gtk-enable-mnemonics", &enable_mnemonics,
+ "gtk-auto-mnemonics", &auto_mnemonics,
+ NULL);
- if (enable_mnemonics && pattern)
- attrs = gtk_label_pattern_to_attrs (label, pattern);
+ if (enable_mnemonics && priv->mnemonics_visible && pattern &&
+ (!auto_mnemonics ||
+ (GTK_WIDGET_IS_SENSITIVE (label) &&
+ (!label->mnemonic_widget ||
+ GTK_WIDGET_IS_SENSITIVE (label->mnemonic_widget)))))
+ attrs = gtk_label_pattern_to_attrs (label, pattern);
+ else
+ attrs = NULL;
+ }
else
- attrs = NULL;
+ attrs = gtk_label_pattern_to_attrs (label, pattern);
if (label->effective_attrs)
pango_attr_list_unref (label->effective_attrs);
if (pattern)
{
- gtk_label_set_pattern_internal (label, pattern);
+ gtk_label_set_pattern_internal (label, pattern, FALSE);
label->pattern_set = TRUE;
}
else
gtk_label_recalculate (label);
- gtk_label_clear_layout (label);
+ gtk_label_clear_layout (label);
gtk_widget_queue_resize (GTK_WIDGET (label));
}
x = MIN (x, widget->allocation.x + widget->allocation.width - misc->xpad);
x -= logical.x;
- y = floor (widget->allocation.y + (gint)misc->ypad
- + MAX (((widget->allocation.height - widget->requisition.height) * misc->yalign),
- 0));
+ /* bgo#315462 - For single-line labels, *do* align the requisition with
+ * respect to the allocation, even if we are under-allocated. For multi-line
+ * labels, always show the top of the text when they are under-allocated. The
+ * rationale is this:
+ *
+ * - Single-line labels appear in GtkButtons, and it is very easy to get them
+ * to be smaller than their requisition. The button may clip the label, but
+ * the label will still be able to show most of itself and the focus
+ * rectangle. Also, it is fairly easy to read a single line of clipped text.
+ *
+ * - Multi-line labels should not be clipped to showing "something in the
+ * middle". You want to read the first line, at least, to get some context.
+ */
+ if (pango_layout_get_line_count (label->layout) == 1)
+ y = floor (widget->allocation.y + (gint)misc->ypad
+ + (widget->allocation.height - widget->requisition.height) * misc->yalign);
+ else
+ y = floor (widget->allocation.y + (gint)misc->ypad
+ + MAX (((widget->allocation.height - widget->requisition.height) * misc->yalign),
+ 0));
if (xp)
*xp = x;
return FALSE;
}
-static void
-gtk_label_set_uline_text_internal (GtkLabel *label,
- const gchar *str)
+static gboolean
+separate_uline_pattern (const gchar *str,
+ guint *accel_key,
+ gchar **new_str,
+ gchar **pattern)
{
- guint accel_key = GDK_VoidSymbol;
-
- gchar *new_str;
- gchar *pattern;
- const gchar *src;
- gchar *dest, *pattern_dest;
gboolean underscore;
-
- g_return_if_fail (GTK_IS_LABEL (label));
- g_return_if_fail (str != NULL);
+ gchar *src;
+ gchar *dest;
+ gchar *pattern_dest;
+
+ *accel_key = GDK_VoidSymbol;
+ *new_str = g_new (gchar, strlen (str) + 1);
+ *pattern = g_new (gchar, g_utf8_strlen (str, -1) + 1);
- /* Split text into the base text and a separate pattern
- * of underscores.
- */
-
- new_str = g_new (gchar, strlen (str) + 1);
- pattern = g_new (gchar, g_utf8_strlen (str, -1) + 1);
-
underscore = FALSE;
- if (str == NULL)
- str = "";
-
src = str;
- dest = new_str;
- pattern_dest = pattern;
-
+ dest = *new_str;
+ pattern_dest = *pattern;
+
while (*src)
{
gunichar c;
if (c == (gunichar)-1)
{
g_warning ("Invalid input string");
- g_free (new_str);
- g_free (pattern);
- return;
+ g_free (*new_str);
+ g_free (*pattern);
+
+ return FALSE;
}
next_src = g_utf8_next_char (src);
-
+
if (underscore)
{
if (c == '_')
else
{
*pattern_dest++ = '_';
- if (accel_key == GDK_VoidSymbol)
- accel_key = gdk_keyval_to_lower (gdk_unicode_to_keyval (c));
+ if (*accel_key == GDK_VoidSymbol)
+ *accel_key = gdk_keyval_to_lower (gdk_unicode_to_keyval (c));
}
while (src < next_src)
*dest++ = *src++;
-
+
underscore = FALSE;
}
else
{
while (src < next_src)
*dest++ = *src++;
-
+
*pattern_dest++ = ' ';
}
}
}
+
*dest = 0;
*pattern_dest = 0;
-
- gtk_label_set_text_internal (label, new_str);
- gtk_label_set_pattern_internal (label, pattern);
-
- g_free (pattern);
+ return TRUE;
+}
+
+static void
+gtk_label_set_uline_text_internal (GtkLabel *label,
+ const gchar *str)
+{
+ guint accel_key = GDK_VoidSymbol;
+ gchar *new_str;
+ gchar *pattern;
+
+ g_return_if_fail (GTK_IS_LABEL (label));
+ g_return_if_fail (str != NULL);
+
+ /* Split text into the base text and a separate pattern
+ * of underscores.
+ */
+ if (!separate_uline_pattern (str, &accel_key, &new_str, &pattern))
+ return;
+
+ gtk_label_set_text_internal (label, new_str);
+ gtk_label_set_pattern_internal (label, pattern, TRUE);
label->mnemonic_keyval = accel_key;
+
+ g_free (pattern);
}
-guint
+guint
gtk_label_parse_uline (GtkLabel *label,
const gchar *str)
{
gint trailing = 0;
const gchar *cluster;
const gchar *cluster_end;
+ gboolean inside;
*index = 0;
x *= PANGO_SCALE;
y *= PANGO_SCALE;
- if (pango_layout_xy_to_index (label->layout,
- x, y,
- index, &trailing))
- {
- cluster = label->text + *index;
- cluster_end = cluster;
- while (trailing)
- {
- cluster_end = g_utf8_next_char (cluster_end);
- --trailing;
- }
-
- *index += (cluster_end - cluster);
+ inside = pango_layout_xy_to_index (label->layout,
+ x, y,
+ index, &trailing);
- return TRUE;
+ cluster = label->text + *index;
+ cluster_end = cluster;
+ while (trailing)
+ {
+ cluster_end = g_utf8_next_char (cluster_end);
+ --trailing;
}
- return FALSE;
+ *index += (cluster_end - cluster);
+
+ return inside;
}
static void
info->selection_anchor == info->selection_end &&
info->link_clicked)
{
- gboolean handled;
-
- g_signal_emit (label, signals[ACTIVATE_LINK], 0, &handled);
- if (handled && !info->active_link->visited)
- {
- info->active_link->visited = TRUE;
- /* FIXME: shouldn't have to redo everything here */
- gtk_label_recalculate (label);
- }
-
+ emit_activate_link (label, info->active_link);
info->link_clicked = 0;
return TRUE;
return TRUE;
}
+static void
+connect_mnemonics_visible_notify (GtkLabel *label)
+{
+ GtkLabelPrivate *priv = GTK_LABEL_GET_PRIVATE (label);
+ GtkWidget *toplevel;
+ gboolean connected;
+
+ toplevel = gtk_widget_get_toplevel (GTK_WIDGET (label));
+
+ if (!GTK_IS_WINDOW (toplevel))
+ return;
+
+ /* always set up this widgets initial value */
+ priv->mnemonics_visible =
+ gtk_window_get_mnemonics_visible (GTK_WINDOW (toplevel));
+
+ connected =
+ GPOINTER_TO_INT (g_object_get_data (G_OBJECT (toplevel),
+ "gtk-label-mnemonics-visible-connected"));
+
+ if (!connected)
+ {
+ g_signal_connect (toplevel,
+ "notify::mnemonics-visible",
+ G_CALLBACK (label_mnemonics_visible_changed),
+ label);
+ g_object_set_data (G_OBJECT (toplevel),
+ "gtk-label-mnemonics-visible-connected",
+ GINT_TO_POINTER (1));
+ }
+}
+
static void
drag_begin_cb (GtkWidget *widget,
GdkDragContext *context,
* pixel positions, in combination with gtk_label_get_layout_offsets().
* The returned layout is owned by the label so need not be
* freed by the caller.
- *
- * Return value: the #PangoLayout for this label
+ *
+ * Return value: (transfer none): the #PangoLayout for this label
**/
PangoLayout*
gtk_label_get_layout (GtkLabel *label)
GtkLabel *label)
{
GtkLabelLink *link;
- gboolean handled;
link = gtk_label_get_current_link (label);
if (link)
- {
- g_signal_emit (label, signals[ACTIVATE_LINK], 0, &handled);
- if (handled && !link->visited)
- {
- link->visited = TRUE;
- /* FIXME: shouldn't have to redo everything here */
- gtk_label_recalculate (label);
- }
- }
+ emit_activate_link (label, link);
}
static void
PangoAttrIterator *iter;
GList *links;
- if (!label->select_info)
+ if (!label->select_info || !label->select_info->links)
return;
attlist = pango_layout_get_attributes (layout);
}
static gboolean
-gtk_label_activate_link (GtkLabel *label)
+gtk_label_activate_link (GtkLabel *label,
+ const gchar *uri)
{
GtkWidget *widget = GTK_WIDGET (label);
- GtkLabelLink *link;
- const gchar *uri;
GError *error = NULL;
- link = gtk_label_get_current_link (label);
+ if (!gtk_show_uri (gtk_widget_get_screen (widget),
+ uri, gtk_get_current_event_time (), &error))
+ {
+ g_warning ("Unable to show '%s': %s", uri, error->message);
+ g_error_free (error);
+ }
- if (link)
+ return TRUE;
+}
+
+static void
+emit_activate_link (GtkLabel *label,
+ GtkLabelLink *link)
+{
+ gboolean handled;
+
+ g_signal_emit (label, signals[ACTIVATE_LINK], 0, link->uri, &handled);
+ if (handled && label->track_links && !link->visited)
{
- uri = link->uri;
+ link->visited = TRUE;
+ /* FIXME: shouldn't have to redo everything here */
+ gtk_label_recalculate (label);
+ }
+}
- if (!gtk_show_uri (gtk_widget_get_screen (widget),
- uri, gtk_get_current_event_time (), &error))
- {
- g_warning ("Unable to show '%s': %s", uri, error->message);
- g_error_free (error);
- }
+static void
+gtk_label_activate_current_link (GtkLabel *label)
+{
+ GtkLabelLink *link;
+ GtkWidget *widget = GTK_WIDGET (label);
+
+ link = gtk_label_get_focus_link (label);
+
+ if (link)
+ {
+ emit_activate_link (label, link);
}
else
{
if (window &&
window->default_widget != widget &&
!(widget == window->focus_widget &&
- (!window->default_widget || !GTK_WIDGET_SENSITIVE (window->default_widget))))
+ (!window->default_widget || !GTK_WIDGET_IS_SENSITIVE (window->default_widget))))
gtk_window_activate_default (window);
}
}
-
- return TRUE;
}
static GtkLabelLink *
* selectable label, the link in which the text cursor is currently
* positioned.
*
- * This function is intended for use in a #GtkLabel::link-activate handler
+ * This function is intended for use in a #GtkLabel::activate-link handler
* or for use in a #GtkWidget::query-tooltip handler.
*
* Returns: the currently active URI. The string is owned by GTK+ and must
return NULL;
}
+/**
+ * gtk_label_set_track_visited_links:
+ * @label: a #GtkLabel
+ * @track_links: %TRUE to track visited links
+ *
+ * Sets whether the label should keep track of clicked
+ * links (and use a different color for them).
+ *
+ * Since: 2.18
+ */
+void
+gtk_label_set_track_visited_links (GtkLabel *label,
+ gboolean track_links)
+{
+ g_return_if_fail (GTK_IS_LABEL (label));
+
+ track_links = track_links != FALSE;
+
+ if (label->track_links != track_links)
+ {
+ label->track_links = track_links;
+
+ /* FIXME: shouldn't have to redo everything here */
+ gtk_label_recalculate (label);
+
+ g_object_notify (G_OBJECT (label), "track-visited-links");
+ }
+}
+
+/**
+ * gtk_label_get_track_visited_links:
+ * @label: a #GtkLabel
+ *
+ * Returns whether the label is currently keeping track
+ * of clicked links.
+ *
+ * Returns: %TRUE if clicked links are remembered
+ *
+ * Since: 2.18
+ */
+gboolean
+gtk_label_get_track_visited_links (GtkLabel *label)
+{
+ g_return_val_if_fail (GTK_IS_LABEL (label), FALSE);
+
+ return label->track_links;
+}
static gboolean
gtk_label_query_tooltip (GtkWidget *widget,