rust/cargo-c: update to 0.10.7+cargo-0.84.0
[oi-userland.git] / components / x11 / libXaw4 / src / Xaw3_1SimpleMenu.c
blobdf045d926e46235f615f80d519692369e77decf9
1 #if ( !defined(lint) && !defined(SABER) )
2 static char Xrcsid[] = "$XConsortium: SimpleMenu.c,v 1.32 89/12/11 15:01:50 kit Exp $";
3 #endif
5 /*
6 * Copyright 1989 Massachusetts Institute of Technology
8 * Permission to use, copy, modify, distribute, and sell this software and its
9 * documentation for any purpose is hereby granted without fee, provided that
10 * the above copyright notice appear in all copies and that both that
11 * copyright notice and this permission notice appear in supporting
12 * documentation, and that the name of M.I.T. not be used in advertising or
13 * publicity pertaining to distribution of the software without specific,
14 * written prior permission. M.I.T. makes no representations about the
15 * suitability of this software for any purpose. It is provided "as is"
16 * without express or implied warranty.
18 * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
20 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
21 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
22 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
23 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
27 * SimpleMenu.c - Source code file for SimpleMenu widget.
29 * Date: April 3, 1989
31 * By: Chris D. Peterson
32 * MIT X Consortium
33 * kit@expo.lcs.mit.edu
36 #include <stdio.h>
37 #include <X11/IntrinsicP.h>
38 #include <X11/StringDefs.h>
40 #include <./Xaw3_1XawInit.h>
41 #include <./Xaw3_1SimpleMenP.h>
42 #include <./Xaw3_1SmeBSB.h>
43 #include <./Xaw3_1Cardinals.h>
45 #include <X11/Xmu/Initer.h>
46 #include <X11/Xmu/CharSet.h>
48 #define streq(a, b) ( strcmp((a), (b)) == 0 )
50 #define offset(field) XtOffset(SimpleMenuWidget, simple_menu.field)
52 static XtResource resources[] = {
55 * Label Resources.
58 {XtNlabel, XtCLabel, XtRString, sizeof(String),
59 offset(label_string), XtRString, NULL},
60 {XtNlabelClass, XtCLabelClass, XtRPointer, sizeof(WidgetClass),
61 offset(label_class), XtRImmediate, (caddr_t) NULL},
64 * Layout Resources.
67 {XtNrowHeight, XtCRowHeight, XtRDimension, sizeof(Dimension),
68 offset(row_height), XtRImmediate, (caddr_t) 0},
69 {XtNtopMargin, XtCVerticalMargins, XtRDimension, sizeof(Dimension),
70 offset(top_margin), XtRImmediate, (caddr_t) 0},
71 {XtNbottomMargin, XtCVerticalMargins, XtRDimension, sizeof(Dimension),
72 offset(bottom_margin), XtRImmediate, (caddr_t) 0},
75 * Misc. Resources
78 { XtNallowShellResize, XtCAllowShellResize, XtRBoolean, sizeof(Boolean),
79 XtOffset(SimpleMenuWidget, shell.allow_shell_resize),
80 XtRImmediate, (XtPointer) TRUE },
81 {XtNcursor, XtCCursor, XtRCursor, sizeof(Cursor),
82 offset(cursor), XtRImmediate, (caddr_t) None},
83 {XtNmenuOnScreen, XtCMenuOnScreen, XtRBoolean, sizeof(Boolean),
84 offset(menu_on_screen), XtRImmediate, (caddr_t) TRUE},
85 {XtNpopupOnEntry, XtCPopupOnEntry, XtRWidget, sizeof(Widget),
86 offset(popup_entry), XtRWidget, NULL},
87 {XtNbackingStore, XtCBackingStore, XtRBackingStore, sizeof (int),
88 offset(backing_store),
89 XtRImmediate, (caddr_t) (Always + WhenMapped + NotUseful)},
90 };
91 #undef offset
93 static char defaultTranslations[] =
94 "<EnterWindow>: highlight() \n\
95 <LeaveWindow>: unhighlight() \n\
96 <BtnMotion>: highlight() \n\
97 <BtnUp>: MenuPopdown() notify() unhighlight()";
100 * Semi Public function definitions.
103 static void Redisplay(), Realize(), Resize(), ChangeManaged();
104 static void Initialize(), ClassInitialize(), ClassPartInitialize();
105 static Boolean SetValues(), SetValuesHook();
106 static XtGeometryResult GeometryManager();
109 * Action Routine Definitions
112 static void Highlight(), Unhighlight(), Notify(), PositionMenuAction();
115 * Private Function Definitions.
118 static void MakeSetValuesRequest(), CreateLabel(), Layout();
119 static void AddPositionAction(), PositionMenu(), ChangeCursorOnGrab();
120 static Dimension GetMenuWidth(), GetMenuHeight();
121 static Widget FindMenu();
122 static SmeObject GetEventEntry();
124 static XtActionsRec actionsList[] =
126 {"notify", Notify},
127 {"highlight", Highlight},
128 {"unhighlight", Unhighlight},
131 CompositeClassExtensionRec extension_rec = {
132 /* next_extension */ NULL,
133 /* record_type */ NULLQUARK,
134 /* version */ XtCompositeExtensionVersion,
135 /* record_size */ sizeof(CompositeClassExtensionRec),
136 /* accepts_objects */ TRUE,
139 #define superclass (&overrideShellClassRec)
141 SimpleMenuClassRec simpleMenuClassRec = {
143 /* superclass */ (WidgetClass) superclass,
144 /* class_name */ "SimpleMenu",
145 /* size */ sizeof(SimpleMenuRec),
146 /* class_initialize */ ClassInitialize,
147 /* class_part_initialize*/ ClassPartInitialize,
148 /* Class init'ed */ FALSE,
149 /* initialize */ Initialize,
150 /* initialize_hook */ NULL,
151 /* realize */ Realize,
152 /* actions */ actionsList,
153 /* num_actions */ XtNumber(actionsList),
154 /* resources */ resources,
155 /* resource_count */ XtNumber(resources),
156 /* xrm_class */ NULLQUARK,
157 /* compress_motion */ TRUE,
158 /* compress_exposure */ TRUE,
159 /* compress_enterleave*/ TRUE,
160 /* visible_interest */ FALSE,
161 /* destroy */ NULL,
162 /* resize */ Resize,
163 /* expose */ Redisplay,
164 /* set_values */ SetValues,
165 /* set_values_hook */ SetValuesHook,
166 /* set_values_almost */ XtInheritSetValuesAlmost,
167 /* get_values_hook */ NULL,
168 /* accept_focus */ NULL,
169 /* intrinsics version */ XtVersion,
170 /* callback offsets */ NULL,
171 /* tm_table */ defaultTranslations,
172 /* query_geometry */ NULL,
173 /* display_accelerator*/ NULL,
174 /* extension */ NULL
176 /* geometry_manager */ GeometryManager,
177 /* change_managed */ ChangeManaged,
178 /* insert_child */ XtInheritInsertChild,
179 /* delete_child */ XtInheritDeleteChild,
180 /* extension */ NULL
182 /* Shell extension */ NULL
184 /* Override extension */ NULL
186 /* Simple Menu extension*/ NULL
190 WidgetClass simpleMenuWidgetClass = (WidgetClass)&simpleMenuClassRec;
192 /************************************************************
194 * Semi-Public Functions.
196 ************************************************************/
198 /* Function Name: ClassInitialize
199 * Description: Class Initialize routine, called only once.
200 * Arguments: none.
201 * Returns: none.
204 static void
205 ClassInitialize()
207 XawInitializeWidgetSet();
208 XtAddConverter( XtRString, XtRBackingStore, XmuCvtStringToBackingStore,
209 NULL, 0 );
210 XmuAddInitializer( AddPositionAction, NULL);
213 /* Function Name: ClassInitialize
214 * Description: Class Part Initialize routine, called for every
215 * subclass. Makes sure that the subclasses pick up
216 * the extension record.
217 * Arguments: wc - the widget class of the subclass.
218 * Returns: none.
221 static void
222 ClassPartInitialize(wc)
223 WidgetClass wc;
225 SimpleMenuWidgetClass smwc = (SimpleMenuWidgetClass) wc;
228 * Make sure that our subclass gets the extension rec too.
231 extension_rec.next_extension = smwc->composite_class.extension;
232 smwc->composite_class.extension = (caddr_t) &extension_rec;
235 /* Function Name: Initialize
236 * Description: Initializes the simple menu widget
237 * Arguments: request - the widget requested by the argument list.
238 * new - the new widget with both resource and non
239 * resource values.
240 * Returns: none.
243 /* ARGSUSED */
244 static void
245 Initialize(request, new)
246 Widget request, new;
248 SimpleMenuWidget smw = (SimpleMenuWidget) new;
250 XmuCallInitializers(XtWidgetToApplicationContext(new));
252 if (smw->simple_menu.label_class == NULL)
253 smw->simple_menu.label_class = smeBSBObjectClass;
255 smw->simple_menu.label = NULL;
256 smw->simple_menu.entry_set = NULL;
257 smw->simple_menu.recursive_set_values = FALSE;
259 if (smw->simple_menu.label_string != NULL)
260 CreateLabel(new);
262 smw->simple_menu.menu_width = TRUE;
264 if (smw->core.width == 0) {
265 smw->simple_menu.menu_width = FALSE;
266 smw->core.width = GetMenuWidth(new, NULL);
269 smw->simple_menu.menu_height = TRUE;
271 if (smw->core.height == 0) {
272 smw->simple_menu.menu_height = FALSE;
273 smw->core.height = GetMenuHeight(new);
277 * Add a popup_callback routine for changing the cursor.
280 XtAddCallback(new, XtNpopupCallback, ChangeCursorOnGrab, NULL);
283 /* Function Name: Redisplay
284 * Description: Redisplays the contents of the widget.
285 * Arguments: w - the simple menu widget.
286 * event - the X event that caused this redisplay.
287 * region - the region the needs to be repainted.
288 * Returns: none.
291 /* ARGSUSED */
292 static void
293 Redisplay(w, event, region)
294 Widget w;
295 XEvent * event;
296 Region region;
298 SimpleMenuWidget smw = (SimpleMenuWidget) w;
299 SmeObject * entry;
300 SmeObjectClass class;
302 if (region == NULL)
303 XClearWindow(XtDisplay(w), XtWindow(w));
306 * Check and Paint each of the entries - including the label.
309 ForAllChildren(smw, entry) {
310 if (!XtIsManaged ( (Widget) *entry)) continue;
312 if (region != NULL)
313 switch(XRectInRegion(region, (int) (*entry)->rectangle.x,
314 (int) (*entry)->rectangle.y,
315 (unsigned int) (*entry)->rectangle.width,
316 (unsigned int) (*entry)->rectangle.height)) {
317 case RectangleIn:
318 case RectanglePart:
319 break;
320 default:
321 continue;
323 class = (SmeObjectClass) (*entry)->object.widget_class;
325 if (class->rect_class.expose != NULL)
326 (class->rect_class.expose)( (Widget) *entry, NULL, NULL);
330 /* Function Name: Realize
331 * Description: Realizes the widget.
332 * Arguments: w - the simple menu widget.
333 * mask - value mask for the window to create.
334 * attrs - attributes for the window to create.
335 * Returns: none
338 static void
339 Realize(w, mask, attrs)
340 Widget w;
341 XtValueMask * mask;
342 XSetWindowAttributes * attrs;
344 SimpleMenuWidget smw = (SimpleMenuWidget) w;
346 attrs->cursor = smw->simple_menu.cursor;
347 *mask |= CWCursor;
348 if ((smw->simple_menu.backing_store == Always) ||
349 (smw->simple_menu.backing_store == NotUseful) ||
350 (smw->simple_menu.backing_store == WhenMapped) ) {
351 *mask |= CWBackingStore;
352 attrs->backing_store = smw->simple_menu.backing_store;
354 else
355 *mask &= ~CWBackingStore;
357 (*superclass->core_class.realize) (w, mask, attrs);
360 /* Function Name: Resize
361 * Description: Handle the menu being resized bigger.
362 * Arguments: w - the simple menu widget.
363 * Returns: none.
366 static void
367 Resize(w)
368 Widget w;
370 SimpleMenuWidget smw = (SimpleMenuWidget) w;
371 SmeObject * entry;
373 if ( !XtIsRealized(w) ) return;
375 ForAllChildren(smw, entry) /* reset width of all entries. */
376 if (XtIsManaged( (Widget) *entry))
377 (*entry)->rectangle.width = smw->core.width;
379 Redisplay(w, (XEvent *) NULL, (Region) NULL);
382 /* Function Name: SetValues
383 * Description: Relayout the menu when one of the resources is changed.
384 * Arguments: current - current state of the widget.
385 * request - what was requested.
386 * new - what the widget will become.
387 * Returns: none
390 /* ARGSUSED */
391 static Boolean
392 SetValues(current, request, new)
393 Widget current, request, new;
395 SimpleMenuWidget smw_old = (SimpleMenuWidget) current;
396 SimpleMenuWidget smw_new = (SimpleMenuWidget) new;
397 Boolean ret_val = FALSE, layout = FALSE;
399 if (!XtIsRealized(current)) return(FALSE);
401 if (!smw_new->simple_menu.recursive_set_values) {
402 if (smw_new->core.width != smw_old->core.width) {
403 smw_new->simple_menu.menu_width = (smw_new->core.width != 0);
404 layout = TRUE;
406 if (smw_new->core.height != smw_old->core.height) {
407 smw_new->simple_menu.menu_height = (smw_new->core.height != 0);
408 layout = TRUE;
412 if (smw_old->simple_menu.cursor != smw_new->simple_menu.cursor)
413 XDefineCursor(XtDisplay(new),
414 XtWindow(new), smw_new->simple_menu.cursor);
416 if (smw_old->simple_menu.label_string !=smw_new->simple_menu.label_string)
417 if (smw_new->simple_menu.label_string == NULL) /* Destroy. */
418 XtDestroyWidget((Widget)smw_old->simple_menu.label);
419 else if (smw_old->simple_menu.label_string == NULL) /* Create. */
420 CreateLabel(new);
421 else { /* Change. */
422 Arg args[1];
424 XtSetArg(args[0], XtNlabel, smw_new->simple_menu.label_string);
425 XtSetValues((Widget)smw_new->simple_menu.label, args, ONE);
428 if (smw_old->simple_menu.label_class != smw_new->simple_menu.label_class)
429 XtAppWarning(XtWidgetToApplicationContext(new),
430 "No Dynamic class change of the SimpleMenu Label.");
432 if ((smw_old->simple_menu.top_margin != smw_new->simple_menu.top_margin) ||
433 (smw_old->simple_menu.bottom_margin !=
434 smw_new->simple_menu.bottom_margin) /* filler................. */ ) {
435 layout = TRUE;
436 ret_val = TRUE;
439 if (layout)
440 Layout(new, NULL, NULL);
442 return(ret_val);
445 /* Function Name: SetValuesHook
446 * Description: To handle a special case, this is passed the
447 * actual arguments.
448 * Arguments: w - the menu widget.
449 * arglist - the argument list passed to XtSetValues.
450 * num_args - the number of args.
451 * Returns: none
455 * If the user actually passed a width and height to the widget
456 * then this MUST be used, rather than our newly calculated width and
457 * height.
460 static Boolean
461 SetValuesHook(w, arglist, num_args)
462 Widget w;
463 ArgList arglist;
464 Cardinal *num_args;
466 register Cardinal i;
467 Dimension width, height;
469 width = w->core.width;
470 height = w->core.height;
472 for ( i = 0 ; i < *num_args ; i++) {
473 if ( streq(arglist[i].name, XtNwidth) )
474 width = (Dimension) arglist[i].value;
475 if ( streq(arglist[i].name, XtNheight) )
476 height = (Dimension) arglist[i].value;
479 if ((width != w->core.width) || (height != w->core.height))
480 MakeSetValuesRequest(w, width, height);
481 return(FALSE);
484 /************************************************************
486 * Geometry Management routines.
488 ************************************************************/
490 /* Function Name: GeometryManager
491 * Description: This is the SimpleMenu Widget's Geometry Manager.
492 * Arguments: w - the Menu Entry making the request.
493 * request - requested new geometry.
494 * reply - the allowed geometry.
495 * Returns: XtGeometry{Yes, No, Almost}.
498 static XtGeometryResult
499 GeometryManager(w, request, reply)
500 Widget w;
501 XtWidgetGeometry * request, * reply;
503 SimpleMenuWidget smw = (SimpleMenuWidget) XtParent(w);
504 SmeObject entry = (SmeObject) w;
505 XtGeometryMask mode = request->request_mode;
506 XtGeometryResult answer;
507 Dimension old_height, old_width;
509 if ( !(mode & CWWidth) && !(mode & CWHeight) )
510 return(XtGeometryNo);
512 reply->width = request->width;
513 reply->height = request->height;
515 old_width = entry->rectangle.width;
516 old_height = entry->rectangle.height;
518 Layout(w, &(reply->width), &(reply->height) );
521 * Since we are an override shell and have no parent there is no one to
522 * ask to see if this geom change is okay, so I am just going to assume
523 * we can do whatever we want. If you subclass be very careful with this
524 * assumption, it could bite you.
526 * Chris D. Peterson - Sept. 1989.
529 if ( (reply->width == request->width) &&
530 (reply->height == request->height) ) {
532 if ( mode & XtCWQueryOnly ) { /* Actually perform the layout. */
533 entry->rectangle.width = old_width;
534 entry->rectangle.height = old_height;
536 else {
537 Layout(( Widget) smw, NULL, NULL);
539 answer = XtGeometryDone;
541 else {
542 entry->rectangle.width = old_width;
543 entry->rectangle.height = old_height;
545 if ( ((reply->width == request->width) && !(mode & CWHeight)) ||
546 ((reply->height == request->height) && !(mode & CWWidth)) ||
547 ((reply->width == request->width) &&
548 (reply->height == request->height)) )
549 answer = XtGeometryNo;
550 else {
551 answer = XtGeometryAlmost;
552 reply->request_mode = 0;
553 if (reply->width != request->width)
554 reply->request_mode |= CWWidth;
555 if (reply->height != request->height)
556 reply->request_mode |= CWHeight;
559 return(answer);
562 /* Function Name: ChangeManaged
563 * Description: called whenever a new child is managed.
564 * Arguments: w - the simple menu widget.
565 * Returns: none.
568 static void
569 ChangeManaged(w)
570 Widget w;
572 Layout(w, NULL, NULL);
575 /************************************************************
577 * Global Action Routines.
579 * These actions routines will be added to the application's
580 * global action list.
582 ************************************************************/
584 /* Function Name: PositionMenuAction
585 * Description: Positions the simple menu widget.
586 * Arguments: w - a widget (no the simple menu widget.)
587 * event - the event that caused this action.
588 * params, num_params - parameters passed to the routine.
589 * we expect the name of the menu here.
590 * Returns: none
593 /* ARGSUSED */
594 static void
595 PositionMenuAction(w, event, params, num_params)
596 Widget w;
597 XEvent * event;
598 String * params;
599 Cardinal * num_params;
601 Widget menu;
602 XPoint loc;
604 if (*num_params != 1) {
605 char error_buf[BUFSIZ];
606 sprintf(error_buf, "%s %s",
607 "Xaw - SimpleMenuWidget: position menu action expects only one",
608 "parameter which is the name of the menu.");
609 XtAppWarning(XtWidgetToApplicationContext(w), error_buf);
610 return;
613 if ( (menu = FindMenu(w, params[0])) == NULL) {
614 char error_buf[BUFSIZ];
615 sprintf(error_buf, "%s '%s'",
616 "Xaw - SimpleMenuWidget: could not find menu named: ", params[0]);
617 XtAppWarning(XtWidgetToApplicationContext(w), error_buf);
618 return;
621 switch (event->type) {
622 case ButtonPress:
623 case ButtonRelease:
624 loc.x = event->xbutton.x_root;
625 loc.y = event->xbutton.y_root;
626 PositionMenu(menu, &loc);
627 break;
628 case EnterNotify:
629 case LeaveNotify:
630 loc.x = event->xcrossing.x_root;
631 loc.y = event->xcrossing.y_root;
632 PositionMenu(menu, &loc);
633 break;
634 case MotionNotify:
635 loc.x = event->xmotion.x_root;
636 loc.y = event->xmotion.y_root;
637 PositionMenu(menu, &loc);
638 break;
639 default:
640 PositionMenu(menu, NULL);
641 break;
645 /************************************************************
647 * Widget Action Routines.
649 ************************************************************/
651 /* Function Name: Unhighlight
652 * Description: Unhighlights current entry.
653 * Arguments: w - the simple menu widget.
654 * event - the event that caused this action.
655 * params, num_params - ** NOT USED **
656 * Returns: none
659 /* ARGSUSED */
660 static void
661 Unhighlight(w, event, params, num_params)
662 Widget w;
663 XEvent * event;
664 String * params;
665 Cardinal * num_params;
667 SimpleMenuWidget smw = (SimpleMenuWidget) w;
668 SmeObject entry = smw->simple_menu.entry_set;
669 SmeObjectClass class;
671 if ( entry == NULL) return;
673 smw->simple_menu.entry_set = NULL;
674 class = (SmeObjectClass) entry->object.widget_class;
675 (class->sme_class.unhighlight) ( (Widget) entry);
678 /* Function Name: Highlight
679 * Description: Highlights current entry.
680 * Arguments: w - the simple menu widget.
681 * event - the event that caused this action.
682 * params, num_params - ** NOT USED **
683 * Returns: none
686 /* ARGSUSED */
687 static void
688 Highlight(w, event, params, num_params)
689 Widget w;
690 XEvent * event;
691 String * params;
692 Cardinal * num_params;
694 SimpleMenuWidget smw = (SimpleMenuWidget) w;
695 SmeObject entry;
696 SmeObjectClass class;
698 if ( !XtIsSensitive(w) ) return;
700 entry = GetEventEntry(w, event);
702 if (entry == smw->simple_menu.entry_set) return;
704 Unhighlight(w, event, params, num_params);
706 if (entry == NULL) return;
708 if ( !XtIsSensitive( (Widget) entry)) {
709 smw->simple_menu.entry_set = NULL;
710 return;
713 smw->simple_menu.entry_set = entry;
714 class = (SmeObjectClass) entry->object.widget_class;
716 (class->sme_class.highlight) ( (Widget) entry);
719 /* Function Name: Notify
720 * Description: Notify user of current entry.
721 * Arguments: w - the simple menu widget.
722 * event - the event that caused this action.
723 * params, num_params - ** NOT USED **
724 * Returns: none
727 /* ARGSUSED */
728 static void
729 Notify(w, event, params, num_params)
730 Widget w;
731 XEvent * event;
732 String * params;
733 Cardinal * num_params;
735 SimpleMenuWidget smw = (SimpleMenuWidget) w;
736 SmeObject entry = smw->simple_menu.entry_set;
737 SmeObjectClass class;
739 if ( (entry == NULL) || !XtIsSensitive((Widget) entry) ) return;
741 class = (SmeObjectClass) entry->object.widget_class;
742 (class->sme_class.notify)( (Widget) entry );
745 /************************************************************
747 * Public Functions.
749 ************************************************************/
751 /* Function Name: XawSimpleMenuAddGlobalActions
752 * Description: adds the global actions to the simple menu widget.
753 * Arguments: app_con - the appcontext.
754 * Returns: none.
757 void
758 XawSimpleMenuAddGlobalActions(app_con)
759 XtAppContext app_con;
761 XtInitializeWidgetClass(simpleMenuWidgetClass);
762 XmuCallInitializers( app_con );
766 /* Function Name: XawSimpleMenuGetActiveEntry
767 * Description: Gets the currently active (set) entry.
768 * Arguments: w - the smw widget.
769 * Returns: the currently set entry or NULL if none is set.
772 Widget
773 XawSimpleMenuGetActiveEntry(w)
774 Widget w;
776 SimpleMenuWidget smw = (SimpleMenuWidget) w;
778 return( (Widget) smw->simple_menu.entry_set);
781 /* Function Name: XawSimpleMenuClearActiveEntry
782 * Description: Unsets the currently active (set) entry.
783 * Arguments: w - the smw widget.
784 * Returns: none.
787 void
788 XawSimpleMenuClearActiveEntry(w)
789 Widget w;
791 SimpleMenuWidget smw = (SimpleMenuWidget) w;
793 smw->simple_menu.entry_set = NULL;
796 /************************************************************
798 * Private Functions.
800 ************************************************************/
802 /* Function Name: CreateLabel
803 * Description: Creates a the menu label.
804 * Arguments: w - the smw widget.
805 * Returns: none.
807 * Creates the label object and makes sure it is the first child in
808 * in the list.
811 static void
812 CreateLabel(w)
813 Widget w;
815 SimpleMenuWidget smw = (SimpleMenuWidget) w;
816 register Widget * child, * next_child;
817 register int i;
818 Arg args[2];
820 if ( (smw->simple_menu.label_string == NULL) ||
821 (smw->simple_menu.label != NULL) ) {
822 char error_buf[BUFSIZ];
824 sprintf(error_buf, "Xaw Simple Menu Widget: %s or %s, %s",
825 "label string is NULL", "label already exists",
826 "no label is being created.");
827 XtAppWarning(XtWidgetToApplicationContext(w), error_buf);
828 return;
831 XtSetArg(args[0], XtNlabel, smw->simple_menu.label_string);
832 XtSetArg(args[1], XtNjustify, XtJustifyCenter);
833 smw->simple_menu.label = (SmeObject)
834 XtCreateManagedWidget("menuLabel",
835 smw->simple_menu.label_class, w,
836 args, TWO);
838 next_child = NULL;
839 for (child = smw->composite.children + smw->composite.num_children,
840 i = smw->composite.num_children ; i > 0 ; i--, child--) {
841 if (next_child != NULL)
842 *next_child = *child;
843 next_child = child;
845 *child = (Widget) smw->simple_menu.label;
848 /* Function Name: Layout
849 * Description: lays the menu entries out all nice and neat.
850 * Arguments: w - See below (+++)
851 * width_ret, height_ret - The returned width and
852 * height values.
853 * Returns: none.
855 * if width == NULL || height == NULL then it assumes the you do not care
856 * about the return values, and just want a relayout.
858 * if this is not the case then it will set width_ret and height_ret
859 * to be width and height that the child would get if it were layed out
860 * at this time.
862 * +++ "w" can be the simple menu widget or any of its object children.
865 static void
866 Layout(w, width_ret, height_ret)
867 Widget w;
868 Dimension *width_ret, *height_ret;
870 SmeObject current_entry, *entry;
871 SimpleMenuWidget smw;
872 Dimension width, height;
873 Boolean do_layout = ((height_ret == NULL) || (width_ret == NULL));
874 Boolean allow_change_size;
875 height = 0;
877 if ( XtIsSubclass(w, simpleMenuWidgetClass) ) {
878 smw = (SimpleMenuWidget) w;
879 current_entry = NULL;
881 else {
882 smw = (SimpleMenuWidget) XtParent(w);
883 current_entry = (SmeObject) w;
886 allow_change_size = (!XtIsRealized((Widget)smw) ||
887 (smw->shell.allow_shell_resize));
889 if ( smw->simple_menu.menu_height )
890 height = smw->core.height;
891 else
892 if (do_layout) {
893 height = smw->simple_menu.top_margin;
894 ForAllChildren(smw, entry) {
895 if (!XtIsManaged( (Widget) *entry)) continue;
897 if ( (smw->simple_menu.row_height != 0) &&
898 (*entry != smw->simple_menu.label) )
899 (*entry)->rectangle.height = smw->simple_menu.row_height;
901 (*entry)->rectangle.y = height;
902 (*entry)->rectangle.x = 0;
903 height += (*entry)->rectangle.height;
905 height += smw->simple_menu.bottom_margin;
907 else {
908 if ((smw->simple_menu.row_height != 0) &&
909 (current_entry != smw->simple_menu.label) )
910 height = smw->simple_menu.row_height;
913 if (smw->simple_menu.menu_width)
914 width = smw->core.width;
915 else if ( allow_change_size )
916 width = GetMenuWidth((Widget) smw, (Widget) current_entry);
917 else
918 width = smw->core.width;
920 if (do_layout) {
921 ForAllChildren(smw, entry)
922 if (XtIsManaged( (Widget) *entry))
923 (*entry)->rectangle.width = width;
925 if (allow_change_size)
926 MakeSetValuesRequest((Widget) smw, width, height);
928 else {
929 *width_ret = width;
930 if (height != 0)
931 *height_ret = height;
935 /* Function Name: AddPositionAction
936 * Description: Adds the XawPositionSimpleMenu action to the global
937 * action list for this appcon.
938 * Arguments: app_con - the application context for this app.
939 * data - NOT USED.
940 * Returns: none.
943 /* ARGSUSED */
944 static void
945 AddPositionAction(app_con, data)
946 XtAppContext app_con;
947 caddr_t data;
949 static XtActionsRec pos_action[] = {
950 { "XawPositionSimpleMenu", PositionMenuAction },
953 XtAppAddActions(app_con, pos_action, XtNumber(pos_action));
956 /* Function Name: FindMenu
957 * Description: Find the menu give a name and reference widget.
958 * Arguments: widget - reference widget.
959 * name - the menu widget's name.
960 * Returns: the menu widget or NULL.
963 static Widget
964 FindMenu(widget, name)
965 Widget widget;
966 String name;
968 register Widget w, menu;
970 for ( w = widget ; w != NULL ; w = XtParent(w) )
971 if ( (menu = XtNameToWidget(w, name)) != NULL )
972 return(menu);
973 return(NULL);
976 /* Function Name: MoveMenu
977 * Description: Actually moves the menu, may force it to
978 * to be fully visable if menu_on_screen is TRUE.
979 * Arguments: w - the simple menu widget.
980 * x, y - the current location of the widget.
981 * Returns: none
984 static void
985 MoveMenu(w, x, y)
986 Widget w;
987 Position x, y;
989 Arg arglist[2];
990 Cardinal num_args = 0;
991 SimpleMenuWidget smw = (SimpleMenuWidget) w;
993 if (smw->simple_menu.menu_on_screen) {
994 int width = w->core.width + 2 * w->core.border_width;
995 int height = w->core.height + 2 * w->core.border_width;
997 if (x < 0)
998 x = 0;
999 else {
1000 int scr_width = WidthOfScreen(XtScreen(w));
1001 if (x + width > scr_width)
1002 x = scr_width - width;
1005 if (y < 0)
1006 y = 0;
1007 else {
1008 int scr_height = HeightOfScreen(XtScreen(w));
1009 if (y + height > scr_height)
1010 y = scr_height - height;
1014 XtSetArg(arglist[num_args], XtNx, x); num_args++;
1015 XtSetArg(arglist[num_args], XtNy, y); num_args++;
1016 XtSetValues(w, arglist, num_args);
1019 /* Function Name: PositionMenu
1020 * Description: Places the menu
1021 * Arguments: w - the simple menu widget.
1022 * location - a pointer the the position or NULL.
1023 * Returns: none.
1026 static void
1027 PositionMenu(w, location)
1028 Widget w;
1029 XPoint * location;
1031 SimpleMenuWidget smw = (SimpleMenuWidget) w;
1032 SmeObject entry;
1033 XPoint t_point;
1035 if (location == NULL) {
1036 Window junk1, junk2;
1037 int root_x, root_y, junkX, junkY;
1038 unsigned int junkM;
1040 location = &t_point;
1041 if (XQueryPointer(XtDisplay(w), XtWindow(w), &junk1, &junk2,
1042 &root_x, &root_y, &junkX, &junkY, &junkM) == FALSE) {
1043 char error_buf[BUFSIZ];
1044 sprintf(error_buf, "%s %s", "Xaw - SimpleMenuWidget:",
1045 "Could not find location of mouse pointer");
1046 XtAppWarning(XtWidgetToApplicationContext(w), error_buf);
1047 return;
1049 location->x = (short) root_x;
1050 location->y = (short) root_y;
1054 * The width will not be correct unless it is realized.
1057 XtRealizeWidget(w);
1059 location->x -= (Position) w->core.width/2;
1061 if (smw->simple_menu.popup_entry == NULL)
1062 entry = smw->simple_menu.label;
1063 else
1064 entry = smw->simple_menu.popup_entry;
1066 if (entry != NULL)
1067 location->y -= entry->rectangle.y + entry->rectangle.height/2;
1069 MoveMenu(w, (Position) location->x, (Position) location->y);
1072 /* Function Name: ChangeCursorOnGrab
1073 * Description: Changes the cursor on the active grab to the one
1074 * specified in out resource list.
1075 * Arguments: w - the widget.
1076 * junk, garbage - ** NOT USED **.
1077 * Returns: None.
1080 /* ARGSUSED */
1081 static void
1082 ChangeCursorOnGrab(w, junk, garbage)
1083 Widget w;
1084 caddr_t junk, garbage;
1086 SimpleMenuWidget smw = (SimpleMenuWidget) w;
1089 * The event mask here is what is currently in the MIT implementation.
1090 * There really needs to be a way to get the value of the mask out
1091 * of the toolkit (CDP 5/26/89).
1094 XChangeActivePointerGrab(XtDisplay(w), ButtonPressMask|ButtonReleaseMask,
1095 smw->simple_menu.cursor, CurrentTime);
1098 /* Function Name: MakeSetValuesRequest
1099 * Description: Makes a (possibly recursive) call to SetValues,
1100 * I take great pains to not go into an infinite loop.
1101 * Arguments: w - the simple menu widget.
1102 * width, height - the size of the ask for.
1103 * Returns: none
1106 static void
1107 MakeSetValuesRequest(w, width, height)
1108 Widget w;
1109 Dimension width, height;
1111 SimpleMenuWidget smw = (SimpleMenuWidget) w;
1112 Arg arglist[2];
1113 Cardinal num_args = (Cardinal) 0;
1115 if ( !smw->simple_menu.recursive_set_values ) {
1116 if ( (smw->core.width != width) || (smw->core.height != height) ) {
1117 smw->simple_menu.recursive_set_values = TRUE;
1118 XtSetArg(arglist[num_args], XtNwidth, width); num_args++;
1119 XtSetArg(arglist[num_args], XtNheight, height); num_args++;
1120 XtSetValues(w, arglist, num_args);
1122 else if (XtIsRealized( (Widget) smw))
1123 Redisplay((Widget) smw, (XEvent *) NULL, (Region) NULL);
1125 smw->simple_menu.recursive_set_values = FALSE;
1128 /* Function Name: GetMenuWidth
1129 * Description: Sets the length of the widest entry in pixels.
1130 * Arguments: w - the simple menu widget.
1131 * Returns: width of menu.
1134 static Dimension
1135 GetMenuWidth(w, w_ent)
1136 Widget w, w_ent;
1138 SmeObject cur_entry = (SmeObject) w_ent;
1139 SimpleMenuWidget smw = (SimpleMenuWidget) w;
1140 Dimension width, widest = (Dimension) 0;
1141 SmeObject * entry;
1143 if ( smw->simple_menu.menu_width )
1144 return(smw->core.width);
1146 ForAllChildren(smw, entry) {
1147 XtWidgetGeometry preferred;
1149 if (!XtIsManaged( (Widget) *entry)) continue;
1151 if (*entry != cur_entry) {
1152 XtQueryGeometry((Widget)*entry, NULL, &preferred);
1154 if (preferred.request_mode & CWWidth)
1155 width = preferred.width;
1156 else
1157 width = (*entry)->rectangle.width;
1159 else
1160 width = (*entry)->rectangle.width;
1162 if ( width > widest )
1163 widest = width;
1166 return(widest);
1169 /* Function Name: GetMenuHeight
1170 * Description: Sets the length of the widest entry in pixels.
1171 * Arguments: w - the simple menu widget.
1172 * Returns: width of menu.
1175 static Dimension
1176 GetMenuHeight(w)
1177 Widget w;
1179 SimpleMenuWidget smw = (SimpleMenuWidget) w;
1180 SmeObject * entry;
1181 Dimension height;
1183 if (smw->simple_menu.menu_height)
1184 return(smw->core.height);
1186 height = smw->simple_menu.top_margin + smw->simple_menu.bottom_margin;
1188 if (smw->simple_menu.row_height == 0)
1189 ForAllChildren(smw, entry)
1190 if (XtIsManaged ((Widget) *entry))
1191 height += (*entry)->rectangle.height;
1192 else
1193 height += smw->simple_menu.row_height * smw->composite.num_children;
1195 return(height);
1198 /* Function Name: GetEventEntry
1199 * Description: Gets an entry given an event that has X and Y coords.
1200 * Arguments: w - the simple menu widget.
1201 * event - the event.
1202 * Returns: the entry that this point is in.
1205 static SmeObject
1206 GetEventEntry(w, event)
1207 Widget w;
1208 XEvent * event;
1210 Position x_loc, y_loc;
1211 SimpleMenuWidget smw = (SimpleMenuWidget) w;
1212 SmeObject * entry;
1214 switch (event->type) {
1215 case MotionNotify:
1216 x_loc = event->xmotion.x;
1217 y_loc = event->xmotion.y;
1218 break;
1219 case EnterNotify:
1220 case LeaveNotify:
1221 x_loc = event->xcrossing.x;
1222 y_loc = event->xcrossing.y;
1223 break;
1224 case ButtonPress:
1225 case ButtonRelease:
1226 x_loc = event->xbutton.x;
1227 y_loc = event->xbutton.y;
1228 break;
1229 default:
1230 XtAppError(XtWidgetToApplicationContext(w),
1231 "Unknown event type in GetEventEntry().");
1232 break;
1235 if ( (x_loc < 0) || (x_loc >= smw->core.width) || (y_loc < 0) ||
1236 (y_loc >= smw->core.height) )
1237 return(NULL);
1239 ForAllChildren(smw, entry) {
1240 if (!XtIsManaged ((Widget) *entry)) continue;
1242 if ( ((*entry)->rectangle.y < y_loc) &&
1243 ((*entry)->rectangle.y + (*entry)->rectangle.height > y_loc) )
1244 if ( *entry == smw->simple_menu.label )
1245 return(NULL); /* cannot select the label. */
1246 else
1247 return(*entry);
1250 return(NULL);