unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: David Ponce <david@dponce.com>
Cc: emacs-devel@gnu.org
Subject: Re: NT Emacs crashes when selecting a menubar item
Date: Thu, 01 Aug 2002 00:37:05 +0200	[thread overview]
Message-ID: <3D486691.5050708@dponce.com> (raw)
In-Reply-To: 200207312157.g6VLvlL17436@aztec.santafe.edu

[-- Attachment #1: Type: text/plain, Size: 1560 bytes --]

Richard Stallman wrote:

>I figured out how Lisp code was getting called during that loop.
>xmenu.c had the same bug, so I fixed it there.
>
>Now we need a Windows hacker to adapt the same fix to w32menu.c.
>Perhaps macmenu.c needs the same change.
>
>Thanks for figuring this out.
>
>
Hi Richard,

I adapted your changes from xmenu.c to the version of w32menu.c where
I fixed another bug with popup menu, and generalized use of the macros
AREF, ASET, ASIZE, to access vectors.  Attached you will find a new
diff.  The change log is at end.

I currently use this new version and can confirm that you fixed the bug
:-)

Thank you very much for your support!
David

------------ Change Log:

(local_heap, local_alloc, local_free): New macros.
(malloc_widget_value, free_widget_value)
(w32_free_submenu_strings): Use them.

(push_submenu_start, push_submenu_end, push_left_right_boundary)
(push_menu_pane, push_menu_item, single_keymap_panes)
(single_menu_item, Fx_popup_menu, menubar_selection_callback)
(single_submenu, set_frame_menubar)
(w32_menu_show, w32_dialog_show): Use AREF, ASET, ASIZE.

(Fx_popup_menu):  Don't show pop up menu until preceding one is
actually cleaned up.  Moved UNGCPRO outside #ifdef HAVE_MENUS block.

Changes adapted from xmenu.c

(set_frame_menubar): First parse all submenus,
then make widget_value trees from them.
Don't allocate any widget_value objects
until we are done with the parsing.
(parse_single_submenu): New function.
(digest_single_submenu): New function.
(single_submenu): Function deleted, replaced by those two.


[-- Attachment #2: w32menu.patch --]
[-- Type: text/x-patch, Size: 31663 bytes --]

*** w32menu.c.ori	Mon Jul 15 10:48:32 2002
--- w32menu.c	Wed Jul 31 21:22:29 2002
***************
*** 112,120 ****
  #endif
  } widget_value;
  
! /* LocalAlloc/Free is a reasonably good allocator.  */
! #define malloc_widget_value() (void*)LocalAlloc (LMEM_ZEROINIT, sizeof (widget_value))
! #define free_widget_value(wv) LocalFree (wv)
  
  /******************************************************************/
  
--- 112,124 ----
  #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)))
  
  /******************************************************************/
  
***************
*** 318,324 ****
    if (menu_items_used + 1 > menu_items_allocated)
      grow_menu_items ();
  
!   XVECTOR (menu_items)->contents[menu_items_used++] = Qnil;
    menu_items_submenu_depth++;
  }
  
--- 322,328 ----
    if (menu_items_used + 1 > menu_items_allocated)
      grow_menu_items ();
  
!   ASET (menu_items, menu_items_used++, Qnil);
    menu_items_submenu_depth++;
  }
  
***************
*** 330,336 ****
    if (menu_items_used + 1 > menu_items_allocated)
      grow_menu_items ();
  
!   XVECTOR (menu_items)->contents[menu_items_used++] = Qlambda;
    menu_items_submenu_depth--;
  }
  
--- 334,340 ----
    if (menu_items_used + 1 > menu_items_allocated)
      grow_menu_items ();
  
!   ASET (menu_items, menu_items_used++, Qlambda);
    menu_items_submenu_depth--;
  }
  
***************
*** 342,348 ****
    if (menu_items_used + 1 > menu_items_allocated)
      grow_menu_items ();
  
