Fix segfault when creating a tearoff menu using a Pixmap background.
[fvwm.git] / fvwm / menucmd.c
blobbc41ead660fa8ae6623ba50f8767099a521d110c
1 /* -*-c-*- */
2 /* This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * This module is all original code
19 * by Rob Nation
20 * Copyright 1993, Robert Nation
21 * You may use this code for any purpose, as long as the original
22 * copyright remains in the source code and all documentation
25 /* IMPORTANT NOTE: Do *not* use any constant numbers in this file. All values
26 * have to be #defined in the section below or defaults.h to ensure full
27 * control over the menus. */
29 /* ---------------------------- included header files ---------------------- */
31 #include "config.h"
33 #include <stdio.h>
35 #include "libs/Parse.h"
36 #include "libs/Strings.h"
37 #include "fvwm.h"
38 #include "functions.h"
39 #include "repeat.h"
40 #include "misc.h"
41 #include "move_resize.h"
42 #include "screen.h"
43 #include "menus.h"
44 #include "menudim.h"
45 #include "menuroot.h"
46 #include "menustyle.h"
47 #include "menuparameters.h"
49 /* ---------------------------- local definitions -------------------------- */
51 /* ---------------------------- local macros ------------------------------- */
53 /* ---------------------------- imports ------------------------------------ */
55 /* ---------------------------- included code files ------------------------ */
57 /* ---------------------------- local types -------------------------------- */
59 /* ---------------------------- forward declarations ----------------------- */
61 /* ---------------------------- local variables ---------------------------- */
63 /* ---------------------------- exported variables (globals) --------------- */
65 /* ---------------------------- local functions ---------------------------- */
67 static void menu_func(F_CMD_ARGS, Bool fStaysUp)
69 struct MenuRoot *menu;
70 char *ret_action = NULL;
71 struct MenuOptions mops;
72 char *menu_name = NULL;
73 struct MenuParameters mp;
74 struct MenuReturn mret;
75 FvwmWindow * const fw = exc->w.fw;
76 const Window w = exc->w.w;
77 const exec_context_t *exc2;
79 memset(&mops, 0, sizeof(mops));
80 memset(&mret, 0, sizeof(MenuReturn));
81 action = GetNextToken(action,&menu_name);
82 action = get_menu_options(
83 action, w, fw, NULL, NULL, NULL, &mops);
84 while (action && *action && isspace((unsigned char)*action))
86 action++;
88 if (action && *action == 0)
90 action = NULL;
92 menu = menus_find_menu(menu_name);
93 if (menu == NULL)
95 if (menu_name)
97 fvwm_msg(ERR,"menu_func","No such menu %s",menu_name);
98 free(menu_name);
100 return;
102 if (menu_name &&
103 set_repeat_data(
104 menu_name, (fStaysUp) ? REPEAT_MENU : REPEAT_POPUP,NULL))
106 free(menu_name);
109 memset(&mp, 0, sizeof(mp));
110 mp.menu = menu;
111 exc2 = exc_clone_context(exc, NULL, 0);
112 mp.pexc = &exc2;
113 MR_IS_TEAR_OFF_MENU(menu) = 0;
114 mp.flags.has_default_action = (action != NULL);
115 mp.flags.is_sticky = fStaysUp;
116 mp.flags.is_submenu = False;
117 mp.flags.is_already_mapped = False;
118 mp.flags.is_triggered_by_keypress =
119 (exc->x.etrigger->type == KeyPress);
120 mp.pops = &mops;
121 mp.ret_paction = &ret_action;
122 do_menu(&mp, &mret);
123 if (mret.rc == MENU_DOUBLE_CLICKED && action)
125 execute_function(cond_rc, exc2, action, 0);
127 if (ret_action != NULL)
129 free(ret_action);
131 exc_destroy_context(exc2);
133 return;
136 /* ---------------------------- interface functions ------------------------ */
138 /* ---------------------------- builtin commands --------------------------- */
140 /* the function for the "Popup" command */
141 void CMD_Popup(F_CMD_ARGS)
143 menu_func(F_PASS_ARGS, False);
145 return;
148 /* the function for the "Menu" command */
149 void CMD_Menu(F_CMD_ARGS)
151 menu_func(F_PASS_ARGS, True);
153 return;
156 void CMD_AddToMenu(F_CMD_ARGS)
158 MenuRoot *mr;
159 MenuRoot *mrPrior;
160 char *token, *rest,*item;
162 token = PeekToken(action, &rest);
163 if (!token)
165 return;
167 mr = menus_find_menu(token);
168 if (mr && MR_MAPPED_COPIES(mr) != 0)
170 fvwm_msg(ERR,"add_item_to_menu", "menu %s is in use", token);
171 return;
173 mr = FollowMenuContinuations(menus_find_menu(token), &mrPrior);
174 if (mr == NULL)
176 mr = NewMenuRoot(token);
179 /* Set + state to last menu */
180 set_last_added_item(ADDED_MENU, mr);
182 rest = GetNextToken(rest, &item);
183 AddToMenu(mr, item, rest, True /* pixmap scan */, True, False);
184 if (item)
186 free(item);
189 return;
192 void CMD_DestroyMenu(F_CMD_ARGS)
194 MenuRoot *mr;
195 MenuRoot *mrContinuation;
196 Bool do_recreate = False;
197 char *token;
199 token = PeekToken(action, &action);
200 if (!token)
202 return;
204 if (StrEquals(token, "recreate"))
206 do_recreate = True;
207 token = PeekToken(action, NULL);
209 mr = menus_find_menu(token);
210 if (Scr.last_added_item.type == ADDED_MENU)
212 set_last_added_item(ADDED_NONE, NULL);
214 while (mr)
216 /* save continuation before destroy */
217 mrContinuation = MR_CONTINUATION_MENU(mr);
218 if (!DestroyMenu(mr, do_recreate, True))
220 return;
222 /* Don't recreate the continuations */
223 do_recreate = False;
224 mr = mrContinuation;
227 return;
230 void CMD_DestroyMenuStyle(F_CMD_ARGS)
232 MenuStyle *ms = NULL;
233 char *name = NULL;
235 name = PeekToken(action, NULL);
236 if (name == NULL)
238 fvwm_msg(ERR,"DestroyMenuStyle", "needs one parameter");
239 return;
242 ms = menustyle_find(name);
243 if (ms == NULL)
245 return;
247 else if (ms == menustyle_get_default_style())
249 fvwm_msg(ERR,"DestroyMenuStyle",
250 "cannot destroy default menu style. "
251 "To reset the default menu style use\n %s",
252 DEFAULT_MENU_STYLE);
253 return;
255 else if (ST_USAGE_COUNT(ms) != 0)
257 fvwm_msg(ERR, "DestroyMenuStyle", "menu style %s is in use",
258 name);
259 return;
261 else
263 menustyle_free(ms);
265 menus_remove_style_from_menus(ms);
267 return;
270 void CMD_ChangeMenuStyle(F_CMD_ARGS)
272 char *name = NULL;
273 char *menuname = NULL;
274 MenuStyle *ms = NULL;
275 MenuRoot *mr = NULL;
277 name = PeekToken(action, &action);
278 if (name == NULL)
280 fvwm_msg(ERR,"ChangeMenuStyle",
281 "needs at least two parameters");
282 return;
285 ms = menustyle_find(name);
286 if (ms == NULL)
288 fvwm_msg(ERR,"ChangeMenuStyle", "cannot find style %s", name);
289 return;
292 menuname = PeekToken(action, &action);
293 while (menuname && *menuname)
295 mr = menus_find_menu(menuname);
296 if (mr == NULL)
298 fvwm_msg(ERR, "ChangeMenuStyle", "cannot find menu %s",
299 menuname);
300 break;
302 if (MR_MAPPED_COPIES(mr) != 0)
304 fvwm_msg(ERR, "ChangeMenuStyle", "menu %s is in use",
305 menuname);
307 else
309 MR_STYLE(mr) = ms;
310 MR_IS_UPDATED(mr) = 1;
312 menuname = PeekToken(action, &action);
315 return;