emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: NeXTstep (GNUstep/Cocoa) port and merging


From: Chong Yidong
Subject: Re: NeXTstep (GNUstep/Cocoa) port and merging
Date: Sun, 08 Jun 2008 00:48:26 -0400
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux)

Chong Yidong <address@hidden> writes:

> Stefan Monnier <address@hidden> 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));
  
- /* 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));
  
  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;
  }
  
- /* 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++;
- }
- 
- /* 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);
-     }
- }
- 
  /* 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 ****
      }
  }
  
- /* 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);
-       }
-     }
- }
- 
  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;
- }
- 
- /* 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);
-     }
- }
- 
  
  /* Set the contents of the menubar widgets of frame F.
     The argument FIRST_TIME is currently ignored;
--- 686,691 ----




reply via email to

[Prev in Thread] Current Thread [Next in Thread]