2004-08-30 Jan Dj\e,Ad\e(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.
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
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;
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. */
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);
+ }
+}
+
\f
/* Set the contents of the menubar widgets of frame F.
The argument FIRST_TIME is currently ignored;
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,
if (NILP (string))
break;
wv->name = (char *) SDATA (string);
+ update_submenu_strings (wv->contents);
wv = wv->next;
}