From mboxrd@z Thu Jan 1 00:00:00 1970 Path: main.gmane.org!not-for-mail From: David Ponce Newsgroups: gmane.emacs.devel Subject: Re: NT Emacs crashes when selecting a menubar item Date: Thu, 01 Aug 2002 00:37:05 +0200 Sender: emacs-devel-admin@gnu.org Message-ID: <3D486691.5050708@dponce.com> References: <3D2A791A00A0862A@mel-rta9.wanadoo.fr> (added by postmaster@wanadoo.fr) <200207312157.g6VLvlL17436@aztec.santafe.edu> NNTP-Posting-Host: localhost.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------020804070102060107030201" X-Trace: main.gmane.org 1028155403 21866 127.0.0.1 (31 Jul 2002 22:43:23 GMT) X-Complaints-To: usenet@main.gmane.org NNTP-Posting-Date: Wed, 31 Jul 2002 22:43:23 +0000 (UTC) Cc: emacs-devel@gnu.org Return-path: Original-Received: from quimby.gnus.org ([80.91.224.244]) by main.gmane.org with esmtp (Exim 3.33 #1 (Debian)) id 17a2Bc-0005gZ-00 for ; Thu, 01 Aug 2002 00:43:20 +0200 Original-Received: from fencepost.gnu.org ([199.232.76.164]) by quimby.gnus.org with esmtp (Exim 3.12 #1 (Debian)) id 17a2Tt-00035v-00 for ; Thu, 01 Aug 2002 01:02:13 +0200 Original-Received: from localhost ([127.0.0.1] helo=fencepost.gnu.org) by fencepost.gnu.org with esmtp (Exim 3.35 #1 (Debian)) id 17a2Bn-0001q9-00; Wed, 31 Jul 2002 18:43:31 -0400 Original-Received: from smtp-out-4.wanadoo.fr ([193.252.19.23] helo=mel-rto4.wanadoo.fr) by fencepost.gnu.org with esmtp (Exim 3.35 #1 (Debian)) id 17a25I-0001GX-00; Wed, 31 Jul 2002 18:36:49 -0400 Original-Received: from mel-rta8.wanadoo.fr (193.252.19.79) by mel-rto4.wanadoo.fr (6.5.007) id 3D18589F012EC231; Thu, 1 Aug 2002 00:36:48 +0200 Original-Received: from dponce.com (193.249.41.95) by mel-rta8.wanadoo.fr (6.5.007) id 3D2A78F600A71773; Thu, 1 Aug 2002 00:36:48 +0200 User-Agent: Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.1b) Gecko/20020730 X-Accept-Language: fr, en-us, en Original-To: rms@gnu.org Errors-To: emacs-devel-admin@gnu.org X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.0.11 Precedence: bulk List-Help: List-Post: List-Subscribe: , List-Id: Emacs development discussions. List-Unsubscribe: , List-Archive: Xref: main.gmane.org gmane.emacs.devel:6213 X-Report-Spam: http://spam.gmane.org/gmane.emacs.devel:6213 This is a multi-part message in MIME format. --------------020804070102060107030201 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit 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. --------------020804070102060107030201 Content-Type: text/x-patch; name="w32menu.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="w32menu.patch" *** 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; } /* 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); } /* 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; } ! /* 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; } ! /* 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. */ --------------020804070102060107030201--