!   XVECTOR (menu_items)->contents[menu_items_used++] = Qquote;
  }
  
  /* Start a new menu pane in menu_items.
--- 346,352 ----
    if (menu_items_used + 1 > menu_items_allocated)
      grow_menu_items ();
  
!   ASET (menu_items, menu_items_used++, Qquote);
  }
  
  /* Start a new menu pane in menu_items.
***************
*** 357,365 ****
  
    if (menu_items_submenu_depth == 0)
      menu_items_n_panes++;
!   XVECTOR (menu_items)->contents[menu_items_used++] = Qt;
!   XVECTOR (menu_items)->contents[menu_items_used++] = name;
!   XVECTOR (menu_items)->contents[menu_items_used++] = prefix_vec;
  }
  
  /* Push one menu item into the current pane.  NAME is the string to
--- 361,369 ----
  
    if (menu_items_submenu_depth == 0)
      menu_items_n_panes++;
!   ASET (menu_items, menu_items_used++, Qt);
!   ASET (menu_items, menu_items_used++, name);
!   ASET (menu_items, menu_items_used++, prefix_vec);
  }
  
  /* Push one menu item into the current pane.  NAME is the string to
***************
*** 377,390 ****
    if (menu_items_used + MENU_ITEMS_ITEM_LENGTH > menu_items_allocated)
      grow_menu_items ();
  
!   XVECTOR (menu_items)->contents[menu_items_used++] = name;
!   XVECTOR (menu_items)->contents[menu_items_used++] = enable;
!   XVECTOR (menu_items)->contents[menu_items_used++] = key;
!   XVECTOR (menu_items)->contents[menu_items_used++] = equiv;
!   XVECTOR (menu_items)->contents[menu_items_used++] = def;
!   XVECTOR (menu_items)->contents[menu_items_used++] = type;
!   XVECTOR (menu_items)->contents[menu_items_used++] = selected;
!   XVECTOR (menu_items)->contents[menu_items_used++] = help;
  }
  \f
  /* Look through KEYMAPS, a vector of keymaps that is NMAPS long,
--- 381,394 ----
    if (menu_items_used + MENU_ITEMS_ITEM_LENGTH > menu_items_allocated)
      grow_menu_items ();
  
!   ASET (menu_items, menu_items_used++, name);
!   ASET (menu_items, menu_items_used++, enable);
!   ASET (menu_items, menu_items_used++, key);
!   ASET (menu_items, menu_items_used++, equiv);
!   ASET (menu_items, menu_items_used++, def);
!   ASET (menu_items, menu_items_used++, type);
!   ASET (menu_items, menu_items_used++, selected);
!   ASET (menu_items, menu_items_used++, help);
  }
  \f
  /* Look through KEYMAPS, a vector of keymaps that is NMAPS long,
***************
*** 450,462 ****
        else if (VECTORP (item))
  	{
  	  /* Loop over the char values represented in the vector.  */
! 	  int len = XVECTOR (item)->size;
  	  int c;
  	  for (c = 0; c < len; c++)
  	    {
  	      Lisp_Object character;
  	      XSETFASTINT (character, c);
! 	      single_menu_item (character, XVECTOR (item)->contents[c],
  				&pending_maps, notreal, maxdepth);
  	    }
  	}
--- 454,466 ----
        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);
  	    }
  	}
***************
*** 504,510 ****
    if (!res)
      return;			/* Not a menu item.  */
  
!   map = XVECTOR (item_properties)->contents[ITEM_PROPERTY_MAP];
    
    if (notreal)
      {
--- 508,514 ----
    if (!res)
      return;			/* Not a menu item.  */
  
!   map = AREF (item_properties, ITEM_PROPERTY_MAP);
    
    if (notreal)
      {
***************
*** 515,522 ****
        return;
      }
  
!   enabled = XVECTOR (item_properties)->contents[ITEM_PROPERTY_ENABLE];
!   item_string = XVECTOR (item_properties)->contents[ITEM_PROPERTY_NAME]; 
  
    if (!NILP (map) && SREF (item_string, 0) == '@')
      {
--- 519,526 ----
        return;
      }
  
!   enabled = AREF (item_properties, ITEM_PROPERTY_ENABLE);
!   item_string = AREF (item_properties, ITEM_PROPERTY_NAME); 
  
    if (!NILP (map) && SREF (item_string, 0) == '@')
      {
***************
*** 528,538 ****
      }
  
    push_menu_item (item_string, enabled, key,
! 		  XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF],
! 		  XVECTOR (item_properties)->contents[ITEM_PROPERTY_KEYEQ],
! 		  XVECTOR (item_properties)->contents[ITEM_PROPERTY_TYPE],
!                   XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED],
!                   XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP]);
  
    /* Display a submenu using the toolkit.  */
    if (! (NILP (map) || NILP (enabled)))
