From 16ceacc222529b8cdfd6fa7b2031940a926717f0 Mon Sep 17 00:00:00 2001
From: =?utf8?q?Jan=20Dj=C3=A4rv?= <jan.h.d@swipnet.se>
Date: Mon, 30 Aug 2004 20:32:00 +0000
Subject: [PATCH] * macmenu.c (_widget_value): Added lname and lkey.
 (single_submenu): Set lname and lkey in widget_value instead of name and key.
 (update_submenu_strings): New function. (set_frame_menubar): Remove call to
 inhibit_garbage_collection, call update_submenu_strings.

---
 src/ChangeLog |  7 +++++++
 src/macmenu.c | 53 +++++++++++++++++++++++++++++++++++++++++----------
 2 files changed, 50 insertions(+), 10 deletions(-)

diff --git a/src/ChangeLog b/src/ChangeLog
index 8d441748ffd..14eece1b04e 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,12 @@
 2004-08-30  Jan Dj,Ad(Brv  <jan.h.d@swipnet.se>
 
+	* macmenu.c (_widget_value): Added lname and lkey.
+	(single_submenu): Set lname and lkey in widget_value
+	instead of name and key.
+	(update_submenu_strings): New function.
+	(set_frame_menubar): Remove call to inhibit_garbage_collection,
+	call update_submenu_strings.
+
 	* xmenu.c (digest_single_submenu): Set lname and lkey in widget_value
 	instead of name and key.
 	(update_submenu_strings): New function.
diff --git a/src/macmenu.c b/src/macmenu.c
index 9b09bfb3327..88012b01f73 100644
--- a/src/macmenu.c
+++ b/src/macmenu.c
@@ -90,10 +90,12 @@ enum button_type
 typedef struct _widget_value
 {
   /* name of widget */
+  Lisp_Object   lname;
   char*		name;
   /* value (meaning depend on widget type) */
   char*		value;
   /* keyboard equivalent. no implications for XtTranslations */
+  Lisp_Object   lkey;
   char*		key;
   /* Help string or nil if none.
      GC finds this string through the frame's menu_bar_vector
@@ -1221,12 +1223,9 @@ single_submenu (item_key, item_name, maps)
 		save_wv->next = wv;
 	      else
 		first_wv->contents = wv;
-	      wv->name = pane_string;
-	      /* Ignore the @ that means "separate pane".
-		 This is a kludge, but this isn't worth more time.  */
-	      if (!NILP (prefix) && wv->name[0] == '@')
-		wv->name++;
-	      wv->value = 0;
+	      wv->lname = pane_name;
+              /* Set value to 1 so update_submenu_strings can handle '@'  */
+	      wv->value = (char *)1;
 	      wv->enabled = 1;
 	      wv->button_type = BUTTON_TYPE_NONE;
 	      wv->help = Qnil;
@@ -1269,9 +1268,9 @@ single_submenu (item_key, item_name, maps)
 	  else
 	    save_wv->contents = wv;
 
-	  wv->name = (char *) SDATA (item_name);
+	  wv->lname = item_name;
 	  if (!NILP (descrip))
-	    wv->key = (char *) SDATA (descrip);
+	    wv->lkey = descrip;
 	  wv->value = 0;
 	  /* The EMACS_INT cast avoids a warning.  There's no problem
 	     as long as pointers have enough bits to hold small integers.  */
@@ -1310,6 +1309,41 @@ single_submenu (item_key, item_name, maps)
 
   return first_wv;
 }
+/* Walk through the widget_value tree starting at FIRST_WV and update
+   the char * pointers from the corresponding lisp values.
+   We do this after building the whole tree, since GC may happen while the
+   tree is constructed, and small strings are relocated.  So we must wait
+   until no GC can happen before storing pointers into lisp values.  */
+static void
+update_submenu_strings (first_wv)
+     widget_value *first_wv;
+{
+  widget_value *wv;
+
+  for (wv = first_wv; wv; wv = wv->next)
+    {
+      if (wv->lname && ! NILP (wv->lname))
+        {
+          wv->name = SDATA (wv->lname);
+
+          /* Ignore the @ that means "separate pane".
+             This is a kludge, but this isn't worth more time.  */
+          if (wv->value == (char *)1)
+            {
+              if (wv->name[0] == '@')
+		wv->name++;
+              wv->value = 0;
+            }
+        }
+
+      if (wv->lkey && ! NILP (wv->lkey))
+        wv->key = SDATA (wv->lkey);
+
+      if (wv->contents)
+        update_submenu_strings (wv->contents);
+    }
+}
+
 
 /* Set the contents of the menubar widgets of frame F.
    The argument FIRST_TIME is currently ignored;
@@ -1388,8 +1422,6 @@ set_frame_menubar (f, first_time, deep_p)
 
       items = FRAME_MENU_BAR_ITEMS (f);
 
-      inhibit_garbage_collection ();
-
       /* Save the frame's previous menu bar contents data.  */
       if (previous_menu_items_used)
 	bcopy (XVECTOR (f->menu_bar_vector)->contents, previous_items,
@@ -1454,6 +1486,7 @@ set_frame_menubar (f, first_time, deep_p)
 	  if (NILP (string))
 	    break;
 	  wv->name = (char *) SDATA (string);
+          update_submenu_strings (wv->contents);
 	  wv = wv->next;
 	}
 
-- 
2.39.5