all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
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 ----




  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.