--- 532,542 ----
      }
  
    push_menu_item (item_string, enabled, key,
! 		  AREF (item_properties, ITEM_PROPERTY_DEF),
! 		  AREF (item_properties, ITEM_PROPERTY_KEYEQ),
! 		  AREF (item_properties, ITEM_PROPERTY_TYPE),
!                   AREF (item_properties, ITEM_PROPERTY_SELECTED),
!                   AREF (item_properties, ITEM_PROPERTY_HELP));
  
    /* Display a submenu using the toolkit.  */
    if (! (NILP (map) || NILP (enabled)))
***************
*** 745,751 ****
  
        /* Make that be the pane title of the first pane.  */
        if (!NILP (prompt) && menu_items_n_panes >= 0)
! 	XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME] = prompt;
  
        keymaps = 1;
      }
--- 749,755 ----
  
        /* Make that be the pane title of the first pane.  */
        if (!NILP (prompt) && menu_items_n_panes >= 0)
! 	ASET (menu_items, MENU_ITEMS_PANE_NAME, prompt);
  
        keymaps = 1;
      }
***************
*** 777,783 ****
  
        /* Make the title be the pane title of the first pane.  */
        if (!NILP (title) && menu_items_n_panes >= 0)
! 	XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME] = title;
  
        keymaps = 1;
      }
--- 781,787 ----
  
        /* Make the title be the pane title of the first pane.  */
        if (!NILP (title) && menu_items_n_panes >= 0)
! 	ASET (menu_items, MENU_ITEMS_PANE_NAME, title);
  
        keymaps = 1;
      }
***************
*** 800,805 ****
--- 804,819 ----
      }
  
  #ifdef HAVE_MENUS
+   /* If resources from a previous popup menu exist yet, does nothing
+      until the `menu_free_timer' has freed them (see w32fns.c).
+   */
+   if (current_popup_menu)
+     {
+       discard_menu_items ();
+       UNGCPRO;
+       return Qnil;
+     }    
+   
    /* Display them in a menu.  */
    BLOCK_INPUT;
  
***************
*** 808,816 ****
    UNBLOCK_INPUT;
  
    discard_menu_items ();
  
    UNGCPRO;
- #endif /* HAVE_MENUS */
  
    if (error_name) error (error_name);
    return selection;
--- 822,830 ----
    UNBLOCK_INPUT;
  
    discard_menu_items ();
+ #endif /* HAVE_MENUS */
  
    UNGCPRO;
  
    if (error_name) error (error_name);
    return selection;
