1 /**
2 *
3 * $Header: /cvsroot/lesstif/lesstif/lib/Xm-2.1/CascadeBG.c,v 1.1 2004/08/28 19:22:43 dannybackx Exp $
4 *
5 * Copyright (C) 1995 Free Software Foundation, Inc.
6 * Copyright � 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 LessTif Development Team
7 *
8 * This file is part of the GNU LessTif Library.
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
19 *
20 * You should have received a copy of the GNU Library General Public
21 * License along with this library; if not, write to the Free
22 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 **/
25
26 static const char rcsid[] = "$Header: /cvsroot/lesstif/lesstif/lib/Xm-2.1/CascadeBG.c,v 1.1 2004/08/28 19:22:43 dannybackx Exp $";
27
28 #include <LTconfig.h>
29
30 #include <stdarg.h>
31 #include <string.h>
32
33 #include <XmI/XmI.h>
34 #include <Xm/XmP.h>
35 #include <Xm/CacheP.h>
36 #include <Xm/CascadeB.h> /* For XmCascadeButtonHighlight */
37 #include <Xm/CascadeBP.h>
38 #include <Xm/CascadeBGP.h>
39 #include <Xm/ManagerP.h>
40 #include <Xm/MenuShellP.h>
41 #include <Xm/RowColumnP.h>
42 #include <Xm/ScreenP.h>
43 #include <Xm/MenuUtilP.h>
44
45 #include <XmI/DebugUtil.h>
46
47 #define CASCADE_SPACING 4
48
49 /* Forward Declarations */
50
51 static void class_initialize(void);
52
53 static void class_part_initialize(WidgetClass w_class);
54
55 static void initialize(Widget request, Widget new_w,
56 ArgList args, Cardinal *num_args);
57
58 static void resize(Widget w);
59
60 static void destroy(Widget w);
61
62 static void expose(Widget w, XEvent *event, Region region);
63
64 static Boolean set_values(Widget current, Widget request, Widget new_w,
65 ArgList args, Cardinal *num_args);
66
67 static void input_dispatch(Widget gadget, XEvent *event, Mask event_mask);
68
69 static Boolean visual_change(Widget w, Widget parent, Widget n);
70
71 static void secondary_object_create(Widget request, Widget new_w,
72 ArgList args, Cardinal *num_args);
73
74 static void initialize_posthook(Widget request, Widget new_w,
75 ArgList args, Cardinal *num_args);
76
77 static Boolean set_values_prehook(Widget old, Widget request, Widget new_w,
78 ArgList args, Cardinal *num_args);
79
80 static Boolean set_values_posthook(Widget old, Widget request, Widget new_w,
81 ArgList args, Cardinal *num_args);
82
83 static void get_values_prehook(Widget new_w,
84 ArgList args, Cardinal *num_args);
85
86 static void get_values_posthook(Widget new_w,
87 ArgList args, Cardinal *num_args);
88
89 static Cardinal get_sec_res_data(WidgetClass wc,
90 XmSecondaryResourceData **data);
91
92 extern int _XmCascadeBCacheCompare(XtPointer A, XtPointer B);
93
94 static void DelayedArm(Widget w, XEvent *event,
95 String *params, Cardinal *num_params);
96
97 static void CheckDisarm(Widget w, XEvent *event,
98 String *params, Cardinal *num_params);
99
100 static void ArmAndActivate(Widget w, XEvent *event,
101 String *params, Cardinal *num_params);
102
103 static void MenuProcEntry(int proc, Widget rc,...);
104
105 static void CascadePopupHandler(XtPointer clientData, XtIntervalId *id);
106
107 /*
108 * cache resources
109 */
110 #define Offset(field) XtOffsetOf(XmCascadeButtonGCacheObjRec, \
111 cascade_button_cache.field)
112 static XtResource cache_resources[] =
113 {
114 {
115 XmNcascadePixmap, XmCPixmap, XmRGadgetPixmap,
116 sizeof(Pixmap), Offset(cascade_pixmap),
117 XmRImmediate, (XtPointer)XmUNSPECIFIED_PIXMAP
118 },
119 {
120 XmNmappingDelay, XmCMappingDelay, XmRInt,
121 sizeof(int), Offset(map_delay),
122 XmRImmediate, (XtPointer)180
123 }
124 };
125
126 XmCascadeButtonGCacheObjClassRec xmCascadeButtonGCacheObjClassRec = {
127 /* Object class part */
128 {
129 /* superclass */ (WidgetClass) &xmLabelGCacheObjClassRec,
130 /* class_name */ "XmCascadeButtonGCacheObjClass",
131 /* widget_size */ sizeof(XmCascadeButtonGCacheObjRec),
132 /* class_initialize */ NULL,
133 /* class_part_initialize */ NULL,
134 /* class_inited */ False,
135 /* initialize */ NULL,
136 /* initialize_hook */ NULL,
137 /* realize */ NULL,
138 /* actions */ NULL,
139 /* num_actions */ 0,
140 /* resources */ cache_resources,
141 /* num_resources */ XtNumber(cache_resources),
142 /* xrm_class */ NULLQUARK,
143 /* compress_motion */ 0,
144 /* compress_exposure */ 0,
145 /* compress_enterleave */ 0,
146 /* visible_interest */ 0,
147 /* destroy */ NULL,
148 /* resize */ NULL,
149 /* expose */ NULL,
150 /* set_values */ NULL,
151 /* set_values_hook */ NULL,
152 /* set_values_almost */ NULL,
153 /* get_values_hook */ NULL,
154 /* accept_focus */ NULL,
155 /* version */ XtVersionDontCheck,
156 /* callback offsets */ NULL,
157 /* tm_table */ NULL,
158 /* query_geometry */ NULL,
159 /* display_accelerator */ NULL,
160 /* extension */ NULL
161 },
162 /* XmExtObject part */
163 {
164 /* syn_resources */ NULL,
165 /* num_syn_resources */ 0,
166 /* extension */ NULL
167 },
168 /* LabelGCacheObj part */
169 {
170 /* foo */ 0
171 },
172 /* CascadeButtonGCacheObj part */
173 {
174 /* foo */ 0
175 }
176 };
177
178 /*
179 * Resources for the cascadebutton class
180 */
181 #undef Offset
182 #define Offset(field) XtOffsetOf(XmCascadeButtonGadgetRec, cascade_button.field)
183 #define GOffset(field) XtOffsetOf(XmCascadeButtonGadgetRec, gadget.field)
184 static XtResource resources[] = {
185 {
186 XmNactivateCallback, XmCCallback, XmRCallback,
187 sizeof(XtCallbackList), Offset(activate_callback),
188 XmRCallback, (XtPointer)NULL
189 },
190 {
191 XmNcascadingCallback, XmCCallback, XmRCallback,
192 sizeof(XtCallbackList), Offset(cascade_callback),
193 XmRCallback, (XtPointer)NULL
194 },
195 {
196 XmNsubMenuId, XmCMenuWidget, XmRMenuWidget,
197 sizeof(Widget), Offset(submenu),
198 XmRMenuWidget, (XtPointer)NULL
199 },
200 /* resources we override from XmLabelGadget/XmGadget */
201 {
202 XmNshadowThickness, XmCShadowThickness, XmRHorizontalDimension,
203 sizeof(Dimension), GOffset(shadow_thickness),
204 XmRImmediate, (XtPointer)2
205 },
206 {
207 XmNtraversalOn, XmCTraversalOn, XmRBoolean,
208 sizeof(Boolean), GOffset(traversal_on),
209 XmRImmediate, (XtPointer)True
210 },
211 {
212 XmNhighlightThickness, XmCHighlightThickness, XmRHorizontalDimension,
213 sizeof(Dimension), GOffset(highlight_thickness),
214 XmRImmediate, (XtPointer)2
215 },
216 };
217
218 static XmBaseClassExtRec _XmCascadeBGRectClassExtRec = {
219 /* next_extension */ NULL,
220 /* record_type */ NULLQUARK,
221 /* version */ XmBaseClassExtVersion,
222 /* size */ sizeof(XmBaseClassExtRec),
223 /* initialize_prehook */ XmInheritInitializePrehook,
224 /* set_values_prehook */ set_values_prehook,
225 /* initialize_posthook */ initialize_posthook,
226 /* set_values_posthook */ set_values_posthook,
227 /* secondary_object_class */ (WidgetClass)&xmCascadeButtonGCacheObjClassRec,
228 /* secondary_object_create */ secondary_object_create,
229 /* get_secondary_resources */ get_sec_res_data,
230 /* fast_subclass */ { 0 },
231 /* get_values_prehook */ get_values_prehook,
232 /* get_values_posthook */ get_values_posthook,
233 /* class_part_init_prehook */ NULL,
234 /* class_part_init_posthook */ NULL,
235 /* ext_resources */ NULL,
236 /* compiled_ext_resources */ NULL,
237 /* num_ext_resources */ 0,
238 /* use_sub_resources */ False,
239 /* widget_navigable */ XmInheritWidgetNavigable,
240 /* focus_change */ XmInheritFocusChange,
241 /* wrapper_data */ NULL
242 };
243
244 static XmCacheClassPart cache_part = {
245 /* cache head part */
246 {
247 /* next */ NULL,
248 /* prev */ NULL,
249 /* ref_count */ 0
250 },
251 _XmCacheCopy,
252 _XmCacheDelete,
253 _XmCascadeBCacheCompare
254 };
255
256 int _XmArrowPixmapCacheCompare(XtPointer A, XtPointer B);
257
258 static XmCacheClassPart arrow_pixmap_cache = {
259 /* cache head part */
260 {
261 /* next */ NULL,
262 /* prev */ NULL,
263 /* ref_count */ 0
264 },
265 _XmCacheCopy,
266 _XmArrowPixmapCacheDelete,
267 _XmArrowPixmapCacheCompare
268 };
269
270 static XmGadgetClassExtRec _XmCascadeBGGadgetClassExtRec = {
271 /* next_extension */ NULL,
272 /* record_type */ NULLQUARK,
273 /* version */ XmGadgetClassExtVersion,
274 /* size */ sizeof(XmGadgetClassExtRec),
275 /* widget_baseline_proc */ XmInheritBaselineProc,
276 /* display_rect_proc */ XmInheritDisplayRectProc,
277 #if XmVERSION >= 2
278 /* margins_proc */ XmInheritMarginsProc,
279 #endif
280 };
281
282 XmCascadeButtonGadgetClassRec xmCascadeButtonGadgetClassRec = {
283 /* RectObj class part */
284 {
285 /* superclass */ (WidgetClass) &xmLabelGadgetClassRec,
286 /* class_name */ "XmCascadeButtonGadget",
287 /* widget_size */ sizeof(XmCascadeButtonGadgetRec),
288 /* class_initialize */ class_initialize,
289 /* class_part_initialize */ class_part_initialize,
290 /* class_inited */ False,
291 /* initialize */ initialize,
292 /* initialize_hook */ NULL,
293 /* realize */ NULL, /* FIX ME */
294 /* actions */ NULL,
295 /* num_actions */ 0,
296 /* resources */ resources,
297 /* num_resources */ XtNumber(resources),
298 /* xrm_class */ NULLQUARK,
299 /* compress_motion */ True,
300 /* compress_exposure */ XtExposeCompressMaximal,
301 /* compress_enterleave */ True,
302 /* visible_interest */ False,
303 /* destroy */ destroy,
304 /* resize */ resize,
305 /* expose */ expose,
306 /* set_values */ set_values,
307 /* set_values_hook */ NULL,
308 /* set_values_almost */ XtInheritSetValuesAlmost,
309 /* get_values_hook */ NULL,
310 /* accept_focus */ NULL,
311 /* version */ XtVersionDontCheck,
312 /* callback offsets */ NULL,
313 /* tm_table */ NULL,
314 /* query_geometry */ XtInheritQueryGeometry,
315 /* display_accelerator */ NULL,
316 /* extension */ (XtPointer)&_XmCascadeBGRectClassExtRec
317 },
318 /* XmGadget part */
319 {
320 /* border_highlight */ XmInheritBorderHighlight, /* FIX ME */
321 /* border_unhighlight */ XmInheritBorderUnhighlight, /* FIX ME */
322 /* arm_and_activate */ ArmAndActivate,
323 /* input_dispatch */ input_dispatch,
324 /* visual_change */ visual_change,
325 /* syn_resources */ NULL,
326 /* num_syn_resources */ 0,
327 /* cache_part */ &cache_part,
328 /* extension */ (XtPointer)&_XmCascadeBGGadgetClassExtRec
329 },
330 /* XmLabelGadget part */
331 {
332 /* setOverrideCallback */ XmInheritSetOverrideCallback,
333 /* menuProcs */ XmInheritMenuProc,
334 /* extension */ NULL
335 },
336 /* XmCascadeButtonGadget part */
337 {
338 /* extension */ NULL
339 },
340 };
341
342
343 WidgetClass xmCascadeButtonGadgetClass =
344 (WidgetClass)&xmCascadeButtonGadgetClassRec;
345
346 /********************************* CACHE PART *******************************/
347 static void
secondary_object_create(Widget request,Widget new_w,ArgList args,Cardinal * num_args)348 secondary_object_create(Widget request, Widget new_w,
349 ArgList args, Cardinal *num_args)
350 {
351 XmBaseClassExt *bce;
352 XtPointer nsec, rsec;
353 XmWidgetExtData ed;
354 Cardinal size;
355
356 DEBUGOUT(_LtDebug(__FILE__, new_w,
357 "CascadeButtonGCacheRec %s being initialized.\n",
358 XtName(new_w)));
359
360 bce = _XmGetBaseClassExtPtr(XtClass(new_w), XmQmotif);
361
362 size = (*bce)->secondaryObjectClass->core_class.widget_size;
363 nsec = _XmExtObjAlloc(size);
364 rsec = _XmExtObjAlloc(size);
365
366 ((XmExtRec *)nsec)->object.self = (Widget)nsec;
367 ((XmExtRec *)nsec)->object.widget_class = (*bce)->secondaryObjectClass;
368 ((XmExtRec *)nsec)->object.parent = XtParent(new_w);
369 ((XmExtRec *)nsec)->object.xrm_name = new_w->core.xrm_name;
370 ((XmExtRec *)nsec)->object.being_destroyed = False;
371 ((XmExtRec *)nsec)->object.destroy_callbacks = NULL;
372 ((XmExtRec *)nsec)->object.constraints = NULL;
373
374 ExtObj_LogicalParent(nsec) = new_w;
375 ExtObj_ExtensionType(nsec) = XmCACHE_EXTENSION;
376
377 XtGetSubresources(new_w, nsec, NULL, NULL,
378 (*bce)->secondaryObjectClass->core_class.resources,
379 (*bce)->secondaryObjectClass->core_class.num_resources,
380 args, *num_args);
381
382 ed = (XmWidgetExtData)XtMalloc(sizeof(XmWidgetExtDataRec));
383 ed->widget = (Widget)nsec;
384 ed->reqWidget = (Widget)rsec;
385
386 memcpy(rsec, nsec, size);
387
388 ((XmExtRec *)rsec)->object.self = (Widget)rsec;
389
390 _XmPushWidgetExtData(new_w, ed, XmCACHE_EXTENSION);
391
392 LabG_Cache(new_w) = &(((XmLabelGCacheObject)nsec)->label_cache);
393 LabG_Cache(request) = &(((XmLabelGCacheObject)rsec)->label_cache);
394
395 CBG_Cache(new_w) =
396 &(((XmCascadeButtonGCacheObject)nsec)->cascade_button_cache);
397 CBG_Cache(request) =
398 &(((XmCascadeButtonGCacheObject)rsec)->cascade_button_cache);
399 }
400
401 int
_XmCascadeBCacheCompare(XtPointer A,XtPointer B)402 _XmCascadeBCacheCompare(XtPointer A, XtPointer B)
403 {
404 return !memcmp(((XmCascadeButtonGCacheObjPart *)A),
405 ((XmCascadeButtonGCacheObjPart *)B),
406 sizeof(XmCascadeButtonGCacheObjPart));
407 }
408
409 int
_XmArrowPixmapCacheCompare(XtPointer A,XtPointer B)410 _XmArrowPixmapCacheCompare(XtPointer A, XtPointer B)
411 {
412 /* This will get confused by arrow direction and shadow thickness,
413 * which aren't defined in the XmArrowPixmap structure.
414 * But this is how M*tif defines it, so it's too late to do it right.
415 * This will seldom cause confusion, as arrow direction (based on string
416 * direction) is usually consistent throughout an application, and
417 * different shadow thicknesses imply different pixmap sizes (at least
418 * for the same size font).
419 */
420 return !memcmp(A, B, XtOffsetOf(XmArrowPixmap, pixmap));
421 }
422
423 void
_XmArrowPixmapCacheDelete(XtPointer data)424 _XmArrowPixmapCacheDelete(XtPointer data)
425 {
426 XmGadgetCachePtr list;
427
428 /* The pixmap alone isn't sufficient - the display should be passed.
429 * But this is how M*tif defines it...
430 */
431 if ((list = ClassCacheHead(&arrow_pixmap_cache).next))
432 while (list != &ClassCacheHead(&arrow_pixmap_cache))
433 {
434 if (((XmArrowPixmap *)CacheDataPtr(list))->pixmap == (Pixmap)data)
435 {
436 if (!--list->ref_count)
437 {
438 _XmFreeScratchPixmap((XmScreen)XmGetXmScreen(
439 ((XmArrowPixmap *)CacheDataPtr(list))->screen),
440 (Pixmap)data);
441 list->prev->next = list->next;
442 list->next->prev = list->prev;
443 XtFree((char *)list);
444 }
445 return;
446 }
447 list = list->next;
448 }
449
450 _XmWarning(NULL, "_XmArrowPixmapCacheDelete: pixmap not in cache");
451 }
452
453 static Dimension
default_font_height(XmFontList fl)454 default_font_height(XmFontList fl)
455 {
456 XFontStruct *font;
457 Dimension fh;
458
459 #ifdef USE_XFT
460 if (fl->renditions[0]->type == XmFONT_IS_XFT) {
461 fh = fl->renditions[0]->xft_font->height;
462 DEBUGOUT(_LtDebug(__FILE__, NULL, "DefaultFontHeight -> %d\n", fh));
463 return fh;
464 }
465 #endif
466 fh = _XmFontListGetDefaultFont(fl, &font)
467 ? font->ascent + font->descent
468 : 0;
469 DEBUGOUT(_LtDebug(__FILE__, NULL, "DefaultFontHeight -> %d\n", fh));
470 return fh;
471 }
472
473 /* Assumes that the existing pixmaps are freed */
474 void
_XmCreateArrowPixmaps(Widget w)475 _XmCreateArrowPixmaps(Widget w)
476 {
477 Pixel ts, bs;
478 GC tgc, bgc, fgc;
479 XmFontList fl;
480 XmScreen sw;
481 XmArrowPixmap *cp, *acp;
482 Dimension st, th;
483 unsigned char sd;
484 XGCValues values;
485 XmArrowPixmap cpart;
486
487 /* Get info from widget or gadget */
488 if (XmIsGadget(w))
489 {
490 ts = XmParentTopShadowColor(w);
491 bs = XmParentBottomShadowColor(w);
492 values.foreground = XmParentBackground(w);
493 tgc = XmParentTopShadowGC(w);
494 bgc = XmParentBottomShadowGC(w);
495 st = LabG_Shadow(w);
496 sd = LabG_StringDirection(w);
497 fl = LabG_Font(w);
498 }
499 else
500 {
501 ts = Prim_TopShadowColor(w);
502 bs = Prim_BottomShadowColor(w);
503 values.foreground = CoreBackground(w);
504 tgc = Prim_TopShadowGC(w);
505 bgc = Prim_BottomShadowGC(w);
506 st = Lab_Shadow(w);
507 sd = Lab_StringDirection(w);
508 fl = Lab_Font(w);
509 }
510
511 /* Fill in the cache part template */
512 if (!(th = (default_font_height(fl) << 1) / 3))
513 th = 1;
514 cpart.height = cpart.width = th + (st << 1);
515 cpart.foreground_color = values.foreground;
516 cpart.display = XtDisplay(w);
517 cpart.screen = XtScreen(w);
518 cpart.depth = DefaultDepthOfScreen(cpart.screen);
519 cpart.pixmap = XmUNSPECIFIED_PIXMAP;
520
521 /* Get cache records for the normal and armed pixmaps */
522 cpart.top_shadow_color = ts;
523 cpart.bottom_shadow_color = bs;
524 cp = (XmArrowPixmap *)
525 _XmCachePart(&arrow_pixmap_cache, (XtPointer)&cpart, sizeof cpart);
526
527 cpart.top_shadow_color = bs;
528 cpart.bottom_shadow_color = ts;
529 acp = (XmArrowPixmap *)
530 _XmCachePart(&arrow_pixmap_cache, (XtPointer)&cpart, sizeof cpart);
531
532 /* If the cached pixmaps don't exist, create them */
533 if (cp->pixmap == XmUNSPECIFIED_PIXMAP
534 || acp->pixmap == XmUNSPECIFIED_PIXMAP)
535 {
536 fgc = XtGetGC(w, GCForeground, &values);
537 sw = (XmScreen)XmGetXmScreen(cpart.screen);
538
539 if (cp->pixmap == XmUNSPECIFIED_PIXMAP)
540 {
541 cp->pixmap = _XmAllocScratchPixmap(sw, cpart.depth,
542 cpart.width, cpart.height);
543 XFillRectangle(cpart.display, cp->pixmap, fgc, 0, 0,
544 cpart.width, cpart.height);
545
546 _XmDrawArrow(cpart.display, cp->pixmap, tgc, bgc, fgc,
547 st - 1, st - 1, th + 2, th + 2, st,
548 sd == XmSTRING_DIRECTION_L_TO_R
549 ? XmARROW_RIGHT : XmARROW_LEFT);
550 }
551
552 if (acp->pixmap == XmUNSPECIFIED_PIXMAP)
553 {
554 acp->pixmap = _XmAllocScratchPixmap(sw, cpart.depth,
555 cpart.width, cpart.height);
556 XFillRectangle(cpart.display, acp->pixmap, fgc, 0, 0,
557 cpart.width, cpart.height);
558
559 _XmDrawArrow(cpart.display, acp->pixmap, bgc, tgc, fgc,
560 st - 1, st - 1, th + 2, th + 2, st,
561 sd == XmSTRING_DIRECTION_L_TO_R
562 ? XmARROW_RIGHT : XmARROW_LEFT);
563 }
564
565 XtReleaseGC(w, fgc);
566 }
567
568 /* Copy the cached pixmaps into the widget/gadget */
569 if (XmIsGadget(w))
570 {
571 CBG_ArmedPixmap(w) = acp->pixmap;
572 CBG_CascadePixmap(w) = cp->pixmap;
573 }
574 else
575 {
576 CB_ArmedPixmap(w) = acp->pixmap;
577 CB_CascadePixmap(w) = cp->pixmap;
578 }
579 }
580
581 /******************************** GADGET PART *******************************/
582 static void
class_initialize(void)583 class_initialize(void)
584 {
585 XtResourceList combined, labels;
586 int ncom;
587 Cardinal nlabels;
588
589 /* don't let the nulls fool you. look at the header file -- the arg
590 * isn't used. */
591 ClassCacheHead(CBG_ClassCachePart(NULL)).prev =
592 &ClassCacheHead(CBG_ClassCachePart(NULL));
593 ClassCacheHead(CBG_ClassCachePart(NULL)).next =
594 &ClassCacheHead(CBG_ClassCachePart(NULL));
595
596 _XmCascadeBGRectClassExtRec.record_type = XmQmotif;
597
598 /*
599 * Label subclasses (ToggleBG, PushBG, CascadeBG) have a problem. Since
600 * we do all the subpart manipulation in the pre- and post- hooks, and
601 * since those hooks aren't chained, we have to either make multiple
602 * calls to XtGetSubresources/Xt[Get|Set]Subvalues, or merge the resource
603 * lists. Since I just wrote _XmTransformSubresources, seems like a
604 * waste not to use it.
605 */
606 ncom = XtNumber(cache_resources) +
607 xmLabelGCacheObjClassRec.object_class.num_resources;
608
609 _XmTransformSubResources(xmLabelGCacheObjClassRec.object_class.resources,
610 xmLabelGCacheObjClassRec.object_class.num_resources,
611 &labels, &nlabels);
612
613 combined = (XtResourceList)XtMalloc(sizeof(XtResource) * ncom);
614
615 memcpy(combined, labels, nlabels * sizeof(XtResource));
616 memcpy(&combined[nlabels],
617 cache_resources,
618 XtNumber(cache_resources) * sizeof(XtResource));
619
620 XtFree((char *)labels);
621
622 xmCascadeButtonGCacheObjClassRec.object_class.resources = combined;
623 xmCascadeButtonGCacheObjClassRec.object_class.num_resources = ncom;
624 }
625
626 static void
class_part_initialize(WidgetClass widget_class)627 class_part_initialize(WidgetClass widget_class)
628 {
629 _XmFastSubclassInit(widget_class, XmCASCADE_BUTTON_GADGET_BIT);
630 }
631
632 static void
initialize_posthook(Widget request,Widget new_w,ArgList args,Cardinal * num_args)633 initialize_posthook(Widget request, Widget new_w,
634 ArgList args, Cardinal *num_args)
635 {
636 XmWidgetExtData ext;
637
638 DEBUGOUT(_LtDebug(__FILE__, new_w, "CascadeBG InitializePosthook\n"));
639
640 /* don't let the null fool you */
641 LabG_Cache(new_w) = (XmLabelGCacheObjPart *)
642 _XmCachePart(LabG_ClassCachePart(NULL),
643 (XtPointer)LabG_Cache(new_w),
644 sizeof(XmLabelGCacheObjPart));
645 CBG_Cache(new_w) = (XmCascadeButtonGCacheObjPart *)
646 _XmCachePart(CBG_ClassCachePart(NULL),
647 (XtPointer)CBG_Cache(new_w),
648 sizeof(XmCascadeButtonGCacheObjPart));
649
650 _XmPopWidgetExtData(new_w, &ext, XmCACHE_EXTENSION);
651
652 _XmExtObjFree((XtPointer)ext->widget);
653 _XmExtObjFree((XtPointer)ext->reqWidget);
654
655 XtFree((char *)ext);
656 }
657
658 static void
place_cascade(Widget w)659 place_cascade(Widget w)
660 {
661 Position x;
662
663 if (CBG_Submenu(w))
664 {
665 CBG_Cascade_x(w) =
666 LabG_Highlight(w) + LabG_Shadow(w) + LabG_MarginWidth(w);
667 if (LabG_StringDirection(w) == XmSTRING_DIRECTION_L_TO_R)
668 CBG_Cascade_x(w) =
669 XtWidth(w) - CBG_Cascade_x(w) - CBG_Cascade_width(w);
670
671 CBG_Cascade_y(w) = (XtHeight(w) - CBG_Cascade_height(w)) / 2;
672
673 /* Make sure the label and cascade don't overlap */
674
675 if (LabG_StringDirection(w) == XmSTRING_DIRECTION_L_TO_R)
676 {
677 x = CBG_Cascade_x(w) - CASCADE_SPACING - LabG_TextRect_width(w);
678 if (LabG_TextRect_x(w) > x)
679 LabG_TextRect_x(w) = x;
680 }
681 else
682 {
683 x = CBG_Cascade_x(w) + CBG_Cascade_width(w) + CASCADE_SPACING;
684 if (LabG_TextRect_x(w) < x)
685 LabG_TextRect_x(w) = x;
686 }
687 }
688 else
689 {
690 }
691 }
692
693 static void
size_cascade(Widget w)694 size_cascade(Widget w)
695 {
696 int dummy;
697 Window dummyw;
698 unsigned width, height;
699
700 if (CBG_Submenu(w))
701 {
702 if (CBG_CascadePixmap(w) > XmUNSPECIFIED_PIXMAP)
703 {
704 XGetGeometry(XtDisplay(w), CBG_CascadePixmap(w),
705 &dummyw, &dummy, &dummy,
706 &width, &height, (unsigned *)&dummy, (unsigned *)&dummy);
707 CBG_Cascade_width(w) = width;
708 CBG_Cascade_height(w) = height;
709 }
710 else
711 {
712 CBG_Cascade_width(w) = CBG_Cascade_height(w) =
713 LabG_MenuType(w) == XmMENU_OPTION
714 ? default_font_height(LabG_Font(w)) + (LabG_Shadow(w) << 1)
715 : 0;
716 }
717 }
718 else
719 {
720 CBG_Cascade_width(w) = 0;
721 CBG_Cascade_height(w) = 0;
722 }
723 }
724
725 static void
initialize(Widget request,Widget new_w,ArgList args,Cardinal * num_args)726 initialize(Widget request, Widget new_w,
727 ArgList args, Cardinal *num_args)
728 {
729 if (!XmIsManager(XtParent(new_w)))
730 {
731 _XmError(new_w, "parent should be manager.");
732 }
733
734 if (CBG_MapDelay(new_w) < 0)
735 {
736 _XmWarning(new_w, "MappingDelay must be non-negative.");
737 CBG_MapDelay(new_w) = 180;
738 }
739 if (CBG_Submenu(new_w) && (!XmIsRowColumn(CBG_Submenu(new_w)) ||
740 (RC_Type(CBG_Submenu(new_w)) != XmMENU_PULLDOWN)))
741 {
742 _XmWarning(new_w, "Submenu must a pull-down menu.");
743 CBG_Submenu(new_w) = NULL;
744 }
745
746 CBG_Cascade_x(new_w) = 0;
747 CBG_Cascade_y(new_w) = 0;
748 CBG_Cascade_width(new_w) = 0;
749 CBG_Cascade_height(new_w) = 0;
750
751 CBG_SetArmed(new_w, False);
752 CBG_ArmedPixmap(new_w) = None;
753
754 if (LabG_MenuType(new_w) == XmMENU_BAR ||
755 LabG_MenuType(new_w) == XmMENU_POPUP ||
756 LabG_MenuType(new_w) == XmMENU_PULLDOWN)
757 {
758 G_TraversalOn(new_w) = True;
759 LabG_Highlight(new_w) = 0;
760 }
761 else if (LabG_MenuType(new_w) != XmMENU_OPTION)
762 {
763 _XmError(new_w, "Cascade gadget parent is incorrect type.");
764 }
765
766 if (LabG_MenuType(new_w) == XmMENU_BAR)
767 {
768 Dimension margin_width;
769 XtResource resource =
770 {
771 XmNmarginWidth, XmCMarginWidth, XmRHorizontalDimension,
772 sizeof(Dimension), 0,
773 XmRImmediate, (XtPointer)XmINVALID_DIMENSION
774 };
775
776 /* Bend over backwards to see if the user didn't specify a marginWidth.
777 * Why doesn't this just use a default value like CascadeB does?
778 */
779 XtGetSubresources(XtParent(new_w), &margin_width, XtName(new_w),
780 "XmCascadeButtonGCacheObjClass", &resource, 1,
781 args, *num_args);
782 if (margin_width == (Dimension)XmINVALID_DIMENSION)
783 LabG_MarginWidth(new_w) = 6;
784 }
785
786 else
787 {
788 if (LabG_MenuType(new_w) != XmMENU_OPTION &&
789 CBG_CascadePixmap(new_w) == XmUNSPECIFIED_PIXMAP &&
790 CBG_Submenu(new_w))
791 {
792 _XmCreateArrowPixmaps(new_w);
793 }
794 size_cascade(new_w);
795
796 if (CBG_Submenu(new_w))
797 {
798 int margin;
799
800 /* Make sure there's enough room on the side
801 * for the cascade pixmap.
802 */
803 margin = (CBG_Cascade_width(new_w) + CASCADE_SPACING)
804 - (LabG_StringDirection(new_w) == XmSTRING_DIRECTION_L_TO_R
805 ? LabG_MarginRight(new_w) : LabG_MarginLeft(new_w));
806 if (margin > 0)
807 {
808 if (LabG_StringDirection(new_w) == XmSTRING_DIRECTION_L_TO_R)
809 LabG_MarginRight(new_w) += margin;
810 else
811 {
812 LabG_MarginLeft(new_w) += margin;
813 LabG_TextRect_x(new_w) += margin;
814 }
815 if (!XtWidth(request))
816 XtWidth(new_w) += margin;
817 }
818
819 /* Make sure there's enough room vertically */
820 margin = CBG_Cascade_height(new_w) - (LabG_TextRect_height(new_w)
821 + LabG_MarginTop(new_w)
822 + LabG_MarginBottom(new_w));
823 if (margin > 0)
824 {
825 LabG_MarginTop(new_w) += margin >> 1;
826 LabG_MarginBottom(new_w) += (margin + 1) >> 1;
827 if (LabG_MenuType(new_w) != XmMENU_OPTION &&
828 !XtHeight(request))
829 {
830 LabG_TextRect_y(new_w) += margin >> 1;
831 XtHeight(new_w) += margin;
832 }
833 }
834 }
835
836 place_cascade(new_w);
837 }
838
839 if (CBG_Submenu(new_w))
840 {
841 /* Make sure the RC also knows how to locate us */
842 RC_MenuSubmenu(new_w);
843 }
844
845 G_EventMask(new_w) = XmARM_EVENT | XmACTIVATE_EVENT |
846 XmENTER_EVENT | XmLEAVE_EVENT |
847 XmFOCUS_IN_EVENT | XmFOCUS_OUT_EVENT |
848 XmHELP_EVENT | XmBDRAG_EVENT;
849
850 CBG_Timer(new_w) = 0;
851 LabGClass_MenuProcs(XtClass(new_w)) = MenuProcEntry;
852 }
853
854 static void
resize(Widget w)855 resize(Widget w)
856 {
857 #define superclass (&xmLabelGadgetClassRec)
858 (*superclass->rect_class.resize) (w);
859 #undef superclass
860
861 if (LabG_MenuType(w) != XmMENU_BAR)
862 {
863 place_cascade(w);
864 }
865 }
866
867 static void
destroy(Widget w)868 destroy(Widget w)
869 {
870 if (CBG_Timer(w) != 0)
871 {
872 XtRemoveTimeOut(CBG_Timer(w));
873 CBG_Timer(w) = 0;
874 }
875
876 if (CBG_ArmedPixmap(w))
877 {
878 _XmArrowPixmapCacheDelete((XtPointer)CBG_ArmedPixmap(w));
879 _XmArrowPixmapCacheDelete((XtPointer)CBG_CascadePixmap(w));
880 }
881
882 _XmCacheDelete((XtPointer)CBG_Cache(w));
883 }
884
885 static Boolean
set_values_prehook(Widget old,Widget request,Widget new_w,ArgList args,Cardinal * num_args)886 set_values_prehook(Widget old, Widget request, Widget new_w,
887 ArgList args, Cardinal *num_args)
888 {
889 XmBaseClassExt *bce;
890 XmWidgetExtData ed;
891 Cardinal size;
892 XtPointer nsec, rsec;
893
894 bce = _XmGetBaseClassExtPtr(XtClass(new_w), XmQmotif);
895 size = (*bce)->secondaryObjectClass->core_class.widget_size;
896
897 nsec = _XmExtObjAlloc(size);
898 rsec = _XmExtObjAlloc(size);
899
900 ((XmExtRec *)nsec)->object.self = (Widget)nsec;
901 ((XmExtRec *)nsec)->object.widget_class = (*bce)->secondaryObjectClass;
902 ((XmExtRec *)nsec)->object.parent = XtParent(new_w);
903 ((XmExtRec *)nsec)->object.xrm_name = new_w->core.xrm_name;
904 ((XmExtRec *)nsec)->object.being_destroyed = False;
905 ((XmExtRec *)nsec)->object.destroy_callbacks = NULL;
906 ((XmExtRec *)nsec)->object.constraints = NULL;
907
908 ExtObj_LogicalParent(nsec) = new_w;
909 ExtObj_ExtensionType(nsec) = XmCACHE_EXTENSION;
910
911 memcpy(&((XmLabelGCacheObject)nsec)->label_cache,
912 LabG_Cache(new_w),
913 sizeof(XmLabelGCacheObjPart));
914 memcpy(&((XmCascadeButtonGCacheObject)nsec)->cascade_button_cache,
915 CBG_Cache(new_w),
916 sizeof(XmCascadeButtonGCacheObjPart));
917
918 ed = (XmWidgetExtData)XtMalloc(sizeof(XmWidgetExtDataRec));
919
920 ed->widget = (Widget)nsec;
921 ed->reqWidget = (Widget)rsec;
922
923 _XmPushWidgetExtData(new_w, ed, XmCACHE_EXTENSION);
924
925 _XmGadgetImportSecondaryArgs(new_w, args, num_args);
926
927 XtSetSubvalues((XtPointer)nsec,
928 (*bce)->secondaryObjectClass->core_class.resources,
929 (*bce)->secondaryObjectClass->core_class.num_resources,
930 args, *num_args);
931
932 memcpy(rsec, nsec, size);
933
934 LabG_Cache(new_w) = &(((XmCascadeButtonGCacheObject)nsec)->label_cache);
935 LabG_Cache(request) = &(((XmCascadeButtonGCacheObject)rsec)->label_cache);
936
937 CBG_Cache(new_w) =
938 &(((XmCascadeButtonGCacheObject)nsec)->cascade_button_cache);
939 CBG_Cache(request) =
940 &(((XmCascadeButtonGCacheObject)rsec)->cascade_button_cache);
941
942 _XmExtImportArgs((Widget)nsec, args, num_args);
943
944 return False;
945 }
946
947 static Boolean
set_values_posthook(Widget old,Widget request,Widget new_w,ArgList args,Cardinal * num_args)948 set_values_posthook(Widget old, Widget request, Widget new_w,
949 ArgList args, Cardinal *num_args)
950 {
951 XmWidgetExtData ext;
952
953 if (!_XmLabelCacheCompare((XtPointer)LabG_Cache(new_w),
954 (XtPointer)LabG_Cache(old)))
955 {
956
957 _XmCacheDelete((XtPointer)LabG_Cache(old));
958
959 LabG_Cache(new_w) = (XmLabelGCacheObjPart *)
960 _XmCachePart(LabG_ClassCachePart(NULL),
961 (XtPointer)LabG_Cache(new_w),
962 sizeof(XmLabelGCacheObjPart));
963 }
964 else
965 {
966 LabG_Cache(new_w) = LabG_Cache(old);
967 }
968
969 if (!_XmCascadeBCacheCompare((XtPointer)CBG_Cache(new_w),
970 (XtPointer)CBG_Cache(old)))
971 {
972 _XmCacheDelete((XtPointer)CBG_Cache(old));
973
974 CBG_Cache(new_w) = (XmCascadeButtonGCacheObjPart *)
975 _XmCachePart(CBG_ClassCachePart(NULL),
976 (XtPointer)CBG_Cache(new_w),
977 sizeof(XmCascadeButtonGCacheObjPart));
978 }
979 else
980 {
981 CBG_Cache(new_w) = CBG_Cache(old);
982 }
983
984 _XmPopWidgetExtData(new_w, &ext, XmCACHE_EXTENSION);
985
986 _XmExtObjFree((XtPointer)ext->widget);
987 _XmExtObjFree((XtPointer)ext->reqWidget);
988
989 XtFree((char *)ext);
990
991 return False;
992 }
993
994 static Boolean
set_values(Widget old,Widget request,Widget new_w,ArgList args,Cardinal * num_args)995 set_values(Widget old, Widget request, Widget new_w,
996 ArgList args, Cardinal *num_args)
997 {
998 Boolean refresh_needed = False;
999
1000 DEBUGOUT(_LtDebug(__FILE__, new_w, "set_values()\n"));
1001
1002 if (CBG_MapDelay(new_w) < 0)
1003 {
1004 _XmWarning(new_w, "MappingDelay must be non-negative.");
1005 CBG_MapDelay(new_w) = CBG_MapDelay(old);
1006 }
1007 if (CBG_Submenu(new_w) && (!XmIsRowColumn(CBG_Submenu(new_w)) ||
1008 (RC_Type(CBG_Submenu(new_w)) != XmMENU_PULLDOWN)))
1009 {
1010 _XmWarning(new_w, "Submenu must a pull-down menu.");
1011 CBG_Submenu(new_w) = CBG_Submenu(old);
1012 }
1013
1014 if (LabG_MenuType(new_w) != XmMENU_OPTION)
1015 {
1016 G_TraversalOn(new_w) = True;
1017 LabG_Highlight(new_w) = 0;
1018 }
1019
1020 if (CBG_CascadePixmap(old) != CBG_CascadePixmap(new_w) ||
1021 (CBG_Submenu(new_w)
1022 ? CBG_CascadePixmap(new_w) == XmUNSPECIFIED_PIXMAP
1023 : CBG_ArmedPixmap(new_w)) ||
1024 ((CBG_ArmedPixmap(new_w) || (LabG_MenuType(new_w) == XmMENU_OPTION &&
1025 CBG_CascadePixmap(new_w) == XmUNSPECIFIED_PIXMAP)) &&
1026 LabG_Font(old) != LabG_Font(new_w)))
1027 {
1028 if (CBG_ArmedPixmap(old))
1029 {
1030 _XmArrowPixmapCacheDelete((XtPointer)CBG_CascadePixmap(old));
1031 _XmArrowPixmapCacheDelete((XtPointer)CBG_ArmedPixmap(old));
1032 if (CBG_CascadePixmap(old) == CBG_CascadePixmap(new_w))
1033 CBG_CascadePixmap(new_w) = XmUNSPECIFIED_PIXMAP;
1034 CBG_ArmedPixmap(new_w) = None;
1035 }
1036 if (LabG_MenuType(new_w) != XmMENU_BAR)
1037 {
1038 if (LabG_MenuType(new_w) != XmMENU_OPTION &&
1039 CBG_CascadePixmap(new_w) == XmUNSPECIFIED_PIXMAP &&
1040 CBG_Submenu(new_w))
1041 {
1042 _XmCreateArrowPixmaps(new_w);
1043 }
1044 size_cascade(new_w);
1045 refresh_needed = True;
1046 }
1047 }
1048
1049 if (XtSensitive(new_w) != XtSensitive(old))
1050 {
1051 refresh_needed = True;
1052 }
1053
1054 if (CBG_Submenu(old) != CBG_Submenu(new_w))
1055 {
1056 /* Make sure the RC also knows how to locate us */
1057 RC_MenuSubmenu(new_w);
1058 }
1059
1060 /* Adjust margins for the cascade pixmap size if necessary.
1061 * Margins be increased or decreased; if the margin was explicitly set
1062 * in this call, don't decrease it past that (though it can get bigger).
1063 */
1064 if (LabG_MenuType(new_w) != XmMENU_BAR &&
1065 (CBG_Cascade_width(new_w) != CBG_Cascade_width(old)
1066 || CBG_Cascade_height(new_w) != CBG_Cascade_height(old)
1067 || LabG_StringDirection(new_w) != LabG_StringDirection(old)
1068 || (LabG_StringDirection(new_w) == XmSTRING_DIRECTION_L_TO_R
1069 ? LabG_MarginRight(new_w) != LabG_MarginRight(old)
1070 : LabG_MarginLeft(new_w) != LabG_MarginLeft(old))
1071 || LabG_MarginTop(new_w) != LabG_MarginTop(old)
1072 || LabG_MarginBottom(new_w) != LabG_MarginBottom(old)))
1073 {
1074 int margin, tm, bm;
1075
1076 margin = CBG_Cascade_width(new_w) + CASCADE_SPACING
1077 - (LabG_StringDirection(new_w) == XmSTRING_DIRECTION_L_TO_R
1078 ? LabG_MarginRight(new_w) : LabG_MarginLeft(new_w));
1079 if (margin && (margin > 0 ||
1080 (LabG_StringDirection(new_w) == XmSTRING_DIRECTION_L_TO_R
1081 ? LabG_MarginRight(new_w) == LabG_MarginRight(old)
1082 : LabG_MarginLeft(new_w) == LabG_MarginLeft(old))))
1083 {
1084 if (LabG_StringDirection(new_w) == XmSTRING_DIRECTION_L_TO_R)
1085 LabG_MarginRight(new_w) += margin;
1086 else
1087 {
1088 LabG_MarginLeft(new_w) += margin;
1089 LabG_TextRect_x(new_w) += margin;
1090 }
1091 if (LabG_RecomputeSize(new_w) || !XtWidth(request))
1092 XtWidth(new_w) += margin;
1093 }
1094
1095 margin = CBG_Cascade_height(new_w) - (LabG_TextRect_height(new_w)
1096 + LabG_MarginTop(new_w)
1097 + LabG_MarginBottom(new_w));
1098 if (margin)
1099 {
1100 tm = margin / 2;
1101 if (tm < (LabG_MarginTop(new_w) == LabG_MarginTop(old)
1102 ? XmDEFAULT_TOP_MARGIN - (int)LabG_MarginTop(new_w)
1103 : 0))
1104 tm = (LabG_MarginTop(new_w) == LabG_MarginTop(old)
1105 ? XmDEFAULT_TOP_MARGIN - (int)LabG_MarginTop(new_w)
1106 : 0);
1107 LabG_MarginTop(new_w) += tm;
1108 if (LabG_MenuType(new_w) != XmMENU_OPTION &&
1109 (LabG_RecomputeSize(new_w) || !XtHeight(request)))
1110 XtHeight(new_w) += tm;
1111
1112 bm = (margin + 1) / 2;
1113 if (bm < (LabG_MarginBottom(new_w) == LabG_MarginBottom(old)
1114 ? XmDEFAULT_BOTTOM_MARGIN - (int)LabG_MarginBottom(new_w)
1115 : 0))
1116 bm = (LabG_MarginBottom(new_w) == LabG_MarginBottom(old)
1117 ? XmDEFAULT_BOTTOM_MARGIN - (int)LabG_MarginBottom(new_w)
1118 : 0);
1119 LabG_MarginBottom(new_w) += bm;
1120 if (LabG_RecomputeSize(new_w) || !XtHeight(request))
1121 XtHeight(new_w) += bm;
1122
1123 if (tm != bm)
1124 LabG_TextRect_y(new_w) += (tm - bm) / 2;
1125 }
1126
1127 refresh_needed = True;
1128 }
1129
1130 if (LabG_MenuType(new_w) != XmMENU_BAR &&
1131 (CBG_Cascade_width(new_w) != CBG_Cascade_width(old)
1132 || CBG_Cascade_height(new_w) != CBG_Cascade_height(old)
1133 || LabG_Shadow(new_w) != LabG_Shadow(old)
1134 || LabG_MarginWidth(new_w) != LabG_MarginWidth(old)
1135 || LabG_TextRect_y(new_w) != LabG_TextRect_y(old)
1136 || LabG_TextRect_height(new_w) != LabG_TextRect_height(old)
1137 || LabG_StringDirection(new_w) != LabG_StringDirection(old)))
1138 {
1139 Dimension width, height;
1140
1141 width = XtWidth(new_w);
1142 height = XtHeight(new_w);
1143 XtWidth(new_w) = XtWidth(old);
1144 XtHeight(new_w) = XtHeight(old);
1145 place_cascade(new_w);
1146 XtWidth(new_w) = width;
1147 XtHeight(new_w) = height;
1148 refresh_needed = True;
1149 }
1150
1151 return refresh_needed;
1152 }
1153
1154 static void
get_values_prehook(Widget new_w,ArgList args,Cardinal * num_args)1155 get_values_prehook(Widget new_w, ArgList args, Cardinal *num_args)
1156 {
1157 XmBaseClassExt *bce;
1158 XmWidgetExtData ed;
1159 Cardinal size;
1160 XtPointer nsec;
1161
1162 bce = _XmGetBaseClassExtPtr(XtClass(new_w), XmQmotif);
1163 size = (*bce)->secondaryObjectClass->core_class.widget_size;
1164
1165 nsec = _XmExtObjAlloc(size);
1166
1167 memcpy(&((XmLabelGCacheObject)nsec)->label_cache,
1168 LabG_Cache(new_w),
1169 sizeof(XmLabelGCacheObjPart));
1170 memcpy(&((XmCascadeButtonGCacheObject)nsec)->cascade_button_cache,
1171 CBG_Cache(new_w),
1172 sizeof(XmCascadeButtonGCacheObjPart));
1173
1174 /*
1175 * don't do this and ResInd will blow up.
1176 */
1177 ((XmExtRec *)nsec)->object.self = (Widget)nsec;
1178 ((XmExtRec *)nsec)->object.widget_class = (*bce)->secondaryObjectClass;
1179 ((XmExtRec *)nsec)->object.parent = XtParent(new_w);
1180 ((XmExtRec *)nsec)->object.xrm_name = new_w->core.xrm_name;
1181 ((XmExtRec *)nsec)->object.being_destroyed = False;
1182 ((XmExtRec *)nsec)->object.destroy_callbacks = NULL;
1183 ((XmExtRec *)nsec)->object.constraints = NULL;
1184
1185 ExtObj_LogicalParent(nsec) = new_w;
1186 ExtObj_ExtensionType(nsec) = XmCACHE_EXTENSION;
1187
1188 ed = (XmWidgetExtData)XtMalloc(sizeof(XmWidgetExtDataRec));
1189 ed->widget = (Widget)nsec;
1190
1191 _XmPushWidgetExtData(new_w, ed, XmCACHE_EXTENSION);
1192
1193 XtGetSubvalues((XtPointer)nsec,
1194 (*bce)->secondaryObjectClass->core_class.resources,
1195 (*bce)->secondaryObjectClass->core_class.num_resources,
1196 args, *num_args);
1197
1198 _XmExtGetValuesHook((Widget)nsec, args, num_args);
1199 }
1200
1201 static void
get_values_posthook(Widget new_w,ArgList args,Cardinal * num_args)1202 get_values_posthook(Widget new_w, ArgList args, Cardinal *num_args)
1203 {
1204 XmWidgetExtData ext;
1205
1206 _XmPopWidgetExtData(new_w, &ext, XmCACHE_EXTENSION);
1207
1208 _XmExtObjFree((XtPointer)ext->widget);
1209
1210 XtFree((char *)ext);
1211 }
1212
1213
1214 static void
draw_cascade(Widget w)1215 draw_cascade(Widget w)
1216 {
1217 Pixmap pm;
1218
1219 if (CBG_IsArmed(w) || LabG_MenuType(w) == XmMENU_OPTION)
1220 {
1221 _XmDrawShadows(XtDisplay(w), XtWindow(w),
1222 XmParentTopShadowGC(w), XmParentBottomShadowGC(w),
1223 XtX(w) + LabG_Highlight(w), XtY(w) + LabG_Highlight(w),
1224 XtWidth(w) - (LabG_Highlight(w) << 1),
1225 XtHeight(w) - (LabG_Highlight(w) << 1),
1226 LabG_Shadow(w), XmSHADOW_OUT);
1227 }
1228
1229 pm = CBG_IsArmed(w) && CBG_ArmedPixmap(w) > XmUNSPECIFIED_PIXMAP
1230 ? CBG_ArmedPixmap(w)
1231 : CBG_CascadePixmap(w);
1232 if (pm > XmUNSPECIFIED_PIXMAP)
1233 {
1234 XCopyArea(XtDisplay(w), pm, XtWindow(w),
1235 LabG_NormalGC(w),
1236 0, 0,
1237 CBG_Cascade_width(w), CBG_Cascade_height(w),
1238 XtX(w) + CBG_Cascade_x(w), XtY(w) + CBG_Cascade_y(w));
1239 }
1240 else if (pm == XmUNSPECIFIED_PIXMAP && LabG_MenuType(w) == XmMENU_OPTION && CBG_Submenu(w))
1241 {
1242 Dimension width, height, ch;
1243
1244 /* Base the rectangle cascade on the text height,
1245 * but for bigger text, it gets successively squatter.
1246 */
1247 width = CBG_Cascade_width(w) - 3;
1248 height = (LabG_Shadow(w) << 1) + 1;
1249 ch = CBG_Cascade_height(w) - height;
1250 if (ch >= 13)
1251 {
1252 width -= 3;
1253 height += 3;
1254 }
1255 else if (ch >= 9)
1256 {
1257 width -= 2;
1258 height += 2;
1259 }
1260 else if (ch >= 6)
1261 {
1262 width--;
1263 height++;
1264 }
1265 _XmDrawShadows(XtDisplay(w), XtWindow(w),
1266 XmParentTopShadowGC(w), XmParentBottomShadowGC(w),
1267 XtX(w) + CBG_Cascade_x(w),
1268 XtY(w) + CBG_Cascade_y(w) +
1269 ((CBG_Cascade_height(w) - height) >> 1),
1270 width, height, LabG_Shadow(w), XmSHADOW_OUT);
1271 }
1272 }
1273
1274 static void
expose(Widget w,XEvent * event,Region region)1275 expose(Widget w,
1276 XEvent *event,
1277 Region region)
1278 {
1279 DEBUGOUT(_LtDebug(__FILE__, w, "expose() Armed(%d) type %s\n",
1280 CBG_IsArmed(w), _LtDebugMenuType2String(LabG_MenuType(w))));
1281
1282 draw_cascade(w);
1283
1284 #define superclass (&xmLabelGadgetClassRec)
1285 (*superclass->rect_class.expose) (w, event, region);
1286 #undef superclass
1287 }
1288
1289 static Cardinal
get_sec_res_data(WidgetClass wc,XmSecondaryResourceData ** data)1290 get_sec_res_data(WidgetClass wc, XmSecondaryResourceData **data)
1291 {
1292 /* FIX ME */
1293
1294 return _XmSecondaryResourceData(&_XmCascadeBGRectClassExtRec,
1295 data, NULL, NULL, NULL, NULL);
1296 }
1297
1298 static void
DoSelect(Widget w,XEvent * event,String * params,Cardinal * num_params)1299 DoSelect(Widget w, XEvent *event, String *params, Cardinal *num_params)
1300 {
1301 Boolean validButton;
1302
1303 DEBUGOUT(_LtDebug(__FILE__, w, "%s:DoSelect(%d)\n\t%s posted mine %s\n",
1304 __FILE__, __LINE__,
1305 RC_PopupPosted(XtParent(w)) ? XtName(RC_PopupPosted(XtParent(w))) : "nothing",
1306 CBG_Submenu(w) ? XtName(CBG_Submenu(w)) : "none"
1307 ));
1308 DEBUGOUT(_LtDebug("MENU", w, "%s:DoSelect(%d)\n\t%s posted mine %s %s\n",
1309 __FILE__, __LINE__,
1310 RC_PopupPosted(XtParent(w)) ? XtName(RC_PopupPosted(XtParent(w))) : "nothing",
1311 CBG_Submenu(w) ? XtName(CBG_Submenu(w)) : "none",
1312 event ? _LtDebugEventType2String(event->xany.type) : "no-event"
1313 ));
1314 if (event && event->xany.type == ButtonRelease)
1315 {
1316 RC_MenuButton(w, event, &validButton);
1317 }
1318 else
1319 {
1320 validButton = True;
1321 }
1322 if (validButton)
1323 {
1324 XAllowEvents(XtDisplay(w), SyncPointer, CurrentTime);
1325 _XmMenuFocus(XtParent(w), XmMENU_FOCUS_SET, CurrentTime);
1326 if (CBG_Submenu(w))
1327 {
1328 if (RC_PopupPosted(XtParent(w)) != CBG_Submenu(w))
1329 {
1330 _XmCascadingPopup(w, event, True);
1331 }
1332
1333 RCClass_MenuTraverse(CBG_Submenu(w), XmTRAVERSE_HOME);
1334
1335 _XmSetInDragMode(w, False);
1336 }
1337 else
1338 {
1339 XmAnyCallbackStruct cbs;
1340
1341 cbs.reason = XmCR_ACTIVATE;
1342 cbs.event = event;
1343 if (XmIsRowColumn(XtParent(w)))
1344 {
1345 RC_MenuMenuCallback(w, &cbs);
1346 }
1347 if (!LabG_SkipCallback(w) && CBG_ActivateCall(w))
1348 {
1349 XFlush(XtDisplay(w));
1350
1351 XtCallCallbackList(w, CBG_ActivateCall(w), &cbs);
1352 }
1353 XmCascadeButtonGadgetHighlight(w, False);
1354 if (RC_PopupPosted(XtParent(w)))
1355 {
1356 Boolean poppedUp;
1357
1358 RC_MenuShellPopdown(w, event, &poppedUp);
1359 }
1360 }
1361 }
1362 }
1363
1364 static void
MenuBarSelect(Widget w,XEvent * event,String * params,Cardinal * num_params)1365 MenuBarSelect(Widget w, XEvent *event, String *params, Cardinal *num_params)
1366 {
1367 Boolean validButton;
1368
1369 DEBUGOUT(_LtDebug(__FILE__, w, "%s:MenuBarSelect(%d)\n\t%s posted mine %s\n",
1370 __FILE__, __LINE__,
1371 RC_PopupPosted(XtParent(w)) ? XtName(RC_PopupPosted(XtParent(w))) : "nothing",
1372 CBG_Submenu(w) ? XtName(CBG_Submenu(w)) : "none"
1373 ));
1374 DEBUGOUT(_LtDebug("MENU", w, "%s:MenuBarSelect(%d)\n\t%s posted mine %s\n",
1375 __FILE__, __LINE__,
1376 RC_PopupPosted(XtParent(w)) ? XtName(RC_PopupPosted(XtParent(w))) : "nothing",
1377 CBG_Submenu(w) ? XtName(CBG_Submenu(w)) : "none"
1378 ));
1379 if (event && event->xany.type == ButtonPress)
1380 {
1381 RC_MenuButton(w, event, &validButton);
1382 }
1383 else
1384 {
1385 validButton = True;
1386 }
1387 if (validButton)
1388 {
1389 XAllowEvents(XtDisplay(w), SyncPointer, CurrentTime);
1390 XmProcessTraversal(w, XmTRAVERSE_CURRENT);
1391 if (RC_PopupPosted(XtParent(w)))
1392 {
1393 Cardinal i;
1394
1395 for (i = 0; i < MGR_NumChildren(RC_PopupPosted(XtParent(w))); i++)
1396 {
1397 Widget w1 = MGR_Children(RC_PopupPosted(XtParent(w)))[i];
1398
1399 _XmMenuDisarmItem(w1);
1400 }
1401 if (RC_PopupPosted(XtParent(w)) != CBG_Submenu(w))
1402 {
1403 Boolean poppedUp;
1404
1405 RC_MenuShellPopdown(w, event, &poppedUp);
1406 }
1407 else if (CBG_Submenu(w) && RC_PopupPosted(CBG_Submenu(w)))
1408 {
1409 Boolean poppedUp;
1410
1411 RC_MenuShellPopdown(RC_CascadeBtn(RC_PopupPosted(CBG_Submenu(w))), event, &poppedUp);
1412 }
1413 }
1414 XmCascadeButtonGadgetHighlight(w, True);
1415 MGR_ActiveChild(XtParent(w)) = w;
1416
1417 RCClass_MenuProcs(XtClass(XtParent(w)))(XmMENU_ARM, XtParent(w), NULL);
1418
1419 if (RC_PopupPosted(XtParent(w)) != CBG_Submenu(w))
1420 {
1421 _XmCascadingPopup(w, event, True);
1422 }
1423 _XmSetInDragMode(w, True);
1424 }
1425 }
1426
1427 static void
ArmAndPost(Widget w,XEvent * event,String * params,Cardinal * num_params)1428 ArmAndPost(Widget w, XEvent *event, String *params, Cardinal *num_params)
1429 {
1430 DEBUGOUT(_LtDebug(__FILE__, w, "ArmAndPost(): %p %p\n", w, CBG_Submenu(w)));
1431 DEBUGOUT(_LtDebug("MENU", w, "%s:ArmAndPost(%d)\n\t%s posted mine %s\n",
1432 __FILE__, __LINE__,
1433 RC_PopupPosted(XtParent(w)) ? XtName(RC_PopupPosted(XtParent(w))) : "nothing",
1434 CBG_Submenu(w) ? XtName(CBG_Submenu(w)) : "none"
1435 ));
1436
1437 XmProcessTraversal(w, XmTRAVERSE_CURRENT);
1438
1439 #if 0
1440 if (!RC_IsArmed(CBG_Submenu(w)))
1441 {
1442 DEBUGOUT(_LtDebug(__FILE__, w, "MENU_ARM\n"));
1443
1444 RCClass_MenuProcs(XtClass(XtParent(w)))(XmMENU_ARM, XtParent(w), NULL);
1445 }
1446
1447 _XmCascadingPopup(w, event, True);
1448 _XmSetInDragMode(w, True);
1449 #else
1450 XmCascadeButtonGadgetHighlight(w, True);
1451 MGR_ActiveChild(XtParent(w)) = w;
1452 RCClass_MenuProcs(XtClass(XtParent(w)))(XmMENU_ARM, XtParent(w), NULL);
1453 _XmCascadingPopup(w, event, True);
1454 _XmSetInDragMode(w, True);
1455 #endif
1456 }
1457
1458 static void
MenuBarEnter(Widget w,XEvent * event,String * params,Cardinal * num_params)1459 MenuBarEnter(Widget w, XEvent *event, String *params, Cardinal *num_params)
1460 {
1461 DEBUGOUT(_LtDebug(__FILE__, w, "MenuBarEnter\n\t%s %s %s %s posted posting %s\n",
1462 _XmGetInDragMode(w) ? "Dragging" : "Not Dragging",
1463 _LtDebugRcType2String(LabG_MenuType(w)),
1464 RC_IsArmed(XtParent(w)) ? "Armed" : "Not Armed",
1465 RC_PopupPosted(XtParent(w)) ? XtName(RC_PopupPosted(XtParent(w))) : "nothing",
1466 CBG_Submenu(w) ? XtName(CBG_Submenu(w)) : "nothing"
1467 ));
1468 DEBUGOUT(_LtDebug("MENU", w, "MenuBarEnter\n\t%s %s %s %s posted posting %s\n",
1469 _XmGetInDragMode(w) ? "Dragging" : "Not Dragging",
1470 _LtDebugRcType2String(LabG_MenuType(w)),
1471 RC_IsArmed(XtParent(w)) ? "Armed" : "Not Armed",
1472 RC_PopupPosted(XtParent(w)) ? XtName(RC_PopupPosted(XtParent(w))) : "nothing",
1473 CBG_Submenu(w) ? XtName(CBG_Submenu(w)) : "nothing"
1474 ));
1475
1476 if (_XmGetInDragMode(w))
1477 {
1478 if (LabG_MenuType(w) == XmMENU_BAR)
1479 {
1480 if (RC_IsArmed(XtParent(w)))
1481 {
1482 if (CBG_Submenu(w))
1483 {
1484 if (RC_PopupPosted(XtParent(w)) && RC_PopupPosted(XtParent(w)) != CBG_Submenu(w))
1485 {
1486 _XmCascadingPopup(w, event, False);
1487 }
1488 if (RC_PopupPosted(XtParent(w)) && RC_PopupPosted(XtParent(w)) != CBG_Submenu(w))
1489 {
1490 Boolean poppedUp;
1491
1492 RC_MenuShellPopdown(w, event, &poppedUp);
1493 }
1494 XmCascadeButtonGadgetHighlight(w, True);
1495 if (!RC_PopupPosted(XtParent(w)))
1496 {
1497 RC_MenuCascading(w, event);
1498 }
1499 }
1500 else
1501 {
1502 _XmCascadingPopup(w, event, True);
1503 if (RC_PopupPosted(XtParent(w)) && RC_PopupPosted(XtParent(w)) != CBG_Submenu(w))
1504 {
1505 Boolean poppedUp;
1506
1507 RC_MenuShellPopdown(w, event, &poppedUp);
1508 }
1509 XmCascadeButtonGadgetHighlight(w, True);
1510 }
1511 }
1512 }
1513 else
1514 {
1515 _XmWarning(w, "%s(%d) - MenuBarEnter not in MenuBar",
1516 __FILE__, __LINE__);
1517 }
1518 }
1519 }
1520
1521 static void
MenuBarLeave(Widget w,XEvent * event,String * params,Cardinal * num_params)1522 MenuBarLeave(Widget w, XEvent *event, String *params, Cardinal *num_params)
1523 {
1524 if (_XmGetInDragMode(w))
1525 {
1526 if (LabG_MenuType(w) == XmMENU_BAR)
1527 {
1528 if (RC_IsArmed(XtParent(w)))
1529 {
1530 if (!CBG_Submenu(w) || (RC_PopupPosted(XtParent(w)) && RC_PopupPosted(XtParent(w)) != CBG_Submenu(w)))
1531 {
1532 XmCascadeButtonGadgetHighlight(w, False);
1533 }
1534 }
1535 }
1536 else
1537 {
1538 _XmWarning(w, "%s(%d) - MenuBarLeave not in MenuBar",
1539 __FILE__, __LINE__);
1540 }
1541 }
1542 }
1543
1544 static void
StartDrag(Widget w,XEvent * event,String * params,Cardinal * num_params)1545 StartDrag(Widget w, XEvent *event, String *params, Cardinal *num_params)
1546 {
1547 Boolean validButton;
1548 Boolean poppedUp;
1549
1550 DEBUGOUT(_LtDebug(__FILE__, w, "StartDrag()\n"));
1551
1552 XAllowEvents(XtDisplay(w), SyncPointer, CurrentTime);
1553
1554 _XmRecordEvent(event);
1555
1556 /* Is it even the right kind of event? */
1557 if (!event || event->type != ButtonPress)
1558 {
1559 return;
1560 }
1561
1562 /* If the submenu is already active, disable keyboard traversal
1563 and set it to mouse traversal */
1564
1565 /* Was it the right button? */
1566 RC_MenuButton(w, event, &validButton);
1567
1568 DEBUGOUT(_LtDebug("MENU", w, "%s:StartDrag(%d) - %s posted mine %s\n",
1569 __FILE__, __LINE__,
1570 RC_PopupPosted(XtParent(w)) ? XtName(RC_PopupPosted(XtParent(w))) : "None",
1571 CBG_Submenu(w) ? XtName(CBG_Submenu(w)) : "None"
1572 ));
1573 if (validButton)
1574 {
1575 if (CBG_Submenu(w) && RC_PopupPosted(XtParent(w)) == CBG_Submenu(w))
1576 {
1577 Cardinal i;
1578
1579 for (i = 0; i < MGR_NumChildren(CBG_Submenu(w)); i++)
1580 {
1581 _XmMenuDisarmItem(MGR_Children(CBG_Submenu(w))[i]);
1582 }
1583 }
1584 else
1585 {
1586 RC_MenuShellPopdown(w, event, &poppedUp);
1587 _XmCascadingPopup(w, event, True);
1588 {
1589 Cardinal i;
1590 Widget menu = XtParent(w);
1591
1592 for (i = 0; i < MGR_NumChildren(menu); i++)
1593 {
1594 _XmMenuDisarmItem(MGR_Children(menu)[i]);
1595 }
1596 }
1597 XmCascadeButtonGadgetHighlight(w, True);
1598 }
1599
1600 _XmSetInDragMode(w, True);
1601 }
1602 }
1603
1604 static void
CascadePopupHandler(XtPointer clientData,XtIntervalId * id)1605 CascadePopupHandler(XtPointer clientData, XtIntervalId *id)
1606 {
1607 Widget w = (Widget)clientData;
1608
1609 CBG_Timer(w) = 0;
1610
1611 DEBUGOUT(_LtDebug(__FILE__, w, "CascadePopupHandler()\n"));
1612
1613 _XmCascadingPopup(w, NULL, True); /* FIX ME: NULL? */
1614 }
1615
1616
1617 static void
DelayedArm(Widget w,XEvent * event,String * params,Cardinal * num_params)1618 DelayedArm(Widget w, XEvent *event, String *params, Cardinal *num_params)
1619 {
1620 DEBUGOUT(_LtDebug(__FILE__, w, "DelayedArm()\n"));
1621
1622 XAllowEvents(XtDisplay(w), SyncPointer, CurrentTime);
1623
1624 if (_XmGetInDragMode(w))
1625 {
1626 if (RC_PopupPosted(XtParent(w)) != CBG_Submenu(w))
1627 {
1628 Boolean poppedUp;
1629
1630 RC_MenuShellPopdown(w, NULL, &poppedUp);
1631 }
1632 if (!RC_PopupPosted(XtParent(w)))
1633 {
1634 CBG_Timer(w) = XtAppAddTimeOut(XtWidgetToApplicationContext(w),
1635 CBG_MapDelay(w),
1636 CascadePopupHandler,
1637 (XtPointer)w);
1638
1639 XmCascadeButtonGadgetHighlight(w, True);
1640 }
1641 }
1642 }
1643
1644 static void
CheckDisarm(Widget w,XEvent * event,String * params,Cardinal * num_params)1645 CheckDisarm(Widget w, XEvent *event, String *params, Cardinal *num_params)
1646 {
1647 int x = ((XLeaveWindowEvent *)event)->x_root;
1648 int y = ((XLeaveWindowEvent *)event)->y_root;
1649 Widget subpane;
1650
1651 DEBUGOUT(_LtDebug(__FILE__, w, "CheckDisarm() - %i %i %i\n", x, y, XtHeight(w)));
1652
1653 XAllowEvents(XtDisplay(w), SyncPointer, CurrentTime);
1654
1655 if (_XmGetInDragMode(w))
1656 {
1657 if (CBG_Timer(w))
1658 {
1659 XtRemoveTimeOut(CBG_Timer(w));
1660 CBG_Timer(w) = 0;
1661 }
1662 if (!RC_PopupPosted(XtParent(w)) || (CBG_Submenu(w) != RC_PopupPosted(XtParent(w))))
1663 {
1664 XmCascadeButtonGadgetHighlight(w, False);
1665 }
1666 else
1667 {
1668 subpane = XtParent(CBG_Submenu(w));
1669
1670 if (x < XtX(subpane) || x >= XtX(subpane) + XtWidth(subpane) ||
1671 y < XtY(subpane) || y >= XtY(subpane) + XtHeight(subpane))
1672 {
1673 Boolean poppedUp;
1674
1675 RC_MenuShellPopdown(w, event, &poppedUp);
1676 XmCascadeButtonGadgetHighlight(w, False);
1677 }
1678 }
1679 }
1680 }
1681
1682
1683 static void
Help(Widget w,XEvent * event,String * params,Cardinal * num_params)1684 Help(Widget w, XEvent *event, String *params, Cardinal *num_params)
1685 {
1686 Widget cur = w;
1687 XmAnyCallbackStruct cbs;
1688
1689 cbs.reason = XmCR_HELP;
1690 cbs.event = event;
1691
1692 while (cur != NULL)
1693 {
1694 if (XtHasCallbacks(w, XmNhelpCallback) == XtCallbackHasSome)
1695 {
1696 XtCallCallbacks(w, XmNhelpCallback, (XtPointer)&cbs);
1697 return;
1698 }
1699
1700 cur = XtParent(cur);
1701 }
1702 }
1703
1704 static void
ArmAndActivate(Widget w,XEvent * event,String * params,Cardinal * num_params)1705 ArmAndActivate(Widget w, XEvent *event, String *params, Cardinal *num_params)
1706 {
1707 DEBUGOUT(_LtDebug(__FILE__, w, "ArmAndActivate\n"));
1708
1709 MGR_ActiveChild(XtParent(w)) = w;
1710 if (LabG_MenuType(w) == XmMENU_BAR)
1711 {
1712 if (!RC_IsArmed(XtParent(w)))
1713 {
1714 RCClass_MenuProcs(XtClass(XtParent(w)))(XmMENU_ARM, XtParent(w), NULL);
1715 _XmMenuFocus(XtParent(w), XmMENU_FOCUS_SAVE, CurrentTime);
1716 _XmSetInDragMode(XtParent(w), False);
1717 }
1718 _XmMenuFocus(XtParent(w), XmMENU_FOCUS_SET, CurrentTime);
1719 MenuBarSelect(w, event, params, num_params);
1720 DoSelect(w, event, params, num_params);
1721 }
1722 else if (LabG_MenuType(w) == XmMENU_OPTION)
1723 {
1724 XmProcessTraversal(w, XmTRAVERSE_CURRENT);
1725
1726 if (CBG_Submenu(w) && !RC_IsArmed(CBG_Submenu(w)))
1727 {
1728 DEBUGOUT(_LtDebug(__FILE__, w, "MENU_ARM\n"));
1729
1730 RCClass_MenuProcs(XtClass(XtParent(w)))(XmMENU_ARM,
1731 XtParent(w), NULL);
1732 }
1733
1734 CascadePopupHandler((XtPointer)w, NULL);
1735 }
1736 else /* pullright */
1737 {
1738 CascadePopupHandler((XtPointer)w, NULL);
1739 }
1740 }
1741
1742 static void
input_dispatch(Widget gadget,XEvent * event,Mask event_mask)1743 input_dispatch(Widget gadget, XEvent *event, Mask event_mask)
1744 {
1745 Cardinal num_params = 0;
1746
1747 switch (event_mask)
1748 {
1749 case XmARM_EVENT:
1750 if (LabG_MenuType(gadget) == XmMENU_BAR)
1751 {
1752 MenuBarSelect(gadget, event, NULL, &num_params);
1753 }
1754 else if (LabG_MenuType(gadget) == XmMENU_OPTION)
1755 {
1756 ArmAndPost(gadget, event, NULL, &num_params);
1757 }
1758 else
1759 {
1760 StartDrag(gadget, event, NULL, &num_params);
1761 }
1762 break;
1763
1764 case XmACTIVATE_EVENT:
1765 DoSelect(gadget, event, NULL, &num_params);
1766 break;
1767
1768 case XmENTER_EVENT:
1769 if ((LabG_MenuType(gadget) == XmMENU_PULLDOWN) ||
1770 (LabG_MenuType(gadget) == XmMENU_POPUP)) /* rws 23 Mar 1997 */
1771 {
1772 DelayedArm(gadget, event, NULL, &num_params);
1773 }
1774 else if (LabG_MenuType(gadget) == XmMENU_BAR)
1775 {
1776 MenuBarEnter(gadget, event, NULL, &num_params);
1777 }
1778 break;
1779
1780 case XmLEAVE_EVENT:
1781 if ((LabG_MenuType(gadget) == XmMENU_PULLDOWN) ||
1782 (LabG_MenuType(gadget) == XmMENU_POPUP)) /* rws 23 Mar 1997 */
1783 {
1784 CheckDisarm(gadget, event, NULL, &num_params);
1785 }
1786 else if (LabG_MenuType(gadget) == XmMENU_BAR)
1787 {
1788 MenuBarLeave(gadget, event, NULL, &num_params);
1789 }
1790 break;
1791
1792 case XmFOCUS_IN_EVENT:
1793 _XmFocusInGadget(gadget, event, NULL, &num_params);
1794 break;
1795
1796 case XmFOCUS_OUT_EVENT:
1797 _XmFocusOutGadget(gadget, event, NULL, &num_params);
1798 break;
1799
1800 case XmBDRAG_EVENT: /* FIX ME: MLM - is this right? */
1801 _XmProcessDrag(gadget, event, NULL, NULL);
1802 break;
1803
1804 case XmHELP_EVENT:
1805 Help(gadget, event, NULL, &num_params);
1806 break;
1807 }
1808 }
1809
1810 static Boolean
visual_change(Widget w,Widget parent,Widget n)1811 visual_change(Widget w,
1812 Widget parent,
1813 Widget n)
1814 {
1815 _XmWarning(w,"%s(%d) - visual_change not written\n", __FILE__, __LINE__);
1816 return False;
1817 }
1818
1819 static void
MenuProcEntry(int proc,Widget w,...)1820 MenuProcEntry(int proc, Widget w,...)
1821 {
1822 va_list arg_list;
1823 /*
1824 XEvent *event = NULL;
1825 */
1826
1827 va_start(arg_list, w);
1828
1829 switch (proc)
1830 {
1831 case XmMENU_ARM:
1832 {
1833 /* XtExposeProc exp = XtClass(w)->core_class.expose; */
1834
1835 XmCascadeButtonGadgetHighlight(w, True);
1836 XmProcessTraversal(w, XmTRAVERSE_CURRENT);
1837 MGR_ActiveChild(XtParent(w)) = w;
1838 /*
1839 (exp) (w, event, (Region)NULL);
1840 */
1841 }
1842 break;
1843 case XmMENU_DISARM:
1844 {
1845 /* XtExposeProc exp = XtClass(w)->core_class.expose; */
1846
1847 XmCascadeButtonGadgetHighlight(w, False);
1848 MGR_ActiveChild(XtParent(w)) = NULL;
1849 /*
1850 (exp) (w, event, (Region)NULL);
1851 */
1852 }
1853 break;
1854 default:
1855 _XmWarning(w, "%s(%d) - Invalid menuProc function", __FILE__, __LINE__);
1856 break;
1857 }
1858
1859 va_end(arg_list);
1860 }
1861
1862 void
XmCascadeButtonGadgetHighlight(Widget w,Boolean highlight)1863 XmCascadeButtonGadgetHighlight(Widget w, Boolean highlight)
1864 {
1865 DEBUGOUT(_LtDebug(__FILE__, w,
1866 "XmCascadeButtonGadgetHighlight(hl %d, armed %d,"
1867 " apm 0x%X, cpm 0x%X), %s, geo %d %d %dx%d\n",
1868 highlight,
1869 XmIsPrimitive(w) ? CB_IsArmed(w) : CBG_IsArmed(w),
1870 XmIsPrimitive(w) ? CB_ArmedPixmap(w) : CBG_ArmedPixmap(w),
1871 XmIsPrimitive(w) ? CB_CascadePixmap(w) : CBG_CascadePixmap(w),
1872 _LtDebugMenuType2String(LabG_MenuType(w)),
1873 XtX(w), XtY(w), XtWidth(w), XtHeight(w)
1874 ));
1875
1876 if (XmIsPrimitive(w))
1877 {
1878 XmCascadeButtonHighlight(w, highlight);
1879
1880 return;
1881 }
1882 else if (!XmIsCascadeButtonGadget(w))
1883 {
1884 _XmError(w,
1885 "XmCascadeButtonGadgetHighlight called with non-cascade button gadget");
1886
1887 return;
1888 }
1889
1890 if (LabG_MenuType(w) != XmMENU_OPTION)
1891 CBG_SetArmed(w, highlight);
1892
1893 if (XtIsRealized(w))
1894 {
1895 if (!highlight)
1896 {
1897 _XmClearBorder(XtDisplayOfObject(w),
1898 XtWindowOfObject(w),
1899 XtX(w), XtY(w), XtWidth(w), XtHeight(w),
1900 LabG_Shadow(w));
1901 }
1902 draw_cascade(w);
1903 }
1904 }
1905
1906 Widget
XmCreateCascadeButtonGadget(Widget parent,char * name,Arg * arglist,Cardinal argcount)1907 XmCreateCascadeButtonGadget(Widget parent, char *name,
1908 Arg *arglist, Cardinal argcount)
1909 {
1910 return XtCreateWidget(name,
1911 xmCascadeButtonGadgetClass,
1912 parent,
1913 arglist,
1914 argcount);
1915 }
1916