1 /**
2 *
3 * $Header: /cvsroot/lesstif/lesstif/lib/Xm-2.1/RowColumn.c,v 1.10 2007/09/12 20:35:55 jwrdegoede Exp $
4 *
5 * Copyright (C) 1996 Free Software Foundation, Inc.
6 * Copyright � 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2005 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/RowColumn.c,v 1.10 2007/09/12 20:35:55 jwrdegoede Exp $";
27
28 #include <LTconfig.h>
29
30 #include <stdio.h>
31 #include <string.h>
32 #include <stdarg.h>
33
34 #include <XmI/XmI.h>
35 #include <Xm/XmP.h>
36 #include <Xm/BaseClassP.h>
37 #include <Xm/CascadeBP.h>
38 #include <Xm/CascadeBGP.h>
39 #include <Xm/DrawnBP.h>
40 #include <Xm/Label.h>
41 #include <Xm/LabelG.h>
42 #include <Xm/ManagerP.h>
43 #include <Xm/MenuShellP.h>
44 #include <Xm/MenuUtilP.h>
45 #include <Xm/PushBP.h>
46 #include <Xm/PushBGP.h>
47 #include <Xm/RepType.h>
48 #include <Xm/RowColumnP.h>
49 #include <Xm/RCUtilsP.h>
50 #include <Xm/ScreenP.h>
51 #include <Xm/Separator.h>
52 #include <Xm/SeparatoG.h>
53 #include <Xm/TearOffBP.h>
54 #include <Xm/ToggleBP.h>
55 #include <Xm/ToggleBGP.h>
56 #include <Xm/TransltnsP.h>
57 #include <Xm/TearOffP.h>
58 #include <Xm/BulletinBP.h>
59 #include <XmI/MessagesI.h>
60
61 #include <XmI/DebugUtil.h>
62
63 /*
64 * builtin widgets for option menus
65 */
66 #define RC_OPTION_LABEL "OptionLabel"
67 #define RC_OPTION_CBG "OptionButton"
68
69 static Boolean _XmRCdefaultIsAligned = True;
70 static Boolean _XmRCdefaultAdjustMargin = True;
71 static Boolean _XmRCdefaultRadioBehavior = False; /* This should be true according to misc/test16
72 But it messes up toggle buttons in menus!
73 */
74 static Boolean _XmRCdefaultRadioAlwaysOne = True;
75 static Boolean _XmRCdefaultIsHomogeneous = True;
76 static Boolean _XmRCdefaultPopupEnabled = True;
77
78 /* Forward Declarations */
79
80 static void class_initialize(void);
81 static void class_part_initialize(WidgetClass w_class);
82 static void initialize(Widget request, Widget new_w, ArgList args,
83 Cardinal *num_args);
84 static void initialize_prehook(Widget request, Widget new_w, ArgList args,
85 Cardinal *num_args);
86 static void initialize_posthook(Widget request, Widget new_w, ArgList args,
87 Cardinal *num_args);
88 static void destroy(Widget w);
89 static void resize(Widget w);
90 static void realize(Widget w, XtValueMask *value_mask,
91 XSetWindowAttributes *attributes);
92 static void expose(Widget w, XEvent *event, Region region);
93 static XtGeometryResult query_geometry(Widget w, XtWidgetGeometry *proposed,
94 XtWidgetGeometry *answer);
95 static Boolean set_values(Widget current, Widget request, Widget new_w,
96 ArgList args, Cardinal *num_args);
97
98 /* T. Straumann: added get_values_hook method */
99 static void get_values_hook(Widget w, ArgList arg, Cardinal *nargs);
100 static XtGeometryResult geometry_manager(Widget w, XtWidgetGeometry *request,
101 XtWidgetGeometry *reply);
102 static void change_managed(Widget w);
103 static void insert_child(Widget w);
104 static void delete_child(Widget w);
105 static void constraint_initialize(Widget request, Widget neww,
106 ArgList args, Cardinal *num_args);
107 static Boolean constraint_set_values(Widget current, Widget request, Widget neww,
108 ArgList args, Cardinal *num_args);
109 static XmNavigability widget_navigable(Widget w);
110 static void AddPopupHandlers(Widget new_w);
111 static void MenuProcEntry(int proc, Widget rc,...);
112 static void ArmAndActivate(Widget w, XEvent *e, String *args, Cardinal *nargs);
113 static void _XmOptionCallback(Widget w, XtPointer cd, XtPointer cbs);
114 static void RadioHandler(Widget w);
115 static void _XmFromMenuPost(Widget widget, int offset, XtArgVal *value);
116 static void ParsePostString(Widget widget, String menuPost);
117 static XmImportOperator _XmToMenuPost(Widget widget, int offset,
118 XtArgVal *value);
119 static Cardinal _XmRowColumnOrderProc(Widget widget);
120 static void _XmRowColumnEntryClassDefault(Widget w,
121 int offset,
122 XrmValue *val);
123
124 /*
125 static void _XmRowColumnIsHomogeneousDefault(Widget w,
126 int offset,
127 XrmValue *val);
128 */
129
130 /*
131 static void _XmRowColumnMenuAcceleratorDefault(Widget w,
132 int offset,
133 XrmValue *val);
134 */
135
136
137 static void _XmPopupButtonPressHandler(Widget w, XtPointer client_data,
138 XEvent *event, Boolean *cont);
139 static void _XmFixOptionMenu(Widget new_w, Boolean use_set_values);
140
141 /*
142 * offset macros
143 */
144 #define Offset(field) XtOffsetOf(XmRowColumnRec, row_column.field)
145 #define MGR_Offset(field) XtOffsetOf(XmRowColumnRec, manager.field)
146 #define COMP_Offset(field) XtOffsetOf(XmRowColumnRec, composite.field)
147
148 /* Resources for the RowColumn class */
149 static XtResource resources[] =
150 {
151 {
152 XmNresizeWidth, XmCResizeWidth, XmRBoolean,
153 sizeof(Boolean), Offset(resize_width),
154 XmRImmediate, (XtPointer)True
155 },
156 {
157 XmNresizeHeight, XmCResizeHeight, XmRBoolean,
158 sizeof(Boolean), Offset(resize_height),
159 XmRImmediate, (XtPointer)True
160 },
161 {
162 XmNwhichButton, XmCWhichButton, XmRWhichButton,
163 sizeof(unsigned int), Offset(postButton),
164 XmRImmediate, (XtPointer)XmUNSPECIFIED
165 /* add support for this!!! */
166 },
167 {
168 XmNmenuPost, XmCMenuPost, XmRString,
169 sizeof(String), Offset(menuPost),
170 XmRString, (XtPointer)NULL
171 },
172 {
173 XmNadjustLast, XmCAdjustLast, XmRBoolean,
174 sizeof(Boolean), Offset(adjust_last),
175 XmRImmediate, (XtPointer)True
176 },
177 {
178 XmNmarginWidth, XmCMarginWidth, XmRHorizontalDimension,
179 sizeof(Dimension), Offset(margin_width),
180 XmRImmediate, (XtPointer)XmINVALID_DIMENSION
181 },
182 {
183 XmNmarginHeight, XmCMarginHeight, XmRVerticalDimension,
184 sizeof(Dimension), Offset(margin_height),
185 XmRImmediate, (XtPointer)XmINVALID_DIMENSION
186 },
187 {
188 XmNentryCallback, XmCCallback, XmRCallback,
189 sizeof(XtCallbackList), Offset(entry_callback),
190 XmRCallback, (XtPointer)NULL
191 },
192 {
193 XmNmapCallback, XmCCallback, XmRCallback,
194 sizeof(XtCallbackList), Offset(map_callback),
195 XmRCallback, (XtPointer)NULL
196 },
197 {
198 XmNunmapCallback, XmCCallback, XmRCallback,
199 sizeof(XtCallbackList), Offset(unmap_callback),
200 XmRCallback, (XtPointer)NULL
201 },
202 {
203 XmNorientation, XmCOrientation, XmROrientation,
204 sizeof(unsigned char), Offset(orientation),
205 XmRImmediate, (XtPointer)XmUNSPECIFIED
206 /*FIX ME: Should be XmROrientation, (XtPointer)some whacko thing here */
207 },
208 {
209 XmNspacing, XmCSpacing, XmRHorizontalDimension,
210 sizeof(Dimension), Offset(spacing),
211 XmRImmediate, (XtPointer)XmINVALID_DIMENSION
212 },
213 {
214 XmNentryBorder, XmCEntryBorder, XmRHorizontalDimension,
215 sizeof(Dimension), Offset(entry_border),
216 XmRImmediate, (XtPointer)0
217 },
218 {
219 XmNisAligned, XmCIsAligned, XmRBoolean,
220 sizeof(Boolean), Offset(do_alignment),
221 XmRBoolean, (XtPointer)&_XmRCdefaultIsAligned
222 },
223 {
224 XmNentryAlignment, XmCAlignment, XmRAlignment,
225 sizeof(unsigned char), Offset(entry_alignment),
226 XtRImmediate, (XtPointer)XmALIGNMENT_BEGINNING
227 /* FIX ME: Motif has XmRAlignment, (XtPointer)whacko value */
228 },
229 {
230 XmNadjustMargin, XmCAdjustMargin, XmRBoolean,
231 sizeof(Boolean), Offset(adjust_margin),
232 XtRBoolean, (XtPointer)&_XmRCdefaultAdjustMargin
233 },
234 {
235 XmNpacking, XmCPacking, XmRPacking,
236 sizeof(unsigned char), Offset(packing),
237 XmRImmediate, (XtPointer)XmUNSPECIFIED /* To be overruled in initialize */
238 },
239 {
240 XmNnumColumns, XmCNumColumns, XmRShort,
241 sizeof(short), Offset(num_columns),
242 XtRImmediate, (XtPointer)1
243 /* FIX ME: Motif has XmRShort, (XtPointer)whacko value */
244 },
245 {
246 XmNradioBehavior, XmCRadioBehavior, XmRBoolean,
247 sizeof(Boolean), Offset(radio),
248 XmRBoolean, (XtPointer)&_XmRCdefaultRadioBehavior
249 },
250 {
251 XmNradioAlwaysOne, XmCRadioAlwaysOne, XmRBoolean,
252 sizeof(Boolean), Offset(radio_one),
253 XmRBoolean, (XtPointer)&_XmRCdefaultRadioAlwaysOne
254 },
255 {
256 XmNisHomogeneous, XmCIsHomogeneous, XmRBoolean,
257 sizeof(Boolean), Offset(homogeneous),
258 XmRBoolean, (XtPointer)&_XmRCdefaultIsHomogeneous
259 },
260 {
261 XmNentryClass, XmCEntryClass, XmRWidgetClass,
262 sizeof(WidgetClass), Offset(entry_class),
263 XmRCallProc, (XtPointer)_XmRowColumnEntryClassDefault
264 /* Motif has XmRWidgetClass, (XtPointer)NULL */
265 },
266 {
267 XmNrowColumnType, XmCRowColumnType, XmRRowColumnType,
268 sizeof(unsigned char), Offset(type),
269 XtRImmediate, (XtPointer)XmWORK_AREA
270 /* FIX ME: Motif has XmRRowColumnType, (XtPointer)whacko value */
271 },
272 {
273 XmNmenuHelpWidget, XmCMenuWidget, XmRMenuWidget,
274 sizeof(Widget), Offset(help_pushbutton),
275 XmRImmediate, (XtPointer)NULL
276 /* FIX ME: Motif has XmRMenuWidget, (XtPointer)whacko value */
277 },
278 {
279 XmNlabelString, XmCXmString, XmRXmString,
280 sizeof(XmString), Offset(option_label),
281 XmRXmString, (XtPointer)NULL
282 },
283 {
284 XmNsubMenuId, XmCMenuWidget, XmRMenuWidget,
285 sizeof(Widget), Offset(option_submenu),
286 XmRImmediate, (XtPointer)NULL
287 /* FIX ME: Motif has XmRMenuWidget, (XtPointer)whacko value */
288 },
289 {
290 XmNmenuHistory, XmCMenuWidget, XmRMenuWidget,
291 sizeof(Widget), Offset(memory_subwidget),
292 XmRImmediate, (XtPointer)NULL
293 /* FIX ME: Motif has XmRMenuWidget, (XtPointer)whacko value */
294 },
295 {
296 XmNpopupEnabled, XmCPopupEnabled, XmRBoolean,
297 sizeof(Boolean), Offset(popup_enabled),
298 XmRBoolean, (XtPointer)&_XmRCdefaultPopupEnabled
299 },
300 {
301 XmNmenuAccelerator, XmCAccelerators, XmRString,
302 sizeof(String), Offset(menu_accelerator),
303 XmRString, (XtPointer)""
304 },
305 {
306 XmNmnemonic, XmCMnemonic, XmRKeySym,
307 sizeof(KeySym), Offset(mnemonic),
308 XmRImmediate, (XtPointer)NULL
309 },
310 {
311 XmNmnemonicCharSet, XmCMnemonicCharSet, XmRString,
312 sizeof(String), Offset(mnemonicCharSet),
313 XtRImmediate, (XtPointer)XmFONTLIST_DEFAULT_TAG
314 },
315 {
316 XmNshadowThickness, XmCShadowThickness, XmRHorizontalDimension,
317 sizeof(Dimension), MGR_Offset(shadow_thickness),
318 XmRImmediate, (XtPointer)XmINVALID_DIMENSION
319 },
320 {
321 XmNpostFromList, XmCPostFromList, XmRWidgetList,
322 sizeof(WidgetList), Offset(postFromList),
323 XmRWidgetList, (XtPointer)NULL
324 },
325 {
326 XmNpostFromCount, XmCPostFromCount, XmRInt,
327 sizeof(int), Offset(postFromCount),
328 XmRImmediate, (XtPointer)XmUNSPECIFIED
329 },
330 {
331 XmNnavigationType, XmCNavigationType, XmRNavigationType,
332 sizeof(XmNavigationType), MGR_Offset(navigation_type),
333 XmRImmediate, (XtPointer)((XmNavigationType)XmUNSPECIFIED)
334 },
335 {
336 XmNentryVerticalAlignment, XmCVerticalAlignment, XmRVerticalAlignment,
337 sizeof(unsigned char), Offset(entry_vertical_alignment),
338 XtRImmediate, (XtPointer)XmALIGNMENT_BEGINNING
339 /* FIX ME: Motif has XmRVerticalAlignment, (XtPointer)whacko values */
340 },
341 {
342 XmNtearOffModel, XmCTearOffModel, XmRTearOffModel,
343 sizeof(unsigned char), Offset(TearOffModel),
344 XtRImmediate, (XtPointer)XmTEAR_OFF_DISABLED
345 /* FIX ME: Motif has XmRTearOffModel, (XtPointer)whacko values */
346 },
347 {
348 XmNtearOffMenuActivateCallback, XmCCallback, XmRCallback,
349 sizeof(XtCallbackList), Offset(tear_off_activated_callback),
350 XmRCallback, (XtPointer)NULL
351 },
352 {
353 XmNtearOffMenuDeactivateCallback, XmCCallback, XmRCallback,
354 sizeof(XtCallbackList), Offset(tear_off_deactivated_callback),
355 XmRCallback, (XtPointer)NULL
356 },
357 {
358 XmNinsertPosition, XmCInsertPosition, XmRFunction,
359 sizeof(XtOrderProc), COMP_Offset(insert_position),
360 XmRImmediate, (XtPointer)_XmRowColumnOrderProc,
361 }
362 };
363
364 static XmSyntheticResource syn_resources[] =
365 {
366 {
367 XmNmnemonicCharSet,
368 sizeof(String), Offset(mnemonicCharSet),
369 NULL /* FIX ME */ , NULL
370 },
371 {
372 XmNmenuAccelerator,
373 sizeof(String), Offset(menu_accelerator),
374 NULL /* FIX ME */ , NULL
375 },
376 {
377 XmNmenuPost,
378 sizeof(String), Offset(menuPost),
379 _XmFromMenuPost, _XmToMenuPost,
380 },
381 {
382 XmNlabelString,
383 sizeof(XmString), Offset(option_label),
384 NULL /* FIX ME */ , NULL
385 },
386 {
387 XmNspacing,
388 sizeof(Dimension), Offset(spacing),
389 _XmFromHorizontalPixels, _XmToHorizontalPixels
390 },
391 {
392 XmNmarginHeight,
393 sizeof(Dimension), Offset(margin_height),
394 _XmFromVerticalPixels, _XmToVerticalPixels
395 },
396 {
397 XmNmarginWidth,
398 sizeof(Dimension), Offset(margin_width),
399 _XmFromHorizontalPixels, _XmToHorizontalPixels
400 },
401 {
402 XmNentryBorder,
403 sizeof(Dimension), Offset(entry_border),
404 _XmFromHorizontalPixels, _XmToHorizontalPixels
405 }
406 };
407
408 #undef Offset
409
410 #define Offset(field) XtOffsetOf(XmRowColumnConstraintRec, row_column.field)
411 static XtResource rowColumnConstraintResources[] =
412 {
413 {
414 XmNpositionIndex, XmCPositionIndex, XmRShort,
415 sizeof(short), Offset(position_index),
416 XmRImmediate, (XtPointer)XmLAST_POSITION
417 }
418 };
419
420 /* not all actually written yet... */
421 #define STATIC_ACTION(fn) static void (fn)(Widget, XEvent*, String*, Cardinal*)
422 #define ACTION(fn) void (fn)(Widget, XEvent*, String*, Cardinal*)
423
424 STATIC_ACTION(MenuBarGadgetSelect);
425 ACTION(_XmMenuHelp);
426 STATIC_ACTION(MenuEnter);
427 STATIC_ACTION(MenuUnmap);
428 STATIC_ACTION(MenuFocusIn);
429 STATIC_ACTION(MenuFocusOut);
430 STATIC_ACTION(DoBtnEventCleanupReplay);
431
432 #undef STATIC_ACTION
433 #undef ACTION
434
435 static void _XmFocusOut(Widget, XEvent*, String*, Cardinal*);
436 static void _XmFocusIn(Widget, XEvent*, String*, Cardinal*);
437 static void _XmUnmap(Widget, XEvent*, String*, Cardinal*);
438 static void _XmNoop(Widget, XEvent*, String*, Cardinal*);
439
440 static XtActionsRec actions[] =
441 {
442
443 {"MenuHelp", _XmMenuHelp},
444 {"MenuBtnDown", _XmMenuBtnDown},
445 {"MenuBtnUp", _XmMenuBtnUp},
446
447 {"MenuBarGadgetSelect", MenuBarGadgetSelect},
448 {"FocusOut", _XmFocusOut},
449 {"FocusIn", _XmFocusIn},
450 {"Unmap", _XmUnmap},
451 {"Noop", _XmNoop},
452 {"MenuTraverseLeft", _XmMenuTraverseLeft},
453 {"MenuTraverseRight", _XmMenuTraverseRight},
454 {"MenuTraverseUp", _XmMenuTraverseUp},
455 {"MenuTraverseDown", _XmMenuTraverseDown},
456 {"MenuEscape", _XmMenuEscape},
457 {"MenuFocusIn", MenuFocusIn},
458 {"MenuFocusOut", MenuFocusOut},
459 {"MenuUnmap", MenuUnmap},
460 {"MenuEnter", MenuEnter},
461 /*{"MenuGadgetReturn", _XmMenuReturn},*/
462 {"MenuGadgetEscape", _XmMenuEscape},
463 {"MenuGadgetTraverseLeft", _XmRC_GadgetTraverseLeft},
464 {"MenuGadgetTraverseRight", _XmRC_GadgetTraverseRight},
465 {"MenuGadgetTraverseUp", _XmRC_GadgetTraverseUp},
466 {"MenuGadgetTraverseDown", _XmRC_GadgetTraverseDown},
467 };
468
469
470 static XmBaseClassExtRec _XmRowColumnCoreClassExtRec =
471 {
472 /* next_extension */ NULL,
473 /* record_type */ NULLQUARK,
474 /* version */ XmBaseClassExtVersion,
475 /* size */ sizeof(XmBaseClassExtRec),
476 /* initialize_prehook */ initialize_prehook,
477 /* set_values_prehook */ XmInheritSetValuesPrehook /*NULL*/,
478 /* initialize_posthook */ initialize_posthook,
479 /* set_values_posthook */ XmInheritSetValuesPosthook /*NULL*/,
480 /* secondary_object_class */ XmInheritClass /*NULL*/,
481 /* secondary_object_create */ XmInheritSecObjectCreate /*NULL*/,
482 /* get_secondary_resources */ XmInheritGetSecResData /*NULL*/,
483 /* fast_subclass */ {0},
484 /* get_values_prehook */ XmInheritGetValuesPrehook /*NULL*/,
485 /* get_values_posthook */ XmInheritGetValuesPosthook /*NULL*/,
486 /* class_part_init_prehook */ NULL,
487 /* class_part_init_posthook */ NULL,
488 /* ext_resources */ NULL,
489 /* compiled_ext_resources */ NULL,
490 /* num_ext_resources */ 0,
491 /* use_sub_resources */ False,
492 /* widget_navigable */ widget_navigable,
493 /* focus_change */ XmInheritFocusChange,
494 /* wrapper_data */ NULL
495 };
496
497 #if 0
498 static CompositeClassExtensionRec rcCompositeExt =
499 {
500 /* next_extension */ NULL,
501 /* record_type */ NULLQUARK,
502 /* version */ XtCompositeExtensionVersion,
503 /* record_size */ sizeof(CompositeClassExtensionRec),
504 /* accepts_objects */ True,
505 #if XtSpecificationRelease >= 6
506 /* allows_change_managed_set */ True
507 #endif
508 };
509 #endif
510
511 static XmManagerClassExtRec _XmRowColumnMClassExtRec =
512 {
513 /* next_extension */ NULL,
514 /* record_type */ NULLQUARK,
515 /* version */ XmManagerClassExtVersion,
516 /* record_size */ sizeof(XmManagerClassExtRec),
517 /* traversal_children */ NULL /* FIX ME */
518 };
519
520 XmRowColumnClassRec xmRowColumnClassRec =
521 {
522 /* Core class part */
523 {
524 /* superclass */ (WidgetClass) & xmManagerClassRec,
525 /* class_name */ "XmRowColumn",
526 /* widget_size */ sizeof(XmRowColumnRec),
527 /* class_initialize */ class_initialize,
528 /* class_part_initialize */ class_part_initialize,
529 /* class_inited */ False,
530 /* initialize */ initialize,
531 /* initialize_hook */ NULL,
532 /* realize */ realize,
533 /* actions */ actions,
534 /* num_actions */ XtNumber(actions),
535 /* resources */ resources,
536 /* num_resources */ XtNumber(resources),
537 /* xrm_class */ NULLQUARK,
538 /* compress_motion */ True,
539 /* compress_exposure */ XtExposeCompressMaximal /*XtExposeCompressMultiple*/,
540 /* compress_enterleave */ False /*True*/,
541 /* visible_interest */ False /*True*/,
542 /* destroy */ destroy,
543 /* resize */ resize,
544 /* expose */ expose,
545 /* set_values */ set_values,
546 /* set_values_hook */ NULL,
547 /* set_values_almost */ XtInheritSetValuesAlmost,
548 /* get_values_hook */ get_values_hook,
549 /* accept_focus */ NULL,
550 /* version */ XtVersion,
551 /* callback offsets */ NULL,
552 /* tm_table */ XtInheritTranslations, /* should be NULL but
553 we loose togglebg's in
554 a work area if it is
555 togglegb/test1 */
556 /* query_geometry */ query_geometry,
557 /* display_accelerator */ NULL /*XtInheritDisplayAccelerator*/,
558 /* extension */ (XtPointer) &_XmRowColumnCoreClassExtRec
559 },
560 /* Composite class part */
561 {
562 /* geometry manager */ geometry_manager,
563 /* change_managed */ change_managed,
564 /* insert_child */ insert_child,
565 /* delete_child */ delete_child,
566 /* extension */ (XtPointer)NULL /*&rcCompositeExt*/,
567 },
568 /* Constraint class part */
569 {
570 /* subresources */ rowColumnConstraintResources,
571 /* subresource_count */ XtNumber(rowColumnConstraintResources),
572 /* constraint_size */ sizeof(XmRowColumnConstraintRec),
573 /* initialize */ constraint_initialize,
574 /* destroy */ NULL,
575 /* set_values */ constraint_set_values,
576 /* extension */ NULL,
577 },
578 /* XmManager class part */
579 {
580 /* translations */ XtInheritTranslations,
581 /* syn_resources */ syn_resources,
582 /* num_syn_resources */ XtNumber(syn_resources),
583 /* syn_constraint_res */ NULL,
584 /* num_syn_constraint_res */ 0,
585 /* parent_process */ XmInheritParentProcess,
586 /* extension */ (XtPointer)&_XmRowColumnMClassExtRec
587 },
588 /* XmRowColumn Area part */
589 {
590 /* menuProcedures */ MenuProcEntry,
591 /* armAndActivate */ ArmAndActivate,
592 /* traversalHandler */ _XmMenuTraversalHandler,
593 /* extension */ NULL,
594 },
595 };
596
597
598 WidgetClass xmRowColumnWidgetClass = (WidgetClass)&xmRowColumnClassRec;
599
600
601 static XtTranslations menubar_trans;
602 static XtTranslations option_trans;
603 static XtTranslations menu_trans;
604 static XtTranslations menutrav_trans;
605
606 static void
class_initialize(void)607 class_initialize(void)
608 {
609 _XmRowColumnCoreClassExtRec.record_type = XmQmotif;
610
611 menubar_trans = XtParseTranslationTable(_XmRowColumn_bar_table);
612 option_trans = XtParseTranslationTable(_XmRowColumn_option_table);
613 menu_trans = XtParseTranslationTable(_XmRowColumn_menu_table);
614 menutrav_trans = XtParseTranslationTable(_XmRowColumn_menu_traversal_table);
615 }
616
617 static void
class_part_initialize(WidgetClass widget_class)618 class_part_initialize(WidgetClass widget_class)
619 {
620 CompositeClassExtension ext, *extptr;
621 XmRowColumnWidgetClass rc_class = (XmRowColumnWidgetClass)widget_class;
622
623 extptr = (CompositeClassExtension *)
624 _XmGetClassExtensionPtr((XmGenericClassExt *)
625 &(rc_class->composite_class.extension),
626 NULLQUARK);
627
628 if (extptr == NULL || *extptr == NULL)
629 {
630 ext = (CompositeClassExtension)XtNew(CompositeClassExtensionRec);
631 if (ext != NULL)
632 {
633 ext->next_extension = rc_class->composite_class.extension;
634 ext->record_type = NULLQUARK;
635 ext->version = XtCompositeExtensionVersion;
636 ext->record_size = sizeof(CompositeClassExtensionRec);
637 ext->accepts_objects = True;
638 #if XtSpecificationRelease >= 6
639 ext->allows_change_managed_set = True;
640 #endif
641 rc_class->composite_class.extension = (XtPointer)ext;
642 }
643 }
644
645 _XmFastSubclassInit(widget_class, XmROW_COLUMN_BIT);
646 }
647
648 static void
_XmRcCreateTearOffControl(Widget rc)649 _XmRcCreateTearOffControl(Widget rc)
650 {
651 RC_TearOffControl(rc) = XtVaCreateManagedWidget("TearOffControl",
652 xmTearOffButtonWidgetClass, rc,
653 XmNpositionIndex, 0,
654 NULL);
655 }
656
657 static void
_XmRcDestroyTearOffControl(Widget rc)658 _XmRcDestroyTearOffControl(Widget rc)
659 {
660 if (RC_TearOffControl(rc))
661 {
662 XtDestroyWidget(RC_TearOffControl(rc));
663 }
664 RC_TearOffControl(rc) = NULL;
665 }
666
667 static void
initialize_prehook(Widget request,Widget new_w,ArgList args,Cardinal * num_args)668 initialize_prehook(Widget request, Widget new_w,
669 ArgList args, Cardinal *num_args)
670 {
671 if (RC_Type(new_w) == XmWORK_AREA)
672 {
673 MGR_NavigationType(new_w) = XmTAB_GROUP;
674 }
675 else
676 {
677 MGR_NavigationType(new_w) = XmNONE;
678 }
679
680 MGR_TraversalOn(new_w) = True;
681
682 /* this is needed for Xmt. We probably ought to follow suit with
683 * what we do in Label et. al. and override the translations here
684 * rather than in initialize. */
685 _XmSaveCoreClassTranslations(new_w);
686
687 switch (RC_Type(new_w))
688 {
689 case XmMENU_PULLDOWN:
690 case XmMENU_POPUP:
691 CoreClassTranslations(new_w) = (String)menu_trans;
692 break;
693
694 case XmMENU_BAR:
695 CoreClassTranslations(new_w) = (String)menubar_trans;
696 break;
697
698 case XmMENU_OPTION:
699 CoreClassTranslations(new_w) = (String)option_trans;
700 break;
701
702 case XmWORK_AREA:
703 /* rws 8 Mar 1998
704 I think that we should be installing the Manager translations here.
705 misc/test16 shows that Motif sets the tm_table entry to NULL. If we
706 do this toggle button gadgets in work areas will not activate.
707 togglebg/test1
708 */
709 default:
710 break;
711 }
712 }
713
714 static void
initialize_posthook(Widget request,Widget new_w,ArgList args,Cardinal * num_args)715 initialize_posthook(Widget request, Widget new_w,
716 ArgList args, Cardinal *num_args)
717 {
718 _XmRestoreCoreClassTranslations(new_w);
719
720 if (RC_Type(new_w) == XmMENU_OPTION)
721 {
722 Widget cb;
723 if (RC_OptionLabel(new_w) != NULL)
724 {
725 XtVaCreateManagedWidget(RC_OPTION_LABEL,
726 xmLabelGadgetClass,
727 new_w,
728 XmNlabelString, RC_OptionLabel(new_w),
729 XmNmnemonic, RC_Mnemonic(new_w),
730 XmNmnemonicCharSet,
731 RC_MnemonicCharSet(new_w),
732 NULL);
733 }
734 else
735 {
736 XmString s = XmStringCreateLtoR("", XmFONTLIST_DEFAULT_TAG);
737
738 XtVaCreateManagedWidget(RC_OPTION_LABEL,
739 xmLabelGadgetClass,
740 new_w,
741 XmNlabelString, s,
742 XmNmnemonic, RC_Mnemonic(new_w),
743 XmNmnemonicCharSet,
744 RC_MnemonicCharSet(new_w),
745 NULL);
746 XmStringFree(s);
747 }
748 cb = XtVaCreateManagedWidget(RC_OPTION_CBG,
749 xmCascadeButtonGadgetClass,
750 new_w,
751 XmNsubMenuId, RC_OptionSubMenu(new_w),
752 XmNrecomputeSize, False,
753 XmNalignment, XmALIGNMENT_CENTER,
754 NULL);
755
756 RC_DoMarginAdjust(new_w) = False; /* This is to get test28 correct */
757 _XmFixOptionMenu(new_w, True);
758
759 /* If we have XmNmenuHistory, copy it */
760 if (RC_MemWidget(new_w))
761 {
762 XmString xms = NULL;
763 Arg a;
764 XtSetArg(a, XmNlabelString, &xms);
765 XtGetValues(RC_MemWidget(new_w), &a, 1);
766 XtSetArg(a, XmNlabelString, xms);
767 XtSetValues(cb, &a, 1);
768 XmStringFree(xms);
769 }
770 }
771 }
772
773 static void
initialize(Widget request,Widget new_w,ArgList args,Cardinal * num_args)774 initialize(Widget request, Widget new_w,
775 ArgList args, Cardinal *num_args)
776 {
777 RC_Boxes(new_w) = NULL; /* no initial children */
778
779 DEBUGOUT(_LtDebug(__FILE__, new_w,
780 "%s:initialize: %i args\n"
781 "\trequest X %5i Y %5i W %5i H %5i\n"
782 "\t new_w X %5i Y %5i W %5i H %5i\n",
783 __FILE__, *num_args,
784 XtX(request), XtY(request),
785 XtWidth(request), XtHeight(request),
786 XtX(new_w), XtY(new_w),
787 XtWidth(new_w), XtHeight(new_w)));
788 DEBUGOUT(_LtDebugPrintArgList(__FILE__, new_w, args, *num_args, False));
789
790 RC_TearOffLastSelectToplevel(new_w) = NULL;
791 RC_TearOffFocusItem(new_w) = NULL;
792 #if 1
793 /* test38 */
794 /* ddd Edit->GDB settings (option menus) */
795 if (RC_Type(new_w) == XmWORK_AREA)
796 {
797 if (XtWidth(new_w) == 0)
798 {
799 XtWidth(new_w) = 16;
800 }
801 if (XtHeight(new_w) == 0)
802 {
803 XtHeight(new_w) = 16;
804 }
805 }
806 #endif
807 /* FIX ME: Check if parent is MenuShell if pulldown or option menu */
808 if (RC_Type(new_w) == XmMENU_OPTION)
809 {
810 #if 0
811 /* rws 19 Oct 1999
812 openDX shows that Motif seems to force this no matter what is
813 specified.
814 dx -prompter then select Image file. The option menu should not
815 have the shadow around it.
816 */
817 if (MGR_ShadowThickness(new_w) == XmINVALID_DIMENSION)
818 #endif
819 {
820 MGR_ShadowThickness(new_w) = 0;
821 }
822 }
823 else
824 {
825 if (MGR_ShadowThickness(new_w) == XmINVALID_DIMENSION)
826 {
827 if (RC_Type(new_w) == XmMENU_PULLDOWN ||
828 RC_Type(new_w) == XmMENU_POPUP ||
829 RC_Type(new_w) == XmMENU_BAR)
830 {
831 MGR_ShadowThickness(new_w) = 2;
832 }
833 else
834 {
835 MGR_ShadowThickness(new_w) = 0;
836 }
837 }
838 }
839
840 /* now, we install our translations,
841 * depending on the row column type */
842
843 if (RC_Type(new_w) == XmMENU_PULLDOWN ||
844 RC_Type(new_w) == XmMENU_POPUP ||
845 RC_Type(new_w) == XmMENU_BAR)
846 {
847 XtOverrideTranslations(new_w, menutrav_trans);
848 }
849
850 /* menuPost stuff. */
851 if (RC_MenuPost(new_w) == NULL)
852 {
853 if (RC_Type(new_w) == XmMENU_OPTION ||
854 RC_Type(new_w) == XmWORK_AREA ||
855 RC_Type(new_w) == XmMENU_BAR)
856 {
857 RC_MenuPost(new_w) = "<Btn1Down>";
858 }
859 }
860 else
861 ParsePostString(new_w, RC_MenuPost(new_w));
862
863 if (RC_Type(new_w) == XmMENU_POPUP)
864 {
865 if (RC_PostButton(new_w) == XmUNSPECIFIED)
866 {
867 RC_PostEventType(new_w) = ButtonPress;
868 RC_PostButton(new_w) = Button3; /* Fixme: this should be BMenu */
869 RC_PostModifiers(new_w) = 0;
870 }
871 AddPopupHandlers(new_w);
872
873 if (XtParent(new_w) && XmIsMenuShell(XtParent(new_w)))
874 {
875 MS_PrivateShell(XtParent(new_w)) = False;
876 }
877 }
878
879 ((XmRowColumnWidget)new_w)->row_column.armed = 0; /* FIX ME: macro */
880
881 if (RC_Spacing(new_w) == XmINVALID_DIMENSION)
882 {
883 if (RC_Type(new_w) == XmMENU_OPTION || RC_Type(new_w) == XmWORK_AREA)
884 {
885 RC_Spacing(new_w) = 3;
886 }
887 else
888 {
889 RC_Spacing(new_w) = 0;
890 }
891 }
892
893 if (RC_MarginW(new_w) == XmINVALID_DIMENSION)
894 {
895 if (RC_Type(new_w) == XmMENU_POPUP || RC_Type(new_w) == XmMENU_PULLDOWN)
896 {
897 RC_MarginW(new_w) = 0;
898 }
899 else
900 {
901 RC_MarginW(new_w) = 3;
902 }
903 }
904 if (RC_MarginH(new_w) == XmINVALID_DIMENSION)
905 {
906 if (RC_Type(new_w) == XmMENU_POPUP || RC_Type(new_w) == XmMENU_PULLDOWN)
907 {
908 RC_MarginH(new_w) = 0;
909 }
910 else
911 {
912 RC_MarginH(new_w) = 3;
913 }
914 }
915
916 RC_LastSelectToplevel(new_w) = NULL; /* widget id of the menu at the
917 top of the heir
918 */
919
920 if (RC_Type(new_w) == XmMENU_BAR || RC_Type(new_w) == XmMENU_OPTION)
921 {
922 RC_LastSelectToplevel(new_w) = new_w;
923 if (RC_OptionSubMenu(new_w))
924 {
925 /* Make sure the sub-menu has a back pointer to the option menu */
926 RC_LastSelectToplevel(RC_OptionSubMenu(new_w)) = new_w;
927 }
928 }
929
930 /* Internal widgets */
931
932 RC_CascadeBtn(new_w) = NULL; /* widget id of the cascade button
933 that posted this menu
934 */
935 RC_PopupPosted(new_w) = NULL; /* widget id of the menu posted from
936 any button in this menu
937 */
938
939 /* Tear off stuff */
940 RC_SetTornOff(new_w, False);
941 RC_SetFromInit(new_w, False);
942 RC_SetTearOffDirty(new_w, False);
943 RC_SetTearOffActive(new_w, False);
944 RC_ParentShell(new_w) = NULL;
945 RC_TearOffControl(new_w) = NULL;
946 if ((RC_Type(new_w) == XmMENU_POPUP || RC_Type(new_w) == XmMENU_PULLDOWN) &&
947 RC_TearOffModel(new_w) == XmTEAR_OFF_ENABLED)
948 {
949 _XmRcCreateTearOffControl(new_w);
950 }
951
952 /* just to initialize it. */
953 RC_SetFromResize(new_w, False);
954 RC_SetArmed(new_w, False);
955
956 if (RC_Packing(new_w) == (unsigned char)XmUNSPECIFIED)
957 {
958 /*
959 * This is what the XmRowColumn manual page says
960 * (end of the text describing XmNpacking).
961 */
962 if (RC_RadioBehavior(new_w) && RC_Type(new_w) == XmWORK_AREA)
963 {
964 RC_Packing(new_w) = XmPACK_COLUMN;
965 }
966 else if (RC_Type(new_w) == XmMENU_OPTION)
967 {
968 RC_Packing(new_w) = XmPACK_TIGHT;
969 }
970 else
971 {
972 RC_Packing(new_w) = XmPACK_TIGHT;
973 }
974 }
975
976 if (RC_Orientation(new_w) == (unsigned char)XmUNSPECIFIED)
977 {
978 if (RC_Type(new_w) == XmMENU_PULLDOWN ||
979 RC_Type(new_w) == XmMENU_POPUP)
980 {
981 RC_Orientation(new_w) = XmVERTICAL;
982 }
983 else if (RC_Type(new_w) == XmMENU_OPTION ||
984 RC_Type(new_w) == XmMENU_BAR)
985 {
986 RC_Orientation(new_w) = XmHORIZONTAL;
987 }
988 else
989 {
990 RC_Orientation(new_w) = XmVERTICAL;
991 }
992 }
993
994 /* Be verbose about it ... */
995 DEBUGOUT(_LtDebug(__FILE__,
996 new_w,
997 "Initialize: RadioBehavior %s, RC_Type %s => Packing %s\n",
998 _LtDebugBoolean2String(RC_RadioBehavior(new_w)),
999 _LtDebugRcType2String(RC_Type(new_w)),
1000 _LtDebugPacking2String(RC_Packing(new_w))));
1001
1002 #if 0
1003 /* FIX ME: This should be enabled as soon as MGR_HighlightedWidget(w) =
1004 * NULL is moved from MenuUnmap to Manager's event handler.
1005 */
1006 if (RC_Type(new_w) == XmMENU_PULLDOWN)
1007 {
1008 new_w->core.mapped_when_managed = False;
1009 }
1010 #endif
1011 RC_OldWidth(new_w) = XtWidth(new_w);
1012 RC_OldHeight(new_w) = XtHeight(new_w);
1013 RC_OldShadowThickness(new_w) = MGR_ShadowThickness(new_w);
1014
1015 }
1016
xtWarnCB(String message)1017 static void xtWarnCB(String message)
1018 {
1019 }
1020
1021 static void
destroy(Widget w)1022 destroy(Widget w)
1023 {
1024 /* initialize() called AddPopupHandlers() upon a popup menu */
1025 if (RC_Type(w) == XmMENU_POPUP)
1026 {
1027 Widget realpar = NULL;
1028
1029 if (XtIsShell(XtParent(w)))
1030 {
1031 realpar = XtParent(XtParent(w));
1032 }
1033 else
1034 {
1035 realpar = XtParent(w);
1036 }
1037
1038 if (realpar != NULL)
1039 {
1040 XtErrorHandler old_handler;
1041 XtRemoveEventHandler(realpar,
1042 ButtonPressMask|ButtonReleaseMask,
1043 False, _XmPopupButtonPressHandler,
1044 (XtPointer)w );
1045 /* Yes this may not be necessary, shut up Xt see:
1046 http://sourceforge.net/tracker/index.php?func=detail&aid=1217326&group_id=8596&atid=108596 */
1047 old_handler = XtAppSetWarningHandler(
1048 XtWidgetToApplicationContext(realpar),
1049 xtWarnCB);
1050 XtUngrabButton(realpar, RC_PostButton(w), RC_PostModifiers(w));
1051 XtAppSetWarningHandler(XtWidgetToApplicationContext(realpar),
1052 old_handler);
1053 }
1054 }
1055
1056 if (RC_Boxes(w))
1057 {
1058 XtFree((char *)RC_Boxes(w));
1059 }
1060 }
1061
1062 Widget
XmOptionButtonGadget(Widget option_menu)1063 XmOptionButtonGadget(Widget option_menu)
1064 {
1065 return XtNameToWidget(option_menu, RC_OPTION_CBG);
1066 }
1067
1068 Widget
XmOptionLabelGadget(Widget option_menu)1069 XmOptionLabelGadget(Widget option_menu)
1070 {
1071 return XtNameToWidget(option_menu, RC_OPTION_LABEL);
1072 }
1073
1074 static Boolean
set_values(Widget old,Widget request,Widget new_w,ArgList args,Cardinal * num_args)1075 set_values(Widget old, Widget request, Widget new_w,
1076 ArgList args, Cardinal *num_args)
1077 {
1078 Boolean need_refresh = False, need_relayout = False;
1079
1080 DEBUGOUT(_LtDebug(__FILE__, new_w,
1081 "set_values: %i args\n"
1082 "\t old X %5i Y %5i W %5i H %5i\n"
1083 "\trequest X %5i Y %5i W %5i H %5i\n"
1084 "\t new_w X %5i Y %5i W %5i H %5i\n",
1085 *num_args,
1086 XtX(old), XtY(old),
1087 XtWidth(old), XtHeight(old),
1088 XtX(request), XtY(request),
1089 XtWidth(request), XtHeight(request),
1090 XtX(new_w), XtY(new_w),
1091 XtWidth(new_w), XtHeight(new_w)));
1092 DEBUGOUT(_LtDebugPrintArgList(__FILE__, new_w, args, *num_args, False));
1093 DEBUGOUT(_LtDebug("EMACS", new_w,
1094 "set_values: %i args\n"
1095 "\t old X %5i Y %5i W %5i H %5i\n"
1096 "\trequest X %5i Y %5i W %5i H %5i\n"
1097 "\t new_w X %5i Y %5i W %5i H %5i\n",
1098 *num_args,
1099 XtX(old), XtY(old),
1100 XtWidth(old), XtHeight(old),
1101 XtX(request), XtY(request),
1102 XtWidth(request), XtHeight(request),
1103 XtX(new_w), XtY(new_w),
1104 XtWidth(new_w), XtHeight(new_w)));
1105 DEBUGOUT(_LtDebugPrintArgList("EMACS", new_w, args, *num_args, False));
1106
1107 if (MGR_ShadowThickness(old) != MGR_ShadowThickness(new_w))
1108 {
1109 if (!(RC_Type(new_w) == XmMENU_PULLDOWN || RC_Type(new_w) == XmMENU_POPUP))
1110 {
1111 _XmWarning(new_w, _XmMsgRowColumn_0020);
1112 MGR_ShadowThickness(new_w) = MGR_ShadowThickness(old);
1113 }
1114 }
1115 if (RC_EntryAlignment(old) != RC_EntryAlignment(new_w))
1116 {
1117 Cardinal i;
1118 Arg a;
1119
1120 XtSetArg(a, XmNalignment, RC_EntryAlignment(new_w));
1121 DEBUGOUT(_LtDebug(__FILE__, new_w,
1122 "Setting Alignment for children to %s\n",
1123 _LtDebugAlignment2String(RC_EntryAlignment(new_w))));
1124
1125 for (i = 0; i < MGR_NumChildren(new_w); i++)
1126 {
1127 if (XmIsLabel(MGR_Children(new_w)[i])
1128 || XmIsLabelGadget(MGR_Children(new_w)[i]))
1129 {
1130 DEBUGOUT(_LtDebug2(__FILE__, new_w, MGR_Children(new_w)[i],
1131 "Set Alignment to %s\n",
1132 _LtDebugAlignment2String(RC_EntryAlignment(new_w))));
1133 XtSetValues(MGR_Children(new_w)[i], &a, 1);
1134 }
1135 }
1136 }
1137
1138 if ((RC_Orientation(old) != RC_Orientation(new_w)) ||
1139 (RC_Packing(old) != RC_Packing(new_w)))
1140 {
1141 need_relayout = True;
1142 need_refresh = True;
1143 }
1144
1145 if ((RC_TearOffModel(new_w) != RC_TearOffModel(old)) &&
1146 (RC_Type(new_w) == XmMENU_POPUP || RC_Type(new_w) == XmMENU_PULLDOWN))
1147 {
1148 if (RC_TearOffModel(new_w) == XmTEAR_OFF_ENABLED)
1149 {
1150 _XmRcCreateTearOffControl(new_w);
1151 }
1152 else
1153 {
1154 _XmRcDestroyTearOffControl(new_w);
1155 }
1156
1157 need_relayout = True;
1158 }
1159
1160 if (RC_OptionLabel(new_w) != RC_OptionLabel(old))
1161 {
1162 int i;
1163
1164 /* Oh yes this is very efficient :-( */
1165 for (i = 0; i < MGR_NumChildren(new_w); i++)
1166 {
1167 if (XmIsLabelGadget(MGR_Children(new_w)[i]) &&
1168 !XmIsCascadeButtonGadget(MGR_Children(new_w)[i]))
1169 {
1170 if (RC_OptionLabel(new_w) == NULL)
1171 {
1172 XtUnmanageChild(MGR_Children(new_w)[i]);
1173 }
1174 else
1175 {
1176 XtVaSetValues(MGR_Children(new_w)[i],
1177 XmNlabelString, RC_OptionLabel(new_w), NULL);
1178
1179 if (!XtIsManaged(MGR_Children(new_w)[i]))
1180 {
1181 XtManageChild(MGR_Children(new_w)[i]);
1182
1183 need_relayout = True;
1184 need_refresh = True;
1185 }
1186 }
1187
1188 DEBUGOUT(_LtDebug2(__FILE__, new_w, MGR_Children(new_w)[i],
1189 "Assign OptionLabelString\n"));
1190
1191 break;
1192 }
1193 }
1194 }
1195
1196 if (RC_Type(new_w) == XmMENU_OPTION &&
1197 RC_OptionSubMenu(new_w) != RC_OptionSubMenu(old))
1198 {
1199 int i;
1200
1201 /* Make sure the sub-menu has a back pointer to the option menu */
1202 RC_LastSelectToplevel(RC_OptionSubMenu(new_w)) = new_w;
1203 /* Oh yes this is very efficient :-( */
1204 for (i = 0; i < MGR_NumChildren(new_w); i++)
1205 {
1206 if (XtIsSubclass(MGR_Children(new_w)[i],
1207 xmCascadeButtonGadgetClass))
1208 {
1209 XtVaSetValues(MGR_Children(new_w)[i],
1210 XmNsubMenuId,
1211 RC_OptionSubMenu(new_w),
1212 NULL);
1213
1214 DEBUGOUT(_LtDebug2(__FILE__,
1215 new_w,
1216 MGR_Children(new_w)[i],
1217 "Assign SubMenuId (%s)\n",
1218 XtName(RC_OptionSubMenu(new_w))));
1219 break;
1220 }
1221 }
1222
1223 _XmFixOptionMenu(new_w, True);
1224 }
1225
1226 /* rws take care of setValues on menuHistory */
1227 /* rws 21 Nov 1998
1228 rowcolumn/test46 shows that setting menuHistory on the submenu
1229 sets the item also!!!!
1230 */
1231 if (RC_MemWidget(new_w) != RC_MemWidget(old))
1232 {
1233 if (RC_Type(new_w) == XmMENU_OPTION)
1234 {
1235 _XmOptionCallback(RC_MemWidget(new_w), (XtPointer)new_w, NULL);
1236 }
1237 else if (RC_LastSelectToplevel(new_w) && RC_Type(RC_LastSelectToplevel(new_w)) == XmMENU_OPTION)
1238 {
1239 RC_MemWidget(RC_LastSelectToplevel(new_w)) = RC_MemWidget(new_w);
1240 /* dwilliss 28-may-04
1241 * Not enough to just set mem_widget on RC_LastSelectToplevel
1242 * we need to tell it that its changed or the label on the
1243 * option menu won't change
1244 */
1245 _XmOptionCallback(RC_MemWidget(RC_LastSelectToplevel(new_w)),
1246 (XtPointer)RC_LastSelectToplevel(new_w), NULL);
1247 }
1248 }
1249 if (RC_NCol(new_w) != RC_NCol(old))
1250 {
1251 need_relayout = True;
1252 }
1253
1254 if (need_relayout)
1255 {
1256 DEBUGOUT(_LtDebug(__FILE__, new_w,
1257 "_XmRCAdjustSize from set_values\n"));
1258 DEBUGOUT(_LtDebug("EMACS", new_w,
1259 "_XmRCAdjustSize from set_values\n"));
1260 _XmRCAdjustSize(new_w, NULL, NULL);
1261 }
1262
1263 /* We may get stuff for our parent passed. If that's so, pass it along. */
1264 if (XmIsMenuShell(XtParent(new_w)) && (RC_Type(new_w) == XmMENU_POPUP
1265 || RC_Type(new_w) == XmMENU_OPTION
1266 || RC_Type(new_w) == XmMENU_PULLDOWN)) {
1267 Arg al[5];
1268 int i, ac = 0;
1269 for (i=0; i<*num_args; i++) {
1270 if (strcmp(args[i].name, XmNx) == 0) {
1271 XtSetArg(al[ac], XmNx, args[i].value);
1272 ac++;
1273 }
1274 if (strcmp(args[i].name, XmNy) == 0) {
1275 XtSetArg(al[ac], XmNy, args[i].value);
1276 ac++;
1277 }
1278 }
1279 if (ac)
1280 XtSetValues(XtParent(new_w), al, ac);
1281 }
1282
1283 return need_refresh;
1284 }
1285 /* rws 23 Feb 1999
1286 Motif does not have this method
1287 */
1288
1289 /* T. Straumann: If asked for XmNchildren / XmNnumChildren by XtGetValues,
1290 * TearOffControl doesn't show up in the list (M*TIF behavior).
1291 * LESSTIF however passes TearOffControl as children[0] back
1292 * to the requestor.
1293 * I added a get_values_hook method to achieve M*TIF semantics.
1294 */
1295 static void
get_values_hook(Widget w,ArgList args,Cardinal * nargs)1296 get_values_hook(Widget w, ArgList args, Cardinal *nargs)
1297 {
1298 Cardinal i;
1299 static XrmQuark Qchildren = NULLQUARK;
1300 static XrmQuark QnumChildren = NULLQUARK;
1301 XrmQuark *ql;
1302
1303 /* return if there's no tear off control button */
1304 if ( ! RC_TearOffControl(w)
1305 || ! MGR_Children(w)
1306 || MGR_Children(w)[0] != RC_TearOffControl(w) /* paranoia */)
1307 return;
1308
1309 /* one time initialization */
1310 if ( NULLQUARK == Qchildren )
1311 Qchildren = XrmStringToQuark(XmNchildren);
1312
1313 if ( NULLQUARK == QnumChildren )
1314 QnumChildren = XrmStringToQuark(XmNnumChildren);
1315
1316 /* is it really worth the effort (quark vs. strcmp) ? */
1317 ql = (XrmQuark *)XtMalloc(sizeof(XrmQuark)* *nargs);
1318
1319 for (i=0; i< *nargs; i++)
1320 ql[i] = XrmStringToQuark(args[i].name);
1321
1322 /* search through the list whether they ask for children / numChildren */
1323 for (i=0; i< *nargs; i++)
1324 {
1325 /* reduce the number of children by one, if the
1326 * TearOffControl is there.
1327 */
1328 if ( ql[i] == QnumChildren )
1329 (*(Cardinal*)args[i].value)--;
1330
1331 /* adjust the 'children' pointer; skip TearOffControl */
1332 if ( ql[i] == Qchildren )
1333 (*(WidgetList*)args[i].value)++;
1334 }
1335 XtFree((char*)ql);
1336 }
1337
1338 static void
realize(Widget w,XtValueMask * value_mask,XSetWindowAttributes * attributes)1339 realize(Widget w, XtValueMask *value_mask, XSetWindowAttributes *attributes)
1340 {
1341
1342 DEBUGOUT(_LtDebug(__FILE__, w, "%s:realize(%d) - %dx%d\n",
1343 __FILE__, __LINE__,
1344 XtWidth(w), XtHeight(w)));
1345
1346 #define superclass (&xmManagerClassRec)
1347 (*superclass->core_class.realize) (w, value_mask, attributes);
1348 #undef superclass
1349 if (XmIsMenuShell(XtParent(w)) && MS_PrivateShell(XtParent(w)))
1350 {
1351 /* if this is in a private menu shell it was managed during
1352 insert_child. However if someone (Mozilla's go menu)
1353 un-realizes the menu and then realizes it again we must
1354 make sure it is managed.
1355 */
1356 XtManageChild(w);
1357 }
1358 }
1359
1360 static void
resize(Widget w)1361 resize(Widget w)
1362 {
1363 if (!RC_FromResize(w))
1364 {
1365 /* rws 6 Jun 1998
1366 recursion avoidance. Shows up when resizing the width of Mozilla
1367 */
1368 DEBUGOUT(_LtDebug(__FILE__, w,
1369 "RC resize -> wid %d ht %d, call _XmRCAdjustSize\n",
1370 XtWidth(w), XtHeight(w)));
1371 DEBUGOUT(_LtDebug("EMACS", w,
1372 "RC resize -> wid %d ht %d, call _XmRCAdjustSize\n",
1373 XtWidth(w), XtHeight(w)));
1374 #if 0
1375 if (XtWindow(w))
1376 XClearArea(XtDisplay(w), XtWindow(w),
1377 0, 0, XtWidth(w), XtHeight(w),
1378 False);
1379 #endif
1380
1381 RC_SetFromResize(w, 1);
1382
1383 _XmRCAdjustSize(w, NULL, NULL);
1384
1385 RC_SetFromResize(w, 0);
1386
1387 if (RC_Type(w) != XmWORK_AREA && XtIsRealized(w))
1388 {
1389 _XmClearShadowType(w, RC_OldWidth(w), RC_OldHeight(w),
1390 RC_OldShadowThickness(w), 0);
1391
1392 _XmDrawShadows(XtDisplay(w), XtWindow(w),
1393 MGR_TopShadowGC(w), MGR_BottomShadowGC(w),
1394 0, 0, XtWidth(w), XtHeight(w),
1395 MGR_ShadowThickness(w), XmSHADOW_OUT);
1396 }
1397 RC_OldWidth(w) = XtWidth(w);
1398 RC_OldHeight(w) = XtHeight(w);
1399 RC_OldShadowThickness(w) = MGR_ShadowThickness(w);
1400 }
1401 }
1402
1403 static void
expose(Widget w,XEvent * event,Region region)1404 expose(Widget w, XEvent *event, Region region)
1405 {
1406 DEBUGOUT(_LtDebug(__FILE__, w, "Expose (wid %d ht %d)\n",
1407 XtWidth(w), XtHeight(w)));
1408
1409 if (RC_Type(w) != XmWORK_AREA)
1410 {
1411 _XmDrawShadows(XtDisplay(w),
1412 XtWindow(w),
1413 MGR_TopShadowGC(w),
1414 MGR_BottomShadowGC(w),
1415 0, 0,
1416 XtWidth(w),
1417 XtHeight(w),
1418 MGR_ShadowThickness(w),
1419 XmSHADOW_OUT);
1420 }
1421
1422 /* display the gadgets, if there are any */
1423 _XmRedisplayGadgets(w, event, region);
1424 }
1425
1426 static XtGeometryResult
query_geometry(Widget w,XtWidgetGeometry * request,XtWidgetGeometry * reply)1427 query_geometry(Widget w,
1428 XtWidgetGeometry *request,
1429 XtWidgetGeometry *reply)
1430 {
1431 XtWidgetGeometry rcg;
1432
1433 Dimension width, height;
1434
1435 DEBUGOUT(_LtDebug(__FILE__, w,
1436 "RC QueryGeometry, request %s\n",
1437 _LtDebugWidgetGeometry2String(request)));
1438
1439 DEBUGOUT(_LtDebug(__FILE__, w,
1440 "_XmRCPreferredSize from query_geometry\n"));
1441
1442 rcg = *request;
1443 _XmRCPreferredSize(w, &rcg);
1444
1445 #if 1
1446 /* test36 test38 test39 */
1447 rcg.width = rcg.width < 16 ? 16 : rcg.width;
1448 rcg.height = rcg.height < 16 ? 16 : rcg.height;
1449
1450 width = (request->request_mode & CWWidth) ? (request->width < 16 ? 16 : request->width) : rcg.width;
1451 height = (request->request_mode & CWHeight) ? (request->height < 16 ? 16 : request->height) : rcg.height;
1452 #endif
1453
1454 DEBUGOUT(_LtDebug(__FILE__, w,
1455 "preferred size %s\n", _LtDebugWidgetGeometry2String(&rcg)));
1456
1457 reply->width = width;
1458 reply->height = height;
1459
1460 return _XmGMReplyToQueryGeometry(w, request, reply);
1461 }
1462
1463 /*
1464 * Every time we return XtGeometryYes, we have a situation where a
1465 * child widget is granted permission to change its geometry. We'll have to
1466 * assume that it does this, and change our "boxes".
1467 * An alternative would be to indicate in boxes that its contents is invalid,
1468 * and have the next user of boxes look up the new geometry info.
1469 * Partially applied 25/8/1996 (Danny).
1470 */
1471 static XtGeometryResult
geometry_manager(Widget w,XtWidgetGeometry * request,XtWidgetGeometry * reply)1472 geometry_manager(Widget w,
1473 XtWidgetGeometry *request,
1474 XtWidgetGeometry *reply)
1475 {
1476 Widget rc = XtParent(w);
1477 XtWidgetGeometry wants;
1478 int ask, got;
1479
1480 wants = *request;
1481 *reply = wants;
1482
1483 DEBUGOUT(_LtDebug2(__FILE__, rc, w,
1484 "RC geometry_manager: _XmRCAdjustSize\n"));
1485 DEBUGOUT(_LtDebug(__FILE__, rc,
1486 "Is currently %d %d.\n", XtWidth(rc), XtHeight(rc)));
1487 DEBUGOUT(_LtDebug2("EMACS", rc, w,
1488 "RC geometry_manager: _XmRCAdjustSize\n"));
1489 DEBUGOUT(_LtDebug("EMACS", rc,
1490 "Is currently %d %d.\n", XtWidth(rc), XtHeight(rc)));
1491
1492 if (_XmRCAdjustSize(rc, w, reply) == XtGeometryNo)
1493 {
1494 DEBUGOUT(_LtDebug(__FILE__, rc, "Parent said no. So will we.\n"));
1495
1496 return XtGeometryNo;
1497 }
1498
1499 DEBUGOUT(_LtDebug(__FILE__, rc,
1500 "RC geometry_manager after _XmRCAdjustSize [%s] now at %d %d\n",
1501 _LtDebugWidgetGeometry2String(reply),
1502 XtWidth(rc), XtHeight(rc)));
1503 DEBUGOUT(_LtDebug("EMACS", rc,
1504 "RC geometry_manager after _XmRCAdjustSize\n"));
1505 DEBUGOUT(_LtDebug("EMACS", rc,
1506 "Now at %d %d.\n", XtWidth(rc), XtHeight(rc)));
1507
1508 reply->request_mode &= wants.request_mode;
1509
1510 ask = got = 0;
1511
1512 if ((wants.request_mode & CWWidth) == CWWidth)
1513 {
1514 ask++;
1515
1516 if (reply->width == wants.width)
1517 {
1518 got++;
1519 }
1520 else
1521 {
1522 reply->request_mode &= ~CWWidth;
1523 }
1524 }
1525 if ((wants.request_mode & CWHeight) == CWHeight)
1526 {
1527 ask++;
1528
1529 if (reply->height == wants.height)
1530 {
1531 got++;
1532 }
1533 else
1534 {
1535 reply->request_mode &= ~CWHeight;
1536 }
1537 }
1538 if ((wants.request_mode & CWBorderWidth) == CWBorderWidth)
1539 {
1540 ask++;
1541
1542 if (reply->border_width == wants.border_width)
1543 {
1544 got++;
1545 }
1546 else
1547 {
1548 reply->request_mode &= ~CWBorderWidth;
1549 }
1550 }
1551
1552 /*
1553 * the next two are a little tricky. If the child asked for x/y
1554 * and the packing type isn't NONE, they don't get it.
1555 */
1556 if ((wants.request_mode & CWX) == CWX)
1557 {
1558 ask++;
1559
1560 if (RC_Packing(rc) == XmPACK_NONE && reply->x == wants.x)
1561 {
1562 got++;
1563 }
1564 else
1565 {
1566 reply->request_mode &= ~CWX;
1567 }
1568 }
1569 if ((wants.request_mode & CWY) == CWY)
1570 {
1571 ask++;
1572
1573 if (RC_Packing(rc) == XmPACK_NONE && reply->y == wants.y)
1574 {
1575 got++;
1576 }
1577 else
1578 {
1579 reply->request_mode &= ~CWY;
1580 }
1581 }
1582
1583 /* are we ok with everything they want. */
1584 if (ask == got && ask != 0)
1585 {
1586 DEBUGOUT(_LtDebug2(__FILE__, rc, w,
1587 "geometry_manager request [%s] reply [%s] => YES\n",
1588 _LtDebugWidgetGeometry2String(&wants),
1589 _LtDebugWidgetGeometry2String(reply)));
1590 DEBUGOUT(_LtDebug2("EMACS", rc, w,
1591 "geometry_manager request [%s] reply [%s] => YES\n",
1592 _LtDebugWidgetGeometry2String(&wants),
1593 _LtDebugWidgetGeometry2String(reply)));
1594
1595 _XmRCSetMargins(rc);
1596 _XmRCSetKidGeo(RC_Boxes(rc), w);
1597
1598 return XtGeometryYes;
1599 }
1600 /* no, but we can always compromise. LayoutNone is mostly handled if
1601 * we got No when we made the geometry request. Otherwise the layout
1602 * routine computed a compromise, which is typically the size they
1603 * are before they made this request. */
1604 else
1605 {
1606 if (RC_Packing(rc) != XmPACK_NONE)
1607 {
1608 reply->request_mode &= ~(CWX | CWY);
1609 }
1610
1611 DEBUGOUT(_LtDebug2(__FILE__, rc, w,
1612 "geometry_manager request [%s] reply [%s] => ALMOST\n",
1613 _LtDebugWidgetGeometry2String(&wants),
1614 _LtDebugWidgetGeometry2String(reply)));
1615 DEBUGOUT(_LtDebug2("EMACS", rc, w,
1616 "geometry_manager request [%s] reply [%s] => ALMOST\n",
1617 _LtDebugWidgetGeometry2String(&wants),
1618 _LtDebugWidgetGeometry2String(reply)));
1619
1620 return XtGeometryAlmost;
1621 }
1622 }
1623
1624 static void
change_managed(Widget w)1625 change_managed(Widget w)
1626 {
1627 Widget tlm;
1628
1629 DEBUGOUT(_LtDebug(__FILE__, w, "change_managed()\n"));
1630
1631 DEBUGOUT(_LtDebug(__FILE__, w, "_XmRCAdjustSize from change_managed %dx%d\n",
1632 XtWidth(w), XtHeight(w)));
1633 DEBUGOUT(_LtDebug("EMACS", w, "_XmRCAdjustSize from change_managed %dx%d\n",
1634 XtWidth(w), XtHeight(w)));
1635
1636 _XmRCAdjustSize(w, NULL, NULL);
1637
1638 /* rws 28 Apr 1998
1639 If widget w is a pulldown menu that is associated to an option menu
1640 we have a problem here. The option menu XmNmenuHistory could be
1641 pointing to a widget that has just been un-managed. This becomes
1642 a problem if the un-manage is the first step of a destroy. If we
1643 do not find the associated option menu and fix up its XmNmenuHistory
1644 it will be left pointing to a widget that has been destroyed. What
1645 we need is some sort of pointer from the pulldown menu to the
1646 option menu. RC_CascadeBtn() could be used but, currently it is
1647 only valid when the pulldown is visible. The same can be said
1648 for RC_LastSelectToplevel().
1649
1650 RC_CascadeBtn() is set to NULL in MenuShell:MenuShellPopdownOne()
1651 RC_LastSelectToplevel() will be set correctly whenever the menu
1652 gets popped up. If we ensure that it is set correctly whenever
1653 the subMenuId of an option menu changes, that should do it!
1654 */
1655 {
1656 tlm = RC_LastSelectToplevel(w);
1657 if (tlm && RC_Type(tlm) == XmMENU_OPTION)
1658 {
1659 Widget mem;
1660
1661 mem = RC_MemWidget(tlm);
1662 /* rws 25 May 1998
1663 I do not really like this XtIsSensitive stuff. We should
1664 be able to pick a new mem widget even if the menu is not
1665 sensitive. This is needed for xmcd 2.3 otherwise it
1666 screws up on startup because it creates an in-sensitve
1667 option menu.
1668 */
1669 if (XtIsSensitive(tlm) && mem && !XtIsManaged(mem))
1670 {
1671 Widget new_mem;
1672
1673 /* need to pick a new memWidget */
1674 new_mem = _XmMenuNextItem(w, MGR_Children(w)[MGR_NumChildren(w) - 1]);
1675 if (new_mem != mem)
1676 {
1677 _XmOptionCallback(new_mem, (XtPointer)tlm, NULL);
1678 }
1679 else
1680 {
1681 _XmOptionCallback(NULL, (XtPointer)tlm, NULL);
1682 }
1683 }
1684 }
1685 }
1686 if (tlm && RC_Type(tlm) == XmMENU_OPTION)
1687 {
1688 /* rws 30 Apr 1998
1689 we need to force the option menu (tlm) to re-calculate its
1690 layout based on the new size of its submenu (w)
1691 */
1692 _XmRCAdjustSize(tlm, NULL, NULL); /* dwilliss 17 Jun 2004 - OK, now it does :-) */
1693 }
1694
1695 if (RC_Type(w) != XmWORK_AREA && XtIsRealized(w))
1696 {
1697 _XmClearShadowType(w, RC_OldWidth(w), RC_OldHeight(w),
1698 RC_OldShadowThickness(w), 0);
1699
1700 _XmDrawShadows(XtDisplay(w), XtWindow(w),
1701 MGR_TopShadowGC(w), MGR_BottomShadowGC(w),
1702 0, 0, XtWidth(w), XtHeight(w),
1703 MGR_ShadowThickness(w), XmSHADOW_OUT);
1704 }
1705 RC_OldWidth(w) = XtWidth(w);
1706 RC_OldHeight(w) = XtHeight(w);
1707 RC_OldShadowThickness(w) = MGR_ShadowThickness(w);
1708
1709 _XmNavigChangeManaged(w);
1710 }
1711
1712 static void
AddPopupHandlers(Widget new_w)1713 AddPopupHandlers(Widget new_w)
1714 {
1715 Widget realpar = NULL;
1716
1717 /* since we're not managed -- we leave that up to the application
1718 * to get us to pop up, we realize ourselves here. */
1719 /* XtRealizeWidget(new_w); */
1720
1721 if (XtIsShell(XtParent(new_w)))
1722 {
1723 realpar = XtParent(XtParent(new_w));
1724 }
1725 else
1726 {
1727 realpar = XtParent(new_w);
1728 }
1729 if (realpar == NULL)
1730 {
1731 _XmError(new_w, "Can't determine parent of popup menu!\n");
1732 }
1733
1734 XtInsertEventHandler(realpar, ButtonPressMask|ButtonReleaseMask,
1735 False, _XmPopupButtonPressHandler, (XtPointer)new_w,
1736 XtListHead);
1737
1738 DEBUGOUT(_LtDebug(__FILE__, NULL, "GRAB BUTTON: %p %s %d %x\n",
1739 realpar, XtName(realpar),
1740 RC_PostButton(new_w), RC_PostModifiers(new_w)));
1741
1742 XtGrabButton(realpar, RC_PostButton(new_w), RC_PostModifiers(new_w),
1743 True, ButtonReleaseMask, GrabModeSync, GrabModeSync,
1744 XtWindow(realpar), _XmGetMenuCursorByScreen(XtScreen(new_w)));
1745 }
1746
1747 static void
MenuProcEntry(int proc,Widget w,...)1748 MenuProcEntry(int proc, Widget w,...)
1749 {
1750 va_list arg_list;
1751 Display *dpy = XtDisplay(w);
1752 /* Widget top_menu; */
1753 Widget *shell;
1754 Boolean *was_torn;
1755 XEvent *event;
1756
1757 va_start(arg_list, w);
1758
1759 DEBUGOUT(_LtDebug("MENU", w, "%s:MenuProcEntry(%d) - %s\n",
1760 __FILE__, __LINE__,
1761 _LtDebugMenuEnum2String(proc)
1762 ));
1763 DEBUGOUT(_LtDebug("ENTRY", w, "%s:MenuProcEntry(%d) - %s\n",
1764 __FILE__, __LINE__,
1765 _LtDebugMenuEnum2String(proc)
1766 ));
1767
1768 switch (proc)
1769 {
1770 case XmMENU_BUTTON_POPDOWN:
1771 /* widget is requesting that the menu it is in be popped down
1772 */
1773 {
1774 Widget button = w;
1775 Widget menu = XtParent(button);
1776 Widget shell;
1777 Boolean *poppedUp;
1778 Cardinal num_params = 0;
1779
1780 event = (XEvent *)va_arg(arg_list, XtPointer);
1781 poppedUp = va_arg(arg_list, XtPointer);
1782
1783 if (XmIsRowColumn(menu))
1784 {
1785 shell = XtParent(menu);
1786 if (XmIsMenuShell(shell))
1787 {
1788 if (Shell_PoppedUp(shell))
1789 {
1790 _XmMenuFocus(w, XmMENU_FOCUS_RESTORE, CurrentTime);
1791 MSClass_PopdownDone(shell)(shell, event, NULL, &num_params);
1792 #if 1
1793 if (RC_CascadeBtn(menu))
1794 {
1795 Lab_MenuDisarm(RC_CascadeBtn(menu));
1796 if (RC_PopupPosted(XtParent(RC_CascadeBtn(menu))) && RC_PopupPosted(XtParent(RC_CascadeBtn(menu))) == menu)
1797 {
1798 RC_PopupPosted(XtParent(RC_CascadeBtn(menu))) = NULL;
1799 _XmCallRowColumnUnmapCallback(menu, event);
1800 }
1801 }
1802 #endif
1803 *poppedUp = True;
1804 }
1805 else
1806 {
1807 *poppedUp = False;
1808 }
1809 }
1810 else
1811 {
1812 if (_XmIsActiveTearOff(menu))
1813 {
1814 }
1815 else
1816 {
1817 _XmWarning(w, "%s(%d) - RCClass_MenuProcs XmMENU_BUTTON_POPDOWN called with button not in a menu shell", __FILE__, __LINE__);
1818 }
1819 *poppedUp = False;
1820 }
1821 /* set the history of menu to button */
1822 if (!XmIsTearOffButton(button))
1823 {
1824 RC_MemWidget(menu) = button;
1825 }
1826 /* if an option menu, change the CascadeButtonGadget label */
1827 {
1828 Widget tlm;
1829
1830 tlm = RC_LastSelectToplevel(menu);
1831 if (tlm && XmIsRowColumn(tlm) && RC_Type(tlm) == XmMENU_OPTION)
1832 {
1833 _XmOptionCallback(RC_MemWidget(menu), (XtPointer)tlm, NULL);
1834 }
1835 }
1836 }
1837 else
1838 {
1839 _XmWarning(w, "%s(%d) - RCClass_MenuProcs XmMENU_BUTTON_POPDOWN called with button not in a menu", __FILE__, __LINE__);
1840 *poppedUp = False;
1841 }
1842 }
1843 break;
1844
1845 case XmMENU_PROCESS_TREE:
1846 break;
1847
1848 case XmMENU_TRAVERSAL:
1849 /* Arm the first menu item that is not a TearOff
1850 */
1851 {
1852 XmTraversalDirection dir;
1853 Widget menu = w;
1854
1855 dir = va_arg(arg_list, XmTraversalDirection);
1856 switch(dir)
1857 {
1858 case XmTRAVERSE_HOME:
1859 if (RC_CascadeBtn(menu) != 0 && RC_MemWidget(menu) != 0)
1860 {
1861 _XmMenuArmItem(RC_MemWidget(menu));
1862 }
1863 else if (MGR_NumChildren(menu) > 0 && XmGetTearOffControl(menu) != MGR_Children(menu)[0])
1864 {
1865 Widget w1 = MGR_Children(menu)[0];
1866
1867 _XmMenuArmItem(w1);
1868 }
1869 else if (MGR_NumChildren(menu) > 1)
1870 {
1871 Widget w1 = MGR_Children(menu)[1];
1872
1873 _XmMenuArmItem(w1);
1874 }
1875 break;
1876 default:
1877 _XmWarning(w, "%s(%d) - RCClass_MenuProcs XmMENU_TRAVERSAL called with unknown direction", __FILE__, __LINE__);
1878 break;
1879 }
1880 }
1881 break;
1882
1883 case XmMENU_SHELL_POPDOWN:
1884 {
1885 Widget button = w;
1886 Widget menu = XtParent(button);
1887 Widget shell;
1888 Boolean *poppedUp;
1889 Cardinal num_params = 0;
1890
1891 event = (XEvent *)va_arg(arg_list, XtPointer);
1892 poppedUp = va_arg(arg_list, XtPointer);
1893 if (XmIsRowColumn(menu))
1894 {
1895 shell = _XmGetRC_PopupPosted(menu);
1896 if (shell)
1897 {
1898 if (XmIsMenuShell(shell))
1899 {
1900 if (Shell_PoppedUp(shell))
1901 {
1902 MSClass_PopdownEveryone(shell)(shell, event, NULL, &num_params);
1903 *poppedUp = True;
1904 }
1905 else
1906 {
1907 *poppedUp = False;
1908 }
1909 }
1910 else
1911 {
1912 if (XtIsTransientShell(shell) || _XmIsActiveTearOff(menu))
1913 {
1914 }
1915 else
1916 {
1917 _XmWarning(w, "%s(%d) - RCClass_MenuProcs XmMENU_SHELL_POPDOWN called with button not in a menu shell %s %s", __FILE__, __LINE__, XtName(menu), XtName(shell));
1918 }
1919 *poppedUp = False;
1920 }
1921 }
1922 else
1923 {
1924 /* nothing popped up */
1925 *poppedUp = False;
1926 }
1927 }
1928 else
1929 {
1930 _XmWarning(w, "%s(%d) - RCClass_MenuProcs XmMENU_SHELL_POPDOWN called with button not in a menu", __FILE__, __LINE__);
1931 *poppedUp = False;
1932 }
1933 }
1934 break;
1935
1936 case XmMENU_CALLBACK:
1937 /* Called by all label sub-classes that are children of RC just
1938 before invoking any activate or valuechanged callbacks.
1939 */
1940 {
1941 XmAnyCallbackStruct *cbs;
1942
1943 DEBUGOUT(_LtDebug("ENTRY", w, "%s:MenuProcEntry(%d) - %s %sRowColumn %s entryCallbacks\n",
1944 __FILE__, __LINE__,
1945 _LtDebugMenuEnum2String(proc),
1946 XmIsRowColumn(XtParent(w)) ? "" : "not ",
1947 XtHasCallbacks(XtParent(w), XmNentryCallback) == XtCallbackHasSome ? "has" : "no"
1948 ));
1949
1950 if (RC_RadioBehavior(XtParent(w)))
1951 RadioHandler(w);
1952
1953 cbs = va_arg(arg_list, XmAnyCallbackStruct *);
1954 if (XtHasCallbacks(XtParent(w), XmNentryCallback) == XtCallbackHasSome)
1955 {
1956 XmRowColumnCallbackStruct rcb;
1957
1958 rcb.reason = XmCR_ACTIVATE;
1959 rcb.event = cbs->event;
1960 rcb.widget = w;
1961 rcb.callbackstruct = (char *)cbs;
1962 if (XtHasCallbacks(w, XmNactivateCallback) == XtCallbackHasSome ||
1963 XtHasCallbacks(w, XmNvalueChangedCallback) == XtCallbackHasSome)
1964 {
1965 XtCallbackList list = NULL;
1966 int i;
1967
1968 /* rws 8 Jul 1999
1969 We have to do a GetValues here because Xt seems to
1970 store callback lists in some sort of compiled form.
1971 */
1972 XtVaGetValues(w,
1973 XmNactivateCallback, &list,
1974 XmNvalueChangedCallback, &list,
1975 NULL);
1976 for (i = 0; list[i].callback != NULL; i++)
1977 {
1978 rcb.data = (char *)list[i].closure;
1979 XtCallCallbackList(XtParent(w), RC_Entry_cb(XtParent(w)), (XtPointer)&rcb);
1980 }
1981 }
1982 else
1983 {
1984 rcb.data = "";
1985 XtCallCallbackList(XtParent(w), RC_Entry_cb(XtParent(w)), (XtPointer)&rcb);
1986 }
1987 }
1988 else
1989 {
1990 }
1991 }
1992 break;
1993
1994 case XmMENU_BUTTON:
1995 /* widget got a button event, verify that it is a valid button for
1996 this type of menu
1997 */
1998 {
1999 Widget button = w;
2000 Widget menu = XtParent(button);
2001 XButtonEvent *xbe;
2002 Boolean *validButton;
2003 Widget tlm;
2004
2005 if (XmIsRowColumn(button))
2006 {
2007 menu = button;
2008 }
2009 event = (XEvent *)va_arg(arg_list, XtPointer);
2010 validButton = va_arg(arg_list, XtPointer);
2011 DEBUGOUT(_LtDebug0("MENU", w, "\t%s\n",
2012 _LtDebugEventType2String(event->type)
2013 ));
2014 if (event && (event->type == ButtonPress || event->type == ButtonRelease))
2015 {
2016 xbe = &(event->xbutton);
2017 if (XmIsRowColumn(menu))
2018 {
2019 _XmGetActiveTopLevelMenu(menu, &tlm);
2020 if (tlm && XmIsRowColumn(tlm))
2021 {
2022 DEBUGOUT(_LtDebug0("MENU", w, "\t%s %s\n",
2023 _LtDebugRcType2String(RC_Type(tlm)),
2024 XtName(tlm)
2025 ));
2026 switch(RC_Type(tlm))
2027 {
2028 case XmMENU_BAR:
2029 case XmMENU_PULLDOWN:
2030 *validButton = (xbe->button == 1);
2031 break;
2032 case XmMENU_OPTION:
2033 *validButton = (xbe->button == 1) &&
2034 ((Widget)_XmInputForGadget(w, xbe->x, xbe->y) == XmOptionButtonGadget(w));
2035 break;
2036 case XmMENU_POPUP:
2037 *validButton = ((xbe->button == 1) ||
2038 (xbe->button == 3));
2039 break;
2040 default:
2041 _XmWarning(w, "%s(%d) - RCClass_MenuProcs XmMENU_BUTTON do not know the type of TopLevelMenu %s", __FILE__, __LINE__,XtName(tlm));
2042 *validButton = False;
2043 break;
2044 }
2045 }
2046 else
2047 {
2048 _XmWarning(w, "%s(%d) - RCClass_MenuProcs XmMENU_BUTTON could not find TopLevelMenu", __FILE__, __LINE__);
2049 *validButton = False;
2050 }
2051 }
2052 else
2053 {
2054 _XmWarning(w, "%s(%d) - RCClass_MenuProcs XmMENU_BUTTON called by widget without RC parent", __FILE__, __LINE__);
2055 *validButton = False;
2056 }
2057 }
2058 else
2059 {
2060 _XmWarning(w, "%s(%d) - RCClass_MenuProcs XmMENU_BUTTON called with non button event", __FILE__, __LINE__);
2061 *validButton = False;
2062 }
2063 }
2064 break;
2065
2066 case XmMENU_CASCADING:
2067 {
2068 Widget cb = w;
2069 Widget sub_pane, mem_widget;
2070 Widget shell;
2071 Position my_x, my_y;
2072 unsigned char string_direction;
2073
2074 /* FIX ME: lots of this should move to MenuShell:manage_child */
2075 event = (XEvent *)va_arg(arg_list, XtPointer);
2076
2077 if (XmIsGadget(cb))
2078 {
2079 sub_pane = CBG_Submenu(cb);
2080 string_direction = LabG_StringDirection(cb);
2081 }
2082 else
2083 {
2084 sub_pane = CB_Submenu(cb);
2085 string_direction = Lab_StringDirection(cb);
2086 }
2087
2088 DEBUGOUT(_LtDebug0(__FILE__, cb, "\t%s sub-menu %s\n",
2089 _LtDebugRcType2String(RC_Type(XtParent(cb))),
2090 sub_pane ? XtName(sub_pane) : "None"
2091 ));
2092 DEBUGOUT(_LtDebug0("MENU", cb, "\t%s sub-menu %s\n",
2093 _LtDebugRcType2String(RC_Type(XtParent(cb))),
2094 sub_pane ? XtName(sub_pane) : "None"
2095 ));
2096 if (!sub_pane)
2097 {
2098 DEBUGOUT(_LtDebug(__FILE__, cb, "Cascading Popup: no sub pane\n"));
2099
2100 return;
2101 }
2102 {
2103 Widget shell;
2104 Boolean was_torn;
2105
2106 RCClass_MenuProcs(XtClass(sub_pane))(XmMENU_RESTORE_TEAROFF_TO_MENUSHELL,
2107 sub_pane, &shell, &was_torn, event);
2108 }
2109
2110 /* FIX ME: if shared menu shell, configure object, ordinary popup */
2111
2112 shell = XtParent(sub_pane);
2113
2114 /* Register inside the RC that this cascadebutton is the one that
2115 * triggered the menu.
2116 */
2117 RC_CascadeBtn(sub_pane) = cb;
2118
2119 /* position the row column inside the menushell */
2120 _XmMoveObject(sub_pane, 0, 0);
2121
2122 /* now move the menushell */
2123 /* rws 21 Dec 1997
2124 If the is a tear off it is possible that it has been re-parented
2125 a few times. This seems to mess up where Xt thinks the cascade
2126 button is. Therefore we must suffer the round trip server request
2127 to make sure that we get the correct position.
2128 */
2129 #undef TEAROFF_FIX
2130 /* amai: xmgrace 5.x works better w/o this ... */
2131
2132 #ifdef TEAROFF_FIX
2133 if (!_XmIsActiveTearOff(XtParent(cb)))
2134 {
2135 #endif
2136 XtTranslateCoords(cb, 0, 0, &my_x, &my_y);
2137 #ifdef TEAROFF_FIX
2138 }
2139 else
2140 {
2141 Window child;
2142 int x,y;
2143
2144 XTranslateCoordinates(XtDisplay(cb),
2145 XtWindow(cb),
2146 RootWindowOfScreen(XtScreen(cb)),
2147 0, 0,
2148 &x, &y,
2149 &child);
2150 my_x = x; my_y = y;
2151 }
2152 #endif
2153
2154 switch (RC_Type(XtParent(cb)))
2155 {
2156 case XmMENU_BAR:
2157
2158 if (string_direction == XmSTRING_DIRECTION_R_TO_L)
2159 my_x += XtWidth(cb) - XtWidth(sub_pane);
2160
2161 my_y += XtHeight(cb);
2162
2163 /* If the menu goes off the bottom of the screen,
2164 * try placing it above the bar.
2165 */
2166 if (my_y > (Position)(HeightOfScreen(XtScreen(cb))
2167 - XtHeight(sub_pane)) &&
2168 my_y - (Position)(XtHeight(cb) + XtHeight(sub_pane)) >= 0)
2169 my_y -= XtHeight(cb) + XtHeight(sub_pane);
2170 break;
2171
2172 case XmMENU_POPUP:
2173 _XmCallRowColumnMapCallback(sub_pane, event);
2174
2175 case XmMENU_PULLDOWN:
2176
2177 my_x += string_direction == XmSTRING_DIRECTION_L_TO_R
2178 ? (XmIsGadget(cb)
2179 ? CBG_Cascade_x(cb) + CBG_Cascade_width(cb)
2180 : CB_Cascade_x(cb) + CB_Cascade_width(cb))
2181 : (XmIsGadget(cb)
2182 ? CBG_Cascade_x(cb)
2183 : CB_Cascade_x(cb))
2184 - XtWidth(sub_pane);
2185
2186 my_y += XmIsGadget(cb)
2187 ? CBG_Cascade_y(cb)
2188 : CB_Cascade_y(cb);
2189 break;
2190
2191 case XmMENU_OPTION:
2192
2193 mem_widget = RC_MemWidget(XtParent(cb));
2194
2195 my_x += string_direction == XmSTRING_DIRECTION_L_TO_R
2196 ? (LabG_Highlight(cb)
2197 + (mem_widget
2198 ? MGR_ShadowThickness(sub_pane) - XtX(mem_widget)
2199 : 0))
2200 : (XtWidth(cb) - XtWidth(sub_pane) - LabG_Highlight(cb)
2201 - (mem_widget
2202 ? MGR_ShadowThickness(sub_pane) - XtX(mem_widget)
2203 : 0));
2204
2205 /* If the menu goes off one side of the screen,
2206 * try placing it one the opposide side of the cascade.
2207 */
2208 if (my_x > (Position)(WidthOfScreen(XtScreen(cb))
2209 - XtWidth(sub_pane)) &&
2210 my_x - (Position)XtWidth(sub_pane) >= 0)
2211 {
2212 my_x -= string_direction == XmSTRING_DIRECTION_L_TO_R
2213 ? XtWidth(sub_pane)
2214 : XtWidth(cb);
2215 }
2216 else if (my_x < 0 && my_x + (Position)(XtWidth(cb)) <=
2217 (Position)(WidthOfScreen(XtScreen(cb))
2218 - XtWidth(sub_pane)))
2219 {
2220 my_x += string_direction == XmSTRING_DIRECTION_L_TO_R
2221 ? XtWidth(cb)
2222 : XtWidth(sub_pane);
2223 }
2224
2225 my_y += mem_widget
2226 ? ((XtHeight(cb) - XtHeight(mem_widget)) / 2)
2227 - XtY(mem_widget)
2228 : LabG_Highlight(cb);
2229 break;
2230 }
2231
2232 /* Generic check to make sure the menu doesn't go off the edge
2233 * of the screen, especially not the top or left [right].
2234 * But see specific tweaks for menu_bar Y and menu_option X.
2235 */
2236 if (string_direction == XmSTRING_DIRECTION_R_TO_L && my_x < 0)
2237 my_x = 0;
2238 if (my_x >
2239 (Position)(WidthOfScreen(XtScreen(cb)) - XtWidth(sub_pane)))
2240 my_x = WidthOfScreen(XtScreen(cb)) - XtWidth(sub_pane);
2241 if (string_direction == XmSTRING_DIRECTION_L_TO_R && my_x < 0)
2242 my_x = 0;
2243
2244 if (my_y >
2245 (Position)(HeightOfScreen(XtScreen(cb)) - XtHeight(sub_pane)))
2246 my_y = HeightOfScreen(XtScreen(cb)) - XtHeight(sub_pane);
2247 if (my_y < 0)
2248 my_y = 0;
2249
2250 _XmMoveObject(shell, my_x, my_y);
2251
2252 RC_PopupPosted(XtParent(cb)) = sub_pane;
2253 DEBUGOUT(_LtDebug(__FILE__, cb, "%s posted by %s top %s\n",
2254 XtName(sub_pane),
2255 XtName(XtParent(cb)),
2256 RC_LastSelectToplevel(XtParent(cb)) ? XtName(RC_LastSelectToplevel(XtParent(cb))) : "NULL"));
2257
2258 RC_LastSelectToplevel(sub_pane) = RC_LastSelectToplevel(XtParent(cb));
2259 {
2260 int i;
2261
2262 for (i = 0; i < MGR_NumChildren(sub_pane); i++)
2263 {
2264 Widget w = MGR_Children(sub_pane)[i];
2265
2266 _XmMenuDisarmItem(w);
2267 }
2268 }
2269
2270 _XmCallRowColumnMapCallback(sub_pane, event); /* rowcolumn/test45 */
2271 /* This private shell stuff should be hidden in MenuShell somewhere
2272 Nothing but MenuShell needs to know anything about private shells!
2273 */
2274 if (!MS_PrivateShell(shell))
2275 {
2276 XtManageChild(sub_pane);
2277 /* rws 13 Mar 1997
2278 Not too sure about this yet so keep it out for now.
2279 rws 5 Nov 1998
2280 rowcolumn/test43 needs this.
2281 */
2282 XAllowEvents(XtDisplay(sub_pane), SyncPointer, CurrentTime);
2283
2284 _XmAddGrab(shell, False, False);
2285 }
2286 else
2287 {
2288 MSClass_PopupSharedMenuPane(shell)(shell, sub_pane, event);
2289 }
2290 }
2291 break;
2292
2293 case XmMENU_SUBMENU:
2294 {
2295 Widget button = w;
2296 Widget submenu = XmIsGadget(w) ? CBG_Submenu(w) : CB_Submenu(w);
2297
2298 if (RC_Type(XtParent(w)) == XmMENU_OPTION &&
2299 submenu != NULL && XmIsRowColumn(submenu))
2300 {
2301 RC_CascadeBtn(submenu) = button;
2302 RC_OptionSubMenu(XtParent(w)) = submenu;
2303 /* rws 5 May 1998
2304 should be setting RC_LastSelectTopLevel(submenu) = XtParent(button);
2305 I think.
2306 */
2307
2308 if (XmIsGadget(w))
2309 {
2310 _XmFixOptionMenu(XtParent(w), False);
2311 }
2312 else
2313 {
2314 _XmFixOptionMenu(XtParent(w), True);
2315 }
2316 }
2317 }
2318 break;
2319
2320 case XmMENU_ARM:
2321 /* grab the keyboard and freeze everything so that we can be sure that
2322 the next event goes to the right place. */
2323
2324 _XmGrabKeyboard(w, True,
2325 GrabModeSync, GrabModeSync,
2326 CurrentTime);
2327
2328
2329 XAllowEvents(dpy, AsyncKeyboard, CurrentTime);
2330
2331 _XmAddGrab(w, True, True);
2332
2333 /* Initiate a new pointer grab for the menu bar */
2334 /* Pointer mode will change to Sync anyway with the
2335 XAllowEvents. It's also set here, according to xscope - Chris 6/23 */
2336 _XmGrabPointer(w, True,
2337 (ButtonPressMask | ButtonReleaseMask | EnterWindowMask |
2338 LeaveWindowMask),
2339 GrabModeSync,
2340 GrabModeAsync,
2341 None,
2342 _XmGetMenuCursorByScreen(XtScreen(w)),
2343 CurrentTime);
2344
2345
2346 /* Process events until the next button event */
2347 XAllowEvents(dpy, SyncPointer, CurrentTime);
2348
2349 RC_SetArmed(w, True);
2350 break;
2351
2352 case XmMENU_DISARM:
2353 _XmUngrabPointer(w, CurrentTime);
2354
2355 _XmUngrabKeyboard(w, CurrentTime);
2356
2357 _XmRemoveGrab(w);
2358
2359
2360 RC_SetArmed(w, False);
2361
2362 break;
2363
2364 case XmMENU_BAR_CLEANUP:
2365 {
2366 Cardinal i = 0;
2367
2368 DoBtnEventCleanupReplay(w, NULL, NULL, &i);
2369 }
2370 break;
2371
2372 case XmMENU_STATUS:
2373 break;
2374
2375 case XmMENU_MEMWIDGET_UPDATE:
2376 /* rws 5 May 1998
2377 this could call _XmFixOptionMenu
2378 */
2379 break;
2380
2381 case XmMENU_POPDOWN:
2382 break;
2383
2384 case XmMENU_RESTORE_EXCLUDED_TEAROFF_TO_TOPLEVEL_SHELL:
2385 event = va_arg(arg_list, XEvent *);
2386 _XmRestoreExcludedTearOffToToplevelShell(w, event);
2387 break;
2388
2389 case XmMENU_RESTORE_TEAROFF_TO_TOPLEVEL_SHELL:
2390 /* fix up RC_LastSelectTopLevel and RC_CascadeBtn */
2391 event = va_arg(arg_list, XEvent *);
2392 _XmRestoreTearOffToToplevelShell(w, event);
2393 break;
2394
2395 case XmMENU_RESTORE_TEAROFF_TO_MENUSHELL:
2396 shell = va_arg(arg_list, Widget *);
2397 was_torn = va_arg(arg_list, Boolean *);
2398 event = va_arg(arg_list, XEvent *);
2399
2400 /* fix up RC_LastSelectTopLevel and RC_CascadeBtn */
2401 if (RC_TearOffModel(w) == XmTEAR_OFF_ENABLED)
2402 {
2403 DEBUGOUT(_LtDebug(__FILE__, w,
2404 "restoring tear off menu to menu shell\n"));
2405
2406 if (RC_TornOff(w))
2407 {
2408 *was_torn = True;
2409 }
2410
2411 _XmRestoreTearOffToMenuShell(w, event);
2412
2413 *shell = XtParent(w);
2414 }
2415 break;
2416
2417 case XmMENU_GET_LAST_SELECT_TOPLEVEL:
2418 break;
2419
2420 case XmMENU_TEAR_OFF_ARM:
2421 /*
2422 RCClass_MenuProcs(xmRowColumnWidgetClass)(XmMENU_ARM, w, NULL);
2423 */
2424 break;
2425
2426 default:
2427 break;
2428 }
2429
2430 va_end(arg_list);
2431 }
2432
2433 static void
ArmAndActivate(Widget w,XEvent * e,String * args,Cardinal * nargs)2434 ArmAndActivate(Widget w, XEvent *e, String *args, Cardinal *nargs)
2435 {
2436 }
2437
2438 /* rws add callbacks to sub menu */
2439 static void
_XmFixOptionMenu(Widget new_w,Boolean use_set_values)2440 _XmFixOptionMenu(Widget new_w, Boolean use_set_values)
2441 {
2442 /* rws
2443 * Add an activateCallback to all the children of the menu
2444 * display the label of the menuHistory or first item
2445 * set menuHistory if necessary
2446 */
2447
2448 XmString Label;
2449 Pixmap labelPixmap = None, labelInsensitivePixmap = None;
2450 unsigned char labelType;
2451
2452 DEBUGOUT(_LtDebug(__FILE__, new_w, "_XmFixOptionMenu\n"));
2453
2454 if (RC_OptionSubMenu(new_w))
2455 {
2456 RC_OptionSubMenu(RC_OptionSubMenu(new_w)) = new_w;
2457
2458 /* Try to set a history. This may fail when the menu is empty */
2459 /* Crash prevention for test/Xm/scrolledwindow/test13 */
2460 if (RC_MemWidget(new_w) == NULL)
2461 {
2462 if (MGR_NumChildren(RC_OptionSubMenu(new_w)))
2463 {
2464
2465 if (XmIsTearOffButton(MGR_Children(RC_OptionSubMenu(new_w))[0]))
2466 {
2467 if (MGR_NumChildren(RC_OptionSubMenu(new_w)) > 2)
2468 {
2469 RC_MemWidget(new_w) =
2470 MGR_Children(RC_OptionSubMenu(new_w))[1];
2471 }
2472 }
2473 else
2474 {
2475 RC_MemWidget(new_w) =
2476 MGR_Children(RC_OptionSubMenu(new_w))[0];
2477 }
2478
2479 DEBUGOUT(_LtDebug2(__FILE__, new_w, RC_MemWidget(new_w),
2480 "_XmFixOptionMenu: Set RC_MemWidget\n"));
2481 /* 1-sep-04 -- dwilliss - don't ever let MemWidget get set to, for example, a seperator
2482 because we always assume it's a label of some kind */
2483 if (RC_MemWidget(new_w) != NULL && !XmIsLabel(RC_MemWidget(new_w)) && !XmIsLabelGadget(RC_MemWidget(new_w)))
2484 {
2485 RC_MemWidget(new_w) = NULL;
2486 }
2487 }
2488 }
2489
2490 if (RC_MemWidget(new_w) != NULL)
2491 {
2492 Widget button;
2493
2494 XtVaGetValues(RC_MemWidget(new_w),
2495 XmNlabelString, &Label,
2496 XmNlabelPixmap, &labelPixmap,
2497 XmNlabelInsensitivePixmap, &labelInsensitivePixmap,
2498 XmNlabelType, &labelType,
2499 NULL);
2500
2501 /*
2502 * OK, here's the fix for the bug demonstrated in
2503 * test/Xm/rowcolumn/test26.c. The error is in the
2504 * usage of _XmFixOptionMenu in CascadeBG's initialize() and
2505 * set_values() methods.
2506 */
2507 /* rws 15 Nov 1998
2508 This may not be relevent anymore. There was a problem with
2509 memory allocation in MessageB up to and including 1.28 such
2510 that we were allocating 1 less row than we were using to
2511 do the layout, therefore we were messing up some memory that
2512 we should not have been. Since I can't remember how test26
2513 demonstrated this problem I'm going to leave this here.
2514 */
2515 if ((button = XmOptionButtonGadget(new_w)) != NULL)
2516 {
2517 if (use_set_values)
2518 {
2519 XtVaSetValues(button,
2520 XmNlabelString, Label,
2521 XmNlabelPixmap, labelPixmap,
2522 XmNlabelInsensitivePixmap, labelInsensitivePixmap,
2523 XmNlabelType, labelType,
2524 NULL);
2525
2526 /* rws 27 Apr 1997 label should be freed, no??? */
2527 XmStringFree(Label);
2528 }
2529 else
2530 {
2531 if (_XmStringIsXmString((XmString)LabG_Label(button)))
2532 {
2533 XmStringFree((XmString)LabG_Label(button));
2534 }
2535 else
2536 {
2537 _XmStringFree(LabG_Label(button));
2538 }
2539
2540 if (_XmStringIsXmString(Label))
2541 {
2542 LabG_Label(button) = _XmStringCreate(Label);
2543 XmStringFree(Label);
2544 }
2545 else
2546 {
2547 LabG_Label(button) = (_XmString)Label;
2548 LabG_LabelType(button) = labelType;
2549 LabG_Pixmap(button) = labelPixmap;
2550 LabG_PixmapInsensitive(button) = labelInsensitivePixmap;
2551 }
2552 }
2553 }
2554 }
2555 }
2556 }
2557
2558 /* rws Option menu callback */
2559 static void
_XmOptionCallback(Widget w,XtPointer cd,XtPointer cs)2560 _XmOptionCallback(Widget w,
2561 XtPointer cd,
2562 XtPointer cs)
2563 {
2564 XmString ButtonLabel;
2565 Pixmap labelPixmap, labelInsensitivePixmap;
2566 unsigned char labelType;
2567 Widget rc = (Widget)cd;
2568
2569 if (w)
2570 {
2571 XtVaGetValues(w, XmNlabelString, &ButtonLabel,
2572 XmNlabelPixmap, &labelPixmap,
2573 XmNlabelInsensitivePixmap, &labelInsensitivePixmap,
2574 XmNlabelType, &labelType,
2575 NULL);
2576 XtVaSetValues(XmOptionButtonGadget(rc),
2577 XmNlabelString, ButtonLabel,
2578 XmNlabelPixmap, labelPixmap,
2579 XmNlabelInsensitivePixmap, labelInsensitivePixmap,
2580 XmNlabelType, labelType,
2581 NULL);
2582 }
2583 else
2584 {
2585 ButtonLabel = XmStringCreateSimple("");
2586 XtVaSetValues(XmOptionButtonGadget(rc),
2587 XmNlabelString, ButtonLabel,
2588 NULL);
2589 }
2590
2591 RC_MemWidget(rc) = w;
2592
2593 XmStringFree(ButtonLabel);
2594 }
2595
2596
2597 static void
RadioHandler(Widget w)2598 RadioHandler(Widget w)
2599 {
2600 Widget rc = XtParent(w);
2601 Widget tgl, tgl_unset = NULL;
2602 Cardinal i;
2603
2604 Boolean tgl_state = XmIsGadget(w) ? TBG_Set(w) : TB_Set(w);
2605
2606 DEBUGOUT(_LtDebug2(__FILE__, rc, w, "RadioHandler\n"));
2607
2608 /*
2609 * Set the menu history
2610 */
2611 if ((w != NULL) && (XtParent(w) != NULL)) {
2612 XtVaSetValues (XtParent(w), XmNmenuHistory, w, NULL);
2613 }
2614
2615 /*
2616 * If the radio box is supposed to be "always one" then resetting
2617 * a toggle may not be allowed.
2618 * Detect this situation first.
2619 */
2620 if (RC_RadioAlwaysOne(rc) && tgl_state == False)
2621 {
2622 int cnt = 0;
2623
2624 for (i = 0; i < MGR_NumChildren(rc); i++)
2625 {
2626 tgl = MGR_Children(rc)[i];
2627 if (XmIsToggleButton(tgl) && XmToggleButtonGetState(tgl))
2628 {
2629 cnt++;
2630 }
2631 else if (XmIsToggleButtonGadget(tgl) &&
2632 XmToggleButtonGadgetGetState(tgl))
2633 {
2634 cnt++;
2635 }
2636 }
2637 if (cnt == 0)
2638 {
2639 /* Whow. You're resetting the radio box without written permission.
2640 * Stop right there ! */
2641 if (XmIsToggleButton(w))
2642 {
2643 DEBUGOUT(_LtDebug2(__FILE__, rc, w,
2644 "RadioHandler: toggle cnt 0 widget -> True\n"));
2645 XmToggleButtonSetState(w, True, True);
2646 }
2647 else if (XmIsToggleButtonGadget(w))
2648 {
2649 DEBUGOUT(_LtDebug2(__FILE__, rc, w,
2650 "RadioHandler: toggle cnt 0 gadget -> True\n"));
2651 XmToggleButtonGadgetSetState(w, True, True);
2652 }
2653
2654 return;
2655 }
2656 }
2657
2658 /*
2659 * We're ok. Now for the real work.
2660 * Find which toggles need to change because of this action.
2661 */
2662 /*
2663 * Try to be more correct. Danny 12/6/1998
2664 *
2665 * This change also implies changed definitions in ToggleB[G].c
2666 *
2667 * We're exhibiting an ambivalent state with the above code.
2668 * In callback functions called by the XmToggleButtonSetState(_,_,True),
2669 * while only part of the buttons have been modified, some of the buttons
2670 * reflect a state that they shouldn't be in.
2671 */
2672
2673 /* Turning off a toggle has no further repercussions,
2674 * unless we are in must-have-one mode, which is dealt with above.
2675 */
2676 if( tgl_state == False ) return;
2677
2678 /* Turning on a toggle, Might need to unset someone else */
2679 for (i=0; i<MGR_NumChildren(rc); i++) {
2680 tgl = MGR_Children(rc)[i];
2681 if (tgl == w)
2682 continue;
2683 if (XmIsToggleButton(tgl) && XmToggleButtonGetState(tgl)) {
2684 tgl_unset = tgl;
2685 } else if (XmIsToggleButtonGadget(tgl)
2686 && XmToggleButtonGadgetGetState(tgl)) {
2687 tgl_unset = tgl;
2688 }
2689 }
2690
2691 DEBUGOUT(_LtDebug(__FILE__, rc, "Widget to unset %s\n",
2692 tgl_unset ? XtName(tgl_unset) : "(null)"));
2693
2694 /* Set the data structures */
2695
2696 if (tgl_unset) {
2697 if (XmIsToggleButton(tgl_unset)) {
2698 DEBUGOUT(_LtDebug2(__FILE__, rc, tgl_unset,
2699 "Call XmToggleButtonSetState(tgl, False, True)"));
2700 XmToggleButtonSetState(tgl_unset, False, True);
2701 } else if (XmIsToggleButtonGadget(tgl_unset)) {
2702 DEBUGOUT(_LtDebug2(__FILE__, rc, tgl_unset,
2703 "Call XmToggleButtonGadgetSetState(tgl, False, True)"));
2704 XmToggleButtonGadgetSetState(tgl_unset, False, True);
2705 }
2706 }
2707 }
2708
2709 static Cardinal
_XmRowColumnOrderProc(Widget widget)2710 _XmRowColumnOrderProc(Widget widget)
2711 {
2712 if (RCC_PositionIndex(widget) == XmLAST_POSITION ||
2713 RCC_PositionIndex(widget) >=
2714 MGR_NumChildren(XtParent(widget)))
2715 {
2716 return MGR_NumChildren(XtParent(widget));
2717 }
2718 else
2719 {
2720 return RCC_PositionIndex(widget);
2721 }
2722 }
2723
2724 static void
insert_child(Widget w)2725 insert_child(Widget w)
2726 {
2727 Widget rc = (Widget)XtParent(w);
2728 Cardinal i;
2729
2730 #if 0
2731 if ((RC_RadioBehavior(rc) || RC_RadioAlwaysOne(rc)) &&
2732 ((XtClass(w) == xmToggleButtonWidgetClass) ||
2733 (XtClass(w) == xmToggleButtonGadgetClass)))
2734 {
2735 XtAddCallback(w, XmNvalueChangedCallback, _XmRadioCallback, rc);
2736 }
2737 #endif
2738
2739 #define superclass (&xmManagerClassRec)
2740 (*superclass->composite_class.insert_child) (w);
2741 #undef superclass
2742
2743 for (i = 0; i < MGR_NumChildren(rc); i++)
2744 {
2745 RCC_PositionIndex(MGR_Children(rc)[i]) = i;
2746 }
2747
2748 DEBUGOUT(_LtDebug2(__FILE__, rc, w, "InsertChild\n"));
2749
2750 /*
2751 * if it's a label subclass, set its alignment to our
2752 * RC_EntryAlignment resource
2753 */
2754 if (RC_IsAligned(rc) &&
2755 (XmIsLabel(w) || XmIsLabelGadget(w)))
2756 {
2757 Arg arg;
2758
2759 XtSetArg(arg, XmNalignment, RC_EntryAlignment(rc));
2760 XtSetValues(w, &arg, 1);
2761 DEBUGOUT(_LtDebug2(__FILE__, rc, w,
2762 "insert_child: Set Alignment to %s\n",
2763 _LtDebugAlignment2String(RC_EntryAlignment(rc))));
2764 }
2765
2766 if (XtHasCallbacks(rc, XmNentryCallback) == XtCallbackHasSome)
2767 {
2768 if (XmIsLabel(w))
2769 {
2770 (LabClass_SetOverrideCallback(XtClass(w)))(w);
2771 }
2772 else if (XmIsLabelGadget(w))
2773 {
2774 (LabGClass_SetOverrideCallback(XtClass(w)))(w);
2775 }
2776 }
2777
2778 if (XmIsTearOffButton(w))
2779 {
2780 RC_TearOffControl(rc) = w;
2781 DEBUGOUT(_LtDebug2(__FILE__, rc, w,
2782 "InsertChild: this is the TearOff control\n"));
2783 }
2784
2785 /* Option Menu : handle inserting children */
2786 if (RC_CascadeBtn(rc))
2787 {
2788 Widget p = XtParent(RC_CascadeBtn(rc));
2789 if (p && XmIsRowColumn(p) && RC_Type(p) == XmMENU_OPTION)
2790 {
2791 _XmFixOptionMenu(p, True);
2792 }
2793 }
2794 }
2795
2796 static void
delete_child(Widget w)2797 delete_child(Widget w)
2798 {
2799 Widget rc = XtParent(w);
2800 Cardinal i;
2801
2802 DEBUGOUT(_LtDebug2(__FILE__, rc, w, "DeleteChild\n"));
2803
2804 #define superclass (&xmManagerClassRec)
2805 (*superclass->composite_class.delete_child) (w);
2806 #undef superclass
2807
2808 for (i = 0; i < MGR_NumChildren(rc); i++)
2809 {
2810 RCC_PositionIndex(MGR_Children(rc)[i]) = i;
2811 }
2812 if (MGR_ActiveChild(rc) == w)
2813 {
2814 MGR_ActiveChild(rc) = NULL;
2815 }
2816 }
2817
2818 static void
constraint_initialize(Widget request,Widget new_w,ArgList args,Cardinal * num_args)2819 constraint_initialize(Widget request, Widget new_w,
2820 ArgList args, Cardinal *num_args)
2821 {
2822 Dimension *baselines;
2823 int num_baselines;
2824
2825 DEBUGOUT(_LtDebug2(__FILE__, XtParent(new_w), new_w,
2826 "%s:constraint_initialize(%d) - %i args\n"
2827 "\trequest X %5i Y %5i W %5i H %5i\n"
2828 "\t new_w X %5i Y %5i W %5i H %5i\n"
2829 "\t RC W %5i H %5i\n",
2830 __FILE__, __LINE__,
2831 *num_args,
2832 XtX(request), XtY(request),
2833 XtWidth(request), XtHeight(request),
2834 XtX(new_w), XtY(new_w),
2835 XtWidth(new_w), XtHeight(new_w),
2836 XtWidth(XtParent(new_w)), XtHeight(XtParent(new_w))));
2837 DEBUGOUT(_LtDebugPrintArgList(__FILE__, new_w, args, *num_args, False));
2838
2839 RCC_MarginTop(new_w) = RCC_MarginBottom(new_w) = 0;
2840 if (XmIsLabel(new_w))
2841 {
2842 if (!XmIsCascadeButton(new_w) || CB_Submenu(new_w))
2843 {
2844 if (RC_Orientation(XtParent(new_w)) == XmHORIZONTAL)
2845 {
2846 RCC_MarginTop(new_w) = Lab_MarginTop(new_w);
2847 RCC_MarginBottom(new_w) = Lab_MarginBottom(new_w);
2848 }
2849 else
2850 {
2851 RCC_MarginTop(new_w) = Lab_MarginLeft(new_w);
2852 RCC_MarginBottom(new_w) = Lab_MarginRight(new_w);
2853 }
2854 }
2855 }
2856 else if (XmIsLabelGadget(new_w))
2857 {
2858 if (!XmIsCascadeButtonGadget(new_w) || CBG_Submenu(new_w))
2859 {
2860 if (RC_Orientation(XtParent(new_w)) == XmHORIZONTAL)
2861 {
2862 RCC_MarginTop(new_w) = LabG_MarginTop(new_w);
2863 RCC_MarginBottom(new_w) = LabG_MarginBottom(new_w);
2864 }
2865 else
2866 {
2867 RCC_MarginTop(new_w) = LabG_MarginLeft(new_w);
2868 RCC_MarginBottom(new_w) = LabG_MarginRight(new_w);
2869 }
2870 }
2871 }
2872
2873 /* we set the baseline of the child to the lowest baseline of the widget */
2874 if (XmWidgetGetBaselines(new_w, &baselines, &num_baselines))
2875 {
2876 RCC_Baseline(new_w) = baselines[num_baselines - 1];
2877 XtFree((char *)baselines);
2878 }
2879 else
2880 {
2881 /* is this right ? */
2882 RCC_Baseline(new_w) = 0;
2883 }
2884 }
2885
2886
2887 static Boolean
constraint_set_values(Widget current,Widget request,Widget new_w,ArgList args,Cardinal * num_args)2888 constraint_set_values(Widget current, Widget request, Widget new_w,
2889 ArgList args, Cardinal *num_args)
2890 {
2891 Dimension *baselines;
2892 int num_baselines;
2893 Boolean refresh_needed = False;
2894 Cardinal i;
2895 Widget rc = XtParent(new_w);
2896
2897 DEBUGOUT(_LtDebug2(__FILE__, (Widget)rc, new_w,
2898 "%s:constraint_set_values(%d) - %i args\n"
2899 "\tcurrent X %5i Y %5i W %5i H %5i\n"
2900 "\trequest X %5i Y %5i W %5i H %5i\n"
2901 "\t new_w X %5i Y %5i W %5i H %5i\n"
2902 "\t RC W %5i H %5i\n",
2903 __FILE__, __LINE__,
2904 *num_args,
2905 XtX(current), XtY(current),
2906 XtWidth(current), XtHeight(current),
2907 XtX(request), XtY(request),
2908 XtWidth(request), XtHeight(request),
2909 XtX(new_w), XtY(new_w),
2910 XtWidth(new_w), XtHeight(new_w),
2911 XtWidth(XtParent(new_w)), XtHeight(XtParent(new_w))));
2912 DEBUGOUT(_LtDebugPrintArgList(__FILE__, new_w, args, *num_args, False));
2913 DEBUGOUT(_LtDebug2("EMACS", (Widget)rc, new_w,
2914 "%s:constraint_set_values(%d) - %i args\n"
2915 "\tcurrent X %5i Y %5i W %5i H %5i\n"
2916 "\trequest X %5i Y %5i W %5i H %5i\n"
2917 "\t new_w X %5i Y %5i W %5i H %5i\n"
2918 "\t RC W %5i H %5i\n",
2919 __FILE__, __LINE__,
2920 *num_args,
2921 XtX(current), XtY(current),
2922 XtWidth(current), XtHeight(current),
2923 XtX(request), XtY(request),
2924 XtWidth(request), XtHeight(request),
2925 XtX(new_w), XtY(new_w),
2926 XtWidth(new_w), XtHeight(new_w),
2927 XtWidth(XtParent(new_w)), XtHeight(XtParent(new_w))));
2928 DEBUGOUT(_LtDebugPrintArgList("EMACS", new_w, args, *num_args, False));
2929
2930 if (XmIsLabel(new_w))
2931 {
2932 if (!XmIsCascadeButton(new_w) ||
2933 (CB_Submenu(new_w) && Lab_MenuType(new_w) != XmMENU_OPTION))
2934 {
2935 if (RC_Orientation(XtParent(new_w)) == XmHORIZONTAL)
2936 {
2937 RCC_MarginTop(new_w) = Lab_MarginTop(new_w);
2938 RCC_MarginBottom(new_w) = Lab_MarginBottom(new_w);
2939 }
2940 else
2941 {
2942 RCC_MarginTop(new_w) = Lab_MarginLeft(new_w);
2943 RCC_MarginBottom(new_w) = Lab_MarginRight(new_w);
2944 }
2945 }
2946 }
2947 else if (XmIsLabelGadget(new_w))
2948 {
2949 if (!XmIsCascadeButtonGadget(new_w) ||
2950 (CBG_Submenu(new_w) && LabG_MenuType(new_w) != XmMENU_OPTION))
2951 {
2952 if (RC_Orientation(XtParent(new_w)) == XmHORIZONTAL)
2953 {
2954 RCC_MarginTop(new_w) = LabG_MarginTop(new_w);
2955 RCC_MarginBottom(new_w) = LabG_MarginBottom(new_w);
2956 }
2957 else
2958 {
2959 RCC_MarginTop(new_w) = LabG_MarginLeft(new_w);
2960 RCC_MarginBottom(new_w) = LabG_MarginRight(new_w);
2961 }
2962 }
2963 }
2964 if (RC_OptionSubMenu(rc))
2965 {
2966 if (RC_Type(RC_OptionSubMenu(rc)) == XmMENU_OPTION)
2967 {
2968 if(RC_MemWidget(RC_OptionSubMenu(rc)) == new_w)
2969 {
2970 _XmOptionCallback(new_w, (XtPointer)RC_OptionSubMenu(rc), NULL);
2971 }
2972 _XmRCAdjustSize(RC_OptionSubMenu(rc), NULL, NULL);
2973 }
2974 }
2975 if (RCC_PositionIndex(new_w) != RCC_PositionIndex(current))
2976 {
2977 Widget savew;
2978 int pos, lastpos;
2979
2980 #if 1
2981 /* rws 23 Mar 1999
2982 If there is a TearOffControl it doesn't seem to count!! In other
2983 words changing an item to position 0 will really change it to
2984 position 1 _iff_ there is a TearOffControl.
2985 (rowcolumn/test51)
2986 */
2987 if (RC_TearOffControl(rc))
2988 {
2989 pos = RCC_PositionIndex(new_w) + 1;
2990 }
2991 else
2992 {
2993 pos = RCC_PositionIndex(new_w);
2994 }
2995 #endif
2996 lastpos = RCC_PositionIndex(current);
2997
2998 if (RCC_PositionIndex(new_w) == XmLAST_POSITION)
2999 {
3000 RCC_PositionIndex(new_w) = MGR_NumChildren(rc) - 1;
3001 pos = RCC_PositionIndex(new_w);
3002 }
3003
3004 savew = MGR_Children(rc)[lastpos];
3005
3006 if (pos < lastpos)
3007 {
3008 for (i = lastpos; i > pos; i--)
3009 {
3010 MGR_Children(rc)[i] = MGR_Children(rc)[i - 1];
3011 }
3012
3013 MGR_Children(rc)[pos] = savew;
3014 }
3015 else if (pos > lastpos)
3016 {
3017 for (i = lastpos; i < pos; i++)
3018 {
3019 MGR_Children(rc)[i] = MGR_Children(rc)[i + 1];
3020 }
3021
3022 MGR_Children(rc)[pos] = savew;
3023 }
3024
3025 for (i = 0; i < MGR_NumChildren(rc); i++)
3026 {
3027 RCC_PositionIndex(MGR_Children(rc)[i]) = i;
3028 }
3029
3030 DEBUGOUT(_LtDebug(__FILE__, new_w,
3031 "_XmRCAdjustSize from constraint_set_values\n"));
3032 DEBUGOUT(_LtDebug("EMACS", new_w,
3033 "_XmRCAdjustSize from constraint_set_values\n"));
3034 _XmRCAdjustSize(rc, NULL, NULL);
3035
3036 refresh_needed = True;
3037 }
3038
3039 /* we set the baseline of the child to the lowest baseline of the widget */
3040 if (XmWidgetGetBaselines(new_w, &baselines, &num_baselines))
3041 {
3042 RCC_Baseline(new_w) = baselines[num_baselines - 1];
3043 XtFree((char *)baselines);
3044 }
3045 else
3046 {
3047 /* is this right ? */
3048 RCC_Baseline(new_w) = 0;
3049 }
3050
3051 DEBUGOUT(_LtDebug(__FILE__, new_w, "constraint_set_values (end): %d %d\n",
3052 RCC_MarginTop(new_w),
3053 RCC_MarginBottom(new_w)));
3054
3055 return refresh_needed;
3056 }
3057
3058 static XmNavigability
widget_navigable(Widget w)3059 widget_navigable(Widget w)
3060 {
3061 DEBUGOUT(_LtDebug(__FILE__, w, "%s(%d):widget_navigable\n", __FILE__, __LINE__));
3062 DEBUGOUT(_LtDebug(__FILE__, w, " Sensitive %s\n", _LtDebugBoolean2String(XtSensitive(w))));
3063 DEBUGOUT(_LtDebug(__FILE__, w, " TraversalOn %s\n", _LtDebugBoolean2String(MGR_TraversalOn(w))));
3064 DEBUGOUT(_LtDebug(__FILE__, w, " RC_Type %s\n", _LtDebugRcType2String(RC_Type(w))));
3065 DEBUGOUT(_LtDebug(__FILE__, w, " DragMode %s\n", _LtDebugBoolean2String(_XmGetInDragMode(w))));
3066 /*
3067 DEBUGOUT(_LtDebug(__FILE__, w, " RC_PopupPosted %s\n",
3068 RC_PopupPosted(w) ? XtName(RC_PopupPosted(w)) : "NULL" ));
3069 */
3070 DEBUGOUT(_LtDebug(__FILE__, w, " NavType %s\n", _LtDebugNavigationType2String(MGR_NavigationType(w))));
3071 if (XtSensitive(w) && MGR_TraversalOn(w) &&
3072 (((RC_Type(w) == XmWORK_AREA || RC_Type(w) == XmMENU_OPTION)) ||
3073 ((RC_Type(w) == XmMENU_PULLDOWN || RC_Type(w) == XmMENU_POPUP) && !_XmGetInDragMode(w)) ||
3074 (RC_Type(w) == XmMENU_BAR && !_XmGetInDragMode(w) && RC_PopupPosted(w))))
3075 {
3076 if (MGR_NavigationType(w) == XmSTICKY_TAB_GROUP ||
3077 MGR_NavigationType(w) == XmEXCLUSIVE_TAB_GROUP ||
3078 (MGR_NavigationType(w) == XmTAB_GROUP && !_XmShellIsExclusive(w)))
3079 {
3080 return XmDESCENDANTS_TAB_NAVIGABLE;
3081 }
3082
3083 return XmDESCENDANTS_NAVIGABLE;
3084 }
3085
3086 return XmNOT_NAVIGABLE;
3087 }
3088
3089 /* action routines */
3090
3091 static void
DoBtnEventCleanupReplay(Widget w,XEvent * event,String * params,Cardinal * num_params)3092 DoBtnEventCleanupReplay(Widget w, XEvent *event,
3093 String *params, Cardinal *num_params)
3094 {
3095 Widget menu_shell;
3096 Widget tlrc;
3097
3098 DEBUGOUT(_LtDebug(__FILE__, w, "DoBtnEventCleanupReplay\n"));
3099
3100 _XmGetActiveTopLevelMenu(w, &tlrc); /* this is RC_LastSelectToplevel() no?? */
3101
3102 if (!tlrc)
3103 {
3104 /* rws 24 Jun 1998
3105 filesb/test5 gets us into this mess when you click on the Button.
3106 It is a cascade button in a menu bar with no menu! So if we get a
3107 button up and there is no menu we still have to clean up the mess
3108 that is there.
3109 */
3110 Widget tmp = RC_LastSelectToplevel(w);
3111
3112 if (RC_IsArmed(tmp))
3113 {
3114 MenuProcEntry(XmMENU_DISARM, tmp, NULL);
3115 _XmMenuSetInPMMode(w, False);
3116 _XmSetInDragMode(w, False);
3117 XAllowEvents(XtDisplay(w), ReplayPointer, CurrentTime);
3118 }
3119 return;
3120 }
3121
3122 menu_shell = XtParent(tlrc);
3123
3124 if (XmIsMenuShell(menu_shell))
3125 {
3126 DEBUGOUT(_LtDebug(__FILE__, w,
3127 "DoBtnEventCleanupReplay: calling MenuShellPopdownDone\n"));
3128 XtCallActionProc(menu_shell, "MenuShellPopdownDone",
3129 event, params, *num_params);
3130 _XmCallRowColumnUnmapCallback(tlrc, event); /* rowcolumn/test45 */
3131 }
3132 else if (_XmIsActiveTearOff(tlrc))
3133 {
3134 Boolean poppedUp;
3135
3136 /* should use RC_CascadeBtn(RC_PopupPosted(tlrc)) I think.
3137 MGR_ActiveChild is really only for the active Gadget.
3138 */
3139 /*
3140 * T. Straumann: use RC_popupPosted(tlrc) and make sure
3141 * it exists (fixes segfault if releasing
3142 * button outside of a torn-off menu)
3143 */
3144 if ( RC_PopupPosted(tlrc) && RC_CascadeBtn(RC_PopupPosted(tlrc)) )
3145 {
3146 RC_MenuShellPopdown(RC_CascadeBtn(RC_PopupPosted(tlrc)), event, &poppedUp);
3147 }
3148 }
3149
3150 _XmSetInDragMode(w, False);
3151
3152 /* Replay the event */
3153 DEBUGOUT(_LtDebug(__FILE__, w,
3154 "DoBtnEventCleanupReplay: XAllowEvents (replay)\n"));
3155
3156 /* FIX ME: should depend on resource */
3157 /* FIX ME: doesn't work */
3158 XAllowEvents(XtDisplay(w), ReplayPointer, CurrentTime);
3159 }
3160
3161 void
_XmMenuBtnDown(Widget w,XEvent * event,String * params,Cardinal * num_params)3162 _XmMenuBtnDown(Widget w, XEvent *event, String *params, Cardinal *num_params)
3163 {
3164 Boolean validButton;
3165
3166 DEBUGOUT(_LtDebug(__FILE__, w, "_XmMenuBtnDown\n"));
3167
3168 {
3169 Widget gadget;
3170
3171 gadget = (Widget)_XmInputForGadget(w,
3172 event->xkey.x,
3173 event->xkey.y);
3174
3175 if (gadget && event->xbutton.window == XtWindow(w))
3176 {
3177 /* Event was in a gadget */
3178 DEBUGOUT(_LtDebug2(__FILE__, w, gadget, "MenuBtnDown() in gadget\n"));
3179
3180 MGR_HighlightedWidget(w) = gadget;
3181 _XmDispatchGadgetInput((Widget)gadget, event, XmARM_EVENT);
3182 _XmMenuFocus(w, XmMENU_FOCUS_SAVE, CurrentTime);
3183 /* Don't return from here, see bug #721016.
3184 return;
3185 */
3186 }
3187 }
3188 DEBUGOUT(_LtDebug("MENU", w, "_XmMenuBtnDown - %i %s\n",
3189 event->xbutton.button,
3190 _XmIsEventUnique(event) ? "unique" : "not-unique"
3191 ));
3192 DEBUGOUT(_LtDebug("MENU", w, "_XmMenuBtnDown - %s %s posted\n",
3193 _XmGetInDragMode(w) ? "dragging" : "not-dragging",
3194 RC_PopupPosted(w) ? XtName(RC_PopupPosted(w)) : "nothing"
3195 ));
3196 /*
3197 RC_MenuButton(w, event, &validButton);
3198 */
3199 (((XmRowColumnClassRec *)(XtClass(w)))->row_column_class.menuProcedures)(XmMENU_BUTTON, w, event, &validButton);
3200 #if 1
3201 /* rws 16 Mar 1999
3202 This sequence is a result of xscope!!!!
3203 */
3204 if (validButton)
3205 {
3206 _XmGrabKeyboard(w, True,
3207 GrabModeSync, GrabModeSync,
3208 CurrentTime);
3209 if (!_XmGetInDragMode(w) && RC_PopupPosted(w))
3210 {
3211 Boolean poppedUp;
3212 Cardinal i;
3213
3214 _XmMenuFocus(w, XmMENU_FOCUS_RESTORE, CurrentTime);
3215 for (i = 0; i < MGR_NumChildren(RC_PopupPosted(w)); i++)
3216 {
3217 Widget w1 = MGR_Children(RC_PopupPosted(w))[i];
3218
3219 _XmMenuDisarmItem(w1);
3220 }
3221 if (RC_CascadeBtn(RC_PopupPosted(w)))
3222 {
3223 RC_MenuShellPopdown(RC_CascadeBtn(RC_PopupPosted(w)), event, &poppedUp);
3224 }
3225 RC_SetArmed(w, False);
3226 }
3227 else
3228 {
3229 _XmMenuFocus(w, XmMENU_FOCUS_SAVE, CurrentTime);
3230 _XmMenuFocus(w, XmMENU_FOCUS_SET, CurrentTime);
3231 XAllowEvents(XtDisplay(w), AsyncKeyboard, CurrentTime);
3232
3233 /* Initiate a new pointer grab for the menu bar */
3234 /* Pointer mode will change to Sync anyway with the
3235 XAllowEvents. It's also set here, according to xscope - Chris 6/23 */
3236 _XmGrabPointer(w, True,
3237 (ButtonPressMask | ButtonReleaseMask | EnterWindowMask |
3238 LeaveWindowMask),
3239 GrabModeSync,
3240 GrabModeAsync,
3241 None,
3242 _XmGetMenuCursorByScreen(XtScreen(w)),
3243 CurrentTime);
3244
3245 /* rws 7 Apr 1999
3246 What's up with this????
3247 */
3248 if (RC_Type(w) != XmMENU_OPTION)
3249 {
3250 _XmAddGrab(w, True, True);
3251 }
3252
3253 /* Process events until the next button event */
3254 RC_SetArmed(w, True);
3255 _XmSetInDragMode(w, True);
3256 }
3257 }
3258 else
3259 {
3260 DEBUGOUT(_LtDebug0("MENU", w, "_XmMenuBtnDown - %s\n",
3261 "\tbutton not valid\n"
3262 ));
3263 }
3264 XAllowEvents(XtDisplay(w), SyncPointer, CurrentTime);
3265 #endif
3266 }
3267
3268 void
_XmMenuBtnUp(Widget w,XEvent * event,String * params,Cardinal * num_params)3269 _XmMenuBtnUp(Widget w, XEvent *event, String *params, Cardinal *num_params)
3270 {
3271 Widget gadget;
3272
3273 gadget = (Widget)_XmInputForGadget(w,
3274 event->xkey.x,
3275 event->xkey.y);
3276
3277 if (gadget && event->xbutton.window == XtWindow(w))
3278 {
3279
3280 DEBUGOUT(_LtDebug2(__FILE__, w, gadget, "MenuBtnUp(in gadget)\n"));
3281
3282 _XmDispatchGadgetInput((Widget)gadget, event, XmACTIVATE_EVENT);
3283 /*
3284 * Don't return here - see bug #721016.
3285 * return;
3286 */
3287 }
3288 DEBUGOUT(_LtDebug("MENU", w, "_XmMenuBtnUp - %s %s posted\n",
3289 _XmGetInDragMode(w) ? "dragging" : "not-dragging",
3290 RC_PopupPosted(w) ? XtName(RC_PopupPosted(w)) : "nothing"
3291 ));
3292
3293 XAllowEvents(XtDisplay(w), SyncPointer, CurrentTime);
3294 if (_XmGetInDragMode(w))
3295 {
3296 Boolean poppedUp;
3297
3298 #if 1
3299 /* rws 16 Mar 1999
3300 This sequence is from xscope!!!!
3301 */
3302 _XmUngrabKeyboard(w, CurrentTime);
3303 _XmUngrabPointer(w, CurrentTime);
3304 _XmRemoveGrab(w);
3305 #endif
3306 if (RC_PopupPosted(w))
3307 {
3308 Cardinal i;
3309
3310 _XmMenuFocus(w, XmMENU_FOCUS_RESTORE, CurrentTime);
3311 for (i = 0; i < MGR_NumChildren(RC_PopupPosted(w)); i++)
3312 {
3313 Widget w1 = MGR_Children(RC_PopupPosted(w))[i];
3314
3315 _XmMenuDisarmItem(w1);
3316 }
3317 if (RC_CascadeBtn(RC_PopupPosted(w)))
3318 {
3319 RC_MenuShellPopdown(RC_CascadeBtn(RC_PopupPosted(w)), event, &poppedUp);
3320 }
3321 }
3322 RC_SetArmed(w, False);
3323 _XmSetInDragMode(w, False);
3324 }
3325 else
3326 {
3327 if (RC_PopupPosted(w))
3328 {
3329 }
3330 else
3331 {
3332 _XmUngrabPointer(w, CurrentTime);
3333 _XmUngrabKeyboard(w, CurrentTime);
3334 _XmRemoveGrab(w);
3335 RC_SetArmed(w, False);
3336 /* 25 Mar 1999
3337 If a menu button pops up a dialog, this steals focus away from
3338 the dialog. This must be done somewhere else.
3339 _XmMenuFocus(w, XmMENU_FOCUS_RESTORE, CurrentTime);
3340 */
3341 }
3342 }
3343 if (_XmIsActiveTearOff(w))
3344 {
3345 if (RC_TearOffFocusItem(w))
3346 {
3347 Lab_MenuArm(RC_TearOffFocusItem(w));
3348 }
3349 }
3350 }
3351
3352 /* FIX ME: this should happen from XmMenuShell:_XmEnterRowColumn */
3353 static void
MenuEnter(Widget w,XEvent * event,String * params,Cardinal * num_params)3354 MenuEnter(Widget w, XEvent *event, String *params, Cardinal *num_params)
3355 {
3356 }
3357
3358 static void
MenuUnmap(Widget w,XEvent * event,String * params,Cardinal * num_params)3359 MenuUnmap(Widget w, XEvent *event, String *params, Cardinal *num_params)
3360 {
3361 DEBUGOUT(_LtDebug(__FILE__, w, "MenuUnmap()\n"));
3362
3363 MGR_HighlightedWidget(w) = NULL; /* FIX ME: move elsewhere */
3364 }
3365
3366 static void
MenuFocusIn(Widget w,XEvent * event,String * params,Cardinal * num_params)3367 MenuFocusIn(Widget w, XEvent *event, String *params, Cardinal *num_params)
3368 {
3369 DEBUGOUT(_LtDebug(__FILE__, w, "MenuFocusIn\n"));
3370 }
3371
3372 static void
MenuFocusOut(Widget w,XEvent * event,String * params,Cardinal * num_params)3373 MenuFocusOut(Widget w, XEvent *event, String *params, Cardinal *num_params)
3374 {
3375 DEBUGOUT(_LtDebug(__FILE__, w, "MenuFocusOut\n"));
3376 /* restore the focus to the widget that had it before moving to the menu bar */
3377 }
3378
3379 static void
MenuBarGadgetSelect(Widget w,XEvent * event,String * params,Cardinal * num_params)3380 MenuBarGadgetSelect(Widget w, XEvent *event,
3381 String *params, Cardinal *num_params)
3382 {
3383 DEBUGOUT(_LtDebug(__FILE__, w, "MenuBarGadgetSelect()\n"));
3384 }
3385
3386 static void
_XmFocusOut(Widget w,XEvent * event,String * params,Cardinal * num_params)3387 _XmFocusOut(Widget w, XEvent *event,
3388 String *params, Cardinal *num_params)
3389 {
3390 DEBUGOUT(_LtDebug(__FILE__, w, "_XmFocusOut()\n"));
3391 }
3392
3393 static void
_XmFocusIn(Widget w,XEvent * event,String * params,Cardinal * num_params)3394 _XmFocusIn(Widget w, XEvent *event,
3395 String *params, Cardinal *num_params)
3396 {
3397 DEBUGOUT(_LtDebug(__FILE__, w, "FocusIn()\n"));
3398 }
3399
3400 static void
_XmUnmap(Widget w,XEvent * event,String * params,Cardinal * num_params)3401 _XmUnmap(Widget w, XEvent *event,
3402 String *params, Cardinal *num_params)
3403 {
3404 DEBUGOUT(_LtDebug(__FILE__, w, "_XmUnmap()\n"));
3405 }
3406
3407 static void
_XmNoop(Widget w,XEvent * event,String * params,Cardinal * num_params)3408 _XmNoop(Widget w, XEvent *event,
3409 String *params, Cardinal *num_params)
3410 {
3411 DEBUGOUT(_LtDebug(__FILE__, w, "_XmNoop()\n"));
3412 }
3413
3414 /*
3415 * most of these are already written under different names
3416 */
3417 void
_XmPostPopupMenu(Widget wid,XEvent * event)3418 _XmPostPopupMenu(Widget wid, XEvent *event)
3419 {
3420 XmMenuState state = _XmGetMenuState(wid);
3421 int type = event->type;
3422 Time time;
3423
3424 DEBUGOUT(_LtDebug(__FILE__, wid, "PostPopupMenu()\n"));
3425 DEBUGOUT(_LtDebug("MENU", wid, "%s:%s(%d)\n", __FILE__, "_XmPostPopupMenu" , __LINE__));
3426
3427 time = XtLastTimestampProcessed(XtDisplay(wid));
3428 if (type == 0)
3429 {
3430 type = KeyPress;
3431 /* rws 2 Apr 1998
3432 This makes the popup's in ddd and Mozilla work but, the real
3433 problem is the GrabButton is not getting called for some reason.
3434 The grab is placed on the RC in AddPopupHandlers but it never
3435 gets triggered?????
3436 */
3437 type = ButtonPress;
3438 }
3439
3440 state->RC_ButtonEventStatus.waiting_to_be_managed = False;
3441 state->RC_ButtonEventStatus.time = time;
3442
3443 if (!XmIsRowColumn(wid) || RC_Type(wid) != XmMENU_POPUP)
3444 {
3445 _XmWarning(wid, "_XmPostPopupMenu sent non rowcolumn widget\n");
3446
3447 return;
3448 }
3449
3450 if (type == KeyPress || type == KeyRelease)
3451 {
3452 _XmSetInDragMode(wid, False);
3453 }
3454 else
3455 {
3456 _XmSetInDragMode(wid, True);
3457 }
3458 _XmMenuSetInPMMode(wid, True);
3459
3460 if (event->type == ButtonRelease)
3461 {
3462 RCClass_MenuProcs(XtClass(wid))(XmMENU_ARM, wid, NULL);
3463 }
3464
3465 _XmMenuFocus(wid, XmMENU_FOCUS_SAVE, CurrentTime);
3466 /* rws 7 May 1998
3467 Mozilla's Bookmark, Forward, Back button menus do not post without
3468 this XtManageChild().
3469 */
3470 if (!XtIsManaged(wid))
3471 XtManageChild(wid);
3472 else
3473 XtCallActionProc(XtParent(wid), "XtMenuPopup", event, NULL, 0);
3474
3475 RC_SetArmed(wid, True);
3476
3477 RC_CascadeBtn(wid) = NULL;
3478 }
3479
3480 void
_XmSetPopupMenuClick(Widget wid,Boolean popupMenuClick)3481 _XmSetPopupMenuClick(Widget wid,
3482 Boolean popupMenuClick)
3483 {
3484 RC_PopupMenuClick(wid) = True;
3485 }
3486
3487 Boolean
_XmGetPopupMenuClick(Widget wid)3488 _XmGetPopupMenuClick(Widget wid)
3489 {
3490 return RC_PopupMenuClick(wid);
3491 }
3492
3493 void
_XmAllowAcceleratedInsensitiveUnmanagedMenuItems(Widget wid,Boolean allowed)3494 _XmAllowAcceleratedInsensitiveUnmanagedMenuItems(Widget wid,
3495 Boolean allowed)
3496 {
3497 XmMenuState state = _XmGetMenuState(wid);
3498
3499 state->RC_allowAcceleratedInsensitiveUnmanagedMenuItems = allowed;
3500 }
3501
3502 void
_XmSetSwallowEventHandler(Widget widget,Boolean add_handler)3503 _XmSetSwallowEventHandler(Widget widget, Boolean add_handler)
3504 {
3505 }
3506
3507 static Boolean
_XmIsWidgetViewable(Widget w)3508 _XmIsWidgetViewable(Widget w)
3509 {
3510 XWindowAttributes window_attributes;
3511
3512 if (w == NULL || CoreBeingDestroyed(w))
3513 return False;
3514
3515 XGetWindowAttributes(XtDisplay(w), XtWindow(w), &window_attributes);
3516 return(window_attributes.map_state == IsViewable ? True : False);
3517 }
3518
3519 void
_XmMenuFocus(Widget w,int operation,Time _time)3520 _XmMenuFocus(Widget w, int operation, Time _time)
3521 {
3522 XmMenuState state = _XmGetMenuState(w);
3523 Window window_return;
3524 int revert_to_return;
3525 static Boolean SavedState = False;
3526
3527 DEBUGOUT(_LtDebug(__FILE__, w, "%s(%d):_XmMenuFocus() - %s\n",
3528 __FILE__, __LINE__,
3529 _LtDebugMenuFocusOp2String(operation)));
3530 DEBUGOUT(_LtDebug("FOCUS", w, "%s(%d):_XmMenuFocus() - %s\n",
3531 __FILE__, __LINE__,
3532 _LtDebugMenuFocusOp2String(operation)));
3533 /* nothing but a guess here. There are three operations that seem
3534 to take place with respect to focus and menus.
3535
3536 1 - saving the keyboard focus (done at the start of the menu stuff.)
3537 2 - setting the keyboard focus (done at several points.)
3538 3 - restoring the keyboard focus (done at the end of the menu stuff.)
3539
3540 So, those are the three "operations" that are valid to this function.
3541 */
3542 switch (operation)
3543 {
3544 case XmMENU_FOCUS_SAVE:
3545 if (! SavedState)
3546 {
3547 XGetInputFocus(XtDisplay(w),
3548 &state->RC_menuFocus.oldFocus,
3549 &state->RC_menuFocus.oldRevert);
3550
3551 state->RC_menuFocus.oldWidget = XtWindowToWidget(XtDisplay(w),
3552 state->RC_menuFocus.oldFocus);
3553 SavedState = True;
3554 DEBUGOUT(_LtDebug("FOCUS", w, "\tsaving %s\n",
3555 state->RC_menuFocus.oldWidget ? XtName(state->RC_menuFocus.oldWidget) : "NULL"));
3556 }
3557 else
3558 {
3559 #if 0
3560 _XmWarning(w, "%s(%d):_XmMenuFocus() - %s\n trying to save twice",
3561 __FILE__, __LINE__, _LtDebugMenuFocusOp2String(operation));
3562 #endif
3563 }
3564 break;
3565
3566 case XmMENU_FOCUS_RESTORE:
3567
3568 if (SavedState)
3569 {
3570 if (! state->RC_menuFocus.oldWidget)
3571 {
3572 #if 0
3573 _XmWarning(w,"%s(%d) - Restoring focus to NULL widget!\n Must have missed a focus save somewhere.",
3574 __FILE__, __LINE__);
3575 #else
3576 /* rws 7 Mar 2000
3577 Let's try this and see what happens.
3578 */
3579 XSetInputFocus(XtDisplay(w), PointerRoot, RevertToNone, _time);
3580 #endif
3581 }
3582 else
3583 {
3584 if ((state->RC_menuFocus.oldFocus != PointerRoot && state->RC_menuFocus.oldFocus != None) && ! _XmIsWidgetViewable(state->RC_menuFocus.oldWidget))
3585 {
3586 _XmWarning(XtWindowToWidget(XtDisplay(w), state->RC_menuFocus.oldFocus), "%s(%d):_XmMenuFocus() - %s\n window is not viewable",
3587 __FILE__, __LINE__, _LtDebugMenuFocusOp2String(operation));
3588 }
3589 else
3590 {
3591 DEBUGOUT(_LtDebug(__FILE__, w, " Restore focus to %s\n",
3592 XtName(state->RC_menuFocus.oldWidget)));
3593 DEBUGOUT(_LtDebug("FOCUS", w, " Restore focus to %s\n",
3594 XtName(state->RC_menuFocus.oldWidget)));
3595 if (CoreBeingDestroyed(state->RC_menuFocus.oldWidget))
3596 {
3597 _XmWarning(w,"%s(%d) - Restoring focus to %s which is being destroyed!\n Using None instead.",
3598 __FILE__, __LINE__,
3599 XtName(state->RC_menuFocus.oldWidget));
3600 state->RC_menuFocus.oldFocus = None ;
3601 }
3602 XSetInputFocus(XtDisplay(w),
3603 state->RC_menuFocus.oldFocus,
3604 state->RC_menuFocus.oldRevert,
3605 _time);
3606
3607 XmProcessTraversal(state->RC_menuFocus.oldWidget, XmTRAVERSE_CURRENT);
3608
3609 XGetInputFocus(XtDisplay(w),
3610 &window_return,
3611 &revert_to_return);
3612
3613 if (state->RC_menuFocus.oldFocus != window_return
3614 || state->RC_menuFocus.oldRevert != revert_to_return)
3615 {
3616 DEBUGOUT(_LtDebug(__FILE__, w, " SetInputFocus call failed.\n"));
3617 state->RC_menuFocus.oldFocus = window_return;
3618 state->RC_menuFocus.oldRevert = revert_to_return;
3619 state->RC_menuFocus.oldWidget = XtWindowToWidget(XtDisplay(w),
3620 state->RC_menuFocus.oldFocus);
3621 }
3622 else
3623 {
3624 state->RC_menuFocus.oldWidget = NULL;
3625 state->RC_menuFocus.oldFocus = None;
3626 state->RC_menuFocus.oldRevert = RevertToPointerRoot;
3627 }
3628 }
3629 }
3630 SavedState = False;
3631 }
3632 else
3633 {
3634 #ifdef LESSTIF_VERBOSE
3635 _XmWarning(w, "%s(%d):_XmMenuFocus() - %s\n trying to restore without a save",
3636 __FILE__, __LINE__, _LtDebugMenuFocusOp2String(operation));
3637 #endif
3638 }
3639 break;
3640
3641 case XmMENU_FOCUS_SET:
3642 if (! SavedState)
3643 {
3644 #ifdef LESSTIF_VERBOSE
3645 _XmWarning(w, "%s(%d):_XmMenuFocus() - %s\n trying to set without a save, I'll save for you",
3646 __FILE__, __LINE__, _LtDebugMenuFocusOp2String(operation));
3647 #endif
3648 _XmMenuFocus(w, XmMENU_FOCUS_SAVE, CurrentTime);
3649 }
3650 if (! _XmIsWidgetViewable(w))
3651 {
3652 /*
3653 _XmWarning(w, "%s(%d):_XmMenuFocus() - %s\n window is not viewable",
3654 __FILE__, __LINE__, _LtDebugMenuFocusOp2String(operation));
3655 */
3656 }
3657 else
3658 {
3659 XSetInputFocus(XtDisplay(w),
3660 XtWindow(w),
3661 RevertToPointerRoot,
3662 _time);
3663
3664 XtSetKeyboardFocus(w, w);
3665
3666 XGetInputFocus(XtDisplay(w),
3667 &window_return,
3668 &revert_to_return);
3669
3670 if (window_return != XtWindow(w) ||
3671 revert_to_return != RevertToPointerRoot)
3672 {
3673 DEBUGOUT(_LtDebug(__FILE__, w, " setting input focus failed\n"));
3674 _XmUngrabKeyboard(w, _time);
3675 return;
3676 }
3677 }
3678 break;
3679 }
3680 }
3681
3682 void
_XmGetActiveTopLevelMenu(Widget wid,Widget * rwid)3683 _XmGetActiveTopLevelMenu(Widget wid, Widget *rwid)
3684 {
3685 Widget toplevelrc;
3686
3687 DEBUGOUT(_LtDebug(__FILE__, wid, "_XmGetActiveTopLevelMenu()\n"));
3688 /* find the topmost menu pane */
3689 if ((toplevelrc = RC_LastSelectToplevel(wid)))
3690 {
3691 /* Pulldown and option menus keep track over their toplevel
3692 * RowColumn...
3693 */
3694 Widget top_pane;
3695
3696 DEBUGOUT(_LtDebug(__FILE__, wid, "_XmGetActiveTopLevelMenu() - RC_LastSelectTopLevel %s\n",
3697 XtName(toplevelrc)));
3698 if ((top_pane = RC_PopupPosted(toplevelrc)))
3699 {
3700 toplevelrc = top_pane;
3701 DEBUGOUT(_LtDebug(__FILE__, wid, "_XmGetActiveTopLevelMenu() - RC_PopupPosted %s\n",
3702 XtName(toplevelrc)));
3703 }
3704 else
3705 {
3706 if (_XmIsActiveTearOff(wid))
3707 {
3708 toplevelrc = wid;
3709 }
3710 else
3711 {
3712 }
3713 }
3714 }
3715 else
3716 {
3717 /* ... popup menus don't . */
3718 Widget cb;
3719
3720 toplevelrc = wid;
3721 cb = RC_CascadeBtn(toplevelrc);
3722
3723 while (cb)
3724 {
3725 toplevelrc = XtParent(cb);
3726 cb = RC_CascadeBtn(toplevelrc);
3727 }
3728 }
3729
3730 DEBUGOUT(_LtDebug(__FILE__, wid, "_XmGetActiveTopLevelMenu() - returning %s\n",
3731 toplevelrc ? XtName(toplevelrc) : "NULL" ));
3732 *rwid = toplevelrc;
3733 }
3734
3735 Boolean
_XmMatchBSelectEvent(Widget wid,XEvent * event)3736 _XmMatchBSelectEvent(Widget wid, XEvent *event)
3737 {
3738 return False;
3739 }
3740
3741 Boolean
_XmMatchBDragEvent(Widget wid,XEvent * event)3742 _XmMatchBDragEvent(Widget wid, XEvent *event)
3743 {
3744 return False;
3745 }
3746
3747 void
_XmHandleMenuButtonPress(Widget wid,XEvent * event)3748 _XmHandleMenuButtonPress(Widget wid, XEvent *event)
3749 {
3750 }
3751
3752 void
_XmCallRowColumnMapCallback(Widget wid,XEvent * event)3753 _XmCallRowColumnMapCallback(Widget wid, XEvent *event)
3754 {
3755 XmRowColumnCallbackStruct cbs;
3756
3757 cbs.reason = XmCR_MAP;
3758 cbs.event = event;
3759 cbs.widget = NULL;
3760 cbs.data = NULL;
3761 cbs.callbackstruct = NULL;
3762
3763 XtCallCallbackList(wid, RC_Map_cb(wid), (XtPointer)&cbs);
3764 }
3765
3766 void
_XmCallRowColumnUnmapCallback(Widget wid,XEvent * event)3767 _XmCallRowColumnUnmapCallback(Widget wid, XEvent *event)
3768 {
3769 XmRowColumnCallbackStruct cbs;
3770
3771 cbs.reason = XmCR_UNMAP;
3772 cbs.event = event;
3773 cbs.widget = NULL;
3774 cbs.data = NULL;
3775 cbs.callbackstruct = NULL;
3776
3777 XtCallCallbackList(wid, RC_Unmap_cb(wid), (XtPointer)&cbs);
3778 }
3779
3780 void
_XmMenuPopDown(Widget w,XEvent * event,Boolean * popped_up)3781 _XmMenuPopDown(Widget w, XEvent *event, Boolean *popped_up)
3782 {
3783 _XmWarning(w, "%s(%d) - _XmMenuPopDown() not implemented ", __FILE__, __LINE__);
3784 }
3785
3786 Boolean
_XmIsActiveTearOff(Widget w)3787 _XmIsActiveTearOff(Widget w)
3788 {
3789 return RC_TearOffActive(w);
3790 }
3791
3792 void
_XmMenuHelp(Widget w,XEvent * event,String * params,Cardinal * num_params)3793 _XmMenuHelp(Widget w, XEvent *event, String *params, Cardinal *num_params)
3794 {
3795 XtCallCallbacks(w, XmNhelpCallback, NULL);
3796 }
3797
3798 static void
ParsePostString(Widget widget,String menuPost)3799 ParsePostString(Widget widget, String menuPost)
3800 {
3801 unsigned int button = 0;
3802 int type = 0;
3803 unsigned int modifiers = 0;
3804 Widget realpar = NULL;
3805
3806 DEBUGOUT(_LtDebug(__FILE__, widget,
3807 "############### In _XmToMenuPost(%s)\n", menuPost));
3808
3809 if (XtIsShell(XtParent(widget)))
3810 {
3811 realpar = XtParent(XtParent(widget));
3812 }
3813 else
3814 {
3815 realpar = XtParent(widget);
3816 }
3817
3818 if (realpar != NULL && RC_PostButton(widget) != XmUNSPECIFIED)
3819 {
3820 XtUngrabButton(realpar,
3821 RC_PostButton(widget), RC_PostModifiers(widget));
3822 #if 0
3823 XtUngrabKeyboard(realpar, CurrentTime); /* XXX 761607 */
3824 #endif
3825 }
3826
3827 if (menuPost == NULL)
3828 {
3829 DEBUGOUT(_LtDebug(__FILE__, widget,
3830 " Default case -- menupost == null\n"));
3831 return;
3832 }
3833
3834 if (_XmMapBtnEvent(menuPost, &type, &button, &modifiers))
3835 {
3836 /* does this one ever change? */
3837 RC_PostEventType(widget) = type;
3838 RC_PostButton(widget) = button;
3839 RC_PostModifiers(widget) = modifiers;
3840
3841 if (RC_Type(widget) == XmMENU_POPUP && type == ButtonRelease)
3842 {
3843 _XmSetPopupMenuClick(widget, True);
3844 }
3845 else
3846 {
3847 _XmSetPopupMenuClick(widget, False);
3848 }
3849
3850 if (realpar)
3851 {
3852 XtGrabButton(realpar,
3853 RC_PostButton(widget), RC_PostModifiers(widget),
3854 True, ButtonReleaseMask, GrabModeSync, GrabModeSync,
3855 XtWindow(realpar),
3856 _XmGetMenuCursorByScreen(XtScreen(widget)));
3857 }
3858 }
3859 }
3860
3861 /* synthetic resource converters */
3862 static XmImportOperator
_XmToMenuPost(Widget widget,int offset,XtArgVal * value)3863 _XmToMenuPost(Widget widget, int offset, XtArgVal *value)
3864 {
3865 String menuPost = (String)*value; /* the string we're checking/parsing. */
3866
3867 if (menuPost)
3868 {
3869 /* Fixme: this could be a leak */
3870 RC_MenuPost(widget) = XtNewString(menuPost);
3871 }
3872
3873 ParsePostString(widget, RC_MenuPost(widget));
3874
3875 return XmSYNTHETIC_NONE;
3876 }
3877
3878 static void
_XmPopupButtonPressHandler(Widget w,XtPointer client_data,XEvent * event,Boolean * cont)3879 _XmPopupButtonPressHandler(Widget w, XtPointer client_data,
3880 XEvent *event, Boolean *cont)
3881 {
3882 Widget rc = (Widget)client_data;
3883 XmMenuState state = _XmGetMenuState(w);
3884
3885 DEBUGOUT(_LtDebug(__FILE__, w,
3886 "BUTTON PRESS %p %s %p %s\n",
3887 w, XtName(w), rc, XtName(rc)));
3888 #if 0
3889 printf("BUTTON PRESS %p %s %p %s\n",
3890 w, XtName(w), rc, XtName(rc));
3891 #endif
3892 /* first check if the event is valid wrt our menupost resource */
3893 if (event->xany.type != RC_PostEventType(rc) ||
3894 event->xbutton.button != RC_PostButton(rc) ||
3895 event->xbutton.state != RC_PostModifiers(rc))
3896 {
3897 DEBUGOUT(_LtDebug(__FILE__, w,
3898 "Not post button. %d %d Button %d PF %d\n",
3899 event->xany.type, ButtonPress,
3900 event->xbutton.button, RC_PostButton(rc)));
3901 XtUngrabPointer(w,CurrentTime);
3902 XtUngrabKeyboard(w,CurrentTime);
3903 return;
3904 }
3905
3906 /* if we're already waiting to be managed, do nothing. */
3907 if (state->RC_ButtonEventStatus.waiting_to_be_managed)
3908 {
3909 DEBUGOUT(_LtDebug(__FILE__, w, "Waiting to be managed\n"));
3910 XtUngrabPointer(w,CurrentTime);
3911 XtUngrabKeyboard(w,CurrentTime);
3912 return;
3913 }
3914
3915 DEBUGOUT(_LtDebug(__FILE__, rc, " Filling in ButtonEventStatusRec\n"));
3916 DEBUGOUT(_LtDebug(__FILE__, rc,
3917 " Event: win %08x subwin: %08x time: %d ser: %d\n",
3918 event->xbutton.window, event->xbutton.subwindow,
3919 event->xbutton.time, event->xbutton.serial));
3920 DEBUGOUT(_LtDebug(__FILE__, rc,
3921 " x_root %d y_root: %d x: %d y: %d "
3922 "state: %d button: %d\n",
3923 event->xbutton.x_root, event->xbutton.y_root,
3924 event->xbutton.x, event->xbutton.y,
3925 event->xbutton.state, event->xbutton.button));
3926
3927 state->RC_ButtonEventStatus.waiting_to_be_managed = True;
3928 state->RC_ButtonEventStatus.event = event->xbutton;
3929 state->RC_ButtonEventStatus.time = event->xbutton.time;
3930 state->RC_ButtonEventStatus.verified = True; /* Is it really? FIX ME */
3931 XtUngrabPointer(w,CurrentTime);
3932 XtUngrabKeyboard(w,CurrentTime);
3933
3934 #if XmVERSION > 1
3935 /* 10/16/98 pgw@hungry.com
3936 FIX ME: This is a quick hack to get things working.
3937 */
3938 if (RC_PopupEnabled(rc) == XmPOPUP_AUTOMATIC
3939 || RC_PopupEnabled(rc) == XmPOPUP_AUTOMATIC_RECURSIVE)
3940 {
3941 XButtonEvent *be = (XButtonEvent*)event;
3942
3943 /* does it match what XmNwhichButton is set to */
3944 if(be->button == RC_PostButton(rc))
3945 {
3946 XmMenuPosition(rc, be);
3947 XtManageChild(rc);
3948 }
3949 }
3950 #endif
3951 }
3952
3953 static void
_XmFromMenuPost(Widget widget,int offset,XtArgVal * value)3954 _XmFromMenuPost(Widget widget,
3955 int offset,
3956 XtArgVal *value)
3957 {
3958 DEBUGOUT(_LtDebug(__FILE__, widget, "In _XmFromMenuPost()\n"));
3959
3960 if(RC_MenuPost(widget))
3961 *value = (XtArgVal) XtNewString(RC_MenuPost(widget));
3962 else
3963 *value = (XtArgVal) NULL;
3964 }
3965
3966 static void
_XmRowColumnEntryClassDefault(Widget w,int offset,XrmValue * val)3967 _XmRowColumnEntryClassDefault(Widget w,
3968 int offset,
3969 XrmValue *val)
3970 {
3971 static WidgetClass wclass;
3972 /* XmRowColumnWidget rc = (XmRowColumnWidget)w;
3973
3974 if (RC_RadioBehavior(rc) && RC_Type(rc) == XmWORK_AREA)
3975 wclass = xmToggleButtonGadgetClass;
3976 else if (RC_Type(rc) == XmMENU_BAR)
3977 wclass = xmCascadeButtonClass;
3978 else
3979 *//* hmmm.... */ ;
3980
3981 val->addr = (XPointer)&wclass;
3982 }
3983
3984 #if 0
3985 static void
3986 _XmRowColumnIsHomogeneousDefault(Widget w,
3987 int offset,
3988 XrmValue *val)
3989 {
3990 static Boolean homo;
3991
3992 if ((RC_RadioBehavior(w) && RC_Type(w) == XmWORK_AREA) ||
3993 RC_Type(w) == XmMENU_BAR)
3994 {
3995 homo = True;
3996 }
3997 else
3998 {
3999 homo = False;
4000 }
4001
4002 val->addr = (XtPointer)&homo;
4003 }
4004 #endif
4005
4006 #if 0
4007 static void
4008 _XmRowColumnMenuAcceleratorDefault(Widget w,
4009 int offset,
4010 XrmValue *val)
4011 {
4012 static String foo;
4013
4014 if (!foo)
4015 {
4016 foo = XtNewString("foo");
4017 }
4018
4019 val->addr = (XtPointer)&foo;
4020 }
4021 #endif
4022