diff options
| author | Jason Rumney | 2001-12-09 16:48:03 +0000 |
|---|---|---|
| committer | Jason Rumney | 2001-12-09 16:48:03 +0000 |
| commit | d1fffd1db877af2266bf064b101c3b0cf1ccebc2 (patch) | |
| tree | 7082d3c6d7609bcdb10c50aea76057c7870b4dc5 /src | |
| parent | f1a85b8926f3b464bb353ec418b0c04de4053cf4 (diff) | |
| download | emacs-d1fffd1db877af2266bf064b101c3b0cf1ccebc2.tar.gz emacs-d1fffd1db877af2266bf064b101c3b0cf1ccebc2.zip | |
(_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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/w32menu.c | 63 |
1 files 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 | |||
| 61 | BUTTON_TYPE_RADIO | 61 | BUTTON_TYPE_RADIO |
| 62 | }; | 62 | }; |
| 63 | 63 | ||
| 64 | /* This structure is based on the one in ../lwlib/lwlib.h, modified | ||
| 65 | for Windows. */ | ||
| 64 | typedef struct _widget_value | 66 | typedef struct _widget_value |
| 65 | { | 67 | { |
| 66 | /* name of widget */ | 68 | /* name of widget */ |
| @@ -69,8 +71,10 @@ typedef struct _widget_value | |||
| 69 | char* value; | 71 | char* value; |
| 70 | /* keyboard equivalent. no implications for XtTranslations */ | 72 | /* keyboard equivalent. no implications for XtTranslations */ |
| 71 | char* key; | 73 | char* key; |
| 72 | /* Help string or null if none. */ | 74 | /* Help string or nil if none. |
| 73 | char *help; | 75 | GC finds this string through the frame's menu_bar_vector |
| 76 | or through menu_items. */ | ||
| 77 | Lisp_Object help; | ||
| 74 | /* true if enabled */ | 78 | /* true if enabled */ |
| 75 | Boolean enabled; | 79 | Boolean enabled; |
| 76 | /* true if selected */ | 80 | /* true if selected */ |
| @@ -1269,10 +1273,10 @@ single_submenu (item_key, item_name, maps) | |||
| 1269 | abort (); | 1273 | abort (); |
| 1270 | 1274 | ||
| 1271 | wv->selected = !NILP (selected); | 1275 | wv->selected = !NILP (selected); |
| 1272 | if (STRINGP (help)) | 1276 | if (!STRINGP (help)) |
| 1273 | wv->help = (char *) XSTRING (help)->data; | 1277 | help = Qnil; |
| 1274 | else | 1278 | |
| 1275 | wv->help = NULL; | 1279 | wv->help = help; |
| 1276 | 1280 | ||
| 1277 | prev_wv = wv; | 1281 | prev_wv = wv; |
| 1278 | 1282 | ||
| @@ -1727,8 +1731,10 @@ w32_menu_show (f, x, y, for_click, keymaps, title, error) | |||
| 1727 | abort (); | 1731 | abort (); |
| 1728 | 1732 | ||
| 1729 | wv->selected = !NILP (selected); | 1733 | wv->selected = !NILP (selected); |
| 1730 | if (STRINGP (help)) | 1734 | if (!STRINGP (help)) |
| 1731 | wv->help = XSTRING (help)->data; | 1735 | help = Qnil; |
| 1736 | |||
| 1737 | wv->help = help; | ||
| 1732 | 1738 | ||
| 1733 | prev_wv = wv; | 1739 | prev_wv = wv; |
| 1734 | 1740 | ||
| @@ -2083,13 +2089,18 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item) | |||
| 2083 | else | 2089 | else |
| 2084 | out_string = wv->name; | 2090 | out_string = wv->name; |
| 2085 | 2091 | ||
| 2086 | if (wv->title || wv->call_data == 0) | 2092 | if (item != NULL) |
| 2093 | fuFlags = MF_POPUP; | ||
| 2094 | else if (wv->title || wv->call_data == 0) | ||
| 2087 | { | 2095 | { |
| 2088 | /* Only use MF_OWNERDRAW if GetMenuItemInfo is usable, since | 2096 | /* Only use MF_OWNERDRAW if GetMenuItemInfo is usable, since |
| 2089 | we can't deallocate the memory otherwise. */ | 2097 | we can't deallocate the memory otherwise. */ |
| 2090 | if (get_menu_item_info) | 2098 | if (get_menu_item_info) |
| 2091 | { | 2099 | { |
| 2092 | out_string = LocalAlloc (LPTR, strlen (wv->name) + 1); | 2100 | out_string = (char *) LocalAlloc (LPTR, strlen (wv->name) + 1); |
| 2101 | #ifdef MENU_DEBUG | ||
| 2102 | DebPrint ("Menu: allocing %ld for owner-draw", info.dwItemData); | ||
| 2103 | #endif | ||
| 2093 | strcpy (out_string, wv->name); | 2104 | strcpy (out_string, wv->name); |
| 2094 | fuFlags = MF_OWNERDRAW | MF_DISABLED; | 2105 | fuFlags = MF_OWNERDRAW | MF_DISABLED; |
| 2095 | } | 2106 | } |
| @@ -2105,9 +2116,6 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item) | |||
| 2105 | fuFlags |= MF_UNCHECKED; | 2116 | fuFlags |= MF_UNCHECKED; |
| 2106 | } | 2117 | } |
| 2107 | 2118 | ||
| 2108 | if (item != NULL) | ||
| 2109 | fuFlags = MF_POPUP; | ||
| 2110 | |||
| 2111 | return_value = | 2119 | return_value = |
| 2112 | AppendMenu (menu, | 2120 | AppendMenu (menu, |
| 2113 | fuFlags, | 2121 | fuFlags, |
| @@ -2124,15 +2132,11 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item) | |||
| 2124 | info.cbSize = sizeof (info); | 2132 | info.cbSize = sizeof (info); |
| 2125 | info.fMask = MIIM_DATA; | 2133 | info.fMask = MIIM_DATA; |
| 2126 | 2134 | ||
| 2127 | /* Set help string for menu item. Allocate new memory | 2135 | /* Set help string for menu item. Leave it as a Lisp_Object |
| 2128 | from the heap for it, since garbage collection can | 2136 | until it is ready to be displayed, since GC can happen while |
| 2129 | occur while menus are active. */ | 2137 | menus are active. */ |
| 2130 | if (wv->help) | 2138 | if (wv->help) |
| 2131 | { | 2139 | info.dwItemData = (DWORD) wv->help; |
| 2132 | info.dwItemData | ||
| 2133 | = (DWORD) LocalAlloc (LPTR, strlen(wv->help) + 1); | ||
| 2134 | strcpy (info.dwItemData, wv->help); | ||
| 2135 | } | ||
| 2136 | 2140 | ||
| 2137 | if (wv->button_type == BUTTON_TYPE_RADIO) | 2141 | if (wv->button_type == BUTTON_TYPE_RADIO) |
| 2138 | { | 2142 | { |
| @@ -2213,7 +2217,7 @@ w32_menu_display_help (HWND owner, HMENU menu, UINT item, UINT flags) | |||
| 2213 | info.fMask = MIIM_DATA; | 2217 | info.fMask = MIIM_DATA; |
| 2214 | get_menu_item_info (menu, item, FALSE, &info); | 2218 | get_menu_item_info (menu, item, FALSE, &info); |
| 2215 | 2219 | ||
| 2216 | help = info.dwItemData ? build_string ((char *)info.dwItemData) : Qnil; | 2220 | help = info.dwItemData ? (Lisp_Object) info.dwItemData : Qnil; |
| 2217 | } | 2221 | } |
| 2218 | 2222 | ||
| 2219 | /* Store the help echo in the keyboard buffer as the X toolkit | 2223 | /* 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) | |||
| 2232 | } | 2236 | } |
| 2233 | } | 2237 | } |
| 2234 | 2238 | ||
| 2235 | /* Free memory used by owner-drawn and help_echo strings. */ | 2239 | /* Free memory used by owner-drawn strings. */ |
| 2236 | static void | 2240 | static void |
| 2237 | w32_free_submenu_strings (menu) | 2241 | w32_free_submenu_strings (menu) |
| 2238 | HMENU menu; | 2242 | HMENU menu; |
| @@ -2243,13 +2247,18 @@ w32_free_submenu_strings (menu) | |||
| 2243 | MENUITEMINFO info; | 2247 | MENUITEMINFO info; |
| 2244 | 2248 | ||
| 2245 | info.cbSize = sizeof (info); | 2249 | info.cbSize = sizeof (info); |
| 2246 | info.fMask = MIIM_DATA | MIIM_SUBMENU; | 2250 | info.fMask = MIIM_DATA | MIIM_TYPE | MIIM_SUBMENU; |
| 2247 | 2251 | ||
| 2248 | get_menu_item_info (menu, i, TRUE, &info); | 2252 | get_menu_item_info (menu, i, TRUE, &info); |
| 2249 | 2253 | ||
| 2250 | /* Both owner-drawn names and help strings are held in dwItemData. */ | 2254 | /* Owner-drawn names are held in dwItemData. */ |
| 2251 | if (info.dwItemData) | 2255 | if ((info.fType & MF_OWNERDRAW) && info.dwItemData) |
| 2252 | LocalFree (info.dwItemData); | 2256 | { |
| 2257 | #ifdef MENU_DEBUG | ||
| 2258 | DebPrint ("Menu: freeing %ld for owner-draw", info.dwItemData); | ||
| 2259 | #endif | ||
| 2260 | LocalFree (info.dwItemData); | ||
| 2261 | } | ||
| 2253 | 2262 | ||
| 2254 | /* Recurse down submenus. */ | 2263 | /* Recurse down submenus. */ |
| 2255 | if (info.hSubMenu) | 2264 | if (info.hSubMenu) |