1 /*************************************<+>*************************************
2 *****************************************************************************
3 **
4 ** File: MenuBtn.c
5 **
6 ** Project: X Widgets
7 **
8 ** Description: Contains code for primitive widget class: MenuButton
9 **
10 *****************************************************************************
11 **
12 ** Copyright (c) 1988 by Hewlett-Packard Company
13 ** Copyright (c) 1988 by the Massachusetts Institute of Technology
14 **
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
22 ** prior permission.
23 **
24 *****************************************************************************
25 *************************************<+>*************************************/
26
27 /*
28 *#define DEBUG TRUE
29 */
30 #undef NLS16
31
32 /*
33 * Include files & Static Routine Definitions
34 */
35 #include <string.h>
36 #include <X11/IntrinsicP.h>
37 #include <X11/StringDefs.h>
38 #include <X11/keysymdef.h>
39 #include <X11/Xatom.h>
40 #include <X11/Shell.h>
41 #include <Xw/Xw.h>
42 #include <Xw/XwP.h>
43 #include <Xw/MenuBtnP.h>
44 #include <Xw/MenuBtn.h>
45
46 #ifdef NLS16
47 #include <X11/XHPlib.h>
48 #endif
49
50 #ifndef XtRWidget
51 #define XtRWidget XtRPointer
52 #endif
53
54 static void Redisplay();
55 static Boolean SetValues();
56 static void ClassPartInitialize();
57 static void Inverted();
58 static void NonInverted();
59 static void Select();
60 static void Enter();
61 static void Leave();
62 static void Moved();
63 static void Initialize();
64 static void Destroy();
65 static void Realize();
66 static void Resize();
67 static void IdealWidth();
68 static void Unhighlight();
69 static void Highlight();
70 static void SetCascadeEnabled();
71 static void ClearCascadeEnabled();
72 static void EnterParentsWindow();
73 static void SetTraversalType();
74 static void TraverseLeft();
75 static void TraverseRight();
76 static void TraverseNext();
77 static void TraversePrev();
78 static void TraverseHome();
79 static void TraverseUp();
80 static void TraverseDown();
81 static void TraverseNextTop();
82 static void Unmap();
83 static void Visibility();
84 Boolean _XwUniqueEvent();
85
86 /*************************************<->*************************************
87 *
88 *
89 * Description: default translation table for class: MenuButton
90 * -----------
91 *
92 * Matches events with string descriptors for internal routines.
93 *
94 *************************************<->***********************************/
95
96
97 static char defaultTranslations[] =
98 "<Btn1Down>: select()\n\
99 <Visible>: visibility()\n\
100 <Unmap>: unmap()\n\
101 <EnterWindow>: enter()\n\
102 <LeaveWindow>: leave()\n\
103 <Motion>: moved()\n\
104 <Key>Select: select()\n\
105 <Key>Left: traverseLeft()\n\
106 <Key>Up: traverseUp()\n\
107 <Key>Right: traverseRight()\n\
108 <Key>Down: traverseDown()\n\
109 <Key>Prior: traversePrev()\n\
110 <Key>Next: traverseNext()\n\
111 <Key>KP_Enter: traverseNextTop()\n\
112 <Key>Home: traverseHome()";
113
114
115
116 /*************************************<->*************************************
117 *
118 *
119 * Description: action list for class: MenuButton
120 * -----------
121 *
122 * Matches string descriptors with internal routines.
123 *
124 *************************************<->***********************************/
125
126 static XtActionsRec actionsList[] =
127 {
128 {"select", (XtActionProc) Select},
129 {"visibility", (XtActionProc) Visibility},
130 {"unmap", (XtActionProc) Unmap},
131 {"enter", (XtActionProc) Enter},
132 {"leave", (XtActionProc) Leave},
133 {"moved", (XtActionProc) Moved},
134 {"traverseLeft", (XtActionProc) TraverseLeft },
135 {"traverseRight", (XtActionProc) TraverseRight },
136 {"traverseNext", (XtActionProc) TraverseNext },
137 {"traversePrev", (XtActionProc) TraversePrev },
138 {"traverseHome", (XtActionProc) TraverseHome },
139 {"traverseUp", (XtActionProc) TraverseUp },
140 {"traverseDown", (XtActionProc) TraverseDown },
141 {"traverseNextTop", (XtActionProc) TraverseNextTop },
142 };
143
144 /*************************************<->*************************************
145 *
146 *
147 * Description: resource list for class: MenuButton
148 * -----------
149 *
150 * Provides default resource settings for instances of this class.
151 * To get full set of default settings, examine resouce list of super
152 * classes of this class.
153 *
154 *************************************<->***********************************/
155
156 static XtResource resources[] =
157 {
158 {
159 XtNborderWidth, XtCBorderWidth,XtRDimension, sizeof(Dimension),
160 XtOffset(XwMenuButtonWidget, core.border_width),
161 XtRString, "0"
162 },
163
164 {
165 XtNlabelType, XtCLabelType, XtRLabelType, sizeof(int),
166 XtOffset(XwMenuButtonWidget, menubutton.labelType),
167 XtRString, "string"
168 },
169
170 {
171 XtNlabelImage, XtCLabelImage, XtRImage, sizeof(XImage *),
172 XtOffset(XwMenuButtonWidget, menubutton.labelImage),
173 XtRImage, NULL
174 },
175
176 {
177 XtNrectColor, XtCRectColor, XtRPixel, sizeof(Pixel),
178 XtOffset(XwMenuButtonWidget, menubutton.rectColor),
179 XtRString, "white"
180 },
181
182 {
183 XtNrectStipple, XtCRectStipple, XtRPixmap, sizeof(Pixmap),
184 XtOffset(XwMenuButtonWidget, menubutton.rectStipple),
185 XtRPixmap, NULL
186 },
187
188 {
189 XtNcascadeImage, XtCCascadeImage, XtRImage, sizeof(XImage *),
190 XtOffset(XwMenuButtonWidget, menubutton.cascadeImage),
191 XtRImage, NULL
192 },
193
194 {
195 XtNmarkImage, XtCMarkImage, XtRImage, sizeof(XImage *),
196 XtOffset(XwMenuButtonWidget, menubutton.markImage),
197 XtRImage, NULL
198 },
199
200 {
201 XtNsetMark, XtCSetMark, XtRBoolean, sizeof(Boolean),
202 XtOffset(XwMenuButtonWidget, menubutton.setMark),
203 XtRString, "FALSE"
204 },
205
206 {
207 XtNnoPad, XtCNoPad, XtRBoolean, sizeof(Boolean),
208 XtOffset(XwMenuButtonWidget, menubutton.noPad),
209 XtRString, "FALSE"
210 },
211
212 {
213 XtNcascadeOn, XtCCascadeOn, XtRWidget, sizeof(Widget),
214 XtOffset(XwMenuButtonWidget, menubutton.cascadeOn),
215 XtRWidget, NULL
216 },
217
218 {
219 XtNkbdAccelerator, XtCKbdAccelerator, XtRString, sizeof(caddr_t),
220 XtOffset(XwMenuButtonWidget, menubutton.accelerator),
221 XtRString, NULL
222 },
223
224 {
225 XtNhint, XtCHint, XtRString, sizeof(caddr_t),
226 XtOffset(XwMenuButtonWidget, menubutton.hint),
227 XtRString, NULL
228 },
229
230 {
231 XtNhintProc, XtCHintProc, XtRFunction, sizeof(XwStrProc),
232 XtOffset(XwMenuButtonWidget, menubutton.hintProc),
233 XtRFunction, NULL
234 },
235
236 {
237 XtNmgrOverrideMnemonic, XtCMgrOverrideMnemonic, XtRBoolean,
238 sizeof(Boolean),
239 XtOffset(XwMenuButtonWidget, menubutton.mgrOverrideMnemonic),
240 XtRString, "FALSE"
241 },
242
243 {
244 XtNmnemonic, XtCMnemonic, XtRString, sizeof(caddr_t),
245 XtOffset(XwMenuButtonWidget, menubutton.mnemonic),
246 XtRString, NULL
247 },
248
249 {
250 XtNhighlightStyle, XtCHighlightStyle, XtRHighlightStyle, sizeof (int),
251 XtOffset (XwPrimitiveWidget, primitive.highlight_style),
252 XtRString, "widget_defined"
253 },
254
255 {
256 XtNcascadeSelect, XtCCallback, XtRCallback, sizeof(caddr_t),
257 XtOffset (XwMenuButtonWidget, menubutton.cascadeSelect),
258 XtRPointer, (caddr_t) NULL
259 },
260
261 {
262 XtNcascadeUnselect, XtCCallback, XtRCallback, sizeof(caddr_t),
263 XtOffset (XwMenuButtonWidget, menubutton.cascadeUnselect),
264 XtRPointer, (caddr_t) NULL
265 },
266
267 {
268 XtNmenuMgrId, XtCMenuMgrId, XtRWidget, sizeof(Widget),
269 XtOffset (XwMenuButtonWidget, menubutton.menuMgr),
270 XtRWidget, NULL
271 },
272 };
273
274 /*************************************<->*************************************
275 *
276 *
277 * Description: global class record for instances of class: MenuButton
278 * -----------
279 *
280 * Defines default field settings for this class record.
281 *
282 *************************************<->***********************************/
283
284 XwMenuButtonClassRec XwmenubuttonClassRec =
285 {
286 {
287 /* core_class fields */
288 /* superclass */ (WidgetClass) &XwbuttonClassRec,
289 /* class_name */ "XwMenuButton",
290 /* widget_size */ sizeof(XwMenuButtonRec),
291 /* class_initialize */ NULL,
292 /* class_part_init */ ClassPartInitialize,
293 /* class_inited */ FALSE,
294 /* initialize */ Initialize,
295 /* initialize_hook */ NULL,
296 /* realize */ Realize,
297 /* actions */ actionsList,
298 /* num_actions */ XtNumber(actionsList),
299 /* resources */ resources,
300 /* num_resources */ XtNumber(resources),
301 /* xrm_class */ NULLQUARK,
302 /* compress_motion */ TRUE,
303 /* compress_exposure */ TRUE,
304 /* compress_enterlv */ TRUE, /* FIX ME LATER */
305 /* visible_interest */ FALSE,
306 /* destroy */ Destroy,
307 /* resize */ Resize,
308 /* expose */ Redisplay,
309 /* set_values */ SetValues,
310 /* set_values_hook */ NULL,
311 /* set_values_almost */ XtInheritSetValuesAlmost,
312 /* get_values_hook */ NULL,
313 /* accept_focus */ NULL,
314 /* version */ XtVersion,
315 /* cb List */ NULL,
316 /* tm_table */ defaultTranslations,
317 /* query_geometry */ NULL, /* FIX ME LATER */
318 /* display_accelerator */ XtInheritDisplayAccelerator,
319 /* extension */ NULL
320 },
321 {
322 /* primitive class fields */
323 /* border_highlight */ Inverted,
324 /* border_unhighlight */ NonInverted,
325 /* select_proc */ Select,
326 /* release_proc */ NULL,
327 /* toggle_proc */ NULL,
328 /* translations */ NULL,
329 },
330 {
331 /* button class fields */ 0,
332 },
333 {
334 /* menubutton class fields */
335 /* ideal width proc */ IdealWidth,
336 /* unhighlight proc */ Unhighlight,
337 /* highlight proc */ Highlight,
338 /* cascade selected */ SetCascadeEnabled,
339 /* cascade unselected*/ ClearCascadeEnabled,
340 /* enter parents win */ EnterParentsWindow,
341 /* cascadeSelectProc */ NULL,
342 /* cascadeUnselectProc */ NULL,
343 /* setTraversalType */ SetTraversalType
344 }
345 };
346 WidgetClass XwmenubuttonWidgetClass = (WidgetClass)&XwmenubuttonClassRec;
347 WidgetClass XwmenuButtonWidgetClass = (WidgetClass)&XwmenubuttonClassRec;
348
349
350 /*************************************<->*************************************
351 *
352 * SetCascadeEnabled (mbutton)
353 *
354 * Description:
355 * -----------
356 * This routine is called by the Menu Manager to force the menubutton into
357 * thinking that the cascade select callbacks have been recently called.
358 *
359 * Inputs:
360 * ------
361 * mbutton = this menubutton widget
362 *
363 * Outputs:
364 * -------
365 *
366 * Procedures Called
367 * -----------------
368 *
369 *************************************<->***********************************/
SetCascadeEnabled(mbutton)370 static void SetCascadeEnabled (mbutton)
371 XwMenuButtonWidget mbutton;
372 {
373 mbutton->menubutton.cascadeEnabled = TRUE;
374 }
375
376 /*************************************<->*************************************
377 *
378 * ClearCascadeEnabled (mbutton)
379 *
380 * Description:
381 * -----------
382 * This routine is called by the Menu Manager to force the menubutton into
383 * thinking that the cascade unselect callbacks have been recently called.
384 *
385 * Inputs:
386 * ------
387 * mbutton = this menubutton widget
388 *
389 * Outputs:
390 * -------
391 *
392 * Procedures Called
393 * -----------------
394 *
395 *************************************<->***********************************/
ClearCascadeEnabled(mbutton)396 static void ClearCascadeEnabled (mbutton)
397 XwMenuButtonWidget mbutton;
398 {
399 mbutton->menubutton.cascadeEnabled = FALSE;
400 }
401
402 /*************************************<->*************************************
403 *
404 * ClassPartInitialize (parameters)
405 *
406 * Description:
407 * -----------
408 *
409 *
410 * Inputs:
411 * ------
412 *
413 * Outputs:
414 * -------
415 *
416 * Procedures Called
417 * -----------------
418 *
419 *************************************<->***********************************/
420
ClassPartInitialize(wc)421 static void ClassPartInitialize (wc)
422
423 register XwMenuButtonWidgetClass wc;
424
425 {
426 register XwMenuButtonWidgetClass super =
427 (XwMenuButtonWidgetClass) wc->core_class.superclass;
428
429 if (wc->menubutton_class.idealWidthProc == XtInheritIdealWidthProc)
430 wc->menubutton_class.idealWidthProc =
431 super->menubutton_class.idealWidthProc;
432
433 if (wc->menubutton_class.unhighlightProc == XtInheritUnhighlightProc)
434 wc->menubutton_class.unhighlightProc =
435 super->menubutton_class.unhighlightProc;
436
437 if (wc->menubutton_class.highlightProc == XtInheritHighlightProc)
438 wc->menubutton_class.highlightProc =
439 super->menubutton_class.highlightProc;
440
441 if (wc->menubutton_class.setCascadeProc == XtInheritSetCascadeProc)
442 wc->menubutton_class.setCascadeProc =
443 super->menubutton_class.setCascadeProc;
444
445 if (wc->menubutton_class.clearCascadeProc == XtInheritClearCascadeProc)
446 wc->menubutton_class.clearCascadeProc =
447 super->menubutton_class.clearCascadeProc;
448
449 if (wc->menubutton_class.enterParentProc == XtInheritEnterParentProc)
450 wc->menubutton_class.enterParentProc =
451 super->menubutton_class.enterParentProc;
452
453 if (wc->menubutton_class.cascadeSelectProc == XtInheritCascadeSelectProc)
454 wc->menubutton_class.cascadeSelectProc =
455 super->menubutton_class.cascadeSelectProc;
456
457 if (wc->menubutton_class.cascadeUnselectProc == XtInheritCascadeUnselectProc)
458 wc->menubutton_class.cascadeUnselectProc =
459 super->menubutton_class.cascadeUnselectProc;
460
461 if (wc->menubutton_class.setTraversalType == XtInheritSetTraversalTypeProc)
462 wc->menubutton_class.setTraversalType =
463 super->menubutton_class.setTraversalType;
464 }
465
466
467 /*************************************<->*************************************
468 *
469 * ComputeHeight (mbutton)
470 *
471 * Description:
472 * -----------
473 * Returns the ideal height of the menubutton by considering whether the
474 * label is text or image.
475 *
476 * Inputs:
477 * ------
478 * mbutton = widget to compute height of
479 *
480 * Outputs:
481 * -------
482 * returns the ideal height of mbutton
483 *
484 * Procedures Called
485 * -----------------
486 *
487 *************************************<->***********************************/
488
ComputeHeight(mbutton)489 static Dimension ComputeHeight(mbutton)
490 XwMenuButtonWidget mbutton;
491 {
492 Dimension max = 0;
493
494 if (mbutton->menubutton.labelType == XwSTRING)
495 max = mbutton->button.label_height;
496
497 if ((mbutton->menubutton.labelType == XwIMAGE) &&
498 (mbutton->menubutton.labelImage->height > max))
499 max = mbutton->menubutton.labelImage->height;
500
501 if (mbutton->menubutton.markImage->height > max)
502 max = mbutton->menubutton.markImage->height;
503
504 if (mbutton->menubutton.cascadeImage->height > max)
505 max = mbutton->menubutton.cascadeImage->height;
506
507 return (max + 2 * mbutton->button.internal_height +
508 2 * mbutton->primitive.highlight_thickness);
509
510 }
511
512 /*************************************<->*************************************
513 *
514 * ComputeVertical
515 *
516 * Description:
517 * -----------
518 * Computes the values for mark_y, label_y and cascade_y.
519 *
520 * Inputs:
521 * ------
522 * mbutton = menubutton to compute and set values for
523 *
524 * Outputs:
525 * -------
526 *
527 * Procedures Called
528 * -----------------
529 *
530 *************************************<->***********************************/
531
ComputeVertical(mbutton)532 static void ComputeVertical (mbutton)
533 XwMenuButtonWidget mbutton;
534 {
535 Dimension string_y;
536
537 string_y = (mbutton->core.height - mbutton->button.label_height)/2 +
538 mbutton->button.font->max_bounds.ascent;
539
540 if (mbutton->menubutton.labelType == XwSTRING)
541 mbutton->button.label_y = string_y;
542
543 else if (mbutton->menubutton.labelImage)
544 mbutton->button.label_y = (mbutton->core.height -
545 mbutton->menubutton.labelImage->height) / 2;
546
547 mbutton->menubutton.mark_y = (mbutton->core.height -
548 mbutton->menubutton.markImage->height)/2;
549
550 mbutton->menubutton.cascade_y = (mbutton->core.height -
551 mbutton->menubutton.cascadeImage->height)/2;
552
553 }
554
555 /*************************************<->*************************************
556 *
557 * SetUnderline (mbutton)
558 *
559 * Description:
560 * -----------
561 * Set the underline parameters underline_width and underline_y.
562 *
563 * Inputs:
564 * ------
565 * mbutton = menubutton
566 *
567 * Outputs:
568 * -------
569 *
570 * Procedures Called
571 * -----------------
572 * XTextWidth ()
573 * XGetFontProperty ()
574 *
575 *************************************<->***********************************/
576
SetUnderline(mbutton)577 static void SetUnderline (mbutton)
578 XwMenuButtonWidget mbutton;
579 {
580 int i, temp;
581
582 if ((!mbutton->menubutton.mgrOverrideMnemonic) &&
583 (mbutton->menubutton.mnemonic))
584 {
585 mbutton->menubutton.mnemonicMatch = FALSE;
586 temp = XwStrlen (mbutton->button.label);
587
588 for (i = 0; i < temp;)
589 {
590 #ifdef NLS16
591 if (XHPIs16bitCharacter (mbutton->button.font->fid,
592 mbutton->button.label[i],
593 mbutton->button.label[i+1]) == NULL)
594 {
595 #endif
596 if (*mbutton->menubutton.mnemonic ==
597 (char) mbutton->button.label[i])
598 {
599 unsigned long bval;
600
601 mbutton->menubutton.mnemonicMatch = TRUE;
602 mbutton->menubutton.underline_width =
603 XTextWidth(mbutton->button.font, mbutton->button.label+i, 1);
604
605 mbutton->menubutton.underline_x =
606 XTextWidth(mbutton->button.font, mbutton->button.label, i) +
607 mbutton->primitive.highlight_thickness +
608 4 * mbutton->button.internal_width + XwMARKWIDTH;
609
610 if (XGetFontProperty(mbutton->button.font, XA_UNDERLINE_POSITION,
611 &bval) == 0)
612 mbutton->menubutton.underline_y =
613 mbutton->button.font->descent +1;
614 else
615 mbutton->menubutton.underline_y = (Dimension) bval;
616
617 mbutton->menubutton.underline_y += mbutton->button.label_y;
618 break;
619 }
620 else
621 i += 1;
622 #ifdef NLS16
623 }
624 else
625 i += 2;
626 #endif
627 }
628 }
629 else
630 mbutton->menubutton.mnemonicMatch = FALSE;
631 }
632
633 /*************************************<->*************************************
634 *
635 * GetGC (mbutton)
636 *
637 * Description:
638 * -----------
639 * Creates image_GC
640 *
641 * Inputs:
642 * ------
643 * mbutton = menubutton
644 *
645 * Outputs:
646 * -------
647 *
648 * Procedures Called
649 * -----------------
650 * XtGetGC()
651 *
652 *************************************<->***********************************/
653
GetGC(mbutton)654 static void GetGC (mbutton)
655 XwMenuButtonWidget mbutton;
656 {
657
658 XGCValues values;
659 unsigned long dostipple = 0;
660
661 values.function = GXcopy;
662 values.plane_mask = AllPlanes;
663 values.subwindow_mode = ClipByChildren;
664 values.clip_x_origin = 0;
665 values.clip_y_origin = 0;
666 values.clip_mask = None;
667 values.fill_style = FillSolid;
668 values.graphics_exposures = True;
669
670 values.foreground = mbutton->primitive.foreground;
671 values.background = mbutton->core.background_pixel;
672
673 mbutton->menubutton.defPixmap_GC =
674 XtGetGC ((Widget) mbutton,
675 GCFunction | GCPlaneMask | GCSubwindowMode |
676 GCGraphicsExposures | GCClipXOrigin | GCClipYOrigin |
677 GCClipMask | GCForeground | GCBackground,
678 &values);
679
680 values.foreground = mbutton->core.background_pixel;
681 values.background = mbutton->primitive.foreground;
682
683 mbutton->menubutton.invertPixmap_GC =
684 XtGetGC ((Widget) mbutton,
685 GCFunction | GCPlaneMask | GCSubwindowMode |
686 GCGraphicsExposures | GCClipXOrigin | GCClipYOrigin |
687 GCClipMask | GCForeground | GCBackground,
688 &values);
689
690 values.background = mbutton->core.background_pixel;
691 values.stipple = mbutton->menubutton.rectStipple;
692 if (values.stipple != (Pixmap)NULL) {
693 dostipple = GCStipple;
694 values.fill_style = FillOpaqueStippled;
695 values.foreground = mbutton->primitive.foreground;
696 }
697 else
698 values.foreground = mbutton->menubutton.rectColor;
699
700 mbutton->menubutton.rect_GC =
701 XtGetGC ((Widget) mbutton,
702 GCFunction | GCPlaneMask | GCSubwindowMode |
703 GCGraphicsExposures | GCClipXOrigin | GCClipYOrigin |
704 GCClipMask | GCForeground | GCBackground | dostipple |
705 GCFillStyle, &values);
706 }
707
708 /*************************************<->*************************************
709 *
710 * GetDefImages
711 *
712 * Description:
713 * -----------
714 *
715 * Inputs:
716 * ------
717 * mbutton = menubutton
718 *
719 * Outputs:
720 * -------
721 *
722 * Procedures Called
723 * -----------------
724 *
725 *************************************<->***********************************/
726
GetDefImages(mbutton)727 static void GetDefImages (mbutton)
728 XwMenuButtonWidget mbutton;
729 {
730 static unsigned char defMarkData[] =
731 {
732 0x00, 0x10, 0x00, 0x38, 0x00, 0x7c, 0x00, 0x3c,
733 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x07, 0x00, 0x07,
734 0x8c, 0x03, 0x8e, 0x01, 0xde, 0x01, 0xdc, 0x00,
735 0xd8, 0x00, 0x70, 0x00, 0x70, 0x00, 0x20, 0x00,
736 };
737
738 static unsigned char defCascadeData[] =
739 {
740 0x80, 0x00, 0x80, 0x01, 0x80, 0x03, 0x80, 0x07,
741 0x80, 0x0f, 0xfe, 0x1f, 0xfe, 0x3f, 0xfe, 0x7f,
742 0xfe, 0x3f, 0xfe, 0x1f, 0x80, 0x0f, 0x80, 0x07,
743 0x80, 0x03, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00
744 };
745
746 mbutton->menubutton.defMarkImage =
747 XCreateImage (XtDisplay(mbutton), CopyFromParent, 1, XYBitmap, 0,
748 defMarkData, 16, 16, 8, 2);
749
750 mbutton->menubutton.defMarkImage->byte_order = MSBFirst;
751 mbutton->menubutton.defMarkImage->bitmap_bit_order = LSBFirst;
752 mbutton->menubutton.defMarkImage->bitmap_unit = 8;
753
754
755 mbutton->menubutton.defCascadeImage =
756 XCreateImage (XtDisplay(mbutton), CopyFromParent, 1, XYBitmap, 0,
757 defCascadeData, 16, 16, 8, 2);
758
759 mbutton->menubutton.defCascadeImage->byte_order = MSBFirst;
760 mbutton->menubutton.defCascadeImage->bitmap_bit_order = LSBFirst;
761 mbutton->menubutton.defCascadeImage->bitmap_unit = 8;
762 }
763
764 /*************************************<->*************************************
765 *
766 * CreatePixmap
767 *
768 * Description:
769 * -----------
770 *
771 * Inputs:
772 * ------
773 * mbutton = menubutton
774 *
775 * Outputs:
776 * -------
777 *
778 * Procedures Called
779 * -----------------
780 *
781 *************************************<->***********************************/
782
CreatePixmap(mbutton,image,pix,invertedPix)783 static void CreatePixmap (mbutton, image, pix, invertedPix)
784 XwMenuButtonWidget mbutton;
785 XImage * image;
786 Pixmap * pix;
787 Pixmap * invertedPix;
788 {
789 if (*pix != (Pixmap)NULL)
790 XFreePixmap (XtDisplay(mbutton), *pix);
791
792 if (*invertedPix != (Pixmap)NULL)
793 XFreePixmap (XtDisplay(mbutton), *invertedPix);
794
795 if (image)
796 {
797 *pix = XCreatePixmap (XtDisplay(mbutton),
798 RootWindowOfScreen(XtScreen(mbutton)),
799 image->width, image->height,
800 DefaultDepthOfScreen(XtScreen(mbutton)));
801
802 XPutImage (XtDisplay(mbutton), *pix, mbutton->menubutton.defPixmap_GC,
803 image, 0, 0, 0, 0, image->width, image->height);
804
805 if (image->format == XYBitmap)
806 {
807 *invertedPix = XCreatePixmap (XtDisplay(mbutton),
808 RootWindowOfScreen(XtScreen(mbutton)),
809 image->width, image->height,
810 DefaultDepthOfScreen(XtScreen(mbutton)));
811
812 XPutImage (XtDisplay(mbutton), *invertedPix,
813 mbutton->menubutton.invertPixmap_GC,
814 image, 0, 0, 0, 0, image->width, image->height);
815 }
816
817 }
818 else
819 {
820 *pix = (Pixmap)NULL;
821 *invertedPix = (Pixmap)NULL;
822 }
823 }
824
825 /*************************************<->*************************************
826 *
827 * IdealWidth
828 *
829 * Description:
830 * -----------
831 * NOTE!!! This should be eventually replaced by a QueryProc.
832 *
833 * Inputs:
834 * ------
835 * w = menubutton widget
836 *
837 *
838 * Outputs:
839 * -------
840 *
841 * Procedures Called
842 * -----------------
843 *
844 *************************************<->***********************************/
845
IdealWidth(w,width)846 static void IdealWidth (w, width)
847 Widget w;
848 Dimension * width;
849 {
850 XwMenuButtonWidget mbutton = (XwMenuButtonWidget) w;
851
852 *width = 2 * mbutton->primitive.highlight_thickness +
853 2 * (XwMENUBTNPAD + mbutton->button.internal_width) +
854 XwMARKWIDTH + XwCASCADEWIDTH;
855
856 if (mbutton->menubutton.labelType == XwSTRING)
857 *width += mbutton->button.label_width;
858 else if (mbutton->menubutton.labelType == XwIMAGE)
859 *width += mbutton->menubutton.labelImage->width;
860 }
861
862 /*************************************<->*************************************
863 *
864 * Initialize (request, new)
865 *
866 * Description:
867 * -----------
868 * This is the menubutton instance initialize procedure.
869 *
870 *
871 * Inputs:
872 * ------
873 * request = original instance record;
874 *
875 * new = instance record with modifications induced by
876 * other initialize routines, changes are made to this
877 * record;
878 *
879 * args = argument list specified in XtCreateWidget;
880 *
881 * num_args = argument count;
882 *
883 * Outputs:
884 * -------
885 *
886 * Procedures Called
887 * -----------------
888 *
889 *************************************<->***********************************/
890
Initialize(request,new)891 static void Initialize (request, new)
892 Widget request, new;
893 {
894 Dimension dim;
895 KeySym tempKeysym;
896
897 XwMenuButtonWidget mbutton = (XwMenuButtonWidget) new;
898
899 /* Augment our translations to include the traversal actions */
900 XtAugmentTranslations ((Widget)mbutton,
901 XwprimitiveClassRec.primitive_class.translations);
902
903 /*
904 * Always disable traversal in a menubutton. Since the traversal
905 * state is inherited from the menu manager, we will let it control
906 * our traversal state.
907 */
908 mbutton->primitive.traversal_type = XwHIGHLIGHT_OFF;
909
910 mbutton->menubutton.cascadeEnabled = FALSE;
911 mbutton->menubutton.inverted = FALSE;
912 mbutton->menubutton.labelPixmap =
913 mbutton->menubutton.markPixmap =
914 mbutton->menubutton.cascadePixmap =
915 mbutton->menubutton.invertLabelPixmap =
916 mbutton->menubutton.invertMarkPixmap =
917 mbutton->menubutton.invertCascadePixmap = (Pixmap)NULL;
918
919 GetDefImages(mbutton);
920 GetGC(mbutton);
921
922 /*
923 * If the menuMgr field has not been set up, check if in a menu system
924 * (menu manager as ancestor).
925 */
926 if (mbutton->menubutton.menuMgr == NULL)
927 {
928 if ((XtIsSubclass (XtParent (mbutton), XwmenupaneWidgetClass)) &&
929 (XtIsSubclass (XtParent (XtParent (mbutton)), shellWidgetClass)) &&
930 (XtIsSubclass (XtParent (XtParent (XtParent (mbutton))),
931 XwmenumgrWidgetClass)))
932 {
933 mbutton->menubutton.menuMgr =
934 (Widget) XtParent (XtParent (XtParent(mbutton)));
935 }
936 }
937
938 /*
939 * We need to malloc space for the strings and copy them to our
940 * space. The toolkit simply copies the pointer to the string.
941 */
942 if ((mbutton->menubutton.accelerator) &&
943 (_XwMapKeyEvent (mbutton->menubutton.accelerator,
944 &mbutton->menubutton.accelEventType,
945 &tempKeysym,
946 &mbutton->menubutton.accelModifiers)))
947 {
948 mbutton->menubutton.accelDetail = XKeysymToKeycode (XtDisplay(mbutton),
949 tempKeysym);
950 mbutton->menubutton.accelerator =
951 strcpy(XtMalloc((unsigned)(XwStrlen(mbutton->menubutton.accelerator)+1)),
952 mbutton->menubutton.accelerator);
953 }
954 else
955 {
956 if (mbutton->menubutton.accelerator)
957 XtWarning ("MenuButton: Invalid accelerator; disabling feature");
958 mbutton->menubutton.accelerator = NULL;
959 mbutton->menubutton.accelEventType = 0;
960 mbutton->menubutton.accelDetail = 0;
961 mbutton->menubutton.accelModifiers = 0;
962 }
963
964 if (mbutton->menubutton.hint)
965 mbutton->menubutton.hint =
966 strcpy(XtMalloc((unsigned)(XwStrlen(mbutton->menubutton.hint)+1)),
967 mbutton->menubutton.hint);
968
969 /*
970 * malloc space for mnemonic. Only take 1st character & null
971 */
972 if ((mbutton->menubutton.mnemonic) &&
973 (*(mbutton->menubutton.mnemonic) != '\0'))
974 {
975 char mne = mbutton->menubutton.mnemonic[0];
976
977 mbutton->menubutton.mnemonic = (String) XtMalloc(2);
978 mbutton->menubutton.mnemonic[0] = mne;
979 mbutton->menubutton.mnemonic[1] = '\0';
980 }
981 else
982 if (mbutton->menubutton.mnemonic)
983 XtWarning ("MenuButton: Invalid mnemonic; disabling feature");
984
985 if (mbutton->menubutton.labelImage)
986 CreatePixmap(mbutton, mbutton->menubutton.labelImage,
987 &mbutton->menubutton.labelPixmap,
988 &mbutton->menubutton.invertLabelPixmap);
989
990 if (!mbutton->menubutton.markImage)
991 mbutton->menubutton.markImage = mbutton->menubutton.defMarkImage;
992
993 CreatePixmap(mbutton, mbutton->menubutton.markImage,
994 &mbutton->menubutton.markPixmap,
995 &mbutton->menubutton.invertMarkPixmap);
996
997 if (!mbutton->menubutton.cascadeImage)
998 mbutton->menubutton.cascadeImage = mbutton->menubutton.defCascadeImage;
999
1000 CreatePixmap(mbutton, mbutton->menubutton.cascadeImage,
1001 &mbutton->menubutton.cascadePixmap,
1002 &mbutton->menubutton.invertCascadePixmap);
1003
1004 if (request->core.height <= 0)
1005 mbutton->core.height = ComputeHeight(mbutton);
1006
1007 ComputeVertical(mbutton);
1008 SetUnderline(mbutton);
1009
1010 if (request->core.width <= 0)
1011 IdealWidth(mbutton, &mbutton->core.width);
1012 }
1013
1014 /*************************************<->*************************************
1015 *
1016 * Destroy
1017 *
1018 * Description:
1019 * -----------
1020 *
1021 * Inputs:
1022 * ------
1023 *
1024 * Outputs:
1025 * -------
1026 *
1027 * Procedures Called
1028 * -----------------
1029 *
1030 *************************************<->***********************************/
1031
Destroy(mbutton)1032 static void Destroy (mbutton)
1033 XwMenuButtonWidget mbutton;
1034 {
1035 if (mbutton->menubutton.accelerator)
1036 XtFree (mbutton->menubutton.accelerator);
1037
1038 XtDestroyGC (mbutton->menubutton.defPixmap_GC);
1039 XtDestroyGC (mbutton->menubutton.inverted_GC);
1040 XtDestroyGC (mbutton->menubutton.invertPixmap_GC);
1041 XtDestroyGC (mbutton->menubutton.rect_GC);
1042
1043 mbutton->menubutton.defMarkImage->data = NULL;
1044 XDestroyImage (mbutton->menubutton.defMarkImage);
1045 mbutton->menubutton.defCascadeImage->data = NULL;
1046 XDestroyImage (mbutton->menubutton.defCascadeImage);
1047
1048 XtRemoveAllCallbacks ((Widget)mbutton, XtNcascadeSelect);
1049 XtRemoveAllCallbacks ((Widget)mbutton, XtNcascadeUnselect);
1050
1051 XFreePixmap (XtDisplay(mbutton), mbutton->menubutton.markPixmap);
1052 XFreePixmap (XtDisplay(mbutton), mbutton->menubutton.cascadePixmap);
1053 if (mbutton->menubutton.labelPixmap)
1054 XFreePixmap (XtDisplay(mbutton), mbutton->menubutton.labelPixmap);
1055 }
1056
1057 /*************************************<->*************************************
1058 *
1059 * Realize
1060 *
1061 * Description:
1062 * -----------
1063 * Creates the window for this menubutton instance. Sets bit gravity
1064 * so that on resize the menubutton is repainted.
1065 *
1066 *
1067 * Inputs:
1068 * ------
1069 * w = widget to be realized.
1070 *
1071 * valueMask = contains event mask for this window/widget.
1072 *
1073 * attributes = window attributes for this window/widget.
1074 *
1075 * Outputs:
1076 * -------
1077 *
1078 * Procedures Called
1079 * -----------------
1080 * XtCreateWindow()
1081 *************************************<->***********************************/
1082
Realize(w,p_valueMask,attributes)1083 static void Realize(w, p_valueMask, attributes)
1084 Widget w;
1085 XtValueMask * p_valueMask;
1086 XSetWindowAttributes * attributes;
1087 {
1088 XwMenuButtonWidget mbutton = (XwMenuButtonWidget) w;
1089
1090 XtValueMask valueMask = *p_valueMask;
1091 valueMask |= CWBitGravity;
1092 attributes->bit_gravity = ForgetGravity;
1093
1094
1095 XtCreateWindow ((Widget)mbutton, InputOutput, (Visual *) CopyFromParent,
1096 valueMask, attributes);
1097
1098 _XwRegisterName (mbutton);
1099 } /* Realize */
1100
1101 /*************************************<->*************************************
1102 *
1103 * Select (w, event) PRIVATE
1104 *
1105 * Description:
1106 * -----------
1107 * Mark menubutton as selected, (i.e., draw it as active)
1108 * Generate the correct callbacks.
1109 *
1110 *
1111 * Inputs:
1112 * ------
1113 * w = widget instance that was selected.
1114 * event = event record
1115 *
1116 * Outputs:
1117 * -------
1118 *
1119 * Procedures Called
1120 * -----------------
1121 * XtCallCallbacks()
1122 *************************************<->***********************************/
1123
Select(w,event)1124 static void Select(w,event)
1125 Widget w;
1126 XEvent *event;
1127
1128 {
1129 XwMenuButtonWidget mbutton = (XwMenuButtonWidget) w;
1130
1131 /* Don't do anything if its not sensitive. */
1132
1133 if (XtIsSensitive((Widget)mbutton))
1134 {
1135 /*
1136 * if there is a menu manager, call the process select routine to
1137 * determine if the event is valid for the menu system.
1138 */
1139 if (mbutton->menubutton.menuMgr)
1140 {
1141 if ((*(((XwMenuMgrWidgetClass) XtClass(mbutton->menubutton.menuMgr))->
1142 menu_mgr_class.processSelect))
1143 (mbutton->menubutton.menuMgr, mbutton, event) == FALSE)
1144 {
1145 return;
1146 }
1147 }
1148
1149 XtCallCallbacks ((Widget)mbutton, XtNselect, NULL);
1150 }
1151 }
1152
1153 /*************************************<->*************************************
1154 *
1155 * DrawLabelMarkCascade (mbutton)
1156 *
1157 * Description:
1158 * -----------
1159 *
1160 * Inputs:
1161 * ------
1162 *
1163 * Outputs:
1164 * -------
1165 *
1166 * Procedures Called
1167 * -----------------
1168 *
1169 *************************************<->***********************************/
1170
DrawLabelMarkCascade(mbutton)1171 static void DrawLabelMarkCascade (mbutton)
1172 XwMenuButtonWidget mbutton;
1173 {
1174 Dimension labelStarts;
1175 GC theGC;
1176 Pixmap thePixmap;
1177
1178 if (mbutton->menubutton.inverted)
1179 theGC = mbutton->button.inverse_GC;
1180 else
1181 theGC = mbutton->button.normal_GC;
1182
1183
1184 if (mbutton->menubutton.noPad == True)
1185 labelStarts = mbutton->primitive.highlight_thickness +
1186 mbutton->button.internal_width;
1187 else
1188 labelStarts = mbutton->primitive.highlight_thickness +
1189 mbutton->button.internal_width + XwMENUBTNPAD + XwMARKWIDTH;
1190 /*
1191 * Draw the label with its underline if needed.
1192 */
1193 if (mbutton->menubutton.labelType == XwSTRING)
1194 {
1195 XDrawString(
1196 XtDisplay(mbutton), XtWindow(mbutton), theGC,
1197 labelStarts, mbutton->button.label_y,
1198 mbutton->button.label, (int) mbutton->button.label_len);
1199
1200 if ((!mbutton->menubutton.mgrOverrideMnemonic) &&
1201 (mbutton->menubutton.mnemonicMatch))
1202 XDrawLine(
1203 XtDisplay(mbutton), XtWindow(mbutton), theGC,
1204 mbutton->menubutton.underline_x,
1205 mbutton->menubutton.underline_y,
1206 mbutton->menubutton.underline_x +
1207 mbutton->menubutton.underline_width,
1208 mbutton->menubutton.underline_y);
1209 }
1210 else if (mbutton->menubutton.labelType == XwRECT)
1211 {
1212 /* Draw a colored or stippled rectangle with a border around it */
1213
1214 if (mbutton->menubutton.noPad == True) {
1215 XFillRectangle(
1216 XtDisplay(mbutton), XtWindow(mbutton),
1217 mbutton->menubutton.rect_GC,
1218 2, 2, mbutton->menubutton.labelImage->width - 1,
1219 mbutton->menubutton.labelImage->height - 1);
1220 XDrawRectangle(
1221 XtDisplay(mbutton), XtWindow(mbutton), theGC,
1222 2, 2, mbutton->menubutton.labelImage->width - 1,
1223 mbutton->menubutton.labelImage->height - 1);
1224 }
1225 else {
1226 XFillRectangle(
1227 XtDisplay(mbutton), XtWindow(mbutton),
1228 mbutton->menubutton.rect_GC,
1229 XwMARKWIDTH + 3, 3, mbutton->core.width - XwMARKWIDTH - 6,
1230 mbutton->core.height - 6);
1231 XDrawRectangle(
1232 XtDisplay(mbutton), XtWindow(mbutton), theGC,
1233 XwMARKWIDTH + 3, 3, mbutton->core.width - XwMARKWIDTH - 6,
1234 mbutton->core.height - 6);
1235 }
1236 }
1237 else
1238 {
1239 if ((mbutton->menubutton.inverted) &&
1240 (mbutton->menubutton.invertLabelPixmap))
1241 thePixmap = mbutton->menubutton.invertLabelPixmap;
1242 else
1243 thePixmap = mbutton->menubutton.labelPixmap;
1244
1245 XCopyArea (XtDisplay(mbutton), thePixmap, XtWindow(mbutton),
1246 mbutton->menubutton.defPixmap_GC, 0, 0,
1247 mbutton->menubutton.labelImage->width,
1248 mbutton->menubutton.labelImage->height,
1249 labelStarts, mbutton->button.label_y);
1250 }
1251
1252 /*
1253 * If the mark is set, display the mark.
1254 */
1255 if (mbutton->menubutton.setMark)
1256 {
1257 if ((mbutton->menubutton.inverted) &&
1258 (mbutton->menubutton.invertMarkPixmap))
1259 thePixmap = mbutton->menubutton.invertMarkPixmap;
1260 else
1261 thePixmap = mbutton->menubutton.markPixmap;
1262
1263 XCopyArea (XtDisplay(mbutton), thePixmap, XtWindow(mbutton),
1264 mbutton->menubutton.defPixmap_GC, 0, 0,
1265 mbutton->menubutton.markImage->width,
1266 mbutton->menubutton.markImage->height,
1267 mbutton->button.internal_width +
1268 mbutton->primitive.highlight_thickness,
1269 mbutton->menubutton.mark_y);
1270 }
1271
1272 /*
1273 * If the cascade is set, display it.
1274 */
1275 if (mbutton->menubutton.cascadeOn)
1276 {
1277 if ((mbutton->menubutton.inverted) &&
1278 (mbutton->menubutton.invertCascadePixmap))
1279 thePixmap = mbutton->menubutton.invertCascadePixmap;
1280 else
1281 thePixmap = mbutton->menubutton.cascadePixmap;
1282
1283 XCopyArea (XtDisplay(mbutton), thePixmap, XtWindow(mbutton),
1284 mbutton->menubutton.defPixmap_GC, 0, 0,
1285 mbutton->menubutton.cascadeImage->width,
1286 mbutton->menubutton.cascadeImage->height,
1287 mbutton->core.width - XwCASCADEWIDTH -
1288 mbutton->primitive.highlight_thickness -
1289 mbutton->button.internal_width,
1290 mbutton->menubutton.cascade_y);
1291 }
1292 }
1293
1294 /*************************************<->*************************************
1295 *
1296 * Inverted (mbutton)
1297 *
1298 * Description:
1299 * -----------
1300 *
1301 * Inputs:
1302 * ------
1303 *
1304 * Outputs:
1305 * -------
1306 *
1307 * Procedures Called
1308 * -----------------
1309 * XFillRectangle
1310 * DrawLabelMarkCascade
1311 *
1312 *************************************<->***********************************/
1313
Inverted(mw)1314 static void Inverted (mw)
1315 XwMenuButtonWidget mw;
1316
1317 {
1318 mw -> menubutton.inverted = TRUE;
1319
1320 XFillRectangle (XtDisplay (mw), XtWindow (mw),
1321 mw->button.normal_GC,
1322 mw -> primitive.highlight_thickness + 1,
1323 mw -> primitive.highlight_thickness + 1,
1324 mw -> core.width - 2 *
1325 (mw -> primitive.highlight_thickness + 1),
1326 mw -> core.height - 2 *
1327 (mw -> primitive.highlight_thickness + 1));
1328 DrawLabelMarkCascade (mw);
1329 }
1330
1331
1332
1333 /*************************************<->*************************************
1334 *
1335 * NonInverted (mbutton)
1336 *
1337 * Description:
1338 * -----------
1339 *
1340 * Inputs:
1341 * ------
1342 *
1343 * Outputs:
1344 * -------
1345 *
1346 * Procedures Called
1347 * -----------------
1348 * XClearWindow
1349 * DrawLabelMarkCascade
1350 *
1351 *************************************<->***********************************/
1352
NonInverted(mbutton)1353 static void NonInverted (mbutton)
1354 XwMenuButtonWidget mbutton;
1355
1356 {
1357 mbutton->menubutton.inverted = FALSE;
1358
1359 XClearWindow (XtDisplay(mbutton), XtWindow(mbutton));
1360 DrawLabelMarkCascade (mbutton);
1361 }
1362
1363
1364
1365 /*************************************<->*************************************
1366 *
1367 * Highlight(mbutton)
1368 *
1369 * Description:
1370 * -----------
1371 *
1372 * Inputs:
1373 * ------
1374 *
1375 * Outputs:
1376 * -------
1377 *
1378 * Procedures Called
1379 * -----------------
1380 * Moved
1381 * Inverted
1382 *
1383 *************************************<->***********************************/
1384
Highlight(mbutton)1385 static void Highlight (mbutton)
1386 XwMenuButtonWidget mbutton;
1387 {
1388 /*
1389 if (mbutton->primitive.traversal_type == XwHIGHLIGHT_TRAVERSAL)
1390 _XwHighlightBorder(mbutton);
1391 else
1392 */
1393 Inverted (mbutton);
1394 }
1395
1396 /*************************************<->*************************************
1397 *
1398 * Unhighlight (mbutton)
1399 *
1400 * Description:
1401 * -----------
1402 *
1403 * Inputs:
1404 * ------
1405 *
1406 * Outputs:
1407 * -------
1408 *
1409 * Procedures Called
1410 * -----------------
1411 * Moved
1412 * Inverted
1413 *
1414 *************************************<->***********************************/
1415
Unhighlight(mbutton)1416 static void Unhighlight (mbutton)
1417 XwMenuButtonWidget mbutton;
1418 {
1419 /*
1420 if (mbutton->primitive.traversal_type == XwHIGHLIGHT_TRAVERSAL)
1421 _XwUnhighlightBorder(mbutton);
1422 else
1423 */
1424 NonInverted (mbutton);
1425 mbutton->menubutton.cascadeEnabled = FALSE;
1426 }
1427
1428 /*************************************<->*************************************
1429 *
1430 * Enter (w, event) PRIVATE
1431 *
1432 * Description:
1433 * -----------
1434 *
1435 * Inputs:
1436 * ------
1437 * w = widget instance that was selected.
1438 * event = event record
1439 *
1440 * Outputs:
1441 * -------
1442 *
1443 * Procedures Called
1444 * -----------------
1445 * Moved
1446 * Inverted
1447 *
1448 *************************************<->***********************************/
1449
Enter(w,event)1450 static void Enter(w,event)
1451 Widget w;
1452 XEvent *event;
1453 {
1454 XwMenuButtonWidget mbutton = (XwMenuButtonWidget)w;
1455
1456 #ifdef DEBUG
1457 printf ("Enter %s\n", w->core.name);
1458 #endif
1459 if ((mbutton->menubutton.menuMgr == NULL) ||
1460 ((*(((XwMenuMgrWidgetClass)
1461 XtClass (mbutton->menubutton.menuMgr))->menu_mgr_class.validEvent))
1462 (mbutton->menubutton.menuMgr, mbutton, event)))
1463 {
1464 /*
1465 * Check on cascade indicator
1466 */
1467 Moved (w, event);
1468
1469 /*
1470 * if (mbutton->primitive.traversal_type != XwHIGHLIGHT_TRAVERSAL)
1471 */
1472 Inverted(mbutton);
1473 }
1474
1475 /* to-do: if no hintProc is specified, should generate a hint tag */
1476
1477 if ((mbutton->menubutton.hint != NULL) &&
1478 (mbutton->menubutton.hintProc != NULL)) {
1479 mbutton->menubutton.hintProc(mbutton->menubutton.hint);
1480 }
1481 }
1482
1483 /*************************************<->*************************************
1484 *
1485 * EnterParentsWindow (menupane, mbutton,event)
1486 *
1487 * Description:
1488 * -----------
1489 *
1490 * Inputs:
1491 * ------
1492 *
1493 * Outputs:
1494 * -------
1495 *
1496 * Procedures Called
1497 * -----------------
1498 *
1499 *************************************<->***********************************/
1500
EnterParentsWindow(menupane,mbutton,event)1501 static void EnterParentsWindow (menupane, mbutton, event)
1502 Widget menupane;
1503 XwMenuButtonWidget mbutton;
1504 XEvent * event;
1505 {
1506 Boolean remainHighlighted;
1507 XwunselectParams params;
1508
1509 XEnterWindowEvent * entEvent = (XEnterWindowEvent *) event;
1510
1511 #ifdef DEBUG
1512 printf ("EnterParents %s %s ", menupane->core.name, mbutton->core.name);
1513 #endif
1514
1515 /*
1516 * if outside of the menubutton, bring down submenu. I am assuming that
1517 * the x parameters are okay. This means that entering my parents borders
1518 * on the correct y parameters will not cause the unselects to be called.
1519 */
1520 if ((entEvent->y < mbutton->core.y) ||
1521 (entEvent->y > mbutton->core.y + mbutton->core.height +
1522 2 * mbutton->core.border_width))
1523 {
1524 params.rootX = entEvent->x_root;
1525 params.rootY = entEvent->y_root;
1526 params.remainHighlighted = FALSE;
1527
1528 #ifdef DEBUG
1529 printf ("rootX %d rootY %d\n", params.rootX, params.rootY);
1530 printf ("disabled\n");
1531 #endif
1532
1533 XtCallCallbacks ((Widget)mbutton, XtNcascadeUnselect, ¶ms);
1534 mbutton->menubutton.cascadeEnabled = params.remainHighlighted;
1535 if (mbutton->menubutton.cascadeEnabled == FALSE)
1536 Unhighlight (mbutton);
1537 }
1538 /* else
1539 * Moved (mbutton, event);
1540 */
1541
1542 #ifdef DEBUG
1543 printf ("\n");
1544 #endif
1545
1546 XtRemoveEventHandler (menupane, EnterWindowMask, FALSE,
1547 (XtEventHandler)EnterParentsWindow, mbutton);
1548 }
1549
1550 /*************************************<->*************************************
1551 *
1552 * Leave (w, event) PRIVATE
1553 *
1554 * Description:
1555 * -----------
1556 *
1557 * Inputs:
1558 * ------
1559 *
1560 * Outputs:
1561 * -------
1562 *
1563 * Procedures Called
1564 * -----------------
1565 * XtCallCallbacks
1566 * NonInverted
1567 *
1568 *************************************<->***********************************/
1569
Leave(w,event)1570 static void Leave(w,event)
1571 Widget w;
1572 XEvent *event;
1573
1574 {
1575 XwunselectParams params;
1576 XwMenuButtonWidget mbutton = (XwMenuButtonWidget)w;
1577 XLeaveWindowEvent * lEvent = (XLeaveWindowEvent *) event;
1578
1579 params.rootX = lEvent->x_root;
1580 params.rootY = lEvent->y_root;
1581
1582
1583 if ((mbutton->menubutton.menuMgr == NULL) ||
1584 ((*(((XwMenuMgrWidgetClass)
1585 XtClass (mbutton->menubutton.menuMgr))->menu_mgr_class.validEvent))
1586 (mbutton->menubutton.menuMgr, mbutton, event)))
1587 {
1588 if (mbutton->menubutton.cascadeEnabled)
1589 {
1590 params.remainHighlighted = FALSE;
1591 XtCallCallbacks ((Widget)mbutton, XtNcascadeUnselect, ¶ms);
1592 mbutton->menubutton.cascadeEnabled = params.remainHighlighted;
1593
1594 if (mbutton->menubutton.cascadeEnabled)
1595 {
1596 XtAddEventHandler (XtParent(mbutton), EnterWindowMask, FALSE,
1597 (XtEventHandler)EnterParentsWindow, mbutton);
1598 return;
1599 }
1600 }
1601
1602 if (mbutton->menubutton.inverted)
1603 NonInverted(mbutton);
1604 }
1605
1606 if ((mbutton->menubutton.hint != NULL) &&
1607 (mbutton->menubutton.hintProc != NULL)) {
1608 mbutton->menubutton.hintProc("");
1609 }
1610 }
1611
1612 /*************************************<->*************************************
1613 *
1614 * Moved
1615 *
1616 * Description:
1617 * -----------
1618 *
1619 * Inputs:
1620 * ------
1621 *
1622 * Outputs:
1623 * -------
1624 *
1625 * Procedures Called
1626 * -----------------
1627 * XQueryPointer
1628 * XtCallCallbacks
1629 *
1630 *************************************<->***********************************/
1631
Moved(w,event)1632 static void Moved (w,event)
1633 Widget w;
1634 XEvent * event;
1635
1636 {
1637 XwMenuButtonWidget mbutton = (XwMenuButtonWidget)w;
1638
1639 int xPosition, yPosition;
1640 int xroot, yroot;
1641 Window root, child;
1642 unsigned int mask;
1643 XwunselectParams params;
1644
1645 XButtonPressedEvent * buttonEvent = (XButtonPressedEvent *) event;
1646
1647 #ifdef DEBUG
1648 printf ("Moved %s\n", w->core.name);
1649 #endif
1650
1651 /*
1652 * only do this if I have a cascade showing
1653 */
1654 if ((mbutton->menubutton.cascadeOn) &&
1655 (mbutton->primitive.traversal_type == XwHIGHLIGHT_OFF))
1656 {
1657 /*
1658 * if there is a menu manager and the cascade has not been popped up,
1659 * then ask the menu manager if it should be popped up
1660 */
1661 if ((mbutton->menubutton.menuMgr == NULL) ||
1662 (mbutton->menubutton.cascadeEnabled == TRUE) ||
1663 (*(((XwMenuMgrWidgetClass)
1664 XtClass(mbutton->menubutton.menuMgr))->menu_mgr_class.doICascade))
1665 (mbutton->menubutton.menuMgr, mbutton))
1666 {
1667 /*
1668 * check if the event appears to have occurred in the cascade area
1669 */
1670 if ((mbutton->menubutton.cascadeEnabled) ||
1671 ((buttonEvent->y > 0) &&
1672 (buttonEvent->y < mbutton->core.height +
1673 2 * mbutton->core.border_width) &&
1674 (buttonEvent->x < mbutton->core.width +
1675 2 * mbutton->core.border_width) &&
1676 (buttonEvent->x > mbutton->core.width +
1677 2 * mbutton->core.border_width -
1678 XwCASCADEWIDTH -
1679 mbutton->primitive.highlight_thickness -
1680 mbutton->button.internal_width)))
1681 {
1682 /*
1683 * Verify that its really in the cascade area
1684 */
1685 XQueryPointer (XtDisplay(mbutton), mbutton->core.window,
1686 &root, &child, &xroot, &yroot, &xPosition,
1687 &yPosition, &mask);
1688
1689 if ((yPosition > 0) &&
1690 (yPosition < mbutton->core.height +
1691 2 * mbutton->core.border_width) &&
1692 (xPosition < mbutton->core.width +
1693 2 * mbutton->core.border_width) &&
1694 (xPosition > mbutton->core.width +
1695 2 * mbutton->core.border_width - XwCASCADEWIDTH -
1696 mbutton->primitive.highlight_thickness -
1697 mbutton->button.internal_width))
1698 {
1699 if (!mbutton->menubutton.cascadeEnabled)
1700 {
1701 XtCallCallbacks ((Widget)mbutton, XtNcascadeSelect, NULL);
1702 #ifdef DEBUG
1703 printf ("enabled\n");
1704 #endif
1705 mbutton->menubutton.cascadeEnabled = TRUE;
1706 }
1707 }
1708 else if (mbutton->menubutton.cascadeEnabled)
1709 {
1710 params.rootX = xroot;
1711 params.rootY = yroot;
1712 params.remainHighlighted = FALSE;
1713 #ifdef DEBUG
1714 printf ("Moved rootX %d rootY %d\n", params.rootX, params.rootY);
1715 #endif
1716 XtCallCallbacks ((Widget)mbutton, XtNcascadeUnselect, ¶ms);
1717 mbutton->menubutton.cascadeEnabled = params.remainHighlighted;
1718 }
1719 }
1720 }
1721 }
1722 }
1723
1724 /*************************************<->*************************************
1725 *
1726 * Redisplay (w, event)
1727 *
1728 * Description:
1729 * -----------
1730 * Cause the widget, identified by w, to be redisplayed.
1731 *
1732 * Inputs:
1733 * ------
1734 * w = widget to be redisplayed;
1735 * event = event structure identifying need for redisplay on this
1736 * widget.
1737 *
1738 * Outputs:
1739 * -------
1740 *
1741 * Procedures Called
1742 * -----------------
1743 * Inverted
1744 * NonInverted
1745 * _XwHighlightBorder
1746 * _XwUnhighlightBorder
1747 *
1748 *************************************<->***********************************/
1749
Redisplay(w,event)1750 static void Redisplay(w, event)
1751 Widget w;
1752 XEvent *event;
1753 {
1754 XwMenuButtonWidget mbutton = (XwMenuButtonWidget) w;
1755
1756 /*
1757 * if the highlight state has changed since the last redisplay,
1758 * update the window and set the font GC.
1759 */
1760 if (mbutton->menubutton.inverted)
1761 Inverted(mbutton);
1762
1763 else
1764 NonInverted(mbutton);
1765
1766 if (mbutton->primitive.highlighted)
1767 _XwHighlightBorder(mbutton);
1768
1769 else
1770 if (mbutton->primitive.display_highlighted)
1771 _XwUnhighlightBorder(mbutton);
1772 }
1773
1774 /*************************************<->*************************************
1775 *
1776 * SetValues(urrent, request, new)
1777 *
1778 * Description:
1779 * -----------
1780 * This is the set values procedure for the menubutton class. It is
1781 * called last (the set values rtnes for its superclasses are called
1782 * first).
1783 *
1784 *
1785 * Inputs:
1786 * ------
1787 * current = original widget;
1788 * request = copy of current (?);
1789 * new = copy of request which reflects changes made to it by
1790 * set values procedures of its superclasses;
1791 *
1792 * Outputs:
1793 * -------
1794 *
1795 * Procedures Called
1796 * -----------------
1797 *
1798 *************************************<->***********************************/
1799
SetValues(current,request,new)1800 static Boolean SetValues (current, request, new)
1801 Widget current, request, new;
1802 {
1803 XtWidgetGeometry reqGeo;
1804 XtWidgetGeometry replyGeo;
1805 XwMenuButtonWidget curmbutton = (XwMenuButtonWidget) current;
1806 XwMenuButtonWidget newmbutton = (XwMenuButtonWidget) new;
1807 Boolean flag = FALSE; /* our return value */
1808 Dimension dim;
1809 KeySym tempKeysym;
1810
1811 /* We never allow our traversal state to change using SetValues() */
1812 newmbutton->primitive.traversal_type = curmbutton->primitive.traversal_type;
1813
1814 /*
1815 * If the accelerator string changed, malloc space for the string
1816 * and copy it to our space. The old string must be freed.
1817 */
1818
1819 if (curmbutton->menubutton.accelerator !=
1820 newmbutton->menubutton.accelerator)
1821 {
1822 if (newmbutton->menubutton.accelerator)
1823 {
1824 if (_XwMapKeyEvent (newmbutton->menubutton.accelerator,
1825 &newmbutton->menubutton.accelEventType,
1826 &tempKeysym,
1827 &newmbutton->menubutton.accelModifiers)
1828 == FALSE)
1829 {
1830 /* Invalid string; revert to previous one */
1831 XtWarning
1832 ("MenuButton: Invalid accelerator; using previous setting");
1833 newmbutton->menubutton.accelerator =
1834 curmbutton->menubutton.accelerator;
1835 newmbutton->menubutton.accelEventType =
1836 curmbutton->menubutton.accelEventType;
1837 newmbutton->menubutton.accelDetail =
1838 curmbutton->menubutton.accelDetail;
1839 newmbutton->menubutton.accelModifiers =
1840 curmbutton->menubutton.accelModifiers;
1841 }
1842 else
1843 {
1844 /* valid string */
1845 newmbutton->menubutton.accelDetail = XKeysymToKeycode (
1846 XtDisplay(newmbutton), tempKeysym);
1847 newmbutton->menubutton.accelerator =
1848 strcpy(XtMalloc((unsigned)
1849 (XwStrlen(newmbutton->menubutton.accelerator)+1)),
1850 newmbutton->menubutton.accelerator);
1851
1852 if (newmbutton->menubutton.menuMgr)
1853 (*(((XwMenuMgrWidgetClass)
1854 XtClass (newmbutton->menubutton.menuMgr))->
1855 menu_mgr_class.setSelectAccelerator))
1856 (newmbutton->menubutton.menuMgr, (Widget)newmbutton,
1857 newmbutton->menubutton.accelerator,
1858 newmbutton->menubutton.accelEventType,
1859 newmbutton->menubutton.accelDetail,
1860 newmbutton->menubutton.accelModifiers);
1861
1862 if (curmbutton->menubutton.accelerator)
1863 XtFree ((char *) curmbutton->menubutton.accelerator);
1864 }
1865 }
1866 else if (curmbutton->menubutton.accelerator)
1867 {
1868 if (curmbutton->menubutton.menuMgr)
1869 (*(((XwMenuMgrWidgetClass)
1870 XtClass(curmbutton->menubutton.menuMgr))->
1871 menu_mgr_class.clearSelectAccelerator))
1872 (curmbutton->menubutton.menuMgr, (Widget)curmbutton);
1873
1874 XtFree ((char *) curmbutton->menubutton.accelerator);
1875 }
1876 }
1877
1878 /*
1879 * Determine if the mnemonic changed, verify and malloc space.
1880 * Notify menuMgr of the change.
1881 */
1882
1883 if (curmbutton->menubutton.mnemonic != newmbutton->menubutton.mnemonic)
1884 {
1885 if (newmbutton->menubutton.mnemonic)
1886 {
1887 if (*(newmbutton->menubutton.mnemonic) == '\0')
1888 {
1889 XtWarning
1890 ("MenuButton: Invalid mnemonic; using previous setting");
1891 newmbutton->menubutton.mnemonic = curmbutton->menubutton.mnemonic;
1892 }
1893 else
1894 {
1895 char mne = newmbutton->menubutton.mnemonic[0];
1896
1897 newmbutton->menubutton.mnemonic = (String)XtMalloc(2);
1898 newmbutton->menubutton.mnemonic[0] = mne;
1899 newmbutton->menubutton.mnemonic[1] = '\0';
1900
1901 if (newmbutton->menubutton.menuMgr)
1902 (*(((XwMenuMgrWidgetClass)
1903 XtClass (newmbutton->menubutton.menuMgr))->
1904 menu_mgr_class.setSelectMnemonic))
1905 (newmbutton->menubutton.menuMgr, (Widget)newmbutton,
1906 newmbutton->menubutton.mnemonic);
1907
1908 XtFree (curmbutton->menubutton.mnemonic);
1909 }
1910 }
1911 else
1912 {
1913 if (newmbutton->menubutton.menuMgr)
1914 (*(((XwMenuMgrWidgetClass)
1915 XtClass (curmbutton->menubutton.menuMgr))->
1916 menu_mgr_class.clearSelectMnemonic))
1917 (curmbutton->menubutton.menuMgr, (Widget)curmbutton);
1918
1919 XtFree(curmbutton->menubutton.mnemonic);
1920 }
1921 }
1922
1923 /*
1924 * recalculate the underline parameters if mnemonic or font changes
1925 */
1926 if ((newmbutton->menubutton.mnemonic != curmbutton->menubutton.mnemonic) ||
1927 (newmbutton->button.font != curmbutton->button.font))
1928 {
1929 SetUnderline (newmbutton);
1930 flag = TRUE;
1931 }
1932
1933
1934 /*
1935 * If the foreground or background changed, or the color or stipple
1936 * declaration was changed, recreate the GC's
1937 */
1938 if ((newmbutton->primitive.foreground !=
1939 curmbutton->primitive.foreground) ||
1940 (newmbutton->core.background_pixel !=
1941 curmbutton->core.background_pixel) ||
1942 (newmbutton->menubutton.rectColor !=
1943 curmbutton->menubutton.rectColor) ||
1944 (newmbutton->menubutton.rectStipple !=
1945 curmbutton->menubutton.rectStipple))
1946 {
1947 GetGC (newmbutton);
1948 XtDestroyGC (curmbutton->menubutton.defPixmap_GC);
1949 XtDestroyGC (curmbutton->menubutton.invertPixmap_GC);
1950 }
1951
1952 /*
1953 * If the GCs are new, or the images are new, create new pixmaps
1954 */
1955 if ((newmbutton->menubutton.markImage !=
1956 curmbutton->menubutton.markImage) ||
1957 (newmbutton->primitive.foreground !=
1958 curmbutton->primitive.foreground) ||
1959 (newmbutton->core.background_pixel !=
1960 curmbutton->core.background_pixel))
1961 {
1962 if (!newmbutton->menubutton.markImage)
1963 newmbutton->menubutton.markImage =
1964 newmbutton->menubutton.defMarkImage;
1965
1966 CreatePixmap(newmbutton, newmbutton->menubutton.markImage,
1967 &newmbutton->menubutton.markPixmap,
1968 &newmbutton->menubutton.invertMarkPixmap);
1969 flag = TRUE;
1970 }
1971
1972 if ((newmbutton->menubutton.cascadeImage !=
1973 curmbutton->menubutton.cascadeImage) ||
1974 (newmbutton->primitive.foreground !=
1975 curmbutton->primitive.foreground) ||
1976 (newmbutton->core.background_pixel !=
1977 curmbutton->core.background_pixel))
1978 {
1979 if (!newmbutton->menubutton.cascadeImage)
1980 newmbutton->menubutton.cascadeImage =
1981 newmbutton->menubutton.defCascadeImage;
1982
1983 CreatePixmap(newmbutton, newmbutton->menubutton.cascadeImage,
1984 &newmbutton->menubutton.cascadePixmap,
1985 &newmbutton->menubutton.invertCascadePixmap);
1986 flag = TRUE;
1987 }
1988
1989 if ((newmbutton->menubutton.labelImage !=
1990 curmbutton->menubutton.labelImage) ||
1991 (newmbutton->primitive.foreground !=
1992 curmbutton->primitive.foreground) ||
1993 (newmbutton->core.background_pixel !=
1994 curmbutton->core.background_pixel))
1995 {
1996 CreatePixmap(newmbutton, newmbutton->menubutton.labelImage,
1997 &newmbutton->menubutton.labelPixmap,
1998 &newmbutton->menubutton.invertLabelPixmap);
1999
2000 if (newmbutton->menubutton.labelType == XwIMAGE)
2001 flag = TRUE;
2002 }
2003
2004 if ((newmbutton->core.sensitive != curmbutton->core.sensitive) ||
2005 (newmbutton->core.ancestor_sensitive !=
2006 curmbutton->core.ancestor_sensitive))
2007 {
2008 if (curmbutton->menubutton.menuMgr)
2009 {
2010 (*(((XwMenuMgrWidgetClass)
2011 XtClass(curmbutton->menubutton.menuMgr))->
2012 menu_mgr_class.btnSensitivityChanged))
2013 (curmbutton->menubutton.menuMgr, (Widget)newmbutton);
2014 }
2015 }
2016
2017 /*
2018 * fields that change that cause a redraw
2019 */
2020 if ((newmbutton->menubutton.labelType !=
2021 curmbutton->menubutton.labelType) ||
2022 (newmbutton->menubutton.setMark !=
2023 curmbutton->menubutton.setMark) ||
2024 (newmbutton->menubutton.cascadeOn !=
2025 curmbutton->menubutton.cascadeOn) ||
2026 (newmbutton->menubutton.mgrOverrideMnemonic !=
2027 curmbutton->menubutton.mgrOverrideMnemonic) ||
2028 (newmbutton->menubutton.rectColor !=
2029 curmbutton->menubutton.rectColor) ||
2030 (newmbutton->menubutton.rectStipple !=
2031 curmbutton->menubutton.rectStipple))
2032
2033
2034 flag = TRUE;
2035
2036
2037 /**********************************************************************
2038 * Calculate the window size: The assumption here is that if
2039 * the width and height are the same in the new and current instance
2040 * record that those fields were not changed with set values. Therefore
2041 * its okay to recompute the necessary width and height. However, if
2042 * the new and current do have different width/heights then leave them
2043 * alone because that's what the user wants.
2044 *********************************************************************/
2045
2046 /* "noPad" option prevents button from resizing itself 2/24/00 --Tim */
2047
2048 if (curmbutton->core.width == request->core.width &&
2049 curmbutton->menubutton.noPad == False)
2050 {
2051 IdealWidth (newmbutton, &newmbutton->core.width);
2052 flag = TRUE;
2053 }
2054 else if (request->core.width <= 0)
2055 {
2056 XtWarning ("MenuButton: Invalid width; using previous setting");
2057 newmbutton->core.width = curmbutton->core.width;
2058 }
2059
2060 if (curmbutton->core.height == request->core.height &&
2061 curmbutton->menubutton.noPad == False)
2062 {
2063 newmbutton->core.height = ComputeHeight(newmbutton);
2064 flag = TRUE;
2065 }
2066 else if (request->core.height <= 0)
2067 {
2068 XtWarning ("MenuButton: Invalid height; using previous setting");
2069 newmbutton->core.height = curmbutton->core.height;
2070 }
2071
2072 return (flag);
2073 }
2074
2075 /*************************************<->*************************************
2076 *
2077 * Resize(w)
2078 *
2079 * Description:
2080 * -----------
2081 * A resize event has been generated. Recompute location of button
2082 * elements.
2083 *
2084 * Inputs:
2085 * ------
2086 * w = widget to be resized.
2087 *
2088 * Outputs:
2089 * -------
2090 *
2091 * Procedures Called
2092 * -----------------
2093 *
2094 *************************************<->***********************************/
2095
Resize(w)2096 static void Resize(w)
2097 Widget w;
2098 {
2099
2100 XwMenuButtonWidget mbutton = (XwMenuButtonWidget) w;
2101
2102 ComputeVertical(mbutton);
2103 SetUnderline(mbutton);
2104 }
2105
2106
2107 /*************************************<->*************************************
2108 *
2109 * SetTraversalType(w)
2110 *
2111 * Description:
2112 * -----------
2113 *
2114 * Inputs:
2115 * ------
2116 *
2117 * Outputs:
2118 * -------
2119 *
2120 * Procedures Called
2121 * -----------------
2122 *
2123 *************************************<->***********************************/
2124
SetTraversalType(w,highlight_mode)2125 static void SetTraversalType (w, highlight_mode)
2126
2127 Widget w;
2128 int highlight_mode;
2129
2130 {
2131
2132 XwMenuButtonWidget mbutton = (XwMenuButtonWidget) w;
2133
2134 mbutton->primitive.traversal_type = highlight_mode;
2135
2136 if (highlight_mode == XwHIGHLIGHT_TRAVERSAL)
2137 {
2138 XtAugmentTranslations (w, XwprimitiveClassRec.primitive_class.
2139 translations);
2140 w->core.widget_class->core_class.visible_interest = True;
2141 }
2142 }
2143
2144
2145 /*************************************<->*************************************
2146 *
2147 * TraverseRight(w, event)
2148 *
2149 * Description:
2150 * -----------
2151 *
2152 * Inputs:
2153 * ------
2154 *
2155 * Outputs:
2156 * -------
2157 *
2158 * Procedures Called
2159 * -----------------
2160 *
2161 *************************************<->***********************************/
2162
TraverseRight(w,event)2163 static void TraverseRight (w, event)
2164
2165 XwMenuButtonWidget w;
2166 XEvent * event;
2167
2168 {
2169 /*
2170 * Ask the menu manager to traverse to the next menupane, if we
2171 * have a cascade.
2172 */
2173
2174 if ((w->menubutton.cascadeOn) && (w->menubutton.menuMgr) &&
2175 (w->primitive.I_have_traversal) && (_XwUniqueEvent (event)))
2176 {
2177 (*(((XwMenuMgrWidgetClass)
2178 XtClass(w->menubutton.menuMgr))->menu_mgr_class.traverseRight))
2179 (w->menubutton.menuMgr, event);
2180 }
2181 }
2182
2183
2184 /*************************************<->*************************************
2185 *
2186 * TraverseLeft(w, event)
2187 *
2188 * Description:
2189 * -----------
2190 *
2191 * Inputs:
2192 * ------
2193 *
2194 * Outputs:
2195 * -------
2196 *
2197 * Procedures Called
2198 * -----------------
2199 *
2200 *************************************<->***********************************/
2201
TraverseLeft(w,event)2202 static void TraverseLeft (w, event)
2203
2204 XwMenuButtonWidget w;
2205 XEvent * event;
2206
2207 {
2208 /*
2209 * Ask the menu manager to traverse to the previous menupane.
2210 */
2211
2212 if ((w->menubutton.menuMgr) && (_XwUniqueEvent (event)) &&
2213 (w->primitive.I_have_traversal))
2214 {
2215 (*(((XwMenuMgrWidgetClass)
2216 XtClass(w->menubutton.menuMgr))->menu_mgr_class.traverseLeft))
2217 (w->menubutton.menuMgr, event);
2218 }
2219 }
2220
2221
2222 /*************************************<->*************************************
2223 *
2224 * TraverseNext(w, event)
2225 *
2226 * Description:
2227 * -----------
2228 *
2229 * Inputs:
2230 * ------
2231 *
2232 * Outputs:
2233 * -------
2234 *
2235 * Procedures Called
2236 * -----------------
2237 *
2238 *************************************<->***********************************/
2239
TraverseNext(w,event)2240 static void TraverseNext (w, event)
2241
2242 XwMenuButtonWidget w;
2243 XEvent * event;
2244
2245 {
2246 /*
2247 * Ask the menu manager to traverse to the previous menupane.
2248 */
2249
2250 if ((w->menubutton.menuMgr) && (_XwUniqueEvent (event)) &&
2251 (w->primitive.I_have_traversal))
2252 {
2253 (*(((XwMenuMgrWidgetClass)
2254 XtClass(w->menubutton.menuMgr))->menu_mgr_class.traverseNext))
2255 (w->menubutton.menuMgr, event);
2256 }
2257 }
2258
2259
2260 /*************************************<->*************************************
2261 *
2262 * TraversePrev(w, event)
2263 *
2264 * Description:
2265 * -----------
2266 *
2267 * Inputs:
2268 * ------
2269 *
2270 * Outputs:
2271 * -------
2272 *
2273 * Procedures Called
2274 * -----------------
2275 *
2276 *************************************<->***********************************/
2277
TraversePrev(w,event)2278 static void TraversePrev (w, event)
2279
2280 XwMenuButtonWidget w;
2281 XEvent * event;
2282
2283 {
2284 /*
2285 * Ask the menu manager to traverse to the previous menupane.
2286 */
2287
2288 if ((w->menubutton.menuMgr) && (_XwUniqueEvent (event)) &&
2289 (w->primitive.I_have_traversal))
2290 {
2291 (*(((XwMenuMgrWidgetClass)
2292 XtClass(w->menubutton.menuMgr))->menu_mgr_class.traversePrev))
2293 (w->menubutton.menuMgr, event);
2294 }
2295 }
2296
2297
2298 /*************************************<->*************************************
2299 *
2300 * TraverseHome(w)
2301 *
2302 * Description:
2303 * -----------
2304 *
2305 * Inputs:
2306 * ------
2307 *
2308 * Outputs:
2309 * -------
2310 *
2311 * Procedures Called
2312 * -----------------
2313 *
2314 *************************************<->***********************************/
2315
TraverseHome(w,event)2316 static void TraverseHome (w, event)
2317
2318 XwMenuButtonWidget w;
2319 XEvent * event;
2320
2321 {
2322 /*
2323 * Ask the menu manager to traverse to the first menupane.
2324 */
2325
2326 if ((w->menubutton.menuMgr) && (_XwUniqueEvent (event)) &&
2327 (w->primitive.I_have_traversal))
2328 {
2329 (*(((XwMenuMgrWidgetClass)
2330 XtClass(w->menubutton.menuMgr))->menu_mgr_class.traverseHome))
2331 (w->menubutton.menuMgr, event);
2332 }
2333 }
2334
2335
2336 /*************************************<->*************************************
2337 *
2338 * TraverseUp(w)
2339 *
2340 * Description:
2341 * -----------
2342 *
2343 * Inputs:
2344 * ------
2345 *
2346 * Outputs:
2347 * -------
2348 *
2349 * Procedures Called
2350 * -----------------
2351 *
2352 *************************************<->***********************************/
2353
TraverseUp(w,event)2354 static void TraverseUp (w, event)
2355
2356 XwMenuButtonWidget w;
2357 XEvent * event;
2358
2359 {
2360 /*
2361 * Ask the menu manager to traverse up one menu button
2362 */
2363
2364 if ((w->menubutton.menuMgr) && (_XwUniqueEvent (event)) &&
2365 (w->primitive.I_have_traversal))
2366 {
2367 (*(((XwMenuMgrWidgetClass)
2368 XtClass(w->menubutton.menuMgr))->menu_mgr_class.traverseUp))
2369 (w->menubutton.menuMgr, event);
2370 }
2371 }
2372
2373
2374 /*************************************<->*************************************
2375 *
2376 * TraverseDown(w)
2377 *
2378 * Description:
2379 * -----------
2380 *
2381 * Inputs:
2382 * ------
2383 *
2384 * Outputs:
2385 * -------
2386 *
2387 * Procedures Called
2388 * -----------------
2389 *
2390 *************************************<->***********************************/
2391
TraverseDown(w,event)2392 static void TraverseDown (w, event)
2393
2394 XwMenuButtonWidget w;
2395 XEvent * event;
2396
2397 {
2398 /*
2399 * Ask the menu manager to traverse down one menu button
2400 */
2401
2402 if ((w->menubutton.menuMgr) && (_XwUniqueEvent (event)) &&
2403 (w->primitive.I_have_traversal))
2404 {
2405 (*(((XwMenuMgrWidgetClass)
2406 XtClass(w->menubutton.menuMgr))->menu_mgr_class.traverseDown))
2407 (w->menubutton.menuMgr, event);
2408 }
2409 }
2410
2411
2412 /*************************************<->*************************************
2413 *
2414 * TraverseNextTop(w)
2415 *
2416 * Description:
2417 * -----------
2418 *
2419 * Inputs:
2420 * ------
2421 *
2422 * Outputs:
2423 * -------
2424 *
2425 * Procedures Called
2426 * -----------------
2427 *
2428 *************************************<->***********************************/
2429
TraverseNextTop(w,event)2430 static void TraverseNextTop (w, event)
2431
2432 XwMenuButtonWidget w;
2433 XEvent * event;
2434
2435 {
2436 /*
2437 * Ask the menu manager to traverse to the next top level menupane
2438 */
2439
2440 if ((w->menubutton.menuMgr) && (_XwUniqueEvent (event)) &&
2441 (w->primitive.I_have_traversal))
2442 {
2443 (*(((XwMenuMgrWidgetClass)
2444 XtClass(w->menubutton.menuMgr))->menu_mgr_class.traverseNextTop))
2445 (w->menubutton.menuMgr, event);
2446 }
2447 }
2448
2449
2450 /************************************************************************
2451 *
2452 * _XwExtractTime
2453 * Extract the time field from the event structure.
2454 *
2455 ************************************************************************/
2456
_XwExtractTime(event)2457 static Time _XwExtractTime (event)
2458
2459 XEvent * event;
2460
2461 {
2462 if ((event->type == ButtonPress) || (event->type == ButtonRelease))
2463 return (event->xbutton.time);
2464
2465 if ((event->type == KeyPress) || (event->type == KeyRelease))
2466 return (event->xkey.time);
2467
2468 return ((Time) 0);
2469 }
2470
2471
_XwUniqueEvent(event)2472 Boolean _XwUniqueEvent (event)
2473
2474 XEvent * event;
2475
2476 {
2477 static unsigned long serial = 0;
2478 static Time time = 0;
2479 static int type = 0;
2480 Time newTime;
2481
2482 /*
2483 * Ignore duplicate events, caused by an event being dispatched
2484 * to both the focus widget and the spring-loaded widget, where
2485 * these map to the same widget (menus).
2486 */
2487 if ((time != (newTime = _XwExtractTime (event))) ||
2488 (type != event->type) ||
2489 (serial != event->xany.serial))
2490 {
2491 /* Save the fingerprints for the new event */
2492 type = event->type;
2493 serial = event->xany.serial;
2494 time = newTime;
2495
2496 return (TRUE);
2497 }
2498
2499 return (FALSE);
2500 }
2501
2502
2503 /*************************************<->*************************************
2504 *
2505 * Visibility(parameters)
2506 *
2507 * Description:
2508 * -----------
2509 * xxxxxxxxxxxxxxxxxxxxxxx
2510 *
2511 *
2512 * Inputs:
2513 * ------
2514 * xxxxxxxxxxxx = xxxxxxxxxxxxx
2515 *
2516 * Outputs:
2517 * -------
2518 * xxxxxxxxxxxx = xxxxxxxxxxxxx
2519 *
2520 * Procedures Called
2521 * -----------------
2522 *
2523 *************************************<->***********************************/
2524
Visibility(widget,event)2525 static void Visibility (widget, event)
2526
2527 Widget widget;
2528 XEvent * event;
2529
2530 {
2531 /*
2532 * Noop; purpose is to prevent Primitive's translation from
2533 * taking effect.
2534 */
2535 }
2536
2537
2538 /*************************************<->*************************************
2539 *
2540 * Unmap(parameters)
2541 *
2542 * Description:
2543 * -----------
2544 * xxxxxxxxxxxxxxxxxxxxxxx
2545 *
2546 *
2547 * Inputs:
2548 * ------
2549 * xxxxxxxxxxxx = xxxxxxxxxxxxx
2550 *
2551 * Outputs:
2552 * -------
2553 * xxxxxxxxxxxx = xxxxxxxxxxxxx
2554 *
2555 * Procedures Called
2556 * -----------------
2557 *
2558 *************************************<->***********************************/
2559
Unmap(widget,event)2560 static void Unmap (widget, event)
2561
2562 Widget widget;
2563 XEvent * event;
2564
2565 {
2566 /*
2567 * Noop; purpose is to prevent Primitive's translation from
2568 * taking effect.
2569 */
2570 }
2571