1 /*************************************<+>*************************************
2 *****************************************************************************
8 ** Description: Menu Manager Meta Class Widget
10 *****************************************************************************
12 ** Copyright (c) 1988 by Hewlett-Packard Company
13 ** Copyright (c) 1988 by the Massachusetts Institute of Technology
15 ** Permission to use, copy, modify, and distribute this software
16 ** and its documentation for any purpose and without fee is hereby
17 ** granted, provided that the above copyright notice appear in all
18 ** copies and that both that copyright notice and this permission
19 ** notice appear in supporting documentation, and that the names of
20 ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
21 ** pertaining to distribution of the software without specific, written
24 *****************************************************************************
25 *************************************<+>*************************************/
28 #include <X11/IntrinsicP.h>
29 #include <X11/Xutil.h>
30 #include <X11/StringDefs.h>
31 #include <X11/Xatom.h>
35 static void Initialize();
36 static void Destroy();
37 static Boolean
SetValues();
38 static void ClassInitialize();
41 /****************************************************************
45 ****************************************************************/
47 static XtResource resources
[] = {
48 {XtNassociateChildren
, XtCAssociateChildren
, XtRBoolean
, sizeof(Boolean
),
49 XtOffset(XwMenuMgrWidget
, menu_mgr
.associateChildren
), XtRString
,
52 {XtNmenuPost
, XtCMenuPost
, XtRString
, sizeof(String
),
53 XtOffset(XwMenuMgrWidget
, menu_mgr
.postString
), XtRString
,
56 {XtNmenuSelect
, XtCMenuSelect
, XtRString
, sizeof(String
),
57 XtOffset(XwMenuMgrWidget
, menu_mgr
.selectString
), XtRString
,
60 {XtNmenuUnpost
, XtCMenuUnpost
, XtRString
, sizeof(String
),
61 XtOffset(XwMenuMgrWidget
, menu_mgr
.unpostString
), XtRString
,
64 {XtNkbdSelect
, XtCKbdSelect
, XtRString
, sizeof(String
),
65 XtOffset(XwMenuMgrWidget
, menu_mgr
.kbdSelectString
), XtRString
,
70 /****************************************************************
72 * Full class record constant
74 ****************************************************************/
76 XwMenuMgrClassRec XwmenumgrClassRec
= {
78 /* core_class fields */
79 /* superclass */ (WidgetClass
) &XwmanagerClassRec
,
80 /* class_name */ "XwMenuMgr",
81 /* widget_size */ sizeof(XwMenuMgrRec
),
82 /* class_initialize */ ClassInitialize
,
83 /* class_part_init */ NULL
,
84 /* class_inited */ FALSE
,
85 /* initialize */ Initialize
,
86 /* initialize_hook */ NULL
,
90 /* resources */ resources
,
91 /* num_resources */ XtNumber(resources
),
92 /* xrm_class */ NULLQUARK
,
93 /* compress_motion */ TRUE
,
94 /* compress_exposure */ TRUE
,
95 /* compress_enterlv */ TRUE
,
96 /* visible_interest */ FALSE
,
97 /* destroy */ Destroy
,
100 /* set_values */ SetValues
,
101 /* set_values_hook */ NULL
,
102 /* set_values_almost */ XtInheritSetValuesAlmost
,
103 /* get_values_hook */ NULL
,
104 /* accept_focus */ NULL
,
105 /* version */ XtVersion
,
106 /* PRIVATE cb list */ NULL
,
108 /* query_geometry */ NULL
,
109 /* display_accelerator */ XtInheritDisplayAccelerator
,
112 /* composite_class fields */
113 /* geometry_manager */ NULL
,
114 /* change_managed */ NULL
,
115 /* insert_child */ XtInheritInsertChild
,
116 /* delete_child */ XtInheritDeleteChild
,
119 /* constraint class fields */
120 /* resources */ NULL
,
121 /* num_resources */ 0,
122 /* constraint_size */ 0,
123 /* initialize */ NULL
,
125 /* set_values */ NULL
,
128 /* manager_class fields */
129 /* traversal handler */ NULL
,
130 /* translations */ NULL
,
132 /* menu manager class - none */
133 /* attachPane */ NULL
,
134 /* detachPane */ NULL
,
136 /* setSelectAccelerar */ NULL
,
137 /* clearSelectAcceler */ NULL
,
138 /* setPostMnemonic */ NULL
,
139 /* clearPostMnemonic */ NULL
,
140 /* addButton */ NULL
,
141 /* processSelect */ NULL
,
142 /* validEvent */ NULL
,
143 /* doICascade */ NULL
,
144 /* setSelectMnemonic */ NULL
,
145 /* clearSelectMnemon */ NULL
,
146 /* setTitleAttributes */ NULL
,
147 /* paneManagedChildren*/ NULL
,
148 /* traverseLeft */ NULL
,
149 /* traverseRight */ NULL
,
150 /* traverseNext */ NULL
,
151 /* traversePrev */ NULL
,
152 /* traverseHome */ NULL
,
153 /* traverseUp */ NULL
,
154 /* traverseDown */ NULL
,
155 /* traverseNextTop */ NULL
,
156 /* btnSensitivityChan */ NULL
,
157 /* paneSensitivityCha */ NULL
,
161 WidgetClass XwmenumgrWidgetClass
= (WidgetClass
)&XwmenumgrClassRec
;
164 /*************************************<->*************************************
166 * ClassInitialize(parameters)
170 * xxxxxxxxxxxxxxxxxxxxxxx
175 * xxxxxxxxxxxx = xxxxxxxxxxxxx
179 * xxxxxxxxxxxx = xxxxxxxxxxxxx
184 *************************************<->***********************************/
186 static void ClassInitialize ()
191 /*************************************<->*************************************
198 * Initialize the menu_mgr fields within the widget's instance structure.
203 * xxxxxxxxxxxx = xxxxxxxxxxxxx
207 * xxxxxxxxxxxx = xxxxxxxxxxxxx
212 *************************************<->***********************************/
214 static void Initialize (request
, new)
216 XwMenuMgrWidget request
, new;
221 /* FOR NOW, MENUS DO NOT UNDERSTAND TRAVERSAL */
222 /* new->manager.traversal_on = FALSE; */
225 * Save a copy of the posting event string, and also convert it
226 * into a form which can be compared against an X button event.
228 if ((new->menu_mgr
.postString
) &&
229 (strlen(new->menu_mgr
.postString
) > 0))
231 if (_XwMapBtnEvent (new->menu_mgr
.postString
,
232 &new->menu_mgr
.postEventType
,
233 &new->menu_mgr
.postButton
,
234 &new->menu_mgr
.postModifiers
) == FALSE
)
236 /* String was not valid; use the default one */
237 XtWarning("MenuMgr: Invalid post event; using <Btn1Down>");
238 new->menu_mgr
.postString
= (String
) strcpy (XtMalloc (XwStrlen
239 ("<Btn1Down>") + 1), "<Btn1Down>");
241 _XwMapBtnEvent ("<Btn1Down>",
242 &new->menu_mgr
.postEventType
,
243 &new->menu_mgr
.postButton
,
244 &new->menu_mgr
.postModifiers
);
248 /* String was valid */
249 new->menu_mgr
.postString
= (String
) strcpy (XtMalloc (XwStrlen
250 (new->menu_mgr
.postString
) + 1), new->menu_mgr
.postString
);
255 new->menu_mgr
.postString
= NULL
;
256 new->menu_mgr
.postModifiers
= 0;
257 new->menu_mgr
.postButton
= 0;
261 * Save a copy of the selecting event string, and also convert it
262 * into a form which can be compared against an X button event.
264 if ((new->menu_mgr
.selectString
) &&
265 (strlen(new->menu_mgr
.selectString
) > 0))
267 if (_XwMapBtnEvent (new->menu_mgr
.selectString
,
268 &new->menu_mgr
.selectEventType
,
269 &new->menu_mgr
.selectButton
,
270 &new->menu_mgr
.selectModifiers
) == FALSE
)
272 /* String was not valid; use the default one */
273 XtWarning("MenuMgr: Invalid select event; using <Btn1Up>");
274 new->menu_mgr
.selectString
= (String
) strcpy (XtMalloc (XwStrlen
275 ("<Btn1Up>") + 1), "<Btn1Up>");
277 _XwMapBtnEvent ("<Btn1Up>",
278 &new->menu_mgr
.selectEventType
,
279 &new->menu_mgr
.selectButton
,
280 &new->menu_mgr
.selectModifiers
);
284 /* String was valid */
285 new->menu_mgr
.selectString
= (String
) strcpy (XtMalloc (XwStrlen
286 (new->menu_mgr
.selectString
) + 1), new->menu_mgr
.selectString
);
291 new->menu_mgr
.selectString
= NULL
;
292 new->menu_mgr
.selectModifiers
= 0;
293 new->menu_mgr
.selectButton
= 0;
297 * Save a copy of the unposting event string, and also convert it
298 * into a form which can be compared against an X button event.
300 if ((new->menu_mgr
.unpostString
) &&
301 (strlen(new->menu_mgr
.unpostString
) > 0))
303 if (_XwMapKeyEvent (new->menu_mgr
.unpostString
,
304 &new->menu_mgr
.unpostEventType
,
306 &new->menu_mgr
.unpostModifiers
) == FALSE
)
308 /* String was not valid; use the default one */
309 XtWarning("MenuMgr: Invalid unpost event; disabling option");
310 new->menu_mgr
.unpostString
= NULL
;
314 /* String was valid */
315 new->menu_mgr
.unpostKey
= XKeysymToKeycode(XtDisplay(new),tempKeysym
);
316 new->menu_mgr
.unpostString
= (String
) strcpy (XtMalloc (XwStrlen
317 (new->menu_mgr
.unpostString
) + 1), new->menu_mgr
.unpostString
);
322 new->menu_mgr
.unpostString
= NULL
;
323 new->menu_mgr
.unpostModifiers
= 0;
324 new->menu_mgr
.unpostKey
= 0;
328 * Save a copy of the kbd select event string, and also convert it
329 * into a form which can be compared against an X key event.
331 if ((new->menu_mgr
.kbdSelectString
) &&
332 (strlen(new->menu_mgr
.kbdSelectString
) > 0))
334 if (_XwMapKeyEvent (new->menu_mgr
.kbdSelectString
,
335 &new->menu_mgr
.kbdSelectEventType
,
337 &new->menu_mgr
.kbdSelectModifiers
) == FALSE
)
339 /* String was not valid; use the default one */
340 XtWarning("MenuMgr: Invalid keyboard select event; using default");
341 new->menu_mgr
.kbdSelectString
= (String
) strcpy (XtMalloc (XwStrlen
342 ("<Key>Select") + 1), "<Key>Select");
344 _XwMapKeyEvent ("<Key>Select",
345 &new->menu_mgr
.kbdSelectEventType
,
346 &new->menu_mgr
.kbdSelectKey
,
347 &new->menu_mgr
.kbdSelectModifiers
);
351 /* String was valid */
352 new->menu_mgr
.kbdSelectKey
=
353 XKeysymToKeycode(XtDisplay(new),tempKeysym
);
354 new->menu_mgr
.kbdSelectString
= (String
) strcpy (XtMalloc (XwStrlen
355 (new->menu_mgr
.kbdSelectString
) + 1),
356 new->menu_mgr
.kbdSelectString
);
361 new->menu_mgr
.kbdSelectString
= NULL
;
362 new->menu_mgr
.kbdSelectModifiers
= 0;
363 new->menu_mgr
.kbdSelectKey
= 0;
367 /* Allocate space for each of the tables used by a menu manager */
368 new->menu_mgr
.menuBtnAccelTable
=
369 (XwKeyAccel
*) XtMalloc(100 * sizeof(XwKeyAccel
));
370 new->menu_mgr
.numAccels
= 0;
371 new->menu_mgr
.sizeAccelTable
= 100;
373 new->menu_mgr
.pendingAttachList
=
374 (XwAttachList
*) XtMalloc(25 * sizeof(XwAttachList
));
375 new->menu_mgr
.numAttachReqs
= 0;
376 new->menu_mgr
.sizeAttachList
= 25;
380 new->menu_mgr
.menuActive
= FALSE
;
384 /*************************************<->*************************************
391 * This procedure simply checks to see if the post or select specification
392 * has changed, and allocates space for the new string and frees up the
393 * old string. It will also map the new specification into a button/
396 * NOTE: When a new post or select string is specified, this routine will
397 * allocate space for the new string, but will NOT free up the old
398 * string; thus, our subclasses can check to see if these strings
399 * differ, and can remove any translations. It is then upto the
400 * subclass to free the old string and to modify any translations or
401 * button grabs which are associated with the post or select actions.
403 * It is also the responsibility of the subclass to check the state
404 * of the 'associate children' flag, and to modify any corresponding
405 * translations or grabs.
409 * xxxxxxxxxxxx = xxxxxxxxxxxxx
413 * xxxxxxxxxxxx = xxxxxxxxxxxxx
418 *************************************<->***********************************/
420 static Boolean
SetValues (current
, request
, new)
422 XwMenuMgrWidget current
, request
, new;
427 /* FOR NOW, MENUS DO NOT UNDERSTAND TRAVERSAL */
428 /* new->manager.traversal_on = FALSE; */
430 /* Handle the case of a changed posting string */
432 if (current
->menu_mgr
.postString
!= new->menu_mgr
.postString
)
434 /* Allocate a new buffer to hold the string */
435 if ((new->menu_mgr
.postString
) &&
436 (strlen(new->menu_mgr
.postString
) > 0))
438 if (_XwMapBtnEvent (new->menu_mgr
.postString
,
439 &new->menu_mgr
.postEventType
,
440 &new->menu_mgr
.postButton
,
441 &new->menu_mgr
.postModifiers
) == FALSE
)
443 /* Invalid post string; use the previous one */
444 XtWarning("MenuMgr: Invalid post event; using previous setting");
445 new->menu_mgr
.postString
= current
->menu_mgr
.postString
;
446 new->menu_mgr
.postEventType
= current
->menu_mgr
.postEventType
;
447 new->menu_mgr
.postButton
= current
->menu_mgr
.postButton
;
448 new->menu_mgr
.postModifiers
= current
->menu_mgr
.postModifiers
;
452 /* Valid post string */
453 new->menu_mgr
.postString
= (String
)
454 strcpy (XtMalloc (XwStrlen (new->menu_mgr
.postString
) + 1),
455 new->menu_mgr
.postString
);
460 new->menu_mgr
.postString
= NULL
;
461 new->menu_mgr
.postEventType
= 0;
462 new->menu_mgr
.postButton
= 0;
463 new->menu_mgr
.postModifiers
= 0;
467 * Don't free up the buffer holding the old post string.
468 * This is to be done by our subclass.
472 /* Handle the case of a changed select string */
474 if (current
->menu_mgr
.selectString
!= new->menu_mgr
.selectString
)
476 /* Allocate a new buffer to hold the string */
477 if ((new->menu_mgr
.selectString
) &&
478 (strlen(new->menu_mgr
.selectString
) > 0))
480 if (_XwMapBtnEvent (new->menu_mgr
.selectString
,
481 &new->menu_mgr
.selectEventType
,
482 &new->menu_mgr
.selectButton
,
483 &new->menu_mgr
.selectModifiers
) == FALSE
)
485 /* Invalid select string; use the previous one */
486 XtWarning("MenuMgr: Invalid select event; using previous setting");
487 new->menu_mgr
.selectString
= current
->menu_mgr
.selectString
;
488 new->menu_mgr
.selectEventType
= current
->menu_mgr
.selectEventType
;
489 new->menu_mgr
.selectButton
= current
->menu_mgr
.selectButton
;
490 new->menu_mgr
.selectModifiers
= current
->menu_mgr
.selectModifiers
;
494 /* Valid select string */
495 new->menu_mgr
.selectString
= (String
)
496 strcpy (XtMalloc (XwStrlen (new->menu_mgr
.selectString
) + 1),
497 new->menu_mgr
.selectString
);
502 new->menu_mgr
.selectString
= NULL
;
503 new->menu_mgr
.selectEventType
= 0;
504 new->menu_mgr
.selectButton
= 0;
505 new->menu_mgr
.selectModifiers
= 0;
509 * Don't free up the buffer holding the old select string.
510 * This is to be done by our subclass.
514 /* Handle the case of a changed unposting string */
516 if (current
->menu_mgr
.unpostString
!= new->menu_mgr
.unpostString
)
518 /* Allocate a new buffer to hold the string */
519 if ((new->menu_mgr
.unpostString
) &&
520 (strlen(new->menu_mgr
.unpostString
) > 0))
522 if (_XwMapKeyEvent (new->menu_mgr
.unpostString
,
523 &new->menu_mgr
.unpostEventType
,
525 &new->menu_mgr
.unpostModifiers
) == FALSE
)
527 /* Invalid unpost string; use the previous one */
528 XtWarning("MenuMgr: Invalid unpost event; using previous setting");
529 new->menu_mgr
.unpostString
= current
->menu_mgr
.unpostString
;
530 new->menu_mgr
.unpostEventType
= current
->menu_mgr
.unpostEventType
;
531 new->menu_mgr
.unpostKey
= current
->menu_mgr
.unpostKey
;
532 new->menu_mgr
.unpostModifiers
= current
->menu_mgr
.unpostModifiers
;
536 /* Valid unpost string */
537 new->menu_mgr
.unpostKey
= XKeysymToKeycode(XtDisplay(new),
539 new->menu_mgr
.unpostString
= (String
)
540 strcpy (XtMalloc (XwStrlen (new->menu_mgr
.unpostString
) + 1),
541 new->menu_mgr
.unpostString
);
546 new->menu_mgr
.unpostString
= NULL
;
547 new->menu_mgr
.unpostEventType
= 0;
548 new->menu_mgr
.unpostKey
= 0;
549 new->menu_mgr
.unpostModifiers
= 0;
553 * Don't free up the buffer holding the old unpost string.
554 * This is to be done by our subclass.
558 /* Handle the case of a changed kbd select string */
560 if (current
->menu_mgr
.kbdSelectString
!= new->menu_mgr
.kbdSelectString
)
562 /* Allocate a new buffer to hold the string */
563 if ((new->menu_mgr
.kbdSelectString
) &&
564 (strlen(new->menu_mgr
.kbdSelectString
) > 0))
566 if (_XwMapKeyEvent (new->menu_mgr
.kbdSelectString
,
567 &new->menu_mgr
.kbdSelectEventType
,
569 &new->menu_mgr
.kbdSelectModifiers
) == FALSE
)
571 /* Invalid kbd select string; use the previous one */
573 ("MenuMgr: Invalid keyboard select event; using previous setting");
574 new->menu_mgr
.kbdSelectString
= current
->menu_mgr
.kbdSelectString
;
575 new->menu_mgr
.kbdSelectEventType
=
576 current
->menu_mgr
.kbdSelectEventType
;
577 new->menu_mgr
.kbdSelectKey
= current
->menu_mgr
.kbdSelectKey
;
578 new->menu_mgr
.kbdSelectModifiers
=
579 current
->menu_mgr
.kbdSelectModifiers
;
583 /* Valid kbd select string */
584 new->menu_mgr
.kbdSelectKey
= XKeysymToKeycode(XtDisplay(new),
586 new->menu_mgr
.kbdSelectString
= (String
)
587 strcpy (XtMalloc (XwStrlen (new->menu_mgr
.kbdSelectString
) + 1),
588 new->menu_mgr
.kbdSelectString
);
593 new->menu_mgr
.kbdSelectString
= NULL
;
594 new->menu_mgr
.kbdSelectEventType
= 0;
595 new->menu_mgr
.kbdSelectKey
= 0;
596 new->menu_mgr
.kbdSelectModifiers
= 0;
600 * Don't free up the buffer holding the old kbd select string.
601 * This is to be done by our subclass.
609 /*************************************<->*************************************
619 * xxxxxxxxxxxx = xxxxxxxxxxxxx
623 * xxxxxxxxxxxx = xxxxxxxxxxxxx
628 *************************************<->***********************************/
630 static void Destroy (mw
)
635 /* Free up our resources */
637 if (mw
->menu_mgr
.postString
)
638 XtFree (mw
->menu_mgr
.postString
);
640 if (mw
->menu_mgr
.selectString
)
641 XtFree (mw
->menu_mgr
.selectString
);
643 if (mw
->menu_mgr
.unpostString
)
644 XtFree (mw
->menu_mgr
.unpostString
);
646 if (mw
->menu_mgr
.kbdSelectString
)
647 XtFree (mw
->menu_mgr
.kbdSelectString
);
649 XtFree ((char *)(mw
->menu_mgr
.menuBtnAccelTable
));
650 XtFree ((char *)(mw
->menu_mgr
.pendingAttachList
));