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