1 | /* |
---|
2 | * (c) Copyright 1989, 1990, 1991, 1992, 1993 OPEN SOFTWARE FOUNDATION, INC. |
---|
3 | * ALL RIGHTS RESERVED |
---|
4 | */ |
---|
5 | /* |
---|
6 | * Motif Release 1.2.3 |
---|
7 | */ |
---|
8 | #ifdef REV_INFO |
---|
9 | #ifndef lint |
---|
10 | static char rcsid[] = "$RCSfile: WmMenu.c,v $ $Revision: 1.1.1.1 $ $Date: 1997-03-25 09:12:22 $" |
---|
11 | #endif |
---|
12 | #endif |
---|
13 | /* |
---|
14 | * (c) Copyright 1987, 1988, 1989, 1990 HEWLETT-PACKARD COMPANY */ |
---|
15 | /* |
---|
16 | * (c) Copyright 1987, 1988 DIGITAL EQUIPMENT CORPORATION */ |
---|
17 | /* |
---|
18 | * (c) Copyright 1988 MASSACHUSETTS INSTITUTE OF TECHNOLOGY */ |
---|
19 | |
---|
20 | /* |
---|
21 | * Included Files: |
---|
22 | */ |
---|
23 | |
---|
24 | #include "WmGlobal.h" |
---|
25 | #include "WmResource.h" |
---|
26 | #include "WmResParse.h" |
---|
27 | #include <stdio.h> |
---|
28 | |
---|
29 | #include <X11/Shell.h> |
---|
30 | |
---|
31 | #include <Xm/Xm.h> |
---|
32 | #include <Xm/XmP.h> |
---|
33 | #include <Xm/CascadeB.h> |
---|
34 | #include <Xm/CascadeBG.h> |
---|
35 | #include <Xm/Label.h> |
---|
36 | #include <Xm/LabelG.h> |
---|
37 | #include <Xm/MenuShell.h> |
---|
38 | #include <Xm/PushB.h> |
---|
39 | #include <Xm/PushBG.h> |
---|
40 | #include <Xm/RowColumn.h> |
---|
41 | #include <Xm/RowColumnP.h> |
---|
42 | #include <Xm/Separator.h> |
---|
43 | #include <Xm/SeparatoG.h> |
---|
44 | |
---|
45 | #define SHELL_NAME "menu" |
---|
46 | #define SEPARATOR_NAME "separator" |
---|
47 | #define TITLE_NAME "title_name" |
---|
48 | #define CASCADE_BTN_NAME "cascadebutton" |
---|
49 | #define PUSH_BTN_NAME "pushbutton" |
---|
50 | |
---|
51 | #define CHILDREN_CACHE 22 |
---|
52 | #define MENU_BUTTON_INC 5 |
---|
53 | |
---|
54 | /* |
---|
55 | * include extern functions |
---|
56 | */ |
---|
57 | #include "WmMenu.h" |
---|
58 | #include "WmCDecor.h" |
---|
59 | #include "WmColormap.h" |
---|
60 | #include "WmEvent.h" |
---|
61 | #include "WmFunction.h" |
---|
62 | #include "WmIconBox.h" |
---|
63 | #include "WmImage.h" |
---|
64 | #include "WmError.h" |
---|
65 | |
---|
66 | #ifdef AUTOMATION |
---|
67 | #ifdef _NO_PROTO |
---|
68 | static void SetMwmMenuInfo (); |
---|
69 | static void SetMwmMenuWindow (); |
---|
70 | #else |
---|
71 | static void SetMwmMenuInfo (ClientData *pcd, MenuSpec *menuSpec); |
---|
72 | static void SetMwmMenuWindow (ClientData *pcd, Widget menuWidget); |
---|
73 | #endif /* _NO_PROTO */ |
---|
74 | #endif /* AUTOMATION */ |
---|
75 | |
---|
76 | |
---|
77 | |
---|
78 | |
---|
79 | /*************************************<->************************************* |
---|
80 | * |
---|
81 | * MakeMenu (menuName, initialContext, accelContext, moreMenuItems, |
---|
82 | * fSystemMenu) |
---|
83 | * |
---|
84 | * |
---|
85 | * Description: |
---|
86 | * ----------- |
---|
87 | * This function makes a menu widget. |
---|
88 | * |
---|
89 | * |
---|
90 | * Inputs: |
---|
91 | * ------ |
---|
92 | * menuName = name of the top-level menu pane for the menu |
---|
93 | * initialContext = initial context for menuitem sensitivity |
---|
94 | * accelContext = accelerator context |
---|
95 | * moreMenuItems = additional menuitems for custom menu. |
---|
96 | * fSystemMenu = TRUE iff the menu is a client system menu. |
---|
97 | * |
---|
98 | * |
---|
99 | * Outputs: |
---|
100 | * ------- |
---|
101 | * Return = pointer to a MenuSpec structure with updated currentContext, |
---|
102 | * menuWidget, and menuButtons members. |
---|
103 | * |
---|
104 | * |
---|
105 | * Comments: |
---|
106 | * -------- |
---|
107 | * If moreMenuItems is nonNULL, a custom MenuSpec will be created, with |
---|
108 | * menuItem member pointing to moreMenuItems. The menuItems for the |
---|
109 | * standard MenuSpec of the same name and the moreMenuItems list will be |
---|
110 | * used to create menubuttons, and the menu widget will be separate from |
---|
111 | * any existing standard menu widget. |
---|
112 | * |
---|
113 | * When the client is destroyed, this custom MenuSpec, its menuItem and |
---|
114 | * menuButton lists, and its menu widget should be freed. |
---|
115 | * |
---|
116 | *************************************<->***********************************/ |
---|
117 | #ifdef _NO_PROTO |
---|
118 | MenuSpec * |
---|
119 | MakeMenu (pSD, menuName, initialContext, accelContext, |
---|
120 | moreMenuItems, fSystemMenu) |
---|
121 | |
---|
122 | WmScreenData *pSD; |
---|
123 | String menuName; |
---|
124 | Context initialContext; |
---|
125 | Context accelContext; |
---|
126 | MenuItem *moreMenuItems; |
---|
127 | Boolean fSystemMenu; |
---|
128 | #else /* _NO_PROTO */ |
---|
129 | MenuSpec *MakeMenu (WmScreenData *pSD, String menuName, Context initialContext, |
---|
130 | Context accelContext, MenuItem *moreMenuItems, |
---|
131 | Boolean fSystemMenu) |
---|
132 | #endif /* _NO_PROTO */ |
---|
133 | { |
---|
134 | unsigned int n; |
---|
135 | MenuSpec *menuSpec; |
---|
136 | MenuSpec *newMenuSpec; |
---|
137 | MenuItem *menuItem; |
---|
138 | KeySpec *accelKeySpec; |
---|
139 | |
---|
140 | if ((menuName == NULL) || (pSD == NULL)) |
---|
141 | { |
---|
142 | return (NULL); |
---|
143 | } |
---|
144 | |
---|
145 | /* |
---|
146 | * Look for the menu specification: |
---|
147 | */ |
---|
148 | |
---|
149 | menuSpec = pSD->menuSpecs; |
---|
150 | while (menuSpec) |
---|
151 | { |
---|
152 | if ((menuSpec->name != NULL) && !strcmp (menuSpec->name, menuName)) |
---|
153 | /* Found the menu pane. */ |
---|
154 | { |
---|
155 | break; |
---|
156 | } |
---|
157 | menuSpec = menuSpec->nextMenuSpec; |
---|
158 | } |
---|
159 | |
---|
160 | if (menuSpec == NULL) |
---|
161 | /* the menuSpecs list is exhausted */ |
---|
162 | { |
---|
163 | MWarning("Menu specification %s not found\n", menuName); |
---|
164 | return (NULL); |
---|
165 | } |
---|
166 | |
---|
167 | /* |
---|
168 | * The top-level menu pane specification was found. |
---|
169 | * Adjust the menu accelerator context? |
---|
170 | */ |
---|
171 | |
---|
172 | if (fSystemMenu) |
---|
173 | { |
---|
174 | accelContext = 0; |
---|
175 | } |
---|
176 | else if (accelContext & F_CONTEXT_ROOT) |
---|
177 | /* root context accelerators apply everywhere */ |
---|
178 | { |
---|
179 | accelContext = F_CONTEXT_ALL; |
---|
180 | } |
---|
181 | |
---|
182 | /* |
---|
183 | * If making a custom menu, create a custom copy of the specification with |
---|
184 | * which to build the custom menu. |
---|
185 | * Otherwise, if the menu widget exists, possibly modify the accelerator |
---|
186 | * contexts and return the specification. |
---|
187 | */ |
---|
188 | |
---|
189 | if (moreMenuItems != NULL) |
---|
190 | { |
---|
191 | if ((newMenuSpec = (MenuSpec *) XtMalloc (sizeof (MenuSpec))) == NULL) |
---|
192 | /* Handle insufficent memory */ |
---|
193 | { |
---|
194 | MWarning("Insufficient memory for menu %s\n", menuName); |
---|
195 | return (NULL); |
---|
196 | } |
---|
197 | newMenuSpec->name = NULL; /* distinguishes this as custom */ |
---|
198 | newMenuSpec->whichButton = SELECT_BUTTON; |
---|
199 | newMenuSpec->height = 0; |
---|
200 | newMenuSpec->menuItems = menuSpec->menuItems; /* temporary */ |
---|
201 | newMenuSpec->accelContext = menuSpec->accelContext; |
---|
202 | newMenuSpec->accelKeySpecs = NULL; |
---|
203 | newMenuSpec->nextMenuSpec = NULL; |
---|
204 | menuSpec = newMenuSpec; |
---|
205 | } |
---|
206 | else if (menuSpec->menuWidget) |
---|
207 | { |
---|
208 | /* |
---|
209 | * OR the accelContext into the accelerators, if necessary. |
---|
210 | */ |
---|
211 | if (accelContext != (menuSpec->accelContext & accelContext)) |
---|
212 | { |
---|
213 | menuSpec->accelContext |= accelContext; |
---|
214 | accelKeySpec = menuSpec->accelKeySpecs; |
---|
215 | while (accelKeySpec) |
---|
216 | { |
---|
217 | accelKeySpec->context |= accelContext; |
---|
218 | accelKeySpec = accelKeySpec->nextKeySpec; |
---|
219 | } |
---|
220 | } |
---|
221 | return (menuSpec); |
---|
222 | } |
---|
223 | |
---|
224 | /* |
---|
225 | * We have a menu specification with which to build the menu. |
---|
226 | * Set the initial and accelerator contexts -- they are needed within |
---|
227 | * CreateMenuWidget. |
---|
228 | */ |
---|
229 | |
---|
230 | menuSpec->currentContext = initialContext; |
---|
231 | menuSpec->accelContext = accelContext; |
---|
232 | |
---|
233 | /* |
---|
234 | * Scan the toplevel MenuSpec and create its initial menuButtons array |
---|
235 | * if any of its items will need to be included. This array will be |
---|
236 | * created or enlarged within CreateMenuWidget below if necessary. |
---|
237 | */ |
---|
238 | |
---|
239 | n = 0; |
---|
240 | menuItem = menuSpec->menuItems; |
---|
241 | while (menuItem) |
---|
242 | { |
---|
243 | if ((menuItem->greyedContext) || (menuItem->mgtMask)) |
---|
244 | { |
---|
245 | n++; |
---|
246 | } |
---|
247 | menuItem = menuItem->nextMenuItem; |
---|
248 | } |
---|
249 | menuItem = moreMenuItems; |
---|
250 | while (menuItem) |
---|
251 | { |
---|
252 | if ((menuItem->greyedContext) || (menuItem->mgtMask)) |
---|
253 | { |
---|
254 | n++; |
---|
255 | } |
---|
256 | menuItem = menuItem->nextMenuItem; |
---|
257 | } |
---|
258 | if (n) |
---|
259 | { |
---|
260 | if ((menuSpec->menuButtons = |
---|
261 | (MenuButton *) XtMalloc (n * sizeof(MenuButton))) == NULL) |
---|
262 | /* insufficent memory */ |
---|
263 | { |
---|
264 | MWarning("Insufficient memory for menu %s\n", menuName); |
---|
265 | return (NULL); |
---|
266 | } |
---|
267 | menuSpec->menuButtonSize = n; |
---|
268 | } |
---|
269 | else |
---|
270 | { |
---|
271 | menuSpec->menuButtons = NULL; |
---|
272 | menuSpec->menuButtonSize = 0; |
---|
273 | } |
---|
274 | menuSpec->menuButtonCount = 0; |
---|
275 | |
---|
276 | /* |
---|
277 | * Create a PopupShell widget as a child of the workspace manager widget |
---|
278 | * and a PopupMenu as a child of the shell. |
---|
279 | * Fill the PopupMenu with the menu items. |
---|
280 | */ |
---|
281 | |
---|
282 | menuSpec->menuWidget = CreateMenuWidget (pSD, menuName, |
---|
283 | pSD->screenTopLevelW, |
---|
284 | TRUE, menuSpec, moreMenuItems); |
---|
285 | if (menuSpec->menuWidget == NULL) |
---|
286 | { |
---|
287 | /* |
---|
288 | * Could not make the top-level menu pane. |
---|
289 | */ |
---|
290 | return (NULL); |
---|
291 | } |
---|
292 | /* |
---|
293 | _XmSetPopupMenuClick(menuSpec->menuWidget, False); |
---|
294 | */ |
---|
295 | /* Return the top MenuSpec */ |
---|
296 | |
---|
297 | return (menuSpec); |
---|
298 | |
---|
299 | } /* END OF FUNCTION MakeMenu */ |
---|
300 | |
---|
301 | |
---|
302 | |
---|
303 | /*************************************<->***********************************/ |
---|
304 | void CheckTerminalSeparator(menuSpec, buttonWidget, manage) |
---|
305 | MenuSpec *menuSpec; |
---|
306 | Widget buttonWidget; |
---|
307 | Boolean manage; |
---|
308 | { |
---|
309 | CompositeWidget cw; |
---|
310 | WidgetList children; |
---|
311 | Cardinal wPos; |
---|
312 | |
---|
313 | |
---|
314 | if ((menuSpec == NULL) || (menuSpec->menuWidget == NULL)) |
---|
315 | { |
---|
316 | return; |
---|
317 | } |
---|
318 | |
---|
319 | cw = (CompositeWidget)menuSpec->menuWidget; |
---|
320 | children = cw->composite.children; |
---|
321 | |
---|
322 | for (wPos = 0; wPos < cw->composite.num_children; wPos++) |
---|
323 | { |
---|
324 | if((Widget)children[wPos] == buttonWidget) |
---|
325 | { |
---|
326 | break; |
---|
327 | } |
---|
328 | } |
---|
329 | |
---|
330 | |
---|
331 | if(wPos > 0 && |
---|
332 | XtClass((Widget) children[wPos -1]) == xmSeparatorGadgetClass) |
---|
333 | { |
---|
334 | if(manage) |
---|
335 | { |
---|
336 | if (!(XtIsManaged((Widget)children[wPos -1]))) |
---|
337 | { |
---|
338 | XtManageChild((Widget)children[wPos -1]); |
---|
339 | } |
---|
340 | } |
---|
341 | else |
---|
342 | { |
---|
343 | if (XtIsManaged((Widget)children[wPos -1])) |
---|
344 | { |
---|
345 | XtUnmanageChild((Widget)children[wPos -1]); |
---|
346 | } |
---|
347 | } |
---|
348 | } |
---|
349 | |
---|
350 | } /* END OF FUNCTION CheckTerminalSeparator */ |
---|
351 | |
---|
352 | |
---|
353 | |
---|
354 | /*************************************<->************************************* |
---|
355 | * |
---|
356 | * static Boolean |
---|
357 | * AdjustPBs (menuSpec, pCD, newContext) |
---|
358 | * |
---|
359 | * |
---|
360 | * Description: |
---|
361 | * ----------- |
---|
362 | * This procedure adjusts menu PushButton sensitivities and manage/unmanaged |
---|
363 | * status for a toplevel menu. |
---|
364 | * |
---|
365 | * |
---|
366 | * Inputs: |
---|
367 | * ------ |
---|
368 | * menuSpec = nonNULL toplevel menu specification with gadget |
---|
369 | * pCD = client data |
---|
370 | * newContext = context that the menu is to be posted under. |
---|
371 | * |
---|
372 | * |
---|
373 | * Outputs: |
---|
374 | * ------- |
---|
375 | * menuSpec = menu specification with modifications |
---|
376 | * Return = TRUE iff at least one menu item changed manage status. |
---|
377 | * |
---|
378 | * |
---|
379 | * Comments: |
---|
380 | * -------- |
---|
381 | * Adjusts PushButton sensitivity according to context and function type. |
---|
382 | * Manages/Unmanages PushButtons according to clientFunction resource. |
---|
383 | * |
---|
384 | *************************************<->***********************************/ |
---|
385 | #ifdef _NO_PROTO |
---|
386 | static Boolean AdjustPBs (menuSpec, pCD, newContext) |
---|
387 | MenuSpec *menuSpec; /* RETURNED */ |
---|
388 | ClientData *pCD; |
---|
389 | Context newContext; |
---|
390 | |
---|
391 | #else /* NO_PROTO */ |
---|
392 | static Boolean AdjustPBs (MenuSpec *menuSpec, ClientData *pCD, |
---|
393 | Context newContext) |
---|
394 | #endif /* _NO_PROTO */ |
---|
395 | { |
---|
396 | MenuButton *menuButton; |
---|
397 | MenuItem *menuItem; |
---|
398 | int msgc; |
---|
399 | unsigned int n; |
---|
400 | long *pMsg; |
---|
401 | Boolean fSupported; |
---|
402 | Boolean fChangeManaged = FALSE; |
---|
403 | |
---|
404 | /* |
---|
405 | * Set PushButton sensitivity. |
---|
406 | * Set f.send_msg button sensitivity according to context and client |
---|
407 | * message list. Adjust other button sensitivities only for context. |
---|
408 | */ |
---|
409 | |
---|
410 | /* check for bad input value - shouldn't happen. */ |
---|
411 | if (menuSpec == NULL) return (FALSE); |
---|
412 | |
---|
413 | for (n = 0, menuButton = menuSpec->menuButtons; |
---|
414 | n < menuSpec->menuButtonCount; |
---|
415 | n++, menuButton++) |
---|
416 | { |
---|
417 | menuItem = menuButton->menuItem; |
---|
418 | if (menuItem->wmFunction == F_Send_Msg) |
---|
419 | /* f.send_msg button: set according to context and message. */ |
---|
420 | { |
---|
421 | if ((newContext & menuItem->greyedContext) || |
---|
422 | !(pCD && pCD->mwmMessagesCount && pCD->mwmMessages)) |
---|
423 | /* insensitive context or empty client message list */ |
---|
424 | { |
---|
425 | XtSetSensitive (menuButton->buttonWidget, FALSE); |
---|
426 | } |
---|
427 | else |
---|
428 | /* |
---|
429 | * Have a context sensitive f.send_msg item and a client with a |
---|
430 | * nonempty message list. Set sensitive only if the message is |
---|
431 | * supported by this client. Otherwise set insensitive. |
---|
432 | */ |
---|
433 | { |
---|
434 | msgc = pCD->mwmMessagesCount; |
---|
435 | pMsg = pCD->mwmMessages; |
---|
436 | fSupported = FALSE; |
---|
437 | while (msgc--) |
---|
438 | /* scan nonempty message list */ |
---|
439 | { |
---|
440 | if (*pMsg == (long) menuItem->wmFuncArgs) |
---|
441 | /* found match */ |
---|
442 | { |
---|
443 | fSupported = TRUE; |
---|
444 | break; |
---|
445 | } |
---|
446 | pMsg++; /* next message in list */ |
---|
447 | } |
---|
448 | XtSetSensitive (menuButton->buttonWidget, fSupported); |
---|
449 | } |
---|
450 | } |
---|
451 | else |
---|
452 | /* |
---|
453 | * Non f.send_msg button: |
---|
454 | * Adjust sensitivity according to context. |
---|
455 | * Manage/Unmanage according to clientFunction. |
---|
456 | */ |
---|
457 | { |
---|
458 | if (menuSpec->currentContext & menuItem->greyedContext) |
---|
459 | /* button is currently insensitive */ |
---|
460 | { |
---|
461 | if (!(newContext & menuItem->greyedContext)) |
---|
462 | /* insensitive -> sensitive */ |
---|
463 | { |
---|
464 | XtSetSensitive (menuButton->buttonWidget, TRUE); |
---|
465 | } |
---|
466 | } |
---|
467 | else |
---|
468 | /* button is currently sensitive */ |
---|
469 | { |
---|
470 | if (newContext & menuItem->greyedContext) |
---|
471 | /* sensitive -> insensitive */ |
---|
472 | { |
---|
473 | XtSetSensitive (menuButton->buttonWidget, FALSE); |
---|
474 | } |
---|
475 | } |
---|
476 | |
---|
477 | if ((menuItem->mgtMask) && pCD) |
---|
478 | /* PushButton might not apply */ |
---|
479 | { |
---|
480 | if (pCD->clientFunctions & menuItem->mgtMask) |
---|
481 | /* function applies -- manage it */ |
---|
482 | { |
---|
483 | if (!menuButton->managed) |
---|
484 | /* unmanaged -> managed */ |
---|
485 | { |
---|
486 | XtManageChild (menuButton->buttonWidget); |
---|
487 | menuButton->managed = TRUE; |
---|
488 | fChangeManaged = TRUE; |
---|
489 | if (n == menuSpec->menuButtonCount - 1) |
---|
490 | { |
---|
491 | /* |
---|
492 | * last item, if it has a separator before |
---|
493 | * it, manage the separator |
---|
494 | */ |
---|
495 | |
---|
496 | CheckTerminalSeparator(menuSpec, |
---|
497 | menuButton->buttonWidget, |
---|
498 | True); |
---|
499 | } |
---|
500 | } |
---|
501 | } |
---|
502 | else |
---|
503 | /* function does not apply -- unmanage it */ |
---|
504 | { |
---|
505 | if (menuButton->managed) |
---|
506 | /* managed -> unmanaged */ |
---|
507 | { |
---|
508 | XtUnmanageChild (menuButton->buttonWidget); |
---|
509 | menuButton->managed = FALSE; |
---|
510 | fChangeManaged = TRUE; |
---|
511 | |
---|
512 | if (n == menuSpec->menuButtonCount - 1) |
---|
513 | { |
---|
514 | /* |
---|
515 | * last item, if it has a separator before |
---|
516 | * it, unmanage the separator |
---|
517 | */ |
---|
518 | CheckTerminalSeparator(menuSpec, |
---|
519 | menuButton->buttonWidget, |
---|
520 | False); |
---|
521 | } |
---|
522 | |
---|
523 | } |
---|
524 | } |
---|
525 | } |
---|
526 | else if (!menuButton->managed) |
---|
527 | /* unmanaged PushButton applies */ |
---|
528 | { |
---|
529 | XtManageChild (menuButton->buttonWidget); |
---|
530 | menuButton->managed = TRUE; |
---|
531 | fChangeManaged = TRUE; |
---|
532 | } |
---|
533 | } |
---|
534 | } |
---|
535 | #ifdef AUTOMATION |
---|
536 | SetMwmMenuInfo(pCD, menuSpec); |
---|
537 | #endif |
---|
538 | |
---|
539 | return (fChangeManaged); |
---|
540 | |
---|
541 | } /* END OF FUNCTION AdjustPBs */ |
---|
542 | |
---|
543 | |
---|
544 | |
---|
545 | /*************************************<->************************************* |
---|
546 | * |
---|
547 | * static Boolean |
---|
548 | * SavePBInfo (topMenuSpec, menuItem, itemW) |
---|
549 | * |
---|
550 | * |
---|
551 | * Description: |
---|
552 | * ----------- |
---|
553 | * Fills a MenuButton structure for a PushButton. |
---|
554 | * If necessary, mallocs or reallocs the menuButtons array in the toplevel |
---|
555 | * MenuSpec. |
---|
556 | * |
---|
557 | * |
---|
558 | * Inputs: |
---|
559 | * ------ |
---|
560 | * topMenuSpec = pointer to toplevel MenuSpec structure |
---|
561 | * menuItem = pointer to PushButton MenuItem structure |
---|
562 | * itemW = PushButton gadget |
---|
563 | * topMenuSpec->menuButtons[] |
---|
564 | * topMenuSpec->menuButtonSize |
---|
565 | * topMenuSpec->menuButtonCount |
---|
566 | * |
---|
567 | * |
---|
568 | * Outputs: |
---|
569 | * ------- |
---|
570 | * Return = FALSE iff insufficient memory for malloc or realloc |
---|
571 | * or bad input value forces exit. |
---|
572 | * topMenuSpec->menuButtons[] |
---|
573 | * topMenuSpec->menuButtonSize |
---|
574 | * topMenuSpec->menuButtonCount |
---|
575 | * |
---|
576 | * |
---|
577 | * Comments: |
---|
578 | * -------- |
---|
579 | * The initial managed status of PushButtons is TRUE. |
---|
580 | * |
---|
581 | *************************************<->***********************************/ |
---|
582 | #ifdef _NO_PROTO |
---|
583 | static Boolean SavePBInfo (topMenuSpec, menuItem, itemW) |
---|
584 | |
---|
585 | MenuSpec *topMenuSpec; /* RETURNED */ |
---|
586 | MenuItem *menuItem; |
---|
587 | Widget itemW; |
---|
588 | #else /* _NO_PROTO */ |
---|
589 | static Boolean SavePBInfo (MenuSpec *topMenuSpec, MenuItem *menuItem, |
---|
590 | Widget itemW) |
---|
591 | #endif /* _NO_PROTO */ |
---|
592 | { |
---|
593 | MenuButton *menuButton; |
---|
594 | |
---|
595 | |
---|
596 | /* check for bad input value - shouldn't happen. */ |
---|
597 | if (topMenuSpec == NULL) return (FALSE); |
---|
598 | |
---|
599 | if (topMenuSpec->menuButtonSize == 0) |
---|
600 | /* need to create array */ |
---|
601 | { |
---|
602 | topMenuSpec->menuButtonSize = MENU_BUTTON_INC; |
---|
603 | topMenuSpec->menuButtons = |
---|
604 | (MenuButton *) XtMalloc (MENU_BUTTON_INC * sizeof(MenuButton)); |
---|
605 | } |
---|
606 | else if (topMenuSpec->menuButtonCount == topMenuSpec->menuButtonSize) |
---|
607 | /* need larger array */ |
---|
608 | { |
---|
609 | topMenuSpec->menuButtonSize += MENU_BUTTON_INC; |
---|
610 | topMenuSpec->menuButtons = (MenuButton *) |
---|
611 | XtRealloc ((char*)topMenuSpec->menuButtons, |
---|
612 | topMenuSpec->menuButtonSize * sizeof(MenuButton)); |
---|
613 | } |
---|
614 | |
---|
615 | if (topMenuSpec->menuButtons == NULL) |
---|
616 | /* insufficent memory */ |
---|
617 | { |
---|
618 | topMenuSpec->menuButtonSize = 0; |
---|
619 | topMenuSpec->menuButtonCount = 0; |
---|
620 | return (FALSE); |
---|
621 | } |
---|
622 | |
---|
623 | menuButton = &(topMenuSpec->menuButtons[topMenuSpec->menuButtonCount]); |
---|
624 | topMenuSpec->menuButtonCount++; |
---|
625 | |
---|
626 | menuButton->menuItem = menuItem; |
---|
627 | menuButton->buttonWidget = itemW; |
---|
628 | menuButton->managed = TRUE; |
---|
629 | return (TRUE); |
---|
630 | |
---|
631 | } |
---|
632 | |
---|
633 | |
---|
634 | |
---|
635 | /*************************************<->************************************* |
---|
636 | * |
---|
637 | * CreateMenuWidget (pSD, menuName, parent, fTopLevelPane, topMenuSpec, |
---|
638 | * moreMenuItems) |
---|
639 | * |
---|
640 | * |
---|
641 | * Description: |
---|
642 | * ----------- |
---|
643 | * Creates a MenuShell as a child of the specified parent widget, and a |
---|
644 | * PopupMenu or PulldownMenu as a child of the shell. Fill the menu with |
---|
645 | * the named menupane items. |
---|
646 | * |
---|
647 | * |
---|
648 | * Inputs: |
---|
649 | * ------ |
---|
650 | * pSD ---------- pointer to screen data |
---|
651 | * menuName ----- the name of the menu specification to be used to create |
---|
652 | * the menu widget. |
---|
653 | * parent -------- parent of popup shell |
---|
654 | * fTopLevelPane - TRUE iff the menupane is a top level one |
---|
655 | * topMenuSpec --- pointer to the top menu specification. |
---|
656 | * moreMenuItems - pointer to additional menu items for custom menu. |
---|
657 | * |
---|
658 | * |
---|
659 | * Outputs: |
---|
660 | * ------- |
---|
661 | * Return = created PopupMenu or PulldownMenu widget, or NULL. |
---|
662 | * |
---|
663 | * |
---|
664 | * Comments: |
---|
665 | * -------- |
---|
666 | * We attach a popdowncallback to the menu to set wmGD.menuActive to NULL, |
---|
667 | * allowing us to not dispatch key events separately from the toolkit |
---|
668 | * dispatcher. |
---|
669 | * |
---|
670 | *************************************<->***********************************/ |
---|
671 | |
---|
672 | typedef struct _StrList |
---|
673 | { |
---|
674 | XmString string; |
---|
675 | struct _StrList *next; |
---|
676 | } StrList; |
---|
677 | |
---|
678 | #ifdef _NO_PROTO |
---|
679 | Widget CreateMenuWidget (pSD, menuName, parent, fTopLevelPane, |
---|
680 | topMenuSpec, moreMenuItems) |
---|
681 | WmScreenData *pSD; |
---|
682 | String menuName; |
---|
683 | Widget parent; |
---|
684 | Boolean fTopLevelPane; |
---|
685 | MenuSpec *topMenuSpec; |
---|
686 | MenuItem *moreMenuItems; |
---|
687 | #else /* _NO_PROTO */ |
---|
688 | Widget CreateMenuWidget (WmScreenData *pSD, String menuName, Widget parent, |
---|
689 | Boolean fTopLevelPane, MenuSpec *topMenuSpec, |
---|
690 | MenuItem *moreMenuItems) |
---|
691 | #endif /* _NO_PROTO */ |
---|
692 | { |
---|
693 | int i, n; |
---|
694 | Arg sepArgs[1]; |
---|
695 | Arg args[10]; |
---|
696 | MenuSpec *menuSpec; |
---|
697 | MenuItem *menuItem; |
---|
698 | Widget menuShellW; |
---|
699 | Widget menuW; |
---|
700 | Widget subMenuW; |
---|
701 | Widget children[CHILDREN_CACHE]; |
---|
702 | Pixmap labelPixmap; |
---|
703 | KeySpec *accelKeySpec; |
---|
704 | Dimension menuHeight; |
---|
705 | Boolean fUseTitleSep = FALSE; |
---|
706 | StrList *stringsToFree = NULL, *sPtr; |
---|
707 | XmString tmpstr; |
---|
708 | |
---|
709 | |
---|
710 | /* check for bad input values. */ |
---|
711 | if ((menuName == NULL) || (pSD == NULL)) |
---|
712 | { |
---|
713 | return (NULL); |
---|
714 | } |
---|
715 | |
---|
716 | /* |
---|
717 | * Find the menu pane specifications for menuName. |
---|
718 | * The top-level menu specification is passed as an argument (it may |
---|
719 | * be custom). A submenu specification must be found and might not exist. |
---|
720 | * Return NULL if a submenu specification is not found. |
---|
721 | */ |
---|
722 | if (fTopLevelPane) |
---|
723 | { |
---|
724 | menuSpec = topMenuSpec; |
---|
725 | } |
---|
726 | else |
---|
727 | { |
---|
728 | menuSpec = pSD->menuSpecs; |
---|
729 | while (menuSpec) |
---|
730 | { |
---|
731 | if ((menuSpec->name != NULL) && !strcmp (menuSpec->name, menuName)) |
---|
732 | { |
---|
733 | break; /* found menuName's specification */ |
---|
734 | } |
---|
735 | menuSpec = menuSpec->nextMenuSpec; /* keep looking */ |
---|
736 | } |
---|
737 | } |
---|
738 | |
---|
739 | if (menuSpec == NULL) |
---|
740 | /* (submenu) specification not found */ |
---|
741 | { |
---|
742 | MWarning("Menu specification %s not found\n", menuName); |
---|
743 | return (NULL); |
---|
744 | } |
---|
745 | |
---|
746 | /* |
---|
747 | * If menuSpec is marked, we have menu recursion => fail. |
---|
748 | * Otherwise, mark it. |
---|
749 | */ |
---|
750 | |
---|
751 | if (menuSpec->currentContext & CR_MENU_MARK) /* marked? */ |
---|
752 | /* menu recursion */ |
---|
753 | { |
---|
754 | MWarning("Menu recursion detected for %s\n", menuName); |
---|
755 | return (NULL); |
---|
756 | } |
---|
757 | menuSpec->currentContext |= CR_MENU_MARK; /* no, mark it */ |
---|
758 | |
---|
759 | /* |
---|
760 | * Create a PopupShell widget. |
---|
761 | * If the parent of the specified parent ("grandparent") is a MenuShell |
---|
762 | * widget, then use the grandparent as the parent of the PopupShell. |
---|
763 | * Otherwise, use the specified parent. |
---|
764 | */ |
---|
765 | i = 0; |
---|
766 | XtSetArg (args[i], XmNwidth, (XtArgVal) 5); i++; |
---|
767 | XtSetArg (args[i], XmNheight, (XtArgVal) 5); i++; |
---|
768 | XtSetArg (args[i], XmNallowShellResize, (XtArgVal) TRUE); i++; |
---|
769 | XtSetArg (args[i], XtNoverrideRedirect, (XtArgVal) TRUE); i++; |
---|
770 | XtSetArg (args[i], XtNdepth, |
---|
771 | (XtArgVal) DefaultDepth(DISPLAY, pSD->screen)); i++; |
---|
772 | XtSetArg (args[i], XtNscreen, |
---|
773 | (XtArgVal) ScreenOfDisplay(DISPLAY, pSD->screen)); i++; |
---|
774 | |
---|
775 | if ((XtParent (parent) != NULL) && XmIsMenuShell (XtParent (parent))) |
---|
776 | { |
---|
777 | parent = XtParent (parent); |
---|
778 | } |
---|
779 | |
---|
780 | menuShellW = XtCreatePopupShell (SHELL_NAME, xmMenuShellWidgetClass, |
---|
781 | parent, (ArgList) args, i); |
---|
782 | |
---|
783 | /* |
---|
784 | * Create a RowColumn widget as a child of the shell for the menu pane. |
---|
785 | * If the menu pane is top-level, create a popup menu for it and attach |
---|
786 | * the unmap callback to it. |
---|
787 | * Otherwise, create a pulldown menu for it. |
---|
788 | */ |
---|
789 | |
---|
790 | i = 0; |
---|
791 | XtSetArg (args[i], XmNborderWidth, (XtArgVal) 0); i++; |
---|
792 | XtSetArg (args[i], XmNwhichButton, (XtArgVal) SELECT_BUTTON); i++; |
---|
793 | XtSetArg (args[i], XmNadjustMargin, (XtArgVal) TRUE); i++; |
---|
794 | |
---|
795 | if (fTopLevelPane) |
---|
796 | { |
---|
797 | XtSetArg (args[i], XmNrowColumnType, (XtArgVal) XmMENU_POPUP); i++; |
---|
798 | XtSetArg (args[i], XmNpopupEnabled, (XtArgVal) TRUE); i++; |
---|
799 | menuW = XtCreateWidget (menuName, xmRowColumnWidgetClass, menuShellW, |
---|
800 | (ArgList) args, i); |
---|
801 | XtAddCallback (menuW, XmNunmapCallback, (XtCallbackProc)UnmapCallback, |
---|
802 | (XtPointer) menuSpec); |
---|
803 | } |
---|
804 | else |
---|
805 | { |
---|
806 | XtSetArg (args[i], XmNrowColumnType, (XtArgVal) XmMENU_PULLDOWN); i++; |
---|
807 | menuW = XtCreateWidget (menuName, xmRowColumnWidgetClass, menuShellW, |
---|
808 | (ArgList) args, i); |
---|
809 | } |
---|
810 | |
---|
811 | /* |
---|
812 | * Create the specified menu entries as children of the menupane. |
---|
813 | * Menus may contain the following widgets: |
---|
814 | * |
---|
815 | * Label |
---|
816 | * Separator |
---|
817 | * CascadeButton |
---|
818 | * PushButton |
---|
819 | * |
---|
820 | * Add separator gadgets around menu titles. |
---|
821 | */ |
---|
822 | |
---|
823 | XtSetArg (sepArgs[0], XmNseparatorType, (XtArgVal) XmDOUBLE_LINE); |
---|
824 | |
---|
825 | n = 0; |
---|
826 | menuItem = menuSpec->menuItems; |
---|
827 | if ((menuItem == NULL) && (moreMenuItems != NULL)) |
---|
828 | /* handle custom menu with empty standard specification */ |
---|
829 | { |
---|
830 | menuSpec->menuItems = menuItem = moreMenuItems; |
---|
831 | moreMenuItems = NULL; |
---|
832 | } |
---|
833 | while (menuItem) |
---|
834 | { |
---|
835 | i = 0; |
---|
836 | |
---|
837 | if (menuItem->wmFunction == F_Separator) |
---|
838 | /* |
---|
839 | * Add a Separator gadget for a menu separator. |
---|
840 | * An immediately following title will not have a top separator. |
---|
841 | */ |
---|
842 | { |
---|
843 | children[n] = |
---|
844 | XmCreateSeparatorGadget (menuW, SEPARATOR_NAME, |
---|
845 | (ArgList)NULL, 0); |
---|
846 | |
---|
847 | fUseTitleSep = FALSE; |
---|
848 | } /* F_Separator */ |
---|
849 | |
---|
850 | else |
---|
851 | /* |
---|
852 | * We will use one of: |
---|
853 | * |
---|
854 | * Label |
---|
855 | * CascadeButton |
---|
856 | * PushButton |
---|
857 | */ |
---|
858 | { |
---|
859 | /* |
---|
860 | * Construct the label |
---|
861 | */ |
---|
862 | if ((menuItem->labelType == XmPIXMAP) && |
---|
863 | (labelPixmap = |
---|
864 | MakeCachedLabelPixmap (pSD, menuW, |
---|
865 | menuItem->labelBitmapIndex))) |
---|
866 | { |
---|
867 | XtSetArg (args[i], XmNlabelType, (XtArgVal) XmPIXMAP); i++; |
---|
868 | XtSetArg (args[i], XmNlabelPixmap, (XtArgVal) labelPixmap); i++; |
---|
869 | XtSetArg (args[i], XmNlabelInsensitivePixmap, |
---|
870 | (XtArgVal) labelPixmap); i++; |
---|
871 | } |
---|
872 | else |
---|
873 | { |
---|
874 | XtSetArg (args[i], XmNlabelType, (XtArgVal) XmSTRING); i++; |
---|
875 | XtSetArg (args[i], XmNlabelString, (XtArgVal) |
---|
876 | (tmpstr = XmStringLtoRCreate(menuItem->label, |
---|
877 | XmFONTLIST_DEFAULT_TAG))); i++; |
---|
878 | sPtr = (StrList *) XtMalloc(sizeof(StrList)); |
---|
879 | if (sPtr == NULL) |
---|
880 | { |
---|
881 | MWarning ("Insufficient memory for menu %s\n", |
---|
882 | menuName); |
---|
883 | return (NULL); |
---|
884 | } |
---|
885 | else |
---|
886 | { |
---|
887 | sPtr->string = tmpstr; |
---|
888 | sPtr->next = stringsToFree; |
---|
889 | stringsToFree = sPtr; |
---|
890 | } |
---|
891 | } |
---|
892 | |
---|
893 | if (menuItem->wmFunction == F_Title) |
---|
894 | /* |
---|
895 | * Add a centered Label gadget for a menu title. |
---|
896 | * Include separators above and below the title. |
---|
897 | * Don't include the top one if the title is the first pane item |
---|
898 | * or immediately follows a user-supplied separator. |
---|
899 | */ |
---|
900 | { |
---|
901 | if (fUseTitleSep) |
---|
902 | { |
---|
903 | children[n] = |
---|
904 | XmCreateSeparatorGadget (menuW, SEPARATOR_NAME, |
---|
905 | sepArgs, 1); n++; |
---|
906 | } |
---|
907 | |
---|
908 | XtSetArg (args[i], XmNalignment, XmALIGNMENT_CENTER); i++; |
---|
909 | children[n] = XmCreateLabelGadget (menuW, TITLE_NAME, |
---|
910 | (ArgList) args, i); n++; |
---|
911 | children[n] = XmCreateSeparatorGadget (menuW, SEPARATOR_NAME, |
---|
912 | sepArgs, 1); |
---|
913 | |
---|
914 | /* |
---|
915 | * A following title will have both separators. |
---|
916 | */ |
---|
917 | |
---|
918 | fUseTitleSep = TRUE; |
---|
919 | } |
---|
920 | |
---|
921 | else |
---|
922 | /* |
---|
923 | * We will use one of: |
---|
924 | * |
---|
925 | * CascadeButton |
---|
926 | * PushButton |
---|
927 | * |
---|
928 | * Both support mnemonics; only PushButtons support accelerators. |
---|
929 | */ |
---|
930 | { |
---|
931 | /* |
---|
932 | * Align text on the left. |
---|
933 | * Set any mnemonic text. |
---|
934 | */ |
---|
935 | XtSetArg (args[i], XmNalignment, XmALIGNMENT_BEGINNING); i++; |
---|
936 | |
---|
937 | if (menuItem->mnemonic) |
---|
938 | { |
---|
939 | XtSetArg (args[i], XmNmnemonic, |
---|
940 | (XtArgVal) menuItem->mnemonic); i++; |
---|
941 | } |
---|
942 | |
---|
943 | if (menuItem->wmFunction == F_Menu) |
---|
944 | /* |
---|
945 | * Create a PopupShell and PulldownMenu for a submenu (the |
---|
946 | * menushells are linked together). |
---|
947 | * Create a CascadeButton Widget |
---|
948 | * The submenu widget is attached to the CascadeButton gadget |
---|
949 | * using the subMenuId resource. |
---|
950 | * Make the CascadeButton insensitive if the submenu cannot be |
---|
951 | * created. |
---|
952 | */ |
---|
953 | { |
---|
954 | subMenuW = CreateMenuWidget (pSD, |
---|
955 | menuItem->wmFuncArgs, menuW, |
---|
956 | FALSE, topMenuSpec, |
---|
957 | (MenuItem *)NULL); |
---|
958 | if (subMenuW) |
---|
959 | /* |
---|
960 | * Attach submenu to cascade button. |
---|
961 | */ |
---|
962 | { |
---|
963 | XtSetArg (args[i], XmNsubMenuId, (XtArgVal) subMenuW); |
---|
964 | i++; |
---|
965 | children[n] = XmCreateCascadeButtonGadget (menuW, |
---|
966 | CASCADE_BTN_NAME, (ArgList) args, i); |
---|
967 | } |
---|
968 | else |
---|
969 | /* |
---|
970 | * Unable to create submenupane: make the entry insensitive. |
---|
971 | */ |
---|
972 | { |
---|
973 | children[n] = XmCreateCascadeButtonGadget (menuW, |
---|
974 | CASCADE_BTN_NAME, (ArgList) args, i); |
---|
975 | XtSetSensitive (children[n], FALSE); |
---|
976 | } |
---|
977 | |
---|
978 | /* |
---|
979 | * A following title will have both separators. |
---|
980 | */ |
---|
981 | |
---|
982 | fUseTitleSep = TRUE; |
---|
983 | } |
---|
984 | |
---|
985 | else |
---|
986 | /* |
---|
987 | * Create a PushButton gadget. |
---|
988 | */ |
---|
989 | { |
---|
990 | /* |
---|
991 | * If an accelerator is specified, set acceleratorText, |
---|
992 | * then create an accelerator KeySpec and insert it at the |
---|
993 | * head of the toplevel MenuSpec's list. |
---|
994 | */ |
---|
995 | if (menuItem->accelText) |
---|
996 | { |
---|
997 | XtSetArg (args[i], XmNacceleratorText, (XtArgVal) |
---|
998 | (tmpstr = XmStringLtoRCreate(menuItem->accelText, |
---|
999 | XmFONTLIST_DEFAULT_TAG))); i++; |
---|
1000 | sPtr = (StrList *) XtMalloc(sizeof(StrList)); |
---|
1001 | if (sPtr == NULL) |
---|
1002 | { |
---|
1003 | MWarning ("Insufficient memory for menu %s\n", |
---|
1004 | menuName); |
---|
1005 | return (NULL); |
---|
1006 | } |
---|
1007 | else |
---|
1008 | { |
---|
1009 | sPtr->string = tmpstr; |
---|
1010 | sPtr->next = stringsToFree; |
---|
1011 | stringsToFree = sPtr; |
---|
1012 | } |
---|
1013 | |
---|
1014 | if ((accelKeySpec = (KeySpec *) |
---|
1015 | XtMalloc (sizeof (KeySpec ))) == NULL) |
---|
1016 | /* Handle insufficent memory */ |
---|
1017 | { |
---|
1018 | MWarning ("Insufficient memory for menu %s\n", |
---|
1019 | menuName); |
---|
1020 | menuSpec->currentContext &= ~CR_MENU_MARK; |
---|
1021 | return (NULL); |
---|
1022 | } |
---|
1023 | |
---|
1024 | accelKeySpec->state = menuItem->accelState; |
---|
1025 | accelKeySpec->keycode = menuItem->accelKeyCode; |
---|
1026 | accelKeySpec->context = topMenuSpec->accelContext; |
---|
1027 | accelKeySpec->subContext = 0; |
---|
1028 | accelKeySpec->wmFunction = menuItem->wmFunction; |
---|
1029 | accelKeySpec->wmFuncArgs = menuItem->wmFuncArgs; |
---|
1030 | accelKeySpec->nextKeySpec = topMenuSpec->accelKeySpecs; |
---|
1031 | topMenuSpec->accelKeySpecs = accelKeySpec; |
---|
1032 | } |
---|
1033 | |
---|
1034 | children[n] = XmCreatePushButtonGadget (menuW, |
---|
1035 | PUSH_BTN_NAME, (ArgList) args, i); |
---|
1036 | |
---|
1037 | /* |
---|
1038 | * Set sensitivity. Initially we only consider the context |
---|
1039 | * of the top level menupane. |
---|
1040 | */ |
---|
1041 | |
---|
1042 | if (menuItem->greyedContext & topMenuSpec->currentContext) |
---|
1043 | /* insensitive button in this context*/ |
---|
1044 | { |
---|
1045 | XtSetSensitive (children[n], FALSE); |
---|
1046 | } |
---|
1047 | else |
---|
1048 | /* sensitive button in this context*/ |
---|
1049 | { |
---|
1050 | XtSetSensitive (children[n], TRUE); |
---|
1051 | } |
---|
1052 | |
---|
1053 | /* |
---|
1054 | * If necessary, fill a menuButtons element for this |
---|
1055 | * PushButton. Malloc or Realloc the array if necessary. |
---|
1056 | */ |
---|
1057 | if ((menuItem->greyedContext) || (menuItem->mgtMask)) |
---|
1058 | { |
---|
1059 | if (!SavePBInfo (topMenuSpec, menuItem, children[n])) |
---|
1060 | { |
---|
1061 | MWarning("Insufficient memory for menu %s\n", |
---|
1062 | menuName); |
---|
1063 | menuSpec->currentContext &= ~CR_MENU_MARK; |
---|
1064 | return (NULL); |
---|
1065 | } |
---|
1066 | } |
---|
1067 | |
---|
1068 | /* |
---|
1069 | * Set up the function callback. |
---|
1070 | * A following title will have both separators. |
---|
1071 | */ |
---|
1072 | |
---|
1073 | XtAddCallback (children[n], XmNactivateCallback, |
---|
1074 | (XtCallbackProc)ActivateCallback, |
---|
1075 | (XtPointer) menuItem); |
---|
1076 | |
---|
1077 | fUseTitleSep = TRUE; |
---|
1078 | } |
---|
1079 | } |
---|
1080 | } |
---|
1081 | |
---|
1082 | /* |
---|
1083 | * Next menu item: handle custom items and full children[]. |
---|
1084 | */ |
---|
1085 | n++; |
---|
1086 | menuItem = menuItem->nextMenuItem; |
---|
1087 | if ((menuItem == NULL) && (moreMenuItems != NULL)) |
---|
1088 | { |
---|
1089 | menuSpec->menuItems = menuItem = moreMenuItems; |
---|
1090 | moreMenuItems = NULL; |
---|
1091 | } |
---|
1092 | if (n >= CHILDREN_CACHE - 2) /* leave room for title separators */ |
---|
1093 | { |
---|
1094 | XtManageChildren (children, n); |
---|
1095 | n = 0; |
---|
1096 | } |
---|
1097 | } |
---|
1098 | |
---|
1099 | if (n > 0) |
---|
1100 | { |
---|
1101 | XtManageChildren (children, n); |
---|
1102 | } |
---|
1103 | |
---|
1104 | /* |
---|
1105 | * Get the initial height of the top level menu pane shell. |
---|
1106 | * The actual height will change according to clientFunctions. |
---|
1107 | */ |
---|
1108 | if (fTopLevelPane) |
---|
1109 | { |
---|
1110 | i = 0; |
---|
1111 | XtSetArg (args[i], XtNheight, &menuHeight); i++; |
---|
1112 | XtGetValues (menuW, (ArgList)args, i); |
---|
1113 | topMenuSpec->height = (unsigned int) menuHeight; |
---|
1114 | } |
---|
1115 | |
---|
1116 | |
---|
1117 | /* free the string that may have been created earlier. */ |
---|
1118 | for (sPtr = stringsToFree; sPtr != NULL; ) |
---|
1119 | { |
---|
1120 | stringsToFree = stringsToFree->next; |
---|
1121 | XmStringFree(sPtr->string); |
---|
1122 | sPtr = stringsToFree; |
---|
1123 | } |
---|
1124 | |
---|
1125 | |
---|
1126 | /* Unmark the menu specification and return. */ |
---|
1127 | menuSpec->currentContext &= ~CR_MENU_MARK; |
---|
1128 | return (menuW); |
---|
1129 | |
---|
1130 | } /* END OF FUNCTION CreateMenuWidget */ |
---|
1131 | |
---|
1132 | |
---|
1133 | |
---|
1134 | /*************************************<->************************************* |
---|
1135 | * |
---|
1136 | * PostMenu (menuSpec, pCD, x, y, button, newContext, flags, passedInEvent) |
---|
1137 | * |
---|
1138 | * |
---|
1139 | * Description: |
---|
1140 | * ----------- |
---|
1141 | * This function is used to post a menu at a particular location. |
---|
1142 | * |
---|
1143 | * |
---|
1144 | * Inputs: |
---|
1145 | * ------ |
---|
1146 | * menuSpec = menu specification |
---|
1147 | * pCD = client data |
---|
1148 | * x,y = position to post the menu if (flags & POST_AT_XY) set |
---|
1149 | * button = button number posting the menu or NoButton (WmGlobal.h) if |
---|
1150 | * posted by a key |
---|
1151 | * newContext = context that the menu is to be posted under. |
---|
1152 | * flags = POST_AT_XY bit set iff x,y are valid, else compute from pCD |
---|
1153 | * POST_TRAVERSAL_ON bit set if set traversal on |
---|
1154 | * |
---|
1155 | * Outputs: |
---|
1156 | * ------- |
---|
1157 | * menuSpec = menu specification with modifications |
---|
1158 | * wmGD.menuClient = pCD |
---|
1159 | * wmGD.menuActive = menuSpec |
---|
1160 | * |
---|
1161 | * |
---|
1162 | * Comments: |
---|
1163 | * -------- |
---|
1164 | * Accepts x,y only if POST_AT_XY flag bit set. Otherwise, computes from pCD. |
---|
1165 | * Adjusts PushButton sensitivity according to context and function type. |
---|
1166 | * Manages/Unmanages PushButtons according to clientFunction resource. |
---|
1167 | * Sets traversal on if button==NoButton or POST_TRAVERSAL_ON flag bit set. |
---|
1168 | * |
---|
1169 | *************************************<->***********************************/ |
---|
1170 | |
---|
1171 | #ifdef _NO_PROTO |
---|
1172 | void PostMenu (menuSpec, pCD, x, y, button, newContext, flags, passedInEvent) |
---|
1173 | |
---|
1174 | MenuSpec *menuSpec; |
---|
1175 | ClientData *pCD; |
---|
1176 | int x, y; |
---|
1177 | unsigned int button; |
---|
1178 | Context newContext; |
---|
1179 | long flags; |
---|
1180 | XEvent *passedInEvent; |
---|
1181 | |
---|
1182 | #else /* _NO_PROTO */ |
---|
1183 | void PostMenu (MenuSpec *menuSpec, ClientData *pCD, int x, int y, unsigned int button, Context newContext, long flags, XEvent *passedInEvent) |
---|
1184 | #endif /* _NO_PROTO */ |
---|
1185 | { |
---|
1186 | int i; |
---|
1187 | Arg args[3]; |
---|
1188 | unsigned int whichButton; |
---|
1189 | Dimension menuHeight; |
---|
1190 | XButtonPressedEvent event; |
---|
1191 | Window saveWindow; |
---|
1192 | int saveType; |
---|
1193 | |
---|
1194 | if ((menuSpec == NULL) || (menuSpec->menuWidget == NULL)) |
---|
1195 | { |
---|
1196 | return; |
---|
1197 | } |
---|
1198 | |
---|
1199 | |
---|
1200 | /* |
---|
1201 | * Don't post a menu from an icon in the iconbox if the |
---|
1202 | * icon is not visible |
---|
1203 | */ |
---|
1204 | if((newContext == F_SUBCONTEXT_IB_WICON || |
---|
1205 | newContext == F_SUBCONTEXT_IB_IICON) && |
---|
1206 | (!(IconVisible(pCD)))) |
---|
1207 | { |
---|
1208 | return; |
---|
1209 | } |
---|
1210 | |
---|
1211 | /* |
---|
1212 | * Set grabContext to be used in GrabWin when no event is passed |
---|
1213 | * to GrabWin. |
---|
1214 | */ |
---|
1215 | |
---|
1216 | wmGD.grabContext = newContext; |
---|
1217 | |
---|
1218 | /* |
---|
1219 | * Adjust PushButton sensitivity and manage/unmanage status. |
---|
1220 | * If the manage status of the system menu has changed, |
---|
1221 | * then get the height of the top level menu pane shell and |
---|
1222 | * cache it in its MenuSpec. |
---|
1223 | */ |
---|
1224 | |
---|
1225 | |
---|
1226 | if (AdjustPBs (menuSpec, pCD, newContext)) |
---|
1227 | { |
---|
1228 | i = 0; |
---|
1229 | XtSetArg (args[i], XtNheight, &menuHeight); i++; |
---|
1230 | XtGetValues (menuSpec->menuWidget, (ArgList)args, i); |
---|
1231 | menuSpec->height = (unsigned int) menuHeight; |
---|
1232 | } |
---|
1233 | menuSpec->currentContext = newContext; |
---|
1234 | |
---|
1235 | /* |
---|
1236 | * Adjust the whichButton resource if necessary. |
---|
1237 | * Use SELECT_BUTTON for NoButton. |
---|
1238 | */ |
---|
1239 | |
---|
1240 | whichButton = (button == NoButton) ? SELECT_BUTTON : button; |
---|
1241 | if (whichButton != menuSpec->whichButton) |
---|
1242 | { |
---|
1243 | i = 0; |
---|
1244 | XtSetArg (args[i], XmNwhichButton, (XtArgVal) whichButton); i++; |
---|
1245 | XtSetValues (menuSpec->menuWidget, args, i); |
---|
1246 | menuSpec->whichButton = whichButton; |
---|
1247 | } |
---|
1248 | |
---|
1249 | /* |
---|
1250 | * Determine the position of the popup menu. |
---|
1251 | * Compute position if necessary (system menu). |
---|
1252 | */ |
---|
1253 | |
---|
1254 | if (!(flags & POST_AT_XY)) |
---|
1255 | /* compute the position */ |
---|
1256 | { |
---|
1257 | GetSystemMenuPosition (pCD, &x, &y, menuSpec->height, newContext); |
---|
1258 | } |
---|
1259 | |
---|
1260 | event.x_root = x; |
---|
1261 | event.y_root = y; |
---|
1262 | XmMenuPosition (menuSpec->menuWidget, &event); |
---|
1263 | |
---|
1264 | wmGD.menuClient = pCD; |
---|
1265 | wmGD.menuActive = menuSpec; /* set to NULL within UnmapCallback() */ |
---|
1266 | |
---|
1267 | /* |
---|
1268 | * Post the menu by managing its top-level RowColumn. |
---|
1269 | * |
---|
1270 | * First dispatch the event to set the time stamp in the toolkit |
---|
1271 | */ |
---|
1272 | |
---|
1273 | if(passedInEvent) |
---|
1274 | { |
---|
1275 | saveWindow = passedInEvent->xany.window; |
---|
1276 | passedInEvent->xany.window = 0; |
---|
1277 | saveType = passedInEvent->type; |
---|
1278 | passedInEvent->type = 0; |
---|
1279 | |
---|
1280 | XtDispatchEvent(passedInEvent); |
---|
1281 | passedInEvent->xany.window = saveWindow; |
---|
1282 | passedInEvent->type = saveType; |
---|
1283 | } |
---|
1284 | |
---|
1285 | #ifndef ALTERNATE_POSTMENU |
---|
1286 | |
---|
1287 | XtManageChild (menuSpec->menuWidget); |
---|
1288 | |
---|
1289 | #else |
---|
1290 | if (flags & POST_STICKY) |
---|
1291 | { |
---|
1292 | _XmSetPopupMenuClick(menuSpec->menuWidget, True); |
---|
1293 | } |
---|
1294 | else |
---|
1295 | { |
---|
1296 | _XmSetPopupMenuClick(menuSpec->menuWidget, False); |
---|
1297 | } |
---|
1298 | |
---|
1299 | /* |
---|
1300 | * Post the menu by calling the convenience routine that verifies |
---|
1301 | * the button event, updates the Xt timestamp, and finally manages |
---|
1302 | * the pane. |
---|
1303 | */ |
---|
1304 | |
---|
1305 | _XmPostPopupMenu( menuSpec->menuWidget, passedInEvent); |
---|
1306 | #endif |
---|
1307 | |
---|
1308 | #ifdef AUTOMATION |
---|
1309 | SetMwmMenuWindow(pCD, menuSpec->menuWidget); |
---|
1310 | #endif |
---|
1311 | |
---|
1312 | /* |
---|
1313 | * set the traversal state. |
---|
1314 | */ |
---|
1315 | |
---|
1316 | if ((button == NoButton) || (flags & POST_TRAVERSAL_ON)) |
---|
1317 | /* turn traversal on */ |
---|
1318 | { |
---|
1319 | TraversalOn (menuSpec); |
---|
1320 | } |
---|
1321 | else |
---|
1322 | /* turn traversal off */ |
---|
1323 | { |
---|
1324 | TraversalOff (menuSpec); |
---|
1325 | } |
---|
1326 | |
---|
1327 | } /* END OF FUNCTION PostMenu */ |
---|
1328 | |
---|
1329 | |
---|
1330 | |
---|
1331 | /*************************************<->************************************* |
---|
1332 | * |
---|
1333 | * UnpostMenu (menuSpec) |
---|
1334 | * |
---|
1335 | * |
---|
1336 | * Description: |
---|
1337 | * ----------- |
---|
1338 | * This function is used to unpost a menu. |
---|
1339 | * |
---|
1340 | * |
---|
1341 | * Inputs: |
---|
1342 | * ------ |
---|
1343 | * menuSpec = menu specification |
---|
1344 | * |
---|
1345 | * Outputs: |
---|
1346 | * ------- |
---|
1347 | * None. |
---|
1348 | * |
---|
1349 | * |
---|
1350 | * Comments: |
---|
1351 | * -------- |
---|
1352 | * wmGD.menuActive and wmGD.menuUnpostKey are set to NULL within |
---|
1353 | * UnmapCallback. |
---|
1354 | * |
---|
1355 | *************************************<->***********************************/ |
---|
1356 | |
---|
1357 | #ifdef _NO_PROTO |
---|
1358 | void UnpostMenu (menuSpec) |
---|
1359 | |
---|
1360 | MenuSpec *menuSpec; |
---|
1361 | #else /* _NO_PROTO */ |
---|
1362 | void UnpostMenu (MenuSpec *menuSpec) |
---|
1363 | #endif /* _NO_PROTO */ |
---|
1364 | { |
---|
1365 | if (menuSpec && (menuSpec->menuWidget)) |
---|
1366 | /* |
---|
1367 | * Unpost the menu by unmanaging its top-level RowColumn. |
---|
1368 | */ |
---|
1369 | { |
---|
1370 | XtUnmanageChild (menuSpec->menuWidget); |
---|
1371 | #ifndef OLD_COLORMAP |
---|
1372 | ForceColormapFocus (ACTIVE_PSD, ACTIVE_PSD->colormapFocus); |
---|
1373 | #endif |
---|
1374 | } |
---|
1375 | |
---|
1376 | } /* END OF FUNCTION UnpostMenu */ |
---|
1377 | |
---|
1378 | |
---|
1379 | |
---|
1380 | /*************************************<->************************************* |
---|
1381 | * |
---|
1382 | * ActivateCallback (w, client_data, call_data) |
---|
1383 | * |
---|
1384 | * |
---|
1385 | * Description: |
---|
1386 | * ----------- |
---|
1387 | * This function is called whenever a menu item is selected. |
---|
1388 | * |
---|
1389 | * |
---|
1390 | * Inputs: |
---|
1391 | * ------ |
---|
1392 | * w = menubuttonWidget |
---|
1393 | * client_data = pointer to menu button's MenuItem structure |
---|
1394 | * call_data = not used |
---|
1395 | * wmGD.menuClient = pointer to client's ClientData structure |
---|
1396 | * |
---|
1397 | * |
---|
1398 | * Outputs: |
---|
1399 | * ------- |
---|
1400 | * None. |
---|
1401 | * |
---|
1402 | * |
---|
1403 | * Comments: |
---|
1404 | * -------- |
---|
1405 | * None. |
---|
1406 | * |
---|
1407 | *************************************<->***********************************/ |
---|
1408 | |
---|
1409 | #ifdef _NO_PROTO |
---|
1410 | void ActivateCallback (w, client_data, call_data) |
---|
1411 | |
---|
1412 | Widget w; |
---|
1413 | XtPointer client_data; |
---|
1414 | XtPointer call_data; |
---|
1415 | #else /* _NO_PROTO */ |
---|
1416 | void ActivateCallback (Widget w, XtPointer client_data, XtPointer call_data) |
---|
1417 | #endif /* _NO_PROTO */ |
---|
1418 | { |
---|
1419 | ((MenuItem *)client_data)->wmFunction ( |
---|
1420 | ((MenuItem *)client_data)->wmFuncArgs, wmGD.menuClient, NULL); |
---|
1421 | |
---|
1422 | } /* END OF FUNCTION ActivateCallback */ |
---|
1423 | |
---|
1424 | |
---|
1425 | |
---|
1426 | /*************************************<->************************************* |
---|
1427 | * |
---|
1428 | * UnmapCallback (w, client_data, call_data) |
---|
1429 | * |
---|
1430 | * |
---|
1431 | * Description: |
---|
1432 | * ----------- |
---|
1433 | * This function is called whenever a toplevel RowColumn is unmapped. |
---|
1434 | * |
---|
1435 | * |
---|
1436 | * Inputs: |
---|
1437 | * ------ |
---|
1438 | * w = |
---|
1439 | * client_data = not used |
---|
1440 | * call_data = not used |
---|
1441 | * wmGD.gadgetClient = last client with depressed client |
---|
1442 | * |
---|
1443 | * |
---|
1444 | * Outputs: |
---|
1445 | * ------- |
---|
1446 | * wmGD.menuActive = NULL |
---|
1447 | * wmGD.menuUnpostKeySpec = NULL |
---|
1448 | * wmGD.checkHotspot = FALSE |
---|
1449 | * |
---|
1450 | * |
---|
1451 | * Comments: |
---|
1452 | * -------- |
---|
1453 | * None. |
---|
1454 | * |
---|
1455 | *************************************<->***********************************/ |
---|
1456 | |
---|
1457 | #ifdef _NO_PROTO |
---|
1458 | void UnmapCallback (w, client_data, call_data) |
---|
1459 | |
---|
1460 | Widget w; |
---|
1461 | XtPointer client_data; |
---|
1462 | XtPointer call_data; |
---|
1463 | #else /* _NO_PROTO */ |
---|
1464 | void UnmapCallback (Widget w, XtPointer client_data, XtPointer call_data) |
---|
1465 | #endif /* _NO_PROTO */ |
---|
1466 | { |
---|
1467 | wmGD.menuActive = NULL; |
---|
1468 | wmGD.menuUnpostKeySpec = NULL; |
---|
1469 | wmGD.checkHotspot = FALSE; |
---|
1470 | |
---|
1471 | if (wmGD.gadgetClient) |
---|
1472 | { |
---|
1473 | PopGadgetOut(wmGD.gadgetClient, FRAME_SYSTEM); |
---|
1474 | } |
---|
1475 | |
---|
1476 | #ifndef OLD_COLORMAP |
---|
1477 | ForceColormapFocus (ACTIVE_PSD, ACTIVE_PSD->colormapFocus); |
---|
1478 | #endif |
---|
1479 | PullExposureEvents(); |
---|
1480 | |
---|
1481 | } /* END OF FUNCTION UnmapCallback */ |
---|
1482 | |
---|
1483 | |
---|
1484 | /*************************************<->************************************* |
---|
1485 | * |
---|
1486 | * MWarning (message) |
---|
1487 | * |
---|
1488 | * |
---|
1489 | * Description: |
---|
1490 | * ----------- |
---|
1491 | * This function lists a message to stderr. |
---|
1492 | * |
---|
1493 | * |
---|
1494 | * Inputs: |
---|
1495 | * ------ |
---|
1496 | * format = pointer to a format string |
---|
1497 | * message = pointer to a message string |
---|
1498 | * |
---|
1499 | *************************************<->***********************************/ |
---|
1500 | |
---|
1501 | #ifdef _NO_PROTO |
---|
1502 | void MWarning (format, message) |
---|
1503 | |
---|
1504 | char *format; |
---|
1505 | char *message; |
---|
1506 | #else /* _NO_PROTO */ |
---|
1507 | void MWarning (char *format, char *message) |
---|
1508 | #endif /* _NO_PROTO */ |
---|
1509 | { |
---|
1510 | #define MAXPATH 1023 |
---|
1511 | |
---|
1512 | if (strlen(format) + strlen(message) < MAXPATH) |
---|
1513 | { |
---|
1514 | char pch[MAXPATH+1]; |
---|
1515 | |
---|
1516 | sprintf (pch, format, message); |
---|
1517 | Warning (pch); |
---|
1518 | } |
---|
1519 | |
---|
1520 | } /* END OF FUNCTION MWarning */ |
---|
1521 | |
---|
1522 | |
---|
1523 | |
---|
1524 | /*************************************<->************************************* |
---|
1525 | * |
---|
1526 | * TraversalOff (menuSpec) |
---|
1527 | * |
---|
1528 | * |
---|
1529 | * Description: |
---|
1530 | * ----------- |
---|
1531 | * This function turns menu traversal off. |
---|
1532 | * |
---|
1533 | * |
---|
1534 | * Inputs: |
---|
1535 | * ------ |
---|
1536 | * menuSpec = menu specification |
---|
1537 | * |
---|
1538 | * |
---|
1539 | * Outputs: |
---|
1540 | * ------- |
---|
1541 | * None. |
---|
1542 | * |
---|
1543 | * |
---|
1544 | * Comments: |
---|
1545 | * -------- |
---|
1546 | * None. |
---|
1547 | * |
---|
1548 | *************************************<->***********************************/ |
---|
1549 | |
---|
1550 | #ifdef _NO_PROTO |
---|
1551 | void TraversalOff (menuSpec) |
---|
1552 | |
---|
1553 | MenuSpec *menuSpec; |
---|
1554 | #else /* _NO_PROTO */ |
---|
1555 | void TraversalOff (MenuSpec *menuSpec) |
---|
1556 | #endif /* _NO_PROTO */ |
---|
1557 | { |
---|
1558 | if (menuSpec && (menuSpec->menuWidget)) |
---|
1559 | { |
---|
1560 | /* function pointer */ |
---|
1561 | (*((XmRowColumnWidgetClass) XtClass (menuSpec->menuWidget)) |
---|
1562 | ->row_column_class.menuProcedures) |
---|
1563 | /* argument list */ |
---|
1564 | (XmMENU_TRAVERSAL, menuSpec->menuWidget, False, NULL, NULL); |
---|
1565 | } |
---|
1566 | |
---|
1567 | } /* END OF FUNCTION TraversalOff */ |
---|
1568 | |
---|
1569 | |
---|
1570 | |
---|
1571 | /*************************************<->************************************* |
---|
1572 | * |
---|
1573 | * TraversalOn (menuSpec) |
---|
1574 | * |
---|
1575 | * |
---|
1576 | * Description: |
---|
1577 | * ----------- |
---|
1578 | * This function turns menu traversal on. |
---|
1579 | * |
---|
1580 | * |
---|
1581 | * Inputs: |
---|
1582 | * ------ |
---|
1583 | * menuSpec = menu specification |
---|
1584 | * |
---|
1585 | * |
---|
1586 | * Outputs: |
---|
1587 | * ------- |
---|
1588 | * None. |
---|
1589 | * |
---|
1590 | * |
---|
1591 | * Comments: |
---|
1592 | * -------- |
---|
1593 | * None. |
---|
1594 | * |
---|
1595 | *************************************<->***********************************/ |
---|
1596 | |
---|
1597 | #ifdef _NO_PROTO |
---|
1598 | void TraversalOn (menuSpec) |
---|
1599 | |
---|
1600 | MenuSpec *menuSpec; |
---|
1601 | #else /* _NO_PROTO */ |
---|
1602 | void TraversalOn (MenuSpec *menuSpec) |
---|
1603 | #endif /* _NO_PROTO */ |
---|
1604 | { |
---|
1605 | |
---|
1606 | if (menuSpec && (menuSpec->menuWidget)) |
---|
1607 | { |
---|
1608 | /* function pointer */ |
---|
1609 | (*((XmRowColumnWidgetClass) XtClass (menuSpec->menuWidget)) |
---|
1610 | ->row_column_class.menuProcedures) |
---|
1611 | /*argument list */ |
---|
1612 | (XmMENU_TRAVERSAL, menuSpec->menuWidget, True, NULL, NULL); |
---|
1613 | } |
---|
1614 | |
---|
1615 | } /* END OF FUNCTION TraversalOn */ |
---|
1616 | |
---|
1617 | |
---|
1618 | |
---|
1619 | /*************************************<->************************************* |
---|
1620 | * |
---|
1621 | * FreeCustomMenuSpec (menuSpec) |
---|
1622 | * |
---|
1623 | * |
---|
1624 | * Description: |
---|
1625 | * ----------- |
---|
1626 | * This procedure destroys a custom MenuSpec structure and its associated |
---|
1627 | * menu widget, menuItems list, menuButtons array, and menu accelerator list. |
---|
1628 | * |
---|
1629 | * |
---|
1630 | * Inputs: |
---|
1631 | * ------ |
---|
1632 | * menuSpec = MenuSpec structure |
---|
1633 | * |
---|
1634 | * |
---|
1635 | * Outputs: |
---|
1636 | * ------- |
---|
1637 | * None. |
---|
1638 | * |
---|
1639 | * |
---|
1640 | * Comments: |
---|
1641 | * -------- |
---|
1642 | * Assumes that a MenuSpec is custom iff its name is NULL. |
---|
1643 | * |
---|
1644 | * Assumes that ParseWmFuncStr() has parsed a menu item's function |
---|
1645 | * argument only for F_Exec and F_Menu. If it is used for other functions, |
---|
1646 | * be sure to include them here! |
---|
1647 | * |
---|
1648 | *************************************<->***********************************/ |
---|
1649 | |
---|
1650 | #ifdef _NO_PROTO |
---|
1651 | void FreeCustomMenuSpec (menuSpec) |
---|
1652 | |
---|
1653 | MenuSpec *menuSpec; |
---|
1654 | #else /* _NO_PROTO */ |
---|
1655 | void FreeCustomMenuSpec (MenuSpec *menuSpec) |
---|
1656 | #endif /* _NO_PROTO */ |
---|
1657 | { |
---|
1658 | MenuItem *menuItem; |
---|
1659 | MenuItem *nextMenuItem; |
---|
1660 | KeySpec *accelKeySpec; |
---|
1661 | KeySpec *nextAccelKeySpec; |
---|
1662 | |
---|
1663 | if ((menuSpec == NULL) || (menuSpec->name != NULL)) |
---|
1664 | /* we only destroy custom menus! */ |
---|
1665 | { |
---|
1666 | return; |
---|
1667 | } |
---|
1668 | |
---|
1669 | /* |
---|
1670 | * Fix for CR 5450 - If the custom menu is the same as wmGD.menuActive, call |
---|
1671 | * the UnmapCallback directly to clean things up. Since |
---|
1672 | * the menu is going to be destroyed, this callback will |
---|
1673 | * not get called, leaving MWM in a failure state. |
---|
1674 | */ |
---|
1675 | if (wmGD.menuActive == menuSpec) |
---|
1676 | UnmapCallback((Widget)NULL, (caddr_t)NULL, (caddr_t)NULL); |
---|
1677 | /* |
---|
1678 | * End fix for CR 5450 |
---|
1679 | */ |
---|
1680 | |
---|
1681 | menuItem = menuSpec->menuItems; |
---|
1682 | while (menuItem) |
---|
1683 | { |
---|
1684 | nextMenuItem = menuItem->nextMenuItem; |
---|
1685 | FreeMenuItem (menuItem); |
---|
1686 | menuItem = nextMenuItem; |
---|
1687 | } |
---|
1688 | |
---|
1689 | if (menuSpec->menuButtons) |
---|
1690 | { |
---|
1691 | XtFree ((char *)menuSpec->menuButtons); |
---|
1692 | } |
---|
1693 | |
---|
1694 | accelKeySpec = menuSpec->accelKeySpecs; |
---|
1695 | while (accelKeySpec) |
---|
1696 | { |
---|
1697 | nextAccelKeySpec = accelKeySpec->nextKeySpec; |
---|
1698 | XtFree ((char *)accelKeySpec); |
---|
1699 | accelKeySpec = nextAccelKeySpec; |
---|
1700 | } |
---|
1701 | |
---|
1702 | if (menuSpec->menuWidget) |
---|
1703 | /* destroy all children of the menu's MenuShell parent */ |
---|
1704 | { |
---|
1705 | XtDestroyWidget (XtParent(menuSpec->menuWidget)); |
---|
1706 | } |
---|
1707 | |
---|
1708 | XtFree ((char *)menuSpec); |
---|
1709 | |
---|
1710 | } /* END OF FUNCTION FreeCustomMenuSpec */ |
---|
1711 | |
---|
1712 | |
---|
1713 | #ifdef AUTOMATION |
---|
1714 | #ifdef _NO_PROTO |
---|
1715 | static void SetMwmMenuInfo (pCD, menuSpec) |
---|
1716 | ClientData *pCD; |
---|
1717 | MenuSpec *menuSpec; |
---|
1718 | |
---|
1719 | #else |
---|
1720 | static void SetMwmMenuInfo (ClientData *pCD, MenuSpec *menuSpec) |
---|
1721 | #endif /* _NO_PROTO */ |
---|
1722 | { |
---|
1723 | |
---|
1724 | PropMwmFrameIconInfo FrameIconProp; |
---|
1725 | char *RetData; |
---|
1726 | Atom FrameIconAtom, NewType; |
---|
1727 | int NewFormat; |
---|
1728 | unsigned long NewNitems, NewBytesAfter; |
---|
1729 | int SensitiveCount; |
---|
1730 | MenuInfo *NewMenuInfo; |
---|
1731 | MenuButton *NewMenuButton; |
---|
1732 | MenuItem *NewMenuItem; |
---|
1733 | unsigned int n; |
---|
1734 | int status; |
---|
1735 | |
---|
1736 | |
---|
1737 | RetData = NULL; |
---|
1738 | |
---|
1739 | if (pCD == NULL || menuSpec == NULL) |
---|
1740 | return; |
---|
1741 | |
---|
1742 | FrameIconAtom = XmInternAtom(DISPLAY, _XA_MOTIF_WM_FRAME_ICON_INFO, False); |
---|
1743 | status = XGetWindowProperty(DISPLAY, pCD->client, FrameIconAtom, 0L, |
---|
1744 | PROP_MWM_FRAME_ICON_INFO_ELEMENTS, False, |
---|
1745 | AnyPropertyType, &NewType, &NewFormat, |
---|
1746 | &NewNitems, &NewBytesAfter, |
---|
1747 | (unsigned char **)&RetData); |
---|
1748 | if (status != Success || RetData == NULL) |
---|
1749 | { |
---|
1750 | /* Need a warning here; waiting for general warning handling code */ |
---|
1751 | return; |
---|
1752 | } |
---|
1753 | |
---|
1754 | bcopy((char *)RetData, (char *)&FrameIconProp, |
---|
1755 | PROP_MWM_FRAME_ICON_INFO_ELEMENTS); |
---|
1756 | /* Swap bytes if necessary */ |
---|
1757 | AutoSwapBytes(&FrameIconProp); |
---|
1758 | |
---|
1759 | FrameIconProp.menuItemCount = 0; |
---|
1760 | FrameIconProp.sensitiveItemCount = 0; |
---|
1761 | |
---|
1762 | FrameIconProp.menuItemCount = menuSpec->menuButtonCount; |
---|
1763 | NewMenuInfo = &FrameIconProp.windowMenu[0]; |
---|
1764 | for (n = 0; n < FrameIconProp.menuItemCount; n++) |
---|
1765 | { |
---|
1766 | |
---|
1767 | NewMenuInfo->item_name[0] = '\0'; |
---|
1768 | NewMenuInfo->sensitive = FALSE; |
---|
1769 | NewMenuInfo++; |
---|
1770 | |
---|
1771 | } |
---|
1772 | |
---|
1773 | NewMenuInfo = &FrameIconProp.windowMenu[0]; |
---|
1774 | SensitiveCount = 0; |
---|
1775 | |
---|
1776 | for (n = 0, NewMenuButton = menuSpec->menuButtons; |
---|
1777 | n < menuSpec->menuButtonCount; |
---|
1778 | n++, NewMenuButton++) |
---|
1779 | { |
---|
1780 | |
---|
1781 | if (NewMenuButton->managed == FALSE) |
---|
1782 | continue; |
---|
1783 | |
---|
1784 | NewMenuItem = NewMenuButton->menuItem; |
---|
1785 | strcpy(NewMenuInfo->item_name, NewMenuItem->label); |
---|
1786 | NewMenuInfo->sensitive = NewMenuButton->buttonWidget->core.sensitive; |
---|
1787 | NewMenuInfo->item_y = NewMenuButton->buttonWidget->core.y + |
---|
1788 | (NewMenuButton->buttonWidget->core.height / 2); |
---|
1789 | if (NewMenuInfo->sensitive == TRUE) |
---|
1790 | SensitiveCount++; |
---|
1791 | NewMenuInfo++; |
---|
1792 | |
---|
1793 | } |
---|
1794 | |
---|
1795 | FrameIconProp.byte_order = AutoByteOrderChar; |
---|
1796 | FrameIconProp.sensitiveItemCount = SensitiveCount; |
---|
1797 | XChangeProperty(DISPLAY, pCD->client, wmGD.xa_MWM_FRAME_ICON_INFO, |
---|
1798 | wmGD.xa_MWM_FRAME_ICON_INFO, 8, PropModeReplace, |
---|
1799 | (unsigned char *)&FrameIconProp, |
---|
1800 | PROP_MWM_FRAME_ICON_INFO_ELEMENTS); |
---|
1801 | XSync(DISPLAY, False); |
---|
1802 | |
---|
1803 | if (RetData != NULL) |
---|
1804 | XFree((char *)RetData); |
---|
1805 | |
---|
1806 | } /* SetMwmMenuInfo */ |
---|
1807 | |
---|
1808 | |
---|
1809 | #ifdef _NO_PROTO |
---|
1810 | static void SetMwmMenuWindow (pCD, menuWidget) |
---|
1811 | ClientData *pCD; |
---|
1812 | Widget menuWidget; |
---|
1813 | |
---|
1814 | #else |
---|
1815 | static void SetMwmMenuWindow (ClientData *pCD, Widget menuWidget) |
---|
1816 | #endif /* _NO_PROTO */ |
---|
1817 | { |
---|
1818 | |
---|
1819 | PropMwmFrameIconInfo FrameIconProp; |
---|
1820 | char *RetData; |
---|
1821 | Atom FrameIconAtom, NewType; |
---|
1822 | int NewFormat; |
---|
1823 | unsigned long NewNitems, NewBytesAfter; |
---|
1824 | Window MenuWin; |
---|
1825 | int status; |
---|
1826 | |
---|
1827 | if (pCD == NULL) |
---|
1828 | return; |
---|
1829 | |
---|
1830 | MenuWin = XtWindow(menuWidget); |
---|
1831 | |
---|
1832 | FrameIconAtom = XmInternAtom(DISPLAY, _XA_MOTIF_WM_FRAME_ICON_INFO, False); |
---|
1833 | status = XGetWindowProperty(DISPLAY, pCD->client, FrameIconAtom, 0L, |
---|
1834 | PROP_MWM_FRAME_ICON_INFO_ELEMENTS, False, |
---|
1835 | AnyPropertyType, &NewType, &NewFormat, |
---|
1836 | &NewNitems, &NewBytesAfter, |
---|
1837 | (unsigned char **)&RetData); |
---|
1838 | if (status != Success || RetData == NULL) |
---|
1839 | { |
---|
1840 | /* Need a warning here; waiting for general warning handling code */ |
---|
1841 | return; |
---|
1842 | } |
---|
1843 | |
---|
1844 | bcopy((char *)RetData, (char *)&FrameIconProp, |
---|
1845 | PROP_MWM_FRAME_ICON_INFO_ELEMENTS); |
---|
1846 | /* Swap bytes if necessary */ |
---|
1847 | AutoSwapBytes(&FrameIconProp); |
---|
1848 | |
---|
1849 | FrameIconProp.byte_order = AutoByteOrderChar; |
---|
1850 | FrameIconProp.menuWin = MenuWin; |
---|
1851 | XChangeProperty(DISPLAY, pCD->client, wmGD.xa_MWM_FRAME_ICON_INFO, |
---|
1852 | wmGD.xa_MWM_FRAME_ICON_INFO, 8, PropModeReplace, |
---|
1853 | (unsigned char *)&FrameIconProp, |
---|
1854 | PROP_MWM_FRAME_ICON_INFO_ELEMENTS); |
---|
1855 | XSync(DISPLAY, False); |
---|
1856 | |
---|
1857 | if (RetData != NULL) |
---|
1858 | XFree((char *)RetData); |
---|
1859 | |
---|
1860 | return; |
---|
1861 | |
---|
1862 | } /* SetMwmMenuWindow */ |
---|
1863 | |
---|
1864 | #endif /* AUTOMATION */ |
---|