comparison src/w32menu.c @ 46815:52f36f4b0e4f

(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.
author Richard M. Stallman <rms@gnu.org>
date Mon, 05 Aug 2002 16:33:44 +0000
parents 40db0673e6f0
children 4d7b83cc03aa
comparison
equal deleted inserted replaced
46814:f7dd9a44324f 46815:52f36f4b0e4f
110 */ 110 */
111 struct _widget_value *free_list; 111 struct _widget_value *free_list;
112 #endif 112 #endif
113 } widget_value; 113 } widget_value;
114 114
115 /* LocalAlloc/Free is a reasonably good allocator. */ 115 /* Local memory management */
116 #define malloc_widget_value() (void*)LocalAlloc (LMEM_ZEROINIT, sizeof (widget_value)) 116 #define local_heap (GetProcessHeap ())
117 #define free_widget_value(wv) LocalFree (wv) 117 #define local_alloc(n) (HeapAlloc (local_heap, HEAP_ZERO_MEMORY, (n)))
118 #define local_free(p) (HeapFree (local_heap, 0, ((LPVOID) (p))))
119
120 #define malloc_widget_value() ((widget_value *) local_alloc (sizeof (widget_value)))
121 #define free_widget_value(wv) (local_free ((wv)))
118 122
119 /******************************************************************/ 123 /******************************************************************/
120 124
121 #ifndef TRUE 125 #ifndef TRUE
122 #define TRUE 1 126 #define TRUE 1
316 push_submenu_start () 320 push_submenu_start ()
317 { 321 {
318 if (menu_items_used + 1 > menu_items_allocated) 322 if (menu_items_used + 1 > menu_items_allocated)
319 grow_menu_items (); 323 grow_menu_items ();
320 324
321 XVECTOR (menu_items)->contents[menu_items_used++] = Qnil; 325 ASET (menu_items, menu_items_used++, Qnil);
322 menu_items_submenu_depth++; 326 menu_items_submenu_depth++;
323 } 327 }
324 328
325 /* End a submenu. */ 329 /* End a submenu. */
326 330
328 push_submenu_end () 332 push_submenu_end ()
329 { 333 {
330 if (menu_items_used + 1 > menu_items_allocated) 334 if (menu_items_used + 1 > menu_items_allocated)
331 grow_menu_items (); 335 grow_menu_items ();
332 336
333 XVECTOR (menu_items)->contents[menu_items_used++] = Qlambda; 337 ASET (menu_items, menu_items_used++, Qlambda);
334 menu_items_submenu_depth--; 338 menu_items_submenu_depth--;
335 } 339 }
336 340
337 /* Indicate boundary between left and right. */ 341 /* Indicate boundary between left and right. */
338 342
340 push_left_right_boundary () 344 push_left_right_boundary ()
341 { 345 {
342 if (menu_items_used + 1 > menu_items_allocated) 346 if (menu_items_used + 1 > menu_items_allocated)
343 grow_menu_items (); 347 grow_menu_items ();
344 348
345 XVECTOR (menu_items)->contents[menu_items_used++] = Qquote; 349 ASET (menu_items, menu_items_used++, Qquote);
346 } 350 }
347 351
348 /* Start a new menu pane in menu_items. 352 /* Start a new menu pane in menu_items.
349 NAME is the pane name. PREFIX_VEC is a prefix key for this pane. */ 353 NAME is the pane name. PREFIX_VEC is a prefix key for this pane. */
350 354
355 if (menu_items_used + MENU_ITEMS_PANE_LENGTH > menu_items_allocated) 359 if (menu_items_used + MENU_ITEMS_PANE_LENGTH > menu_items_allocated)
356 grow_menu_items (); 360 grow_menu_items ();
357 361
358 if (menu_items_submenu_depth == 0) 362 if (menu_items_submenu_depth == 0)
359 menu_items_n_panes++; 363 menu_items_n_panes++;
360 XVECTOR (menu_items)->contents[menu_items_used++] = Qt; 364 ASET (menu_items, menu_items_used++, Qt);
361 XVECTOR (menu_items)->contents[menu_items_used++] = name; 365 ASET (menu_items, menu_items_used++, name);
362 XVECTOR (menu_items)->contents[menu_items_used++] = prefix_vec; 366 ASET (menu_items, menu_items_used++, prefix_vec);
363 } 367 }
364 368
365 /* Push one menu item into the current pane. NAME is the string to 369 /* Push one menu item into the current pane. NAME is the string to
366 display. ENABLE if non-nil means this item can be selected. KEY 370 display. ENABLE if non-nil means this item can be selected. KEY
367 is the key generated by choosing this item, or nil if this item 371 is the key generated by choosing this item, or nil if this item
375 Lisp_Object name, enable, key, def, equiv, type, selected, help; 379 Lisp_Object name, enable, key, def, equiv, type, selected, help;
376 { 380 {
377 if (menu_items_used + MENU_ITEMS_ITEM_LENGTH > menu_items_allocated) 381 if (menu_items_used + MENU_ITEMS_ITEM_LENGTH > menu_items_allocated)
378 grow_menu_items (); 382 grow_menu_items ();
379 383
380 XVECTOR (menu_items)->contents[menu_items_used++] = name; 384 ASET (menu_items, menu_items_used++, name);
381 XVECTOR (menu_items)->contents[menu_items_used++] = enable; 385 ASET (menu_items, menu_items_used++, enable);
382 XVECTOR (menu_items)->contents[menu_items_used++] = key; 386 ASET (menu_items, menu_items_used++, key);
383 XVECTOR (menu_items)->contents[menu_items_used++] = equiv; 387 ASET (menu_items, menu_items_used++, equiv);
384 XVECTOR (menu_items)->contents[menu_items_used++] = def; 388 ASET (menu_items, menu_items_used++, def);
385 XVECTOR (menu_items)->contents[menu_items_used++] = type; 389 ASET (menu_items, menu_items_used++, type);
386 XVECTOR (menu_items)->contents[menu_items_used++] = selected; 390 ASET (menu_items, menu_items_used++, selected);
387 XVECTOR (menu_items)->contents[menu_items_used++] = help; 391 ASET (menu_items, menu_items_used++, help);
388 } 392 }
389 393
390 /* Look through KEYMAPS, a vector of keymaps that is NMAPS long, 394 /* Look through KEYMAPS, a vector of keymaps that is NMAPS long,
391 and generate menu panes for them in menu_items. 395 and generate menu panes for them in menu_items.
392 If NOTREAL is nonzero, 396 If NOTREAL is nonzero,
448 single_menu_item (XCAR (item), XCDR (item), 452 single_menu_item (XCAR (item), XCDR (item),
449 &pending_maps, notreal, maxdepth); 453 &pending_maps, notreal, maxdepth);
450 else if (VECTORP (item)) 454 else if (VECTORP (item))
451 { 455 {
452 /* Loop over the char values represented in the vector. */ 456 /* Loop over the char values represented in the vector. */
453 int len = XVECTOR (item)->size; 457 int len = ASIZE (item);
454 int c; 458 int c;
455 for (c = 0; c < len; c++) 459 for (c = 0; c < len; c++)
456 { 460 {
457 Lisp_Object character; 461 Lisp_Object character;
458 XSETFASTINT (character, c); 462 XSETFASTINT (character, c);
459 single_menu_item (character, XVECTOR (item)->contents[c], 463 single_menu_item (character, AREF (item, c),
460 &pending_maps, notreal, maxdepth); 464 &pending_maps, notreal, maxdepth);
461 } 465 }
462 } 466 }
463 UNGCPRO; 467 UNGCPRO;
464 } 468 }
502 res = parse_menu_item (item, notreal, 0); 506 res = parse_menu_item (item, notreal, 0);
503 UNGCPRO; 507 UNGCPRO;
504 if (!res) 508 if (!res)
505 return; /* Not a menu item. */ 509 return; /* Not a menu item. */
506 510
507 map = XVECTOR (item_properties)->contents[ITEM_PROPERTY_MAP]; 511 map = AREF (item_properties, ITEM_PROPERTY_MAP);
508 512
509 if (notreal) 513 if (notreal)
510 { 514 {
511 /* We don't want to make a menu, just traverse the keymaps to 515 /* We don't want to make a menu, just traverse the keymaps to
512 precompute equivalent key bindings. */ 516 precompute equivalent key bindings. */
513 if (!NILP (map)) 517 if (!NILP (map))
514 single_keymap_panes (map, Qnil, key, 1, maxdepth - 1); 518 single_keymap_panes (map, Qnil, key, 1, maxdepth - 1);
515 return; 519 return;
516 } 520 }
517 521
518 enabled = XVECTOR (item_properties)->contents[ITEM_PROPERTY_ENABLE]; 522 enabled = AREF (item_properties, ITEM_PROPERTY_ENABLE);
519 item_string = XVECTOR (item_properties)->contents[ITEM_PROPERTY_NAME]; 523 item_string = AREF (item_properties, ITEM_PROPERTY_NAME);
520 524
521 if (!NILP (map) && SREF (item_string, 0) == '@') 525 if (!NILP (map) && SREF (item_string, 0) == '@')
522 { 526 {
523 if (!NILP (enabled)) 527 if (!NILP (enabled))
524 /* An enabled separate pane. Remember this to handle it later. */ 528 /* An enabled separate pane. Remember this to handle it later. */
526 *pending_maps_ptr); 530 *pending_maps_ptr);
527 return; 531 return;
528 } 532 }
529 533
530 push_menu_item (item_string, enabled, key, 534 push_menu_item (item_string, enabled, key,
531 XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF], 535 AREF (item_properties, ITEM_PROPERTY_DEF),
532 XVECTOR (item_properties)->contents[ITEM_PROPERTY_KEYEQ], 536 AREF (item_properties, ITEM_PROPERTY_KEYEQ),
533 XVECTOR (item_properties)->contents[ITEM_PROPERTY_TYPE], 537 AREF (item_properties, ITEM_PROPERTY_TYPE),
534 XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED], 538 AREF (item_properties, ITEM_PROPERTY_SELECTED),
535 XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP]); 539 AREF (item_properties, ITEM_PROPERTY_HELP));
536 540
537 /* Display a submenu using the toolkit. */ 541 /* Display a submenu using the toolkit. */
538 if (! (NILP (map) || NILP (enabled))) 542 if (! (NILP (map) || NILP (enabled)))
539 { 543 {
540 push_submenu_start (); 544 push_submenu_start ();
743 if (NILP (title) && !NILP (prompt)) 747 if (NILP (title) && !NILP (prompt))
744 title = prompt; 748 title = prompt;
745 749
746 /* Make that be the pane title of the first pane. */ 750 /* Make that be the pane title of the first pane. */
747 if (!NILP (prompt) && menu_items_n_panes >= 0) 751 if (!NILP (prompt) && menu_items_n_panes >= 0)
748 XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME] = prompt; 752 ASET (menu_items, MENU_ITEMS_PANE_NAME, prompt);
749 753
750 keymaps = 1; 754 keymaps = 1;
751 } 755 }
752 else if (CONSP (menu) && KEYMAPP (XCAR (menu))) 756 else if (CONSP (menu) && KEYMAPP (XCAR (menu)))
753 { 757 {
775 /* Extract the detailed info to make one pane. */ 779 /* Extract the detailed info to make one pane. */
776 keymap_panes (maps, nmaps, NILP (position)); 780 keymap_panes (maps, nmaps, NILP (position));
777 781
778 /* Make the title be the pane title of the first pane. */ 782 /* Make the title be the pane title of the first pane. */
779 if (!NILP (title) && menu_items_n_panes >= 0) 783 if (!NILP (title) && menu_items_n_panes >= 0)
780 XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME] = title; 784 ASET (menu_items, MENU_ITEMS_PANE_NAME, title);
781 785
782 keymaps = 1; 786 keymaps = 1;
783 } 787 }
784 else 788 else
785 { 789 {
798 UNGCPRO; 802 UNGCPRO;
799 return Qnil; 803 return Qnil;
800 } 804 }
801 805
802 #ifdef HAVE_MENUS 806 #ifdef HAVE_MENUS
807 /* If resources from a previous popup menu exist yet, does nothing
808 until the `menu_free_timer' has freed them (see w32fns.c).
809 */
810 if (current_popup_menu)
811 {
812 discard_menu_items ();
813 UNGCPRO;
814 return Qnil;
815 }
816
803 /* Display them in a menu. */ 817 /* Display them in a menu. */
804 BLOCK_INPUT; 818 BLOCK_INPUT;
805 819
806 selection = w32_menu_show (f, xpos, ypos, for_click, 820 selection = w32_menu_show (f, xpos, ypos, for_click,
807 keymaps, title, &error_name); 821 keymaps, title, &error_name);
808 UNBLOCK_INPUT; 822 UNBLOCK_INPUT;
809 823
810 discard_menu_items (); 824 discard_menu_items ();
825 #endif /* HAVE_MENUS */
811 826
812 UNGCPRO; 827 UNGCPRO;
813 #endif /* HAVE_MENUS */
814 828
815 if (error_name) error (error_name); 829 if (error_name) error (error_name);
816 return selection; 830 return selection;
817 } 831 }
818 832
979 vector = f->menu_bar_vector; 993 vector = f->menu_bar_vector;
980 prefix = Qnil; 994 prefix = Qnil;
981 i = 0; 995 i = 0;
982 while (i < f->menu_bar_items_used) 996 while (i < f->menu_bar_items_used)
983 { 997 {
984 if (EQ (XVECTOR (vector)->contents[i], Qnil)) 998 if (EQ (AREF (vector, i), Qnil))
985 { 999 {
986 subprefix_stack[submenu_depth++] = prefix; 1000 subprefix_stack[submenu_depth++] = prefix;
987 prefix = entry; 1001 prefix = entry;
988 i++; 1002 i++;
989 } 1003 }
990 else if (EQ (XVECTOR (vector)->contents[i], Qlambda)) 1004 else if (EQ (AREF (vector, i), Qlambda))
991 { 1005 {
992 prefix = subprefix_stack[--submenu_depth]; 1006 prefix = subprefix_stack[--submenu_depth];
993 i++; 1007 i++;
994 } 1008 }
995 else if (EQ (XVECTOR (vector)->contents[i], Qt)) 1009 else if (EQ (AREF (vector, i), Qt))
996 { 1010 {
997 prefix = XVECTOR (vector)->contents[i + MENU_ITEMS_PANE_PREFIX]; 1011 prefix = AREF (vector, i + MENU_ITEMS_PANE_PREFIX);
998 i += MENU_ITEMS_PANE_LENGTH; 1012 i += MENU_ITEMS_PANE_LENGTH;
999 } 1013 }
1000 else 1014 else
1001 { 1015 {
1002 entry = XVECTOR (vector)->contents[i + MENU_ITEMS_ITEM_VALUE]; 1016 entry = AREF (vector, i + MENU_ITEMS_ITEM_VALUE);
1003 /* The EMACS_INT cast avoids a warning. There's no problem 1017 /* The EMACS_INT cast avoids a warning. There's no problem
1004 as long as pointers have enough bits to hold small integers. */ 1018 as long as pointers have enough bits to hold small integers. */
1005 if ((int) (EMACS_INT) client_data == i) 1019 if ((int) (EMACS_INT) client_data == i)
1006 { 1020 {
1007 int j; 1021 int j;
1073 void 1087 void
1074 free_menubar_widget_value_tree (wv) 1088 free_menubar_widget_value_tree (wv)
1075 widget_value *wv; 1089 widget_value *wv;
1076 { 1090 {
1077 if (! wv) return; 1091 if (! wv) return;
1078 1092
1079 wv->name = wv->value = wv->key = (char *) 0xDEADBEEF; 1093 wv->name = wv->value = wv->key = (char *) 0xDEADBEEF;
1080 1094
1081 if (wv->contents && (wv->contents != (widget_value*)1)) 1095 if (wv->contents && (wv->contents != (widget_value*)1))
1082 { 1096 {
1083 free_menubar_widget_value_tree (wv->contents); 1097 free_menubar_widget_value_tree (wv->contents);
1091 BLOCK_INPUT; 1105 BLOCK_INPUT;
1092 free_widget_value (wv); 1106 free_widget_value (wv);
1093 UNBLOCK_INPUT; 1107 UNBLOCK_INPUT;
1094 } 1108 }
1095 1109
1096 /* Return a tree of widget_value structures for a menu bar item 1110 /* Set up data i menu_items for a menu bar item
1097 whose event type is ITEM_KEY (with string ITEM_NAME) 1111 whose event type is ITEM_KEY (with string ITEM_NAME)
1098 and whose contents come from the list of keymaps MAPS. */ 1112 and whose contents come from the list of keymaps MAPS. */
1099 1113
1100 static widget_value * 1114 static int
1101 single_submenu (item_key, item_name, maps) 1115 parse_single_submenu (item_key, item_name, maps)
1102 Lisp_Object item_key, item_name, maps; 1116 Lisp_Object item_key, item_name, maps;
1103 { 1117 {
1104 widget_value *wv, *prev_wv, *save_wv, *first_wv;
1105 int i;
1106 int submenu_depth = 0;
1107 Lisp_Object length; 1118 Lisp_Object length;
1108 int len; 1119 int len;
1109 Lisp_Object *mapvec; 1120 Lisp_Object *mapvec;
1110 widget_value **submenu_stack; 1121 int i;
1111 int previous_items = menu_items_used;
1112 int top_level_items = 0; 1122 int top_level_items = 0;
1113 1123
1114 length = Flength (maps); 1124 length = Flength (maps);
1115 len = XINT (length); 1125 len = XINT (length);
1116 1126
1119 for (i = 0; i < len; i++) 1129 for (i = 0; i < len; i++)
1120 { 1130 {
1121 mapvec[i] = Fcar (maps); 1131 mapvec[i] = Fcar (maps);
1122 maps = Fcdr (maps); 1132 maps = Fcdr (maps);
1123 } 1133 }
1124
1125 menu_items_n_panes = 0;
1126 1134
1127 /* Loop over the given keymaps, making a pane for each map. 1135 /* Loop over the given keymaps, making a pane for each map.
1128 But don't make a pane that is empty--ignore that map instead. */ 1136 But don't make a pane that is empty--ignore that map instead. */
1129 for (i = 0; i < len; i++) 1137 for (i = 0; i < len; i++)
1130 { 1138 {
1139 Qnil, Qnil, Qnil, Qnil); 1147 Qnil, Qnil, Qnil, Qnil);
1140 } 1148 }
1141 else 1149 else
1142 single_keymap_panes (mapvec[i], item_name, item_key, 0, 10); 1150 single_keymap_panes (mapvec[i], item_name, item_key, 0, 10);
1143 } 1151 }
1144 1152
1145 /* Create a tree of widget_value objects 1153 return top_level_items;
1146 representing the panes and their items. */ 1154 }
1155
1156
1157 /* Create a tree of widget_value objects
1158 representing the panes and items
1159 in menu_items starting at index START, up to index END. */
1160
1161 static widget_value *
1162 digest_single_submenu (start, end, top_level_items)
1163 int start, end;
1164 {
1165 widget_value *wv, *prev_wv, *save_wv, *first_wv;
1166 int i;
1167 int submenu_depth = 0;
1168 widget_value **submenu_stack;
1147 1169
1148 submenu_stack 1170 submenu_stack
1149 = (widget_value **) alloca (menu_items_used * sizeof (widget_value *)); 1171 = (widget_value **) alloca (menu_items_used * sizeof (widget_value *));
1150 wv = xmalloc_widget_value (); 1172 wv = xmalloc_widget_value ();
1151 wv->name = "menu"; 1173 wv->name = "menu";
1159 1181
1160 /* Loop over all panes and items made during this call 1182 /* Loop over all panes and items made during this call
1161 and construct a tree of widget_value objects. 1183 and construct a tree of widget_value objects.
1162 Ignore the panes and items made by previous calls to 1184 Ignore the panes and items made by previous calls to
1163 single_submenu, even though those are also in menu_items. */ 1185 single_submenu, even though those are also in menu_items. */
1164 i = previous_items; 1186 i = start;
1165 while (i < menu_items_used) 1187 while (i < end)
1166 { 1188 {
1167 if (EQ (XVECTOR (menu_items)->contents[i], Qnil)) 1189 if (EQ (AREF (menu_items, i), Qnil))
1168 { 1190 {
1169 submenu_stack[submenu_depth++] = save_wv; 1191 submenu_stack[submenu_depth++] = save_wv;
1170 save_wv = prev_wv; 1192 save_wv = prev_wv;
1171 prev_wv = 0; 1193 prev_wv = 0;
1172 i++; 1194 i++;
1173 } 1195 }
1174 else if (EQ (XVECTOR (menu_items)->contents[i], Qlambda)) 1196 else if (EQ (AREF (menu_items, i), Qlambda))
1175 { 1197 {
1176 prev_wv = save_wv; 1198 prev_wv = save_wv;
1177 save_wv = submenu_stack[--submenu_depth]; 1199 save_wv = submenu_stack[--submenu_depth];
1178 i++; 1200 i++;
1179 } 1201 }
1180 else if (EQ (XVECTOR (menu_items)->contents[i], Qt) 1202 else if (EQ (AREF (menu_items, i), Qt)
1181 && submenu_depth != 0) 1203 && submenu_depth != 0)
1182 i += MENU_ITEMS_PANE_LENGTH; 1204 i += MENU_ITEMS_PANE_LENGTH;
1183 /* Ignore a nil in the item list. 1205 /* Ignore a nil in the item list.
1184 It's meaningful only for dialog boxes. */ 1206 It's meaningful only for dialog boxes. */
1185 else if (EQ (XVECTOR (menu_items)->contents[i], Qquote)) 1207 else if (EQ (AREF (menu_items, i), Qquote))
1186 i += 1; 1208 i += 1;
1187 else if (EQ (XVECTOR (menu_items)->contents[i], Qt)) 1209 else if (EQ (AREF (menu_items, i), Qt))
1188 { 1210 {
1189 /* Create a new pane. */ 1211 /* Create a new pane. */
1190 Lisp_Object pane_name, prefix; 1212 Lisp_Object pane_name, prefix;
1191 char *pane_string; 1213 char *pane_string;
1192 1214
1193 pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME]; 1215 pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME);
1194 prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX]; 1216 prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
1195 1217
1196 #ifndef HAVE_MULTILINGUAL_MENU 1218 #ifndef HAVE_MULTILINGUAL_MENU
1197 if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name)) 1219 if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
1198 { 1220 {
1199 pane_name = ENCODE_SYSTEM (pane_name); 1221 pane_name = ENCODE_SYSTEM (pane_name);
1200 AREF (menu_items, i + MENU_ITEMS_PANE_NAME) = pane_name; 1222 ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
1201 } 1223 }
1202 #endif 1224 #endif
1203 pane_string = (NILP (pane_name) 1225 pane_string = (NILP (pane_name)
1204 ? "" : (char *) SDATA (pane_name)); 1226 ? "" : (char *) SDATA (pane_name));
1205 /* If there is just one top-level pane, put all its items directly 1227 /* If there is just one top-level pane, put all its items directly
1247 1269
1248 #ifndef HAVE_MULTILINGUAL_MENU 1270 #ifndef HAVE_MULTILINGUAL_MENU
1249 if (STRING_MULTIBYTE (item_name)) 1271 if (STRING_MULTIBYTE (item_name))
1250 { 1272 {
1251 item_name = ENCODE_SYSTEM (item_name); 1273 item_name = ENCODE_SYSTEM (item_name);
1252 AREF (menu_items, i + MENU_ITEMS_ITEM_NAME) = item_name; 1274 ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
1253 } 1275 }
1254 1276
1255 if (STRINGP (descrip) && STRING_MULTIBYTE (descrip)) 1277 if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
1256 { 1278 {
1257 descrip = ENCODE_SYSTEM (descrip); 1279 descrip = ENCODE_SYSTEM (descrip);
1258 AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY) = descrip; 1280 ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
1259 } 1281 }
1260 #endif /* not HAVE_MULTILINGUAL_MENU */ 1282 #endif /* not HAVE_MULTILINGUAL_MENU */
1261 1283
1262 wv = xmalloc_widget_value (); 1284 wv = xmalloc_widget_value ();
1263 if (prev_wv) 1285 if (prev_wv)
1318 int deep_p; 1340 int deep_p;
1319 { 1341 {
1320 HMENU menubar_widget = f->output_data.w32->menubar_widget; 1342 HMENU menubar_widget = f->output_data.w32->menubar_widget;
1321 Lisp_Object items; 1343 Lisp_Object items;
1322 widget_value *wv, *first_wv, *prev_wv = 0; 1344 widget_value *wv, *first_wv, *prev_wv = 0;
1323 int i; 1345 int i, last_i;
1346 int *submenu_start, *submenu_end;
1347 int *submenu_top_level_items;
1324 1348
1325 /* We must not change the menubar when actually in use. */ 1349 /* We must not change the menubar when actually in use. */
1326 if (f->output_data.w32->menubar_active) 1350 if (f->output_data.w32->menubar_active)
1327 return; 1351 return;
1328 1352
1330 1354
1331 if (! menubar_widget) 1355 if (! menubar_widget)
1332 deep_p = 1; 1356 deep_p = 1;
1333 else if (pending_menu_activation && !deep_p) 1357 else if (pending_menu_activation && !deep_p)
1334 deep_p = 1; 1358 deep_p = 1;
1335
1336 wv = xmalloc_widget_value ();
1337 wv->name = "menubar";
1338 wv->value = 0;
1339 wv->enabled = 1;
1340 wv->button_type = BUTTON_TYPE_NONE;
1341 wv->help = Qnil;
1342 first_wv = wv;
1343 1359
1344 if (deep_p) 1360 if (deep_p)
1345 { 1361 {
1346 /* Make a widget-value tree representing the entire menu trees. */ 1362 /* Make a widget-value tree representing the entire menu trees. */
1347 1363
1382 safe_run_hooks (Qmenu_bar_update_hook); 1398 safe_run_hooks (Qmenu_bar_update_hook);
1383 FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f)); 1399 FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
1384 1400
1385 items = FRAME_MENU_BAR_ITEMS (f); 1401 items = FRAME_MENU_BAR_ITEMS (f);
1386 1402
1387 inhibit_garbage_collection ();
1388
1389 /* Save the frame's previous menu bar contents data. */ 1403 /* Save the frame's previous menu bar contents data. */
1390 if (previous_menu_items_used) 1404 if (previous_menu_items_used)
1391 bcopy (XVECTOR (f->menu_bar_vector)->contents, previous_items, 1405 bcopy (XVECTOR (f->menu_bar_vector)->contents, previous_items,
1392 previous_menu_items_used * sizeof (Lisp_Object)); 1406 previous_menu_items_used * sizeof (Lisp_Object));
1393 1407
1394 /* Fill in the current menu bar contents. */ 1408 /* Fill in menu_items with the current menu bar contents.
1409 This can evaluate Lisp code. */
1395 menu_items = f->menu_bar_vector; 1410 menu_items = f->menu_bar_vector;
1396 menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0; 1411 menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0;
1412 submenu_start = (int *) alloca (XVECTOR (items)->size * sizeof (int *));
1413 submenu_end = (int *) alloca (XVECTOR (items)->size * sizeof (int *));
1414 submenu_top_level_items
1415 = (int *) alloca (XVECTOR (items)->size * sizeof (int *));
1397 init_menu_items (); 1416 init_menu_items ();
1398 for (i = 0; i < XVECTOR (items)->size; i += 4) 1417 for (i = 0; i < ASIZE (items); i += 4)
1399 { 1418 {
1400 Lisp_Object key, string, maps; 1419 Lisp_Object key, string, maps;
1401 1420
1402 key = XVECTOR (items)->contents[i]; 1421 last_i = i;
1403 string = XVECTOR (items)->contents[i + 1]; 1422
1404 maps = XVECTOR (items)->contents[i + 2]; 1423 key = AREF (items, i);
1424 string = AREF (items, i + 1);
1425 maps = AREF (items, i + 2);
1405 if (NILP (string)) 1426 if (NILP (string))
1406 break; 1427 break;
1407 1428
1408 wv = single_submenu (key, string, maps); 1429 submenu_start[i] = menu_items_used;
1430
1431 menu_items_n_panes = 0;
1432 submenu_top_level_items[i]
1433 = parse_single_submenu (key, string, maps);
1434
1435 submenu_end[i] = menu_items_used;
1436 }
1437
1438 finish_menu_items ();
1439
1440 /* Convert menu_items into widget_value trees
1441 to display the menu. This cannot evaluate Lisp code. */
1442
1443 wv = xmalloc_widget_value ();
1444 wv->name = "menubar";
1445 wv->value = 0;
1446 wv->enabled = 1;
1447 wv->button_type = BUTTON_TYPE_NONE;
1448 wv->help = Qnil;
1449 first_wv = wv;
1450
1451 for (i = 0; i < last_i; i += 4)
1452 {
1453 wv = digest_single_submenu (submenu_start[i], submenu_end[i],
1454 submenu_top_level_items[i]);
1409 if (prev_wv) 1455 if (prev_wv)
1410 prev_wv->next = wv; 1456 prev_wv->next = wv;
1411 else 1457 else
1412 first_wv->contents = wv; 1458 first_wv->contents = wv;
1413 /* Don't set wv->name here; GC during the loop might relocate it. */ 1459 /* Don't set wv->name here; GC during the loop might relocate it. */
1414 wv->enabled = 1; 1460 wv->enabled = 1;
1415 wv->button_type = BUTTON_TYPE_NONE; 1461 wv->button_type = BUTTON_TYPE_NONE;
1416 prev_wv = wv; 1462 prev_wv = wv;
1417 } 1463 }
1418 1464
1419 finish_menu_items ();
1420
1421 set_buffer_internal_1 (prev); 1465 set_buffer_internal_1 (prev);
1422 unbind_to (specpdl_count, Qnil); 1466 unbind_to (specpdl_count, Qnil);
1423 1467
1424 /* If there has been no change in the Lisp-level contents 1468 /* If there has been no change in the Lisp-level contents
1425 of the menu bar, skip redisplaying it. Just exit. */ 1469 of the menu bar, skip redisplaying it. Just exit. */
1426 1470
1427 for (i = 0; i < previous_menu_items_used; i++) 1471 for (i = 0; i < previous_menu_items_used; i++)
1428 if (menu_items_used == i 1472 if (menu_items_used == i
1429 || (!EQ (previous_items[i], XVECTOR (menu_items)->contents[i]))) 1473 || (!EQ (previous_items[i], AREF (menu_items, i))))
1430 break; 1474 break;
1431 if (i == menu_items_used && i == previous_menu_items_used && i != 0) 1475 if (i == menu_items_used && i == previous_menu_items_used && i != 0)
1432 { 1476 {
1433 free_menubar_widget_value_tree (first_wv); 1477 free_menubar_widget_value_tree (first_wv);
1434 menu_items = Qnil; 1478 menu_items = Qnil;
1440 so it's safe to store data from a Lisp_String, as long as 1484 so it's safe to store data from a Lisp_String, as long as
1441 local copies are made when the actual menu is created. 1485 local copies are made when the actual menu is created.
1442 Windows takes care of this for normal string items, but 1486 Windows takes care of this for normal string items, but
1443 not for owner-drawn items or additional item-info. */ 1487 not for owner-drawn items or additional item-info. */
1444 wv = first_wv->contents; 1488 wv = first_wv->contents;
1445 for (i = 0; i < XVECTOR (items)->size; i += 4) 1489 for (i = 0; i < ASIZE (items); i += 4)
1446 { 1490 {
1447 Lisp_Object string; 1491 Lisp_Object string;
1448 string = XVECTOR (items)->contents[i + 1]; 1492 string = AREF (items, i + 1);
1449 if (NILP (string)) 1493 if (NILP (string))
1450 break; 1494 break;
1451 wv->name = (char *) SDATA (string); 1495 wv->name = (char *) SDATA (string);
1452 wv = wv->next; 1496 wv = wv->next;
1453 } 1497 }
1459 else 1503 else
1460 { 1504 {
1461 /* Make a widget-value tree containing 1505 /* Make a widget-value tree containing
1462 just the top level menu bar strings. */ 1506 just the top level menu bar strings. */
1463 1507
1508 wv = xmalloc_widget_value ();
1509 wv->name = "menubar";
1510 wv->value = 0;
1511 wv->enabled = 1;
1512 wv->button_type = BUTTON_TYPE_NONE;
1513 wv->help = Qnil;
1514 first_wv = wv;
1515
1464 items = FRAME_MENU_BAR_ITEMS (f); 1516 items = FRAME_MENU_BAR_ITEMS (f);
1465 for (i = 0; i < XVECTOR (items)->size; i += 4) 1517 for (i = 0; i < ASIZE (items); i += 4)
1466 { 1518 {
1467 Lisp_Object string; 1519 Lisp_Object string;
1468 1520
1469 string = XVECTOR (items)->contents[i + 1]; 1521 string = AREF (items, i + 1);
1470 if (NILP (string)) 1522 if (NILP (string))
1471 break; 1523 break;
1472 1524
1473 wv = xmalloc_widget_value (); 1525 wv = xmalloc_widget_value ();
1474 wv->name = (char *) SDATA (string); 1526 wv->name = (char *) SDATA (string);
1623 1675
1624 /* Loop over all panes and items, filling in the tree. */ 1676 /* Loop over all panes and items, filling in the tree. */
1625 i = 0; 1677 i = 0;
1626 while (i < menu_items_used) 1678 while (i < menu_items_used)
1627 { 1679 {
1628 if (EQ (XVECTOR (menu_items)->contents[i], Qnil)) 1680 if (EQ (AREF (menu_items, i), Qnil))
1629 { 1681 {
1630 submenu_stack[submenu_depth++] = save_wv; 1682 submenu_stack[submenu_depth++] = save_wv;
1631 save_wv = prev_wv; 1683 save_wv = prev_wv;
1632 prev_wv = 0; 1684 prev_wv = 0;
1633 first_pane = 1; 1685 first_pane = 1;
1634 i++; 1686 i++;
1635 } 1687 }
1636 else if (EQ (XVECTOR (menu_items)->contents[i], Qlambda)) 1688 else if (EQ (AREF (menu_items, i), Qlambda))
1637 { 1689 {
1638 prev_wv = save_wv; 1690 prev_wv = save_wv;
1639 save_wv = submenu_stack[--submenu_depth]; 1691 save_wv = submenu_stack[--submenu_depth];
1640 first_pane = 0; 1692 first_pane = 0;
1641 i++; 1693 i++;
1642 } 1694 }
1643 else if (EQ (XVECTOR (menu_items)->contents[i], Qt) 1695 else if (EQ (AREF (menu_items, i), Qt)
1644 && submenu_depth != 0) 1696 && submenu_depth != 0)
1645 i += MENU_ITEMS_PANE_LENGTH; 1697 i += MENU_ITEMS_PANE_LENGTH;
1646 /* Ignore a nil in the item list. 1698 /* Ignore a nil in the item list.
1647 It's meaningful only for dialog boxes. */ 1699 It's meaningful only for dialog boxes. */
1648 else if (EQ (XVECTOR (menu_items)->contents[i], Qquote)) 1700 else if (EQ (AREF (menu_items, i), Qquote))
1649 i += 1; 1701 i += 1;
1650 else if (EQ (XVECTOR (menu_items)->contents[i], Qt)) 1702 else if (EQ (AREF (menu_items, i), Qt))
1651 { 1703 {
1652 /* Create a new pane. */ 1704 /* Create a new pane. */
1653 Lisp_Object pane_name, prefix; 1705 Lisp_Object pane_name, prefix;
1654 char *pane_string; 1706 char *pane_string;
1655 pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME); 1707 pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME);
1656 prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX); 1708 prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
1657 #ifndef HAVE_MULTILINGUAL_MENU 1709 #ifndef HAVE_MULTILINGUAL_MENU
1658 if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name)) 1710 if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
1659 { 1711 {
1660 pane_name = ENCODE_SYSTEM (pane_name); 1712 pane_name = ENCODE_SYSTEM (pane_name);
1661 AREF (menu_items, i + MENU_ITEMS_PANE_NAME) = pane_name; 1713 ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
1662 } 1714 }
1663 #endif 1715 #endif
1664 pane_string = (NILP (pane_name) 1716 pane_string = (NILP (pane_name)
1665 ? "" : (char *) SDATA (pane_name)); 1717 ? "" : (char *) SDATA (pane_name));
1666 /* If there is just one top-level pane, put all its items directly 1718 /* If there is just one top-level pane, put all its items directly
1711 1763
1712 #ifndef HAVE_MULTILINGUAL_MENU 1764 #ifndef HAVE_MULTILINGUAL_MENU
1713 if (STRINGP (item_name) && STRING_MULTIBYTE (item_name)) 1765 if (STRINGP (item_name) && STRING_MULTIBYTE (item_name))
1714 { 1766 {
1715 item_name = ENCODE_SYSTEM (item_name); 1767 item_name = ENCODE_SYSTEM (item_name);
1716 AREF (menu_items, i + MENU_ITEMS_ITEM_NAME) = item_name; 1768 ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
1717 } 1769 }
1718 if (STRINGP (descrip) && STRING_MULTIBYTE (descrip)) 1770 if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
1719 { 1771 {
1720 descrip = ENCODE_SYSTEM (descrip); 1772 descrip = ENCODE_SYSTEM (descrip);
1721 AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY) = descrip; 1773 ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
1722 } 1774 }
1723 #endif /* not HAVE_MULTILINGUAL_MENU */ 1775 #endif /* not HAVE_MULTILINGUAL_MENU */
1724 1776
1725 wv = xmalloc_widget_value (); 1777 wv = xmalloc_widget_value ();
1726 if (prev_wv) 1778 if (prev_wv)
1816 1868
1817 prefix = entry = Qnil; 1869 prefix = entry = Qnil;
1818 i = 0; 1870 i = 0;
1819 while (i < menu_items_used) 1871 while (i < menu_items_used)
1820 { 1872 {
1821 if (EQ (XVECTOR (menu_items)->contents[i], Qnil)) 1873 if (EQ (AREF (menu_items, i), Qnil))
1822 { 1874 {
1823 subprefix_stack[submenu_depth++] = prefix; 1875 subprefix_stack[submenu_depth++] = prefix;
1824 prefix = entry; 1876 prefix = entry;
1825 i++; 1877 i++;
1826 } 1878 }
1827 else if (EQ (XVECTOR (menu_items)->contents[i], Qlambda)) 1879 else if (EQ (AREF (menu_items, i), Qlambda))
1828 { 1880 {
1829 prefix = subprefix_stack[--submenu_depth]; 1881 prefix = subprefix_stack[--submenu_depth];
1830 i++; 1882 i++;
1831 } 1883 }
1832 else if (EQ (XVECTOR (menu_items)->contents[i], Qt)) 1884 else if (EQ (AREF (menu_items, i), Qt))
1833 { 1885 {
1834 prefix 1886 prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
1835 = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
1836 i += MENU_ITEMS_PANE_LENGTH; 1887 i += MENU_ITEMS_PANE_LENGTH;
1837 } 1888 }
1838 /* Ignore a nil in the item list. 1889 /* Ignore a nil in the item list.
1839 It's meaningful only for dialog boxes. */ 1890 It's meaningful only for dialog boxes. */
1840 else if (EQ (XVECTOR (menu_items)->contents[i], Qquote)) 1891 else if (EQ (AREF (menu_items, i), Qquote))
1841 i += 1; 1892 i += 1;
1842 else 1893 else
1843 { 1894 {
1844 entry 1895 entry = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
1845 = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_VALUE];
1846 if (menu_item_selection == i) 1896 if (menu_item_selection == i)
1847 { 1897 {
1848 if (keymaps != 0) 1898 if (keymaps != 0)
1849 { 1899 {
1850 int j; 1900 int j;
1901 /* Create a tree of widget_value objects 1951 /* Create a tree of widget_value objects
1902 representing the text label and buttons. */ 1952 representing the text label and buttons. */
1903 { 1953 {
1904 Lisp_Object pane_name, prefix; 1954 Lisp_Object pane_name, prefix;
1905 char *pane_string; 1955 char *pane_string;
1906 pane_name = XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME]; 1956 pane_name = AREF (menu_items, MENU_ITEMS_PANE_NAME);
1907 prefix = XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_PREFIX]; 1957 prefix = AREF (menu_items, MENU_ITEMS_PANE_PREFIX);
1908 pane_string = (NILP (pane_name) 1958 pane_string = (NILP (pane_name)
1909 ? "" : (char *) SDATA (pane_name)); 1959 ? "" : (char *) SDATA (pane_name));
1910 prev_wv = xmalloc_widget_value (); 1960 prev_wv = xmalloc_widget_value ();
1911 prev_wv->value = pane_string; 1961 prev_wv->value = pane_string;
1912 if (keymaps && !NILP (prefix)) 1962 if (keymaps && !NILP (prefix))
1922 { 1972 {
1923 1973
1924 /* Create a new item within current pane. */ 1974 /* Create a new item within current pane. */
1925 Lisp_Object item_name, enable, descrip, help; 1975 Lisp_Object item_name, enable, descrip, help;
1926 1976
1927 item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME]; 1977 item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
1928 enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE]; 1978 enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
1929 descrip 1979 descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY);
1930 = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY]; 1980 help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
1931 help = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_HELP];
1932 1981
1933 if (NILP (item_name)) 1982 if (NILP (item_name))
1934 { 1983 {
1935 free_menubar_widget_value_tree (first_wv); 1984 free_menubar_widget_value_tree (first_wv);
1936 *error = "Submenu in dialog items"; 1985 *error = "Submenu in dialog items";
1955 prev_wv->next = wv; 2004 prev_wv->next = wv;
1956 wv->name = (char *) button_names[nb_buttons]; 2005 wv->name = (char *) button_names[nb_buttons];
1957 if (!NILP (descrip)) 2006 if (!NILP (descrip))
1958 wv->key = (char *) SDATA (descrip); 2007 wv->key = (char *) SDATA (descrip);
1959 wv->value = (char *) SDATA (item_name); 2008 wv->value = (char *) SDATA (item_name);
1960 wv->call_data = (void *) &XVECTOR (menu_items)->contents[i]; 2009 wv->call_data = (void *) &AREF (menu_items, i);
1961 wv->enabled = !NILP (enable); 2010 wv->enabled = !NILP (enable);
1962 wv->help = Qnil; 2011 wv->help = Qnil;
1963 prev_wv = wv; 2012 prev_wv = wv;
1964 2013
1965 if (! boundary_seen) 2014 if (! boundary_seen)
2025 i = 0; 2074 i = 0;
2026 while (i < menu_items_used) 2075 while (i < menu_items_used)
2027 { 2076 {
2028 Lisp_Object entry; 2077 Lisp_Object entry;
2029 2078
2030 if (EQ (XVECTOR (menu_items)->contents[i], Qt)) 2079 if (EQ (AREF (menu_items, i), Qt))
2031 { 2080 {
2032 prefix 2081 prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
2033 = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
2034 i += MENU_ITEMS_PANE_LENGTH; 2082 i += MENU_ITEMS_PANE_LENGTH;
2035 } 2083 }
2036 else 2084 else
2037 { 2085 {
2038 entry 2086 entry = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
2039 = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_VALUE];
2040 if (menu_item_selection == i) 2087 if (menu_item_selection == i)
2041 { 2088 {
2042 if (keymaps != 0) 2089 if (keymaps != 0)
2043 { 2090 {
2044 entry = Fcons (entry, Qnil); 2091 entry = Fcons (entry, Qnil);
2115 { 2162 {
2116 /* Only use MF_OWNERDRAW if GetMenuItemInfo is usable, since 2163 /* Only use MF_OWNERDRAW if GetMenuItemInfo is usable, since
2117 we can't deallocate the memory otherwise. */ 2164 we can't deallocate the memory otherwise. */
2118 if (get_menu_item_info) 2165 if (get_menu_item_info)
2119 { 2166 {
2120 out_string = (char *) LocalAlloc (LPTR, strlen (wv->name) + 1); 2167 out_string = (char *) local_alloc (strlen (wv->name) + 1);
2168 strcpy (out_string, wv->name);
2121 #ifdef MENU_DEBUG 2169 #ifdef MENU_DEBUG
2122 DebPrint ("Menu: allocing %ld for owner-draw", info.dwItemData); 2170 DebPrint ("Menu: allocing %ld for owner-draw", out_string);
2123 #endif 2171 #endif
2124 strcpy (out_string, wv->name);
2125 fuFlags = MF_OWNERDRAW | MF_DISABLED; 2172 fuFlags = MF_OWNERDRAW | MF_DISABLED;
2126 } 2173 }
2127 else 2174 else
2128 fuFlags = MF_DISABLED; 2175 fuFlags = MF_DISABLED;
2129 } 2176 }
2275 if ((info.fType & MF_OWNERDRAW) && info.dwItemData) 2322 if ((info.fType & MF_OWNERDRAW) && info.dwItemData)
2276 { 2323 {
2277 #ifdef MENU_DEBUG 2324 #ifdef MENU_DEBUG
2278 DebPrint ("Menu: freeing %ld for owner-draw", info.dwItemData); 2325 DebPrint ("Menu: freeing %ld for owner-draw", info.dwItemData);
2279 #endif 2326 #endif
2280 LocalFree (info.dwItemData); 2327 local_free (info.dwItemData);
2281 } 2328 }
2282 2329
2283 /* Recurse down submenus. */ 2330 /* Recurse down submenus. */
2284 if (info.hSubMenu) 2331 if (info.hSubMenu)
2285 w32_free_submenu_strings (info.hSubMenu); 2332 w32_free_submenu_strings (info.hSubMenu);