***************
*** 981,1005 ****
    i = 0;
    while (i < f->menu_bar_items_used)
      {
!       if (EQ (XVECTOR (vector)->contents[i], Qnil))
  	{
  	  subprefix_stack[submenu_depth++] = prefix;
  	  prefix = entry;
  	  i++;
  	}
!       else if (EQ (XVECTOR (vector)->contents[i], Qlambda))
  	{
  	  prefix = subprefix_stack[--submenu_depth];
  	  i++;
  	}
!       else if (EQ (XVECTOR (vector)->contents[i], Qt))
  	{
! 	  prefix = XVECTOR (vector)->contents[i + MENU_ITEMS_PANE_PREFIX];
  	  i += MENU_ITEMS_PANE_LENGTH;
  	}
        else
  	{
! 	  entry = XVECTOR (vector)->contents[i + MENU_ITEMS_ITEM_VALUE];
  	  /* The EMACS_INT cast avoids a warning.  There's no problem
  	     as long as pointers have enough bits to hold small integers.  */
  	  if ((int) (EMACS_INT) client_data == i)
--- 995,1019 ----
    i = 0;
    while (i < f->menu_bar_items_used)
      {
!       if (EQ (AREF (vector, i), Qnil))
  	{
  	  subprefix_stack[submenu_depth++] = prefix;
  	  prefix = entry;
  	  i++;
  	}
!       else if (EQ (AREF (vector, i), Qlambda))
  	{
  	  prefix = subprefix_stack[--submenu_depth];
  	  i++;
  	}
!       else if (EQ (AREF (vector, i), Qt))
  	{
! 	  prefix = AREF (vector, i + MENU_ITEMS_PANE_PREFIX);
  	  i += MENU_ITEMS_PANE_LENGTH;
  	}
        else
  	{
! 	  entry = AREF (vector, i + MENU_ITEMS_ITEM_VALUE);
  	  /* The EMACS_INT cast avoids a warning.  There's no problem
  	     as long as pointers have enough bits to hold small integers.  */
  	  if ((int) (EMACS_INT) client_data == i)
***************
*** 1075,1081 ****
       widget_value *wv;
  {
    if (! wv) return;
! 
    wv->name = wv->value = wv->key = (char *) 0xDEADBEEF;
  
    if (wv->contents && (wv->contents != (widget_value*)1))
--- 1089,1095 ----
       widget_value *wv;
  {
    if (! wv) return;
!   
    wv->name = wv->value = wv->key = (char *) 0xDEADBEEF;
  
    if (wv->contents && (wv->contents != (widget_value*)1))
***************
*** 1093,1114 ****
    UNBLOCK_INPUT;
  }
  \f
! /* Return a tree of widget_value structures 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 widget_value *
! single_submenu (item_key, item_name, maps)
       Lisp_Object item_key, item_name, maps;
  {
-   widget_value *wv, *prev_wv, *save_wv, *first_wv;
-   int i;
-   int submenu_depth = 0;
    Lisp_Object length;
    int len;
    Lisp_Object *mapvec;
!   widget_value **submenu_stack;
!   int previous_items = menu_items_used;
    int top_level_items = 0;
  
    length = Flength (maps);
--- 1107,1124 ----
    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);
***************
*** 1122,1129 ****
        maps = Fcdr (maps);
      }
  
-   menu_items_n_panes = 0;
- 
    /* 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++)
--- 1132,1137 ----
***************
*** 1141,1149 ****
        else
  	single_keymap_panes (mapvec[i], item_name, item_key, 0, 10);
      }
  
!   /* Create a tree of widget_value objects
!      representing the panes and their items.  */
  
    submenu_stack
      = (widget_value **) alloca (menu_items_used * sizeof (widget_value *));
--- 1149,1171 ----
        else
  	single_keymap_panes (mapvec[i], 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;
! {
!   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 *));
***************
*** 1161,1203 ****
       and construct a tree of widget_value objects.
       Ignore the panes and items made by previous calls to
       single_submenu, even though those are also in menu_items.  */
!   i = previous_items;
!   while (i < menu_items_used)
      {
!       if (EQ (XVECTOR (menu_items)->contents[i], Qnil))
  	{
  	  submenu_stack[submenu_depth++] = save_wv;
  	  save_wv = prev_wv;
  	  prev_wv = 0;
  	  i++;
  	}
!       else if (EQ (XVECTOR (menu_items)->contents[i], Qlambda))
  	{
  	  prev_wv = save_wv;
  	  save_wv = submenu_stack[--submenu_depth];
  	  i++;
  	}
!       else if (EQ (XVECTOR (menu_items)->contents[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 (XVECTOR (menu_items)->contents[i], Qquote))
  	i += 1;
!       else if (EQ (XVECTOR (menu_items)->contents[i], Qt))
  	{
  	  /* Create a new pane.  */
  	  Lisp_Object pane_name, prefix;
  	  char *pane_string;
  
! 	  pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME];
! 	  prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
  
  #ifndef HAVE_MULTILINGUAL_MENU
  	  if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
  	    {
  	      pane_name = ENCODE_SYSTEM (pane_name);
! 	      AREF (menu_items, i + MENU_ITEMS_PANE_NAME) = pane_name;
  	    }
  #endif
  	  pane_string = (NILP (pane_name)
--- 1183,1225 ----
       and construct a tree of widget_value objects.
       Ignore the panes and items made by previous calls to
       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);
  
  #ifndef HAVE_MULTILINGUAL_MENU
  	  if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
  	    {
  	      pane_name = ENCODE_SYSTEM (pane_name);
! 	      ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
  	    }
  #endif
  	  pane_string = (NILP (pane_name)
***************
*** 1249,1261 ****
  	  if (STRING_MULTIBYTE (item_name))
  	    {
  	      item_name = ENCODE_SYSTEM (item_name);
! 	      AREF (menu_items, i + MENU_ITEMS_ITEM_NAME) = item_name;
  	    }
  
  	  if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
  	    {
  	      descrip = ENCODE_SYSTEM (descrip);
! 	      AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY) = descrip;
  	    }
  #endif /* not HAVE_MULTILINGUAL_MENU */
  
--- 1271,1283 ----
  	  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);
  	    }
  #endif /* not HAVE_MULTILINGUAL_MENU */
  
***************
*** 1320,1326 ****
    HMENU menubar_widget = f->output_data.w32->menubar_widget;
    Lisp_Object items;
    widget_value *wv, *first_wv, *prev_wv = 0;
!   int i;
  
    /* We must not change the menubar when actually in use.  */
    if (f->output_data.w32->menubar_active)
--- 1342,1350 ----
    HMENU menubar_widget = f->output_data.w32->menubar_widget;
    Lisp_Object items;
    widget_value *wv, *first_wv, *prev_wv = 0;
!   int i, last_i;
!   int *submenu_start, *submenu_end;
!   int *submenu_top_level_items;
  
    /* We must not change the menubar when actually in use.  */
    if (f->output_data.w32->menubar_active)
***************
*** 1333,1346 ****
    else if (pending_menu_activation && !deep_p)
      deep_p = 1;
  
-   wv = xmalloc_widget_value ();
-   wv->name = "menubar";
-   wv->value = 0;
-   wv->enabled = 1;
-   wv->button_type = BUTTON_TYPE_NONE;
-   wv->help = Qnil;
-   first_wv = wv;
- 
    if (deep_p)
      {
        /* Make a widget-value tree representing the entire menu trees.  */
--- 1357,1362 ----
***************
*** 1384,1411 ****
  
        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,
  	       previous_menu_items_used * sizeof (Lisp_Object));
  
!       /* Fill in the current menu bar contents.  */
        menu_items = f->menu_bar_vector;
        menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0;
        init_menu_items ();
!       for (i = 0; i < XVECTOR (items)->size; i += 4)
  	{
  	  Lisp_Object key, string, maps;
  
! 	  key = XVECTOR (items)->contents[i];
! 	  string = XVECTOR (items)->contents[i + 1];
! 	  maps = XVECTOR (items)->contents[i + 2];
  	  if (NILP (string))
  	    break;
  
! 	  wv = single_submenu (key, string, maps);
  	  if (prev_wv) 
  	    prev_wv->next = wv;
  	  else
--- 1400,1457 ----
  
        items = FRAME_MENU_BAR_ITEMS (f);
  
        /* Save the frame's previous menu bar contents data.  */
        if (previous_menu_items_used)
  	bcopy (XVECTOR (f->menu_bar_vector)->contents, previous_items,
  	       previous_menu_items_used * sizeof (Lisp_Object));
  
!       /* Fill in menu_items with the current menu bar contents.
! 	 This can evaluate Lisp code.  */
        menu_items = f->menu_bar_vector;
        menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0;
+       submenu_start = (int *) alloca (XVECTOR (items)->size * sizeof (int *));
+       submenu_end = (int *) alloca (XVECTOR (items)->size * sizeof (int *));
+       submenu_top_level_items
+ 	= (int *) alloca (XVECTOR (items)->size * sizeof (int *));
        init_menu_items ();
!       for (i = 0; i < ASIZE (items); i += 4)
  	{
  	  Lisp_Object key, string, maps;
  
! 	  last_i = i;
! 
! 	  key = AREF (items, i);
! 	  string = AREF (items, i + 1);
! 	  maps = AREF (items, i + 2);
  	  if (NILP (string))
  	    break;
  
! 	  submenu_start[i] = menu_items_used;
! 
! 	  menu_items_n_panes = 0;
! 	  submenu_top_level_items[i]
! 	    = parse_single_submenu (key, string, maps);
! 
! 	  submenu_end[i] = menu_items_used;
! 	}
! 
!       finish_menu_items ();
! 
!       /* Convert menu_items into widget_value trees
! 	 to display the menu.  This cannot evaluate Lisp code.  */
! 
!       wv = xmalloc_widget_value ();
!       wv->name = "menubar";
!       wv->value = 0;
!       wv->enabled = 1;
!       wv->button_type = BUTTON_TYPE_NONE;
!       wv->help = Qnil;
!       first_wv = wv;
! 
!       for (i = 0; i < last_i; i += 4)
! 	{
! 	  wv = digest_single_submenu (submenu_start[i], submenu_end[i],
! 				      submenu_top_level_items[i]);
  	  if (prev_wv) 
  	    prev_wv->next = wv;
  	  else
***************
*** 1416,1423 ****
  	  prev_wv = wv;
  	}
  
-       finish_menu_items ();
- 
        set_buffer_internal_1 (prev);
        unbind_to (specpdl_count, Qnil);
  
--- 1462,1467 ----
***************
*** 1426,1432 ****
  
        for (i = 0; i < previous_menu_items_used; i++)
  	if (menu_items_used == i
! 	    || (!EQ (previous_items[i], XVECTOR (menu_items)->contents[i])))
  	  break;
        if (i == menu_items_used && i == previous_menu_items_used && i != 0)
  	{
--- 1470,1476 ----
  
        for (i = 0; i < previous_menu_items_used; i++)
  	if (menu_items_used == i
! 	    || (!EQ (previous_items[i], AREF (menu_items, i))))
  	  break;
        if (i == menu_items_used && i == previous_menu_items_used && i != 0)
  	{
***************
*** 1442,1451 ****
  	 Windows takes care of this for normal string items, but
  	 not for owner-drawn items or additional item-info.  */
        wv = first_wv->contents;
!       for (i = 0; i < XVECTOR (items)->size; i += 4)
  	{
  	  Lisp_Object string;
! 	  string = XVECTOR (items)->contents[i + 1];
  	  if (NILP (string))
  	    break;
  	  wv->name = (char *) SDATA (string);
--- 1486,1495 ----
  	 Windows takes care of this for normal string items, but
  	 not for owner-drawn items or additional item-info.  */
        wv = first_wv->contents;
!       for (i = 0; i < ASIZE (items); i += 4)
  	{
  	  Lisp_Object string;
! 	  string = AREF (items, i + 1);
  	  if (NILP (string))
  	    break;
  	  wv->name = (char *) SDATA (string);
***************
*** 1461,1472 ****
        /* Make a widget-value tree containing
  	 just the top level menu bar strings.  */
  
        items = FRAME_MENU_BAR_ITEMS (f);
!       for (i = 0; i < XVECTOR (items)->size; i += 4)
  	{
  	  Lisp_Object string;
  
! 	  string = XVECTOR (items)->contents[i + 1];
  	  if (NILP (string))
  	    break;
  
--- 1505,1524 ----
        /* Make a widget-value tree containing
  	 just the top level menu bar strings.  */
  
+       wv = xmalloc_widget_value ();
+       wv->name = "menubar";
+       wv->value = 0;
+       wv->enabled = 1;
+       wv->button_type = BUTTON_TYPE_NONE;
+       wv->help = Qnil;
+       first_wv = wv;
+ 
        items = FRAME_MENU_BAR_ITEMS (f);
!       for (i = 0; i < ASIZE (items); i += 4)
  	{
  	  Lisp_Object string;
  
! 	  string = AREF (items, i + 1);
  	  if (NILP (string))
  	    break;
  
***************
*** 1625,1631 ****
    i = 0;
    while (i < menu_items_used)
      {
!       if (EQ (XVECTOR (menu_items)->contents[i], Qnil))
  	{
  	  submenu_stack[submenu_depth++] = save_wv;
  	  save_wv = prev_wv;
--- 1677,1683 ----
    i = 0;
    while (i < menu_items_used)
      {
!       if (EQ (AREF (menu_items, i), Qnil))
  	{
  	  submenu_stack[submenu_depth++] = save_wv;
  	  save_wv = prev_wv;
***************
*** 1633,1653 ****
  	  first_pane = 1;
  	  i++;
  	}
!       else if (EQ (XVECTOR (menu_items)->contents[i], Qlambda))
  	{
  	  prev_wv = save_wv;
  	  save_wv = submenu_stack[--submenu_depth];
  	  first_pane = 0;
  	  i++;
  	}
!       else if (EQ (XVECTOR (menu_items)->contents[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 (XVECTOR (menu_items)->contents[i], Qquote))
  	i += 1;
!       else if (EQ (XVECTOR (menu_items)->contents[i], Qt))
  	{
  	  /* Create a new pane.  */
  	  Lisp_Object pane_name, prefix;
--- 1685,1705 ----
  	  first_pane = 1;
  	  i++;
  	}
!       else if (EQ (AREF (menu_items, i), Qlambda))
  	{
  	  prev_wv = save_wv;
  	  save_wv = submenu_stack[--submenu_depth];
  	  first_pane = 0;
  	  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;
***************
*** 1658,1664 ****
  	  if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
  	    {
  	      pane_name = ENCODE_SYSTEM (pane_name);
! 	      AREF (menu_items, i + MENU_ITEMS_PANE_NAME) = pane_name;
  	    }
  #endif
  	  pane_string = (NILP (pane_name)
--- 1710,1716 ----
  	  if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
  	    {
  	      pane_name = ENCODE_SYSTEM (pane_name);
! 	      ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
  	    }
  #endif
  	  pane_string = (NILP (pane_name)
***************
*** 1713,1724 ****
            if (STRINGP (item_name) && STRING_MULTIBYTE (item_name))
  	    {
  	      item_name = ENCODE_SYSTEM (item_name);
! 	      AREF (menu_items, i + MENU_ITEMS_ITEM_NAME) = item_name;
  	    }
            if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
              {
  	      descrip = ENCODE_SYSTEM (descrip);
! 	      AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY) = descrip;
  	    }
  #endif /* not HAVE_MULTILINGUAL_MENU */
  
--- 1765,1776 ----
            if (STRINGP (item_name) && 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);
  	    }
  #endif /* not HAVE_MULTILINGUAL_MENU */
  
***************
*** 1818,1848 ****
        i = 0;
        while (i < menu_items_used)
  	{
! 	  if (EQ (XVECTOR (menu_items)->contents[i], Qnil))
  	    {
  	      subprefix_stack[submenu_depth++] = prefix;
  	      prefix = entry;
  	      i++;
  	    }
! 	  else if (EQ (XVECTOR (menu_items)->contents[i], Qlambda))
  	    {
  	      prefix = subprefix_stack[--submenu_depth];
  	      i++;
  	    }
! 	  else if (EQ (XVECTOR (menu_items)->contents[i], Qt))
  	    {
! 	      prefix
! 		= XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
  	      i += MENU_ITEMS_PANE_LENGTH;
  	    }
  	  /* Ignore a nil in the item list.
  	     It's meaningful only for dialog boxes.  */
! 	  else if (EQ (XVECTOR (menu_items)->contents[i], Qquote))
  	    i += 1;
  	  else
  	    {
! 	      entry
! 		= XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_VALUE];
  	      if (menu_item_selection == i)
  		{
  		  if (keymaps != 0)
--- 1870,1898 ----
        i = 0;
        while (i < menu_items_used)
  	{
! 	  if (EQ (AREF (menu_items, i), Qnil))
  	    {
  	      subprefix_stack[submenu_depth++] = prefix;
  	      prefix = entry;
  	      i++;
  	    }
! 	  else if (EQ (AREF (menu_items, i), Qlambda))
  	    {
  	      prefix = subprefix_stack[--submenu_depth];
  	      i++;
  	    }
! 	  else if (EQ (AREF (menu_items, i), Qt))
  	    {
! 	      prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
  	      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
  	    {
! 	      entry	= AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
  	      if (menu_item_selection == i)
  		{
  		  if (keymaps != 0)
***************
*** 1903,1910 ****
    {
      Lisp_Object pane_name, prefix;
      char *pane_string;
!     pane_name = XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME];
!     prefix = XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_PREFIX];
      pane_string = (NILP (pane_name)
  		   ? "" : (char *) SDATA (pane_name));  
      prev_wv = xmalloc_widget_value ();
--- 1953,1960 ----
    {
      Lisp_Object pane_name, prefix;
      char *pane_string;
!     pane_name = AREF (menu_items, MENU_ITEMS_PANE_NAME);
!     prefix = AREF (menu_items, MENU_ITEMS_PANE_PREFIX);
      pane_string = (NILP (pane_name)
  		   ? "" : (char *) SDATA (pane_name));  
      prev_wv = xmalloc_widget_value ();
***************
*** 1924,1934 ****
  	/* Create a new item within current pane.  */
  	Lisp_Object item_name, enable, descrip, help;
  
! 	item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME];
! 	enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE];
! 	descrip
! 	  = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY];
!         help = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_HELP];
  	
  	if (NILP (item_name))
  	  {
--- 1974,1983 ----
  	/* Create a new item within current pane.  */
  	Lisp_Object item_name, enable, descrip, 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);
!         help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
  	
  	if (NILP (item_name))
  	  {
***************
*** 1957,1963 ****
  	if (!NILP (descrip))
  	  wv->key = (char *) SDATA (descrip);
  	wv->value = (char *) SDATA (item_name);
! 	wv->call_data = (void *) &XVECTOR (menu_items)->contents[i];
  	wv->enabled = !NILP (enable);
  	wv->help = Qnil;
  	prev_wv = wv;
--- 2006,2012 ----
  	if (!NILP (descrip))
  	  wv->key = (char *) SDATA (descrip);
  	wv->value = (char *) SDATA (item_name);
! 	wv->call_data = (void *) &AREF (menu_items, i);
  	wv->enabled = !NILP (enable);
  	wv->help = Qnil;
  	prev_wv = wv;
***************
*** 2027,2042 ****
  	{
  	  Lisp_Object entry;
  
! 	  if (EQ (XVECTOR (menu_items)->contents[i], Qt))
  	    {
! 	      prefix
! 		= XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
  	      i += MENU_ITEMS_PANE_LENGTH;
  	    }
  	  else
  	    {
! 	      entry
! 		= XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_VALUE];
  	      if (menu_item_selection == i)
  		{
  		  if (keymaps != 0)
--- 2076,2089 ----
  	{
  	  Lisp_Object entry;
  
! 	  if (EQ (AREF (menu_items, i), Qt))
  	    {
! 	      prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
  	      i += MENU_ITEMS_PANE_LENGTH;
  	    }
  	  else
  	    {
! 	      entry	= AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
  	      if (menu_item_selection == i)
  		{
  		  if (keymaps != 0)
***************
*** 2117,2127 ****
  	     we can't deallocate the memory otherwise.  */
  	  if (get_menu_item_info)
  	    {
! 	      out_string = (char *) LocalAlloc (LPTR, strlen (wv->name) + 1);
  #ifdef MENU_DEBUG
! 	      DebPrint ("Menu: allocing %ld for owner-draw", info.dwItemData);
  #endif
- 	      strcpy (out_string, wv->name);
  	      fuFlags = MF_OWNERDRAW | MF_DISABLED;
  	    }
  	  else
--- 2164,2174 ----
  	     we can't deallocate the memory otherwise.  */
  	  if (get_menu_item_info)
  	    {
!               out_string = (char *) local_alloc (strlen (wv->name) + 1);
!               strcpy (out_string, wv->name);
  #ifdef MENU_DEBUG
! 	      DebPrint ("Menu: allocing %ld for owner-draw", out_string);
  #endif
  	      fuFlags = MF_OWNERDRAW | MF_DISABLED;
  	    }
  	  else
***************
*** 2277,2283 ****
  #ifdef MENU_DEBUG
  	  DebPrint ("Menu: freeing %ld for owner-draw", info.dwItemData);
  #endif
! 	  LocalFree (info.dwItemData);
  	}
  
        /* Recurse down submenus.  */
--- 2324,2330 ----
  #ifdef MENU_DEBUG
  	  DebPrint ("Menu: freeing %ld for owner-draw", info.dwItemData);
  #endif
! 	  local_free (info.dwItemData);
  	}
  
        /* Recurse down submenus.  */

  reply	other threads:[~2002-07-31 22:37 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <3D2A791A00A0862A@mel-rta9.wanadoo.fr>
2002-07-31 21:57 ` NT Emacs crashes when selecting a menubar item Richard Stallman
2002-07-31 22:37   ` David Ponce [this message]
2002-08-01 11:39 David PONCE
  -- strict thread matches above, loose matches on Subject: below --
2002-08-01  7:54 jasonr
2002-07-30 11:28 David PONCE
2002-07-24 18:55 David Ponce
2002-07-25 18:07 ` Richard Stallman
2002-07-26 12:30   ` David Ponce
2002-07-27 18:52     ` Richard Stallman
2002-07-28 16:56       ` David Ponce
2002-07-29 17:30         ` Richard Stallman
2002-07-29 18:16           ` David Ponce
2002-07-30 18:46             ` Richard Stallman

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

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3D486691.5050708@dponce.com \
    --to=david@dponce.com \
    --cc=emacs-devel@gnu.org \
    /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 public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).