From: Chong Yidong <cyd@stupidchicken.com>
To: Stefan Monnier <monnier@iro.umontreal.ca>
Cc: Adrian Robert <adrian.b.robert@gmail.com>,
emacs-devel <emacs-devel@gnu.org>
Subject: Re: NeXTstep (GNUstep/Cocoa) port and merging
Date: Sun, 08 Jun 2008 00:48:26 -0400 [thread overview]
Message-ID: <87ej78v8f9.fsf@stupidchicken.com> (raw)
In-Reply-To: <87od6ckbv7.fsf@stupidchicken.com> (Chong Yidong's message of "Sat, 07 Jun 2008 20:29:32 -0400")
Chong Yidong <cyd@stupidchicken.com> writes:
> Stefan Monnier <monnier@iro.umontreal.ca> writes:
>
>>> One area it would be nice to have some feedback on is the added file
>>> "nsmenu_common.c". This file of about 1000 lines contains code that is
>>> more or less duplicated (modulo some divergence) across {x,w32,mac}menu.c,
>>> and is concerned mainly with mediating between lisp and C representations
>>> of menus. I followed xmenu.c when creating the common file. It would be
>>> good to change this to "menu_common.c" and have the other GUIs use it.
>>
>> Yes, it would indeed be good. I've already several times intended to
>> make a similar change but never got around to really do it. If someone
>> could take this part of the Emacs.app patch and make it independent from
>> Emacs.app, that would be great.
>
> I've been working on this, and it's nearly ready. I'll check in a
> platform-independent menu.c sometime this week. It will probably need a
> bit of help from those with access to w32 and mac to get it working
> properly on those platforms.
>
> I'll ping the list when it's checked in.
I've added a new file menu.c to the CVS trunk. This contains
platform-independent parts of the menu code, taken from xmenu.c. Some
definitions have also been moved into keyboard.h.
Currently, I have only removed code from xmenu.c, and menu.c is only
compiled in when HAVE_X_WINDOWS is defined. I cannot test it on Windows
or Mac OS, and I don't want to break things.
I think the following additional patch should DTRT on Windows, but it is
100% untested. Could someone try it? Also, could someone try write up
the analogous code for Mac OS?
Please let me know if there are problems.
*** trunk/src/Makefile.in.~1.386.~ 2008-06-07 23:59:44.000000000 -0400
--- trunk/src/Makefile.in 2008-06-08 00:44:08.000000000 -0400
***************
*** 539,545 ****
#endif /* HAVE_X_WINDOWS */
#endif /* HAVE_WINDOW_SYSTEM */
! #ifdef HAVE_X_WINDOWS
MENU_OBJ = menu.o
#endif
--- 539,545 ----
#endif /* HAVE_X_WINDOWS */
#endif /* HAVE_WINDOW_SYSTEM */
! #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
MENU_OBJ = menu.o
#endif
*** trunk/src/keyboard.h.~1.84.~ 2008-06-08 00:06:07.000000000 -0400
--- trunk/src/keyboard.h 2008-06-08 00:43:45.000000000 -0400
***************
*** 253,259 ****
/* Not nil if item is enabled. */
#define ITEM_PROPERTY_ENABLE 8
! #ifdef HAVE_X_WINDOWS
/* This holds a Lisp vector that holds the results of decoding
the keymaps or alist-of-alists that specify a menu.
--- 253,259 ----
/* Not nil if item is enabled. */
#define ITEM_PROPERTY_ENABLE 8
! #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
/* This holds a Lisp vector that holds the results of decoding
the keymaps or alist-of-alists that specify a menu.
*** trunk/src/w32menu.c~ 2008-06-07 23:11:45.000000000 -0400
--- trunk/src/w32menu.c 2008-06-07 20:53:21.000000000 -0400
***************
*** 51,130 ****
#undef HAVE_DIALOGS /* TODO: Implement native dialogs. */
/******************************************************************/
- /* Definitions copied from lwlib.h */
-
- typedef void * XtPointer;
- typedef char Boolean;
-
- enum button_type
- {
- BUTTON_TYPE_NONE,
- BUTTON_TYPE_TOGGLE,
- BUTTON_TYPE_RADIO
- };
-
- /* This structure is based on the one in ../lwlib/lwlib.h, modified
- for Windows. */
- 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
- or through menu_items. */
- Lisp_Object help;
- /* true if enabled */
- Boolean enabled;
- /* true if selected */
- Boolean selected;
- /* The type of a button. */
- enum button_type button_type;
- /* true if menu title */
- Boolean title;
- #if 0
- /* true if was edited (maintained by get_value) */
- Boolean edited;
- /* true if has changed (maintained by lw library) */
- change_type change;
- /* true if this widget itself has changed,
- but not counting the other widgets found in the `next' field. */
- change_type this_one_change;
- #endif
- /* Contents of the sub-widgets, also selected slot for checkbox */
- struct _widget_value* contents;
- /* data passed to callback */
- XtPointer call_data;
- /* next one in the list */
- struct _widget_value* next;
- #if 0
- /* slot for the toolkit dependent part. Always initialize to NULL. */
- void* toolkit_data;
- /* tell us if we should free the toolkit data slot when freeing the
- widget_value itself. */
- Boolean free_toolkit_data;
-
- /* we resource the widget_value structures; this points to the next
- one on the free list if this one has been deallocated.
- */
- struct _widget_value *free_list;
- #endif
- } widget_value;
-
- /* Local memory management */
- #define local_heap (GetProcessHeap ())
- #define local_alloc(n) (HeapAlloc (local_heap, HEAP_ZERO_MEMORY, (n)))
- #define local_free(p) (HeapFree (local_heap, 0, ((LPVOID) (p))))
-
- #define malloc_widget_value() ((widget_value *) local_alloc (sizeof (widget_value)))
- #define free_widget_value(wv) (local_free ((wv)))
-
- /******************************************************************/
#ifndef TRUE
#define TRUE 1
--- 51,56 ----
***************
*** 180,250 ****
static Lisp_Object w32_menu_show P_ ((FRAME_PTR, int, int, int, int,
Lisp_Object, char **));
- static void keymap_panes P_ ((Lisp_Object *, int, int));
- static void single_keymap_panes P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
- int, int));
- static void single_menu_item P_ ((Lisp_Object, Lisp_Object,
- Lisp_Object *, int, int));
- static void list_of_panes P_ ((Lisp_Object));
- static void list_of_items P_ ((Lisp_Object));
void w32_free_menu_strings P_((HWND));
\f
- /* This holds a Lisp vector that holds the results of decoding
- the keymaps or alist-of-alists that specify a menu.
-
- It describes the panes and items within the panes.
-
- Each pane is described by 3 elements in the vector:
- t, the pane name, the pane's prefix key.
- Then follow the pane's items, with 5 elements per item:
- the item string, the enable flag, the item's value,
- the definition, and the equivalent keyboard key's description string.
-
- In some cases, multiple levels of menus may be described.
- A single vector slot containing nil indicates the start of a submenu.
- A single vector slot containing lambda indicates the end of a submenu.
- The submenu follows a menu item which is the way to reach the submenu.
-
- A single vector slot containing quote indicates that the
- following items should appear on the right of a dialog box.
-
- Using a Lisp vector to hold this information while we decode it
- takes care of protecting all the data from GC. */
-
- #define MENU_ITEMS_PANE_NAME 1
- #define MENU_ITEMS_PANE_PREFIX 2
- #define MENU_ITEMS_PANE_LENGTH 3
-
- enum menu_item_idx
- {
- MENU_ITEMS_ITEM_NAME = 0,
- MENU_ITEMS_ITEM_ENABLE,
- MENU_ITEMS_ITEM_VALUE,
- MENU_ITEMS_ITEM_EQUIV_KEY,
- MENU_ITEMS_ITEM_DEFINITION,
- MENU_ITEMS_ITEM_TYPE,
- MENU_ITEMS_ITEM_SELECTED,
- MENU_ITEMS_ITEM_HELP,
- MENU_ITEMS_ITEM_LENGTH
- };
-
- static Lisp_Object menu_items;
-
- /* Number of slots currently allocated in menu_items. */
- static int menu_items_allocated;
-
- /* This is the index in menu_items of the first empty slot. */
- static int menu_items_used;
-
- /* The number of panes currently recorded in menu_items,
- excluding those within submenus. */
- static int menu_items_n_panes;
-
- /* Current depth within submenus. */
- static int menu_items_submenu_depth;
-
static int next_menubar_widget_id;
/* This is set nonzero after the user activates the menu bar, and set
to zero again after the menu bars are redisplayed by prepare_menu_bar.
While it is nonzero, all calls to set_frame_menubar go deep.
--- 106,117 ----
static Lisp_Object w32_menu_show P_ ((FRAME_PTR, int, int, int, int,
Lisp_Object, char **));
void w32_free_menu_strings P_((HWND));
\f
static int next_menubar_widget_id;
+ extern widget_value *xmalloc_widget_value P_ ((void));
+
/* This is set nonzero after the user activates the menu bar, and set
to zero again after the menu bars are redisplayed by prepare_menu_bar.
While it is nonzero, all calls to set_frame_menubar go deep.
***************
*** 279,504 ****
return 0;
}
\f
- /* Initialize the menu_items structure if we haven't already done so.
- Also mark it as currently empty. */
-
- static void
- init_menu_items ()
- {
- if (NILP (menu_items))
- {
- menu_items_allocated = 60;
- menu_items = Fmake_vector (make_number (menu_items_allocated), Qnil);
- }
-
- menu_items_used = 0;
- menu_items_n_panes = 0;
- menu_items_submenu_depth = 0;
- }
-
- /* Call at the end of generating the data in menu_items.
- This fills in the number of items in the last pane. */
-
- static void
- finish_menu_items ()
- {
- }
-
- /* Call when finished using the data for the current menu
- in menu_items. */
-
- static void
- discard_menu_items ()
- {
- /* Free the structure if it is especially large.
- Otherwise, hold on to it, to save time. */
- if (menu_items_allocated > 200)
- {
- menu_items = Qnil;
- menu_items_allocated = 0;
- }
- }
-
- /* Make the menu_items vector twice as large. */
-
- static void
- grow_menu_items ()
- {
- menu_items_allocated *= 2;
- menu_items = larger_vector (menu_items, menu_items_allocated, Qnil);
- }
-
- /* Begin a submenu. */
-
- static void
- push_submenu_start ()
- {
- if (menu_items_used + 1 > menu_items_allocated)
- grow_menu_items ();
-
- ASET (menu_items, menu_items_used, Qnil);
- menu_items_used++;
- menu_items_submenu_depth++;
- }
-
- /* End a submenu. */
-
- static void
- push_submenu_end ()
- {
- if (menu_items_used + 1 > menu_items_allocated)
- grow_menu_items ();
-
- ASET (menu_items, menu_items_used, Qlambda);
- menu_items_used++;
- menu_items_submenu_depth--;
- }
-
- /* Indicate boundary between left and right. */
-
- static void
- push_left_right_boundary ()
- {
- if (menu_items_used + 1 > menu_items_allocated)
- grow_menu_items ();
-
- ASET (menu_items, menu_items_used, Qquote);
- menu_items_used++;
- }
-
- /* Start a new menu pane in menu_items.
- NAME is the pane name. PREFIX_VEC is a prefix key for this pane. */
-
- static void
- push_menu_pane (name, prefix_vec)
- Lisp_Object name, prefix_vec;
- {
- if (menu_items_used + MENU_ITEMS_PANE_LENGTH > menu_items_allocated)
- grow_menu_items ();
-
- if (menu_items_submenu_depth == 0)
- menu_items_n_panes++;
- ASET (menu_items, menu_items_used, Qt); menu_items_used++;
- ASET (menu_items, menu_items_used, name); menu_items_used++;
- ASET (menu_items, menu_items_used, prefix_vec); menu_items_used++;
- }
-
- /* Push one menu item into the current pane. NAME is the string to
- display. ENABLE if non-nil means this item can be selected. KEY
- is the key generated by choosing this item, or nil if this item
- doesn't really have a definition. DEF is the definition of this
- item. EQUIV is the textual description of the keyboard equivalent
- for this item (or nil if none). TYPE is the type of this menu
- item, one of nil, `toggle' or `radio'. */
-
- static void
- push_menu_item (name, enable, key, def, equiv, type, selected, help)
- Lisp_Object name, enable, key, def, equiv, type, selected, help;
- {
- if (menu_items_used + MENU_ITEMS_ITEM_LENGTH > menu_items_allocated)
- grow_menu_items ();
-
- ASET (menu_items, menu_items_used, name); menu_items_used++;
- ASET (menu_items, menu_items_used, enable); menu_items_used++;
- ASET (menu_items, menu_items_used, key); menu_items_used++;
- ASET (menu_items, menu_items_used, equiv); menu_items_used++;
- ASET (menu_items, menu_items_used, def); menu_items_used++;
- ASET (menu_items, menu_items_used, type); menu_items_used++;
- ASET (menu_items, menu_items_used, selected); menu_items_used++;
- ASET (menu_items, menu_items_used, help); menu_items_used++;
- }
- \f
- /* Look through KEYMAPS, a vector of keymaps that is NMAPS long,
- and generate menu panes for them in menu_items.
- If NOTREAL is nonzero,
- don't bother really computing whether an item is enabled. */
-
- static void
- keymap_panes (keymaps, nmaps, notreal)
- Lisp_Object *keymaps;
- int nmaps;
- int notreal;
- {
- int mapno;
-
- init_menu_items ();
-
- /* Loop over the given keymaps, making a pane for each map.
- But don't make a pane that is empty--ignore that map instead.
- P is the number of panes we have made so far. */
- for (mapno = 0; mapno < nmaps; mapno++)
- single_keymap_panes (keymaps[mapno],
- Fkeymap_prompt (keymaps[mapno]), Qnil, notreal, 10);
-
- finish_menu_items ();
- }
-
- /* This is a recursive subroutine of keymap_panes.
- It handles one keymap, KEYMAP.
- The other arguments are passed along
- or point to local variables of the previous function.
- If NOTREAL is nonzero, only check for equivalent key bindings, don't
- evaluate expressions in menu items and don't make any menu.
-
- If we encounter submenus deeper than MAXDEPTH levels, ignore them. */
-
- static void
- single_keymap_panes (keymap, pane_name, prefix, notreal, maxdepth)
- Lisp_Object keymap;
- Lisp_Object pane_name;
- Lisp_Object prefix;
- int notreal;
- int maxdepth;
- {
- Lisp_Object pending_maps = Qnil;
- Lisp_Object tail, item;
- struct gcpro gcpro1, gcpro2;
-
- if (maxdepth <= 0)
- return;
-
- push_menu_pane (pane_name, prefix);
-
- for (tail = keymap; CONSP (tail); tail = XCDR (tail))
- {
- GCPRO2 (keymap, pending_maps);
- /* Look at each key binding, and if it is a menu item add it
- to this menu. */
- item = XCAR (tail);
- if (CONSP (item))
- single_menu_item (XCAR (item), XCDR (item),
- &pending_maps, notreal, maxdepth);
- else if (VECTORP (item))
- {
- /* Loop over the char values represented in the vector. */
- int len = ASIZE (item);
- int c;
- for (c = 0; c < len; c++)
- {
- Lisp_Object character;
- XSETFASTINT (character, c);
- single_menu_item (character, AREF (item, c),
- &pending_maps, notreal, maxdepth);
- }
- }
- UNGCPRO;
- }
-
- /* Process now any submenus which want to be panes at this level. */
- while (!NILP (pending_maps))
- {
- Lisp_Object elt, eltcdr, string;
- elt = Fcar (pending_maps);
- eltcdr = XCDR (elt);
- string = XCAR (eltcdr);
- /* We no longer discard the @ from the beginning of the string here.
- Instead, we do this in w32_menu_show. */
- single_keymap_panes (Fcar (elt), string,
- XCDR (eltcdr), notreal, maxdepth - 1);
- pending_maps = Fcdr (pending_maps);
- }
- }
- \f
/* This is a subroutine of single_keymap_panes that handles one
keymap entry.
KEY is a key in a keymap and ITEM is its binding.
--- 146,151 ----
***************
*** 564,621 ****
}
}
\f
- /* Push all the panes and items of a menu described by the
- alist-of-alists MENU.
- This handles old-fashioned calls to x-popup-menu. */
-
- static void
- list_of_panes (menu)
- Lisp_Object menu;
- {
- Lisp_Object tail;
-
- init_menu_items ();
-
- for (tail = menu; CONSP (tail); tail = XCDR (tail))
- {
- Lisp_Object elt, pane_name, pane_data;
- elt = XCAR (tail);
- pane_name = Fcar (elt);
- CHECK_STRING (pane_name);
- push_menu_pane (pane_name, Qnil);
- pane_data = Fcdr (elt);
- CHECK_CONS (pane_data);
- list_of_items (pane_data);
- }
-
- finish_menu_items ();
- }
-
- /* Push the items in a single pane defined by the alist PANE. */
-
- static void
- list_of_items (pane)
- Lisp_Object pane;
- {
- Lisp_Object tail, item, item1;
-
- for (tail = pane; CONSP (tail); tail = XCDR (tail))
- {
- item = XCAR (tail);
- if (STRINGP (item))
- push_menu_item (item, Qnil, Qnil, Qt, Qnil, Qnil, Qnil, Qnil);
- else if (NILP (item))
- push_left_right_boundary ();
- else
- {
- CHECK_CONS (item);
- item1 = Fcar (item);
- CHECK_STRING (item1);
- push_menu_item (item1, Qt, Fcdr (item), Qt, Qnil, Qnil, Qnil, Qnil);
- }
- }
- }
- \f
DEFUN ("x-popup-menu", Fx_popup_menu, Sx_popup_menu, 2, 2, 0,
doc: /* Pop up a deck-of-cards menu and return user's selection.
POSITION is a position specification. This is either a mouse button
--- 211,216 ----
***************
*** 1091,1406 ****
w32_free_menu_strings (FRAME_W32_WINDOW (f));
f->output_data.w32->menubar_active = 0;
}
-
- /* Allocate a widget_value, blocking input. */
-
- widget_value *
- xmalloc_widget_value ()
- {
- widget_value *value;
-
- BLOCK_INPUT;
- value = malloc_widget_value ();
- UNBLOCK_INPUT;
-
- return value;
- }
-
- /* This recursively calls free_widget_value on the tree of widgets.
- It must free all data that was malloc'ed for these widget_values.
- In Emacs, many slots are pointers into the data of Lisp_Strings, and
- must be left alone. */
-
- void
- free_menubar_widget_value_tree (wv)
- widget_value *wv;
- {
- if (! wv) return;
-
- wv->name = wv->value = wv->key = (char *) 0xDEADBEEF;
-
- if (wv->contents && (wv->contents != (widget_value*)1))
- {
- free_menubar_widget_value_tree (wv->contents);
- wv->contents = (widget_value *) 0xDEADBEEF;
- }
- if (wv->next)
- {
- free_menubar_widget_value_tree (wv->next);
- wv->next = (widget_value *) 0xDEADBEEF;
- }
- BLOCK_INPUT;
- free_widget_value (wv);
- UNBLOCK_INPUT;
- }
- \f
- /* Set up data i menu_items for a menu bar item
- whose event type is ITEM_KEY (with string ITEM_NAME)
- and whose contents come from the list of keymaps MAPS. */
-
- static int
- parse_single_submenu (item_key, item_name, maps)
- Lisp_Object item_key, item_name, maps;
- {
- Lisp_Object length;
- int len;
- Lisp_Object *mapvec;
- int i;
- int top_level_items = 0;
-
- length = Flength (maps);
- len = XINT (length);
-
- /* Convert the list MAPS into a vector MAPVEC. */
- mapvec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
- for (i = 0; i < len; i++)
- {
- mapvec[i] = Fcar (maps);
- maps = Fcdr (maps);
- }
-
- /* Loop over the given keymaps, making a pane for each map.
- But don't make a pane that is empty--ignore that map instead. */
- for (i = 0; i < len; i++)
- {
- if (SYMBOLP (mapvec[i])
- || (CONSP (mapvec[i]) && !KEYMAPP (mapvec[i])))
- {
- /* Here we have a command at top level in the menu bar
- as opposed to a submenu. */
- top_level_items = 1;
- push_menu_pane (Qnil, Qnil);
- push_menu_item (item_name, Qt, item_key, mapvec[i],
- Qnil, Qnil, Qnil, Qnil);
- }
- else
- {
- Lisp_Object prompt;
- prompt = Fkeymap_prompt (mapvec[i]);
- single_keymap_panes (mapvec[i],
- !NILP (prompt) ? prompt : item_name,
- item_key, 0, 10);
- }
- }
-
- return top_level_items;
- }
-
-
- /* Create a tree of widget_value objects
- representing the panes and items
- in menu_items starting at index START, up to index END. */
-
- static widget_value *
- digest_single_submenu (start, end, top_level_items)
- int start, end, top_level_items;
- {
- widget_value *wv, *prev_wv, *save_wv, *first_wv;
- int i;
- int submenu_depth = 0;
- widget_value **submenu_stack;
-
- submenu_stack
- = (widget_value **) alloca (menu_items_used * sizeof (widget_value *));
- wv = xmalloc_widget_value ();
- wv->name = "menu";
- wv->value = 0;
- wv->enabled = 1;
- wv->button_type = BUTTON_TYPE_NONE;
- wv->help = Qnil;
- first_wv = wv;
- save_wv = 0;
- prev_wv = 0;
-
- /* Loop over all panes and items made by the preceding call
- to parse_single_submenu and construct a tree of widget_value objects.
- Ignore the panes and items used by previous calls to
- digest_single_submenu, even though those are also in menu_items. */
- i = start;
- while (i < end)
- {
- if (EQ (AREF (menu_items, i), Qnil))
- {
- submenu_stack[submenu_depth++] = save_wv;
- save_wv = prev_wv;
- prev_wv = 0;
- i++;
- }
- else if (EQ (AREF (menu_items, i), Qlambda))
- {
- prev_wv = save_wv;
- save_wv = submenu_stack[--submenu_depth];
- i++;
- }
- else if (EQ (AREF (menu_items, i), Qt)
- && submenu_depth != 0)
- i += MENU_ITEMS_PANE_LENGTH;
- /* Ignore a nil in the item list.
- It's meaningful only for dialog boxes. */
- else if (EQ (AREF (menu_items, i), Qquote))
- i += 1;
- else if (EQ (AREF (menu_items, i), Qt))
- {
- /* Create a new pane. */
- Lisp_Object pane_name, prefix;
- char *pane_string;
-
- pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME);
- prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
-
- if (STRINGP (pane_name))
- {
- if (unicode_append_menu)
- /* Encode as UTF-8 for now. */
- pane_name = ENCODE_UTF_8 (pane_name);
- else if (STRING_MULTIBYTE (pane_name))
- pane_name = ENCODE_SYSTEM (pane_name);
-
- ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
- }
-
- pane_string = (NILP (pane_name)
- ? "" : (char *) SDATA (pane_name));
- /* If there is just one top-level pane, put all its items directly
- under the top-level menu. */
- if (menu_items_n_panes == 1)
- pane_string = "";
-
- /* If the pane has a meaningful name,
- make the pane a top-level menu item
- with its items as a submenu beneath it. */
- if (strcmp (pane_string, ""))
- {
- wv = xmalloc_widget_value ();
- if (save_wv)
- save_wv->next = wv;
- else
- first_wv->contents = wv;
- 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;
- }
- save_wv = wv;
- prev_wv = 0;
- i += MENU_ITEMS_PANE_LENGTH;
- }
- else
- {
- /* Create a new item within current pane. */
- Lisp_Object item_name, enable, descrip, def, type, selected;
- Lisp_Object help;
-
- item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
- enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
- descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY);
- def = AREF (menu_items, i + MENU_ITEMS_ITEM_DEFINITION);
- type = AREF (menu_items, i + MENU_ITEMS_ITEM_TYPE);
- selected = AREF (menu_items, i + MENU_ITEMS_ITEM_SELECTED);
- help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
-
- if (STRINGP (item_name))
- {
- if (unicode_append_menu)
- item_name = ENCODE_UTF_8 (item_name);
- else if (STRING_MULTIBYTE (item_name))
- item_name = ENCODE_SYSTEM (item_name);
-
- ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
- }
-
- if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
- {
- descrip = ENCODE_SYSTEM (descrip);
- ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
- }
-
- wv = xmalloc_widget_value ();
- if (prev_wv)
- prev_wv->next = wv;
- else
- save_wv->contents = wv;
-
- wv->lname = item_name;
- if (!NILP (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. */
- wv->call_data = (!NILP (def) ? (void *) (EMACS_INT) i : 0);
- wv->enabled = !NILP (enable);
-
- if (NILP (type))
- wv->button_type = BUTTON_TYPE_NONE;
- else if (EQ (type, QCradio))
- wv->button_type = BUTTON_TYPE_RADIO;
- else if (EQ (type, QCtoggle))
- wv->button_type = BUTTON_TYPE_TOGGLE;
- else
- abort ();
-
- wv->selected = !NILP (selected);
- if (!STRINGP (help))
- help = Qnil;
-
- wv->help = help;
-
- prev_wv = wv;
-
- i += MENU_ITEMS_ITEM_LENGTH;
- }
- }
-
- /* If we have just one "menu item"
- that was originally a button, return it by itself. */
- if (top_level_items && first_wv->contents && first_wv->contents->next == 0)
- {
- wv = first_wv->contents;
- free_widget_value (first_wv);
- return wv;
- }
-
- 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;
--- 686,691 ----
next prev parent reply other threads:[~2008-06-08 4:48 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-06-04 1:44 NeXTstep (GNUstep/Cocoa) port and merging Adrian Robert
2008-06-04 2:34 ` Stefan Monnier
2008-06-08 0:29 ` Chong Yidong
2008-06-08 4:48 ` Chong Yidong [this message]
2008-06-04 16:02 ` Sean O'Rourke
2008-06-07 12:21 ` Thomas Christensen
2008-06-08 4:08 ` İsmail Dönmez
2008-06-08 12:18 ` Thomas Christensen
2008-06-08 12:25 ` İsmail Dönmez
2008-06-14 17:04 ` Sean O'Rourke
2008-06-14 17:07 ` İsmail Dönmez
2008-06-14 17:21 ` Sean O'Rourke
2008-06-14 17:22 ` İsmail Dönmez
2008-06-14 17:41 ` Sean O'Rourke
2008-06-14 17:59 ` Bazaar and savannah don't like each other Stefan Monnier
2008-06-14 18:06 ` Sean O'Rourke
2008-06-14 18:11 ` İsmail Dönmez
2008-06-14 18:20 ` James Westby
2008-06-14 18:22 ` James Westby
2008-06-15 9:05 ` [Savannah-help-public] Bazaar does not fit in GNU Arch hosting [Was: Bazaar and savannah don't like each other] Sylvain Beucler
2008-06-15 9:12 ` Lennart Borgman (gmail)
2008-06-16 2:32 ` [Savannah-help-public] Bazaar does not fit in GNU Arch hosting Stefan Monnier
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87ej78v8f9.fsf@stupidchicken.com \
--to=cyd@stupidchicken.com \
--cc=adrian.b.robert@gmail.com \
--cc=emacs-devel@gnu.org \
--cc=monnier@iro.umontreal.ca \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.