Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/gtk+/ChangeLog,v
retrieving revision 1.5011
diff -u -p -r1.5011 ChangeLog
--- ChangeLog	25 Feb 2004 15:15:19 -0000	1.5011
+++ ChangeLog	25 Feb 2004 17:25:42 -0000
@@ -1,3 +1,9 @@
+Wed Feb 25 12:21:32 2004  Owen Taylor  <otaylor@redhat.com>
+
+	* gtk/gtkwidget.[ch] gtk/gtklabel.c: Patch from
+	Padraig O'Briain to add gtk_widget_add/remove_mnemonic_label,
+	gtk_widget_get_mnemonic_labels(). (#103456)
+
 Wed Feb 25 09:46:34 2004  Owen Taylor  <otaylor@redhat.com>
 
 	* gtk/gtkstyle.c (gtk_style_finalize): Free 
Index: gtk/gtkwidget.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwidget.c,v
retrieving revision 1.367
diff -u -p -r1.367 gtkwidget.c
--- gtk/gtkwidget.c	13 Feb 2004 03:03:20 -0000	1.367
+++ gtk/gtkwidget.c	25 Feb 2004 17:25:43 -0000
@@ -249,6 +249,7 @@ static GQuark		quark_colormap = 0;
 static GQuark		quark_pango_context = 0;
 static GQuark		quark_rc_style = 0;
 static GQuark		quark_accessible_object = 0;
+static GQuark		quark_mnemonic_labels = 0;
 GParamSpecPool         *_gtk_widget_child_property_pool = NULL;
 GObjectNotifyContext   *_gtk_widget_child_property_notify_context = NULL;
 
@@ -322,6 +323,7 @@ gtk_widget_class_init (GtkWidgetClass *k
   quark_pango_context = g_quark_from_static_string ("gtk-pango-context");
   quark_rc_style = g_quark_from_static_string ("gtk-rc-style");
   quark_accessible_object = g_quark_from_static_string ("gtk-accessible-object");
+  quark_mnemonic_labels = g_quark_from_static_string ("gtk-mnemonic-labels");
 
   style_property_spec_pool = g_param_spec_pool_new (FALSE);
   _gtk_widget_child_property_pool = g_param_spec_pool_new (TRUE);
@@ -6362,6 +6364,9 @@ gtk_widget_real_destroy (GtkObject *obje
   g_object_set_qdata (G_OBJECT (widget), quark_accel_path, NULL);
   g_object_set_qdata (G_OBJECT (widget), quark_accel_closures, NULL);
 
+  /* Callers of add_mnemonic_label() should disconnect on ::destroy */
+  g_object_set_qdata (G_OBJECT (widget), quark_mnemonic_labels, NULL);
+  
   gtk_grab_remove (widget);
   
   g_object_unref (widget->style);
@@ -7311,6 +7316,100 @@ gtk_widget_get_clipboard (GtkWidget *wid
 }
 
 /**
+ * gtk_widget_list_mnemonic_labels:
+ * @widget: a #GtkWidget
+ * 
+ * Returns a newly allocated list of the widgets, normally labels, for 
+ * which this widget is a the target of a mnemonic (see for example, 
+ * gtk_label_set_mnemonic_widget()).
+
+ * The widgets in the list are not individually referenced. If you
+ * want to iterate through the list and perform actions involving
+ * callbacks that might destroy the widgets, you
+ * <emphasis>must</emphasis> call <literal>g_list_foreach (result,
+ * (GFunc)g_object_ref, NULL)</literal> first, and then unref all the
+ * widgets afterwards.
+
+ * Return value: the list of mnemonic labels; free this list
+ *  with g_list_free() when you are done with it.
+ *
+ * Since: 2.4
+ **/
+GList *
+gtk_widget_list_mnemonic_labels (GtkWidget *widget)
+{
+  GList *list = NULL;
+  GSList *l;
+  
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
+
+  for (l = g_object_get_qdata (G_OBJECT (widget), quark_mnemonic_labels); l; l = l->next)
+    list = g_list_prepend (list, l->data);
+
+  return list;
+}
+
+/**
+ * gtk_widget_remove_mnemonic_label:
+ * @widget: a #GtkWidget
+ * @label: a #GtkWidget that acts as a mnemonic label for @widget.
+ * 
+ * Adds a widget to the list of mnemonic labels for
+ * this widget. (See gtk_widget_get_mnemonic_labels()). Note the
+ * list of mnemonic labels for the widget is cleared when the
+ * widget is destroyed, so the caller must make sure to update
+ * it's internal state at this point as well, by using a connection
+ * to the ::destroy signal or a weak notifier.
+ *
+ * Since: 2.4
+ **/
+void
+gtk_widget_add_mnemonic_label (GtkWidget *widget,
+                               GtkWidget *label)
+{
+  GSList *old_list, *new_list;
+
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+  g_return_if_fail (GTK_IS_WIDGET (label));
+
+  old_list = g_object_steal_qdata (G_OBJECT (widget), quark_mnemonic_labels);
+  new_list = g_slist_prepend (old_list, label);
+  
+  g_object_set_qdata_full (G_OBJECT (widget), quark_mnemonic_labels,
+			   new_list, (GDestroyNotify) g_slist_free);
+}
+
+/**
+ * gtk_widget_remove_mnemonic_label:
+ * @widget: a #GtkWidget
+ * @label: a #GtkWidget that was previously set as a mnemnic label for
+ *         @widget with gtk_widget_add_mnemonic_label().
+ * 
+ * Removes a widget from the list of mnemonic labels for
+ * this widget. (See gtk_widget_get_mnemonic_labels()). The widget
+ * must have previously been added to the list with
+ * gtk_widget_add_mnemonic_label().
+ *
+ * Since: 2.4
+ **/
+void
+gtk_widget_remove_mnemonic_label (GtkWidget *widget,
+                                  GtkWidget *label)
+{
+  GSList *old_list, *new_list;
+
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+  g_return_if_fail (GTK_IS_WIDGET (label));
+
+  old_list = g_object_steal_qdata (G_OBJECT (widget), quark_mnemonic_labels);
+  new_list = g_slist_remove (old_list, label);
+
+  if (new_list)
+    g_object_set_qdata_full (G_OBJECT (widget), quark_mnemonic_labels,
+			     new_list, (GDestroyNotify) g_slist_free);
+}
+
+/**
  * gtk_widget_get_no_show_all:
  * @widget: a #GtkWidget
  * 
Index: gtk/gtkwidget.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwidget.h,v
retrieving revision 1.147
diff -u -p -r1.147 gtkwidget.h
--- gtk/gtkwidget.h	26 Jan 2004 20:21:09 -0000	1.147
+++ gtk/gtkwidget.h	25 Feb 2004 17:25:43 -0000
@@ -760,6 +760,12 @@ void	     gtk_widget_class_path	   (GtkW
 					    gchar    **path,
 					    gchar    **path_reversed);
 
+GList* gtk_widget_get_mnemonic_labels   (GtkWidget *widget);
+void   gtk_widget_add_mnemonic_label    (GtkWidget *widget,
+					 GtkWidget *label);
+void   gtk_widget_remove_mnemonic_label (GtkWidget *widget,
+					 GtkWidget *label);
+
 GType           gtk_requisition_get_type (void);
 GtkRequisition *gtk_requisition_copy     (const GtkRequisition *requisition);
 void            gtk_requisition_free     (GtkRequisition       *requisition);
@@ -778,7 +784,6 @@ void              _gtk_widget_propagate_
 
 GdkColormap* _gtk_widget_peek_colormap (void);
 
-
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
Index: gtk/gtklabel.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtklabel.c,v
retrieving revision 1.143
diff -u -p -r1.143 gtklabel.c
--- gtk/gtklabel.c	4 Feb 2004 21:55:33 -0000	1.143
+++ gtk/gtklabel.c	25 Feb 2004 17:25:43 -0000
@@ -766,14 +766,20 @@ gtk_label_set_mnemonic_widget (GtkLabel 
     g_return_if_fail (GTK_IS_WIDGET (widget));
 
   if (label->mnemonic_widget)
-    g_object_weak_unref (G_OBJECT (label->mnemonic_widget),
-			 label_mnemonic_widget_weak_notify,
-			 label);
+    {
+      gtk_widget_remove_mnemonic_label (label->mnemonic_widget, GTK_WIDGET (label));
+      g_object_weak_unref (G_OBJECT (label->mnemonic_widget),
+			   label_mnemonic_widget_weak_notify,
+			   label);
+    }
   label->mnemonic_widget = widget;
   if (label->mnemonic_widget)
-    g_object_weak_ref (G_OBJECT (label->mnemonic_widget),
-		       label_mnemonic_widget_weak_notify,
-		       label);
+    {
+      g_object_weak_ref (G_OBJECT (label->mnemonic_widget),
+		         label_mnemonic_widget_weak_notify,
+		         label);
+      gtk_widget_add_mnemonic_label (label->mnemonic_widget, GTK_WIDGET (label));
+    }
   
   g_object_notify (G_OBJECT (label), "mnemonic_widget");
 }
