From d1fffd1db877af2266bf064b101c3b0cf1ccebc2 Mon Sep 17 00:00:00 2001 From: Jason Rumney Date: Sun, 9 Dec 2001 16:48:03 +0000 Subject: [PATCH] (_widget_value): Make `help' field a Lisp_Object. Add comment to explain where the struct came from. (single_submenu, w32_menu_show): Set `help' field as Lisp_Object. (add_menu_item): Process pop-up menus first to avoid memory leak. (add_menu_item, w32_menu_display_help): Use `help' field as Lisp_Object. (w32_free_submenu_strings): Only free owner-drawn strings. --- src/w32menu.c | 63 +++++++++++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/src/w32menu.c b/src/w32menu.c index 3f1b3d07ddb..99376360187 100644 --- a/src/w32menu.c +++ b/src/w32menu.c @@ -61,6 +61,8 @@ enum button_type BUTTON_TYPE_RADIO }; +/* This structure is based on the one in ../lwlib/lwlib.h, modified + for Windows. */ typedef struct _widget_value { /* name of widget */ @@ -69,8 +71,10 @@ typedef struct _widget_value char* value; /* keyboard equivalent. no implications for XtTranslations */ char* key; - /* Help string or null if none. */ - char *help; + /* Help string or nil if none. + GC finds this string through the frame's menu_bar_vector + or through menu_items. */ + Lisp_Object help; /* true if enabled */ Boolean enabled; /* true if selected */ @@ -1269,10 +1273,10 @@ single_submenu (item_key, item_name, maps) abort (); wv->selected = !NILP (selected); - if (STRINGP (help)) - wv->help = (char *) XSTRING (help)->data; - else - wv->help = NULL; + if (!STRINGP (help)) + help = Qnil; + + wv->help = help; prev_wv = wv; @@ -1727,8 +1731,10 @@ w32_menu_show (f, x, y, for_click, keymaps, title, error) abort (); wv->selected = !NILP (selected); - if (STRINGP (help)) - wv->help = XSTRING (help)->data; + if (!STRINGP (help)) + help = Qnil; + + wv->help = help; prev_wv = wv; @@ -2083,13 +2089,18 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item) else out_string = wv->name; - if (wv->title || wv->call_data == 0) + if (item != NULL) + fuFlags = MF_POPUP; + else if (wv->title || wv->call_data == 0) { /* Only use MF_OWNERDRAW if GetMenuItemInfo is usable, since we can't deallocate the memory otherwise. */ if (get_menu_item_info) { - out_string = LocalAlloc (LPTR, strlen (wv->name) + 1); + 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; } @@ -2105,9 +2116,6 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item) fuFlags |= MF_UNCHECKED; } - if (item != NULL) - fuFlags = MF_POPUP; - return_value = AppendMenu (menu, fuFlags, @@ -2124,15 +2132,11 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item) info.cbSize = sizeof (info); info.fMask = MIIM_DATA; - /* Set help string for menu item. Allocate new memory - from the heap for it, since garbage collection can - occur while menus are active. */ + /* Set help string for menu item. Leave it as a Lisp_Object + until it is ready to be displayed, since GC can happen while + menus are active. */ if (wv->help) - { - info.dwItemData - = (DWORD) LocalAlloc (LPTR, strlen(wv->help) + 1); - strcpy (info.dwItemData, wv->help); - } + info.dwItemData = (DWORD) wv->help; if (wv->button_type == BUTTON_TYPE_RADIO) { @@ -2213,7 +2217,7 @@ w32_menu_display_help (HWND owner, HMENU menu, UINT item, UINT flags) info.fMask = MIIM_DATA; get_menu_item_info (menu, item, FALSE, &info); - help = info.dwItemData ? build_string ((char *)info.dwItemData) : Qnil; + help = info.dwItemData ? (Lisp_Object) info.dwItemData : Qnil; } /* Store the help echo in the keyboard buffer as the X toolkit @@ -2232,7 +2236,7 @@ w32_menu_display_help (HWND owner, HMENU menu, UINT item, UINT flags) } } -/* Free memory used by owner-drawn and help_echo strings. */ +/* Free memory used by owner-drawn strings. */ static void w32_free_submenu_strings (menu) HMENU menu; @@ -2243,13 +2247,18 @@ w32_free_submenu_strings (menu) MENUITEMINFO info; info.cbSize = sizeof (info); - info.fMask = MIIM_DATA | MIIM_SUBMENU; + info.fMask = MIIM_DATA | MIIM_TYPE | MIIM_SUBMENU; get_menu_item_info (menu, i, TRUE, &info); - /* Both owner-drawn names and help strings are held in dwItemData. */ - if (info.dwItemData) - LocalFree (info.dwItemData); + /* Owner-drawn names are held in dwItemData. */ + if ((info.fType & MF_OWNERDRAW) && info.dwItemData) + { +#ifdef MENU_DEBUG + DebPrint ("Menu: freeing %ld for owner-draw", info.dwItemData); +#endif + LocalFree (info.dwItemData); + } /* Recurse down submenus. */ if (info.hSubMenu) -- 2.39.2