00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <stdio.h>
00039 #include <X11/IntrinsicP.h>
00040 #include <X11/StringDefs.h>
00041
00042 #include <X11/Xaw3d/XawInit.h>
00043 #include <X11/Xaw3d/SimpleMenP.h>
00044 #include <X11/Xaw3d/SmeBSB.h>
00045 #include <X11/Xaw3d/Cardinals.h>
00046
00047 #include <X11/Xmu/Initer.h>
00048 #include <X11/Xmu/CharSet.h>
00049
00050 #define streq(a, b) ( strcmp((a), (b)) == 0 )
00051
00052 #define offset(field) XtOffsetOf(SimpleMenuRec, simple_menu.field)
00053
00054 static XtResource resources[] = {
00055
00056
00057
00058
00059
00060 {XtNlabel, XtCLabel, XtRString, sizeof(String),
00061 offset(label_string), XtRString, NULL},
00062 {XtNlabelClass, XtCLabelClass, XtRPointer, sizeof(WidgetClass),
00063 offset(label_class), XtRImmediate, (XtPointer) NULL},
00064
00065
00066
00067
00068
00069 {XtNrowHeight, XtCRowHeight, XtRDimension, sizeof(Dimension),
00070 offset(row_height), XtRImmediate, (XtPointer) 0},
00071 {XtNtopMargin, XtCVerticalMargins, XtRDimension, sizeof(Dimension),
00072 offset(top_margin), XtRImmediate, (XtPointer) 0},
00073 {XtNbottomMargin, XtCVerticalMargins, XtRDimension, sizeof(Dimension),
00074 offset(bottom_margin), XtRImmediate, (XtPointer) 0},
00075
00076
00077
00078
00079
00080 { XtNallowShellResize, XtCAllowShellResize, XtRBoolean, sizeof(Boolean),
00081 XtOffsetOf(SimpleMenuRec, shell.allow_shell_resize),
00082 XtRImmediate, (XtPointer) TRUE },
00083 {XtNcursor, XtCCursor, XtRCursor, sizeof(Cursor),
00084 offset(cursor), XtRImmediate, (XtPointer) None},
00085 {XtNmenuOnScreen, XtCMenuOnScreen, XtRBoolean, sizeof(Boolean),
00086 offset(menu_on_screen), XtRImmediate, (XtPointer) TRUE},
00087 {XtNpopupOnEntry, XtCPopupOnEntry, XtRWidget, sizeof(Widget),
00088 offset(popup_entry), XtRWidget, NULL},
00089 {XtNbackingStore, XtCBackingStore, XtRBackingStore, sizeof (int),
00090 offset(backing_store),
00091 XtRImmediate, (XtPointer) (Always + WhenMapped + NotUseful)},
00092 };
00093 #undef offset
00094
00095 static char defaultTranslations[] =
00096 ":<EnterWindow>: highlight() \n\
00097 :<LeaveWindow>: unhighlight() \n\
00098 :<BtnMotion>: highlight() \n\
00099 :<BtnUp>: MenuPopdown() notify() unhighlight()";
00100
00101
00102
00103
00104
00105 static void Redisplay(), Realize(), Resize(), ChangeManaged();
00106 static void Initialize(), ClassInitialize(), ClassPartInitialize();
00107 static Boolean SetValues(), SetValuesHook();
00108 static XtGeometryResult GeometryManager();
00109
00110
00111
00112
00113
00114 static void Highlight(), Unhighlight(), Notify(), PositionMenuAction();
00115
00116
00117
00118
00119
00120 static void MakeSetValuesRequest(), CreateLabel(), Layout();
00121 static void AddPositionAction(), PositionMenu(), ChangeCursorOnGrab();
00122 static Dimension GetMenuWidth(), GetMenuHeight();
00123 static Widget FindMenu();
00124 static SmeObject GetEventEntry();
00125 static void MoveMenu();
00126
00127 static XtActionsRec actionsList[] =
00128 {
00129 {"notify", Notify},
00130 {"highlight", Highlight},
00131 {"unhighlight", Unhighlight},
00132 };
00133
00134 static CompositeClassExtensionRec extension_rec = {
00135 NULL,
00136 NULLQUARK,
00137 XtCompositeExtensionVersion,
00138 sizeof(CompositeClassExtensionRec),
00139 TRUE,
00140 };
00141
00142 #define superclass (&overrideShellClassRec)
00143
00144 SimpleMenuClassRec simpleMenuClassRec = {
00145 {
00146 (WidgetClass) superclass,
00147 "SimpleMenu",
00148 sizeof(SimpleMenuRec),
00149 ClassInitialize,
00150 ClassPartInitialize,
00151 FALSE,
00152 Initialize,
00153 NULL,
00154 Realize,
00155 actionsList,
00156 XtNumber(actionsList),
00157 resources,
00158 XtNumber(resources),
00159 NULLQUARK,
00160 TRUE,
00161 TRUE,
00162 TRUE,
00163 FALSE,
00164 NULL,
00165 Resize,
00166 Redisplay,
00167 SetValues,
00168 SetValuesHook,
00169 XtInheritSetValuesAlmost,
00170 NULL,
00171 NULL,
00172 XtVersion,
00173 NULL,
00174 defaultTranslations,
00175 NULL,
00176 NULL,
00177 NULL
00178 },{
00179 GeometryManager,
00180 ChangeManaged,
00181 XtInheritInsertChild,
00182 XtInheritDeleteChild,
00183 NULL
00184 },{
00185 NULL
00186 },{
00187 NULL
00188 },{
00189 NULL
00190 }
00191 };
00192
00193 WidgetClass simpleMenuWidgetClass = (WidgetClass)&simpleMenuClassRec;
00194
00195 #define ForAllChildren(smw, childP) \
00196 for ( (childP) = (SmeObject *) (smw)->composite.children ; \
00197 (childP) < (SmeObject *) ( (smw)->composite.children + \
00198 (smw)->composite.num_children ) ; \
00199 (childP)++ )
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213 static void
00214 ClassInitialize()
00215 {
00216 XawInitializeWidgetSet();
00217 XtAddConverter( XtRString, XtRBackingStore, XmuCvtStringToBackingStore,
00218 (XtConvertArgList)NULL, (Cardinal)0 );
00219 XmuAddInitializer( AddPositionAction, NULL);
00220 }
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230 static void
00231 ClassPartInitialize(wc)
00232 WidgetClass wc;
00233 {
00234 SimpleMenuWidgetClass smwc = (SimpleMenuWidgetClass) wc;
00235
00236
00237
00238
00239
00240 extension_rec.next_extension = smwc->composite_class.extension;
00241 smwc->composite_class.extension = (XtPointer) &extension_rec;
00242 }
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253 static void
00254 Initialize(request, new, args, num_args)
00255 Widget request, new;
00256 ArgList args;
00257 Cardinal *num_args;
00258 {
00259 SimpleMenuWidget smw = (SimpleMenuWidget) new;
00260
00261 XmuCallInitializers(XtWidgetToApplicationContext(new));
00262
00263 if (smw->simple_menu.label_class == NULL)
00264 smw->simple_menu.label_class = smeBSBObjectClass;
00265
00266 smw->simple_menu.label = NULL;
00267 smw->simple_menu.entry_set = NULL;
00268 smw->simple_menu.recursive_set_values = FALSE;
00269
00270 if (smw->simple_menu.label_string != NULL)
00271 CreateLabel(new);
00272
00273 smw->simple_menu.menu_width = TRUE;
00274
00275 if (smw->core.width == 0) {
00276 smw->simple_menu.menu_width = FALSE;
00277 smw->core.width = GetMenuWidth(new, (Widget)NULL);
00278 }
00279
00280 smw->simple_menu.menu_height = TRUE;
00281
00282 if (smw->core.height == 0) {
00283 smw->simple_menu.menu_height = FALSE;
00284 smw->core.height = GetMenuHeight(new);
00285 }
00286
00287
00288
00289
00290
00291 XtAddCallback(new, XtNpopupCallback, ChangeCursorOnGrab, (XtPointer)NULL);
00292 }
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303 static void
00304 Redisplay(w, event, region)
00305 Widget w;
00306 XEvent * event;
00307 Region region;
00308 {
00309 SimpleMenuWidget smw = (SimpleMenuWidget) w;
00310 SmeObject * entry;
00311 SmeObjectClass class;
00312
00313 if (region == NULL)
00314 XClearWindow(XtDisplay(w), XtWindow(w));
00315
00316
00317
00318
00319
00320 ForAllChildren(smw, entry) {
00321 if (!XtIsManaged ( (Widget) *entry)) continue;
00322
00323 if (region != NULL)
00324 switch(XRectInRegion(region, (int) (*entry)->rectangle.x,
00325 (int) (*entry)->rectangle.y,
00326 (unsigned int) (*entry)->rectangle.width,
00327 (unsigned int) (*entry)->rectangle.height)) {
00328 case RectangleIn:
00329 case RectanglePart:
00330 break;
00331 default:
00332 continue;
00333 }
00334 class = (SmeObjectClass) (*entry)->object.widget_class;
00335
00336 if (class->rect_class.expose != NULL)
00337 (class->rect_class.expose)( (Widget) *entry, NULL, NULL);
00338 }
00339 }
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349 static void
00350 Realize(w, mask, attrs)
00351 Widget w;
00352 XtValueMask * mask;
00353 XSetWindowAttributes * attrs;
00354 {
00355 SimpleMenuWidget smw = (SimpleMenuWidget) w;
00356
00357 attrs->cursor = smw->simple_menu.cursor;
00358 *mask |= CWCursor;
00359 if ((smw->simple_menu.backing_store == Always) ||
00360 (smw->simple_menu.backing_store == NotUseful) ||
00361 (smw->simple_menu.backing_store == WhenMapped) ) {
00362 *mask |= CWBackingStore;
00363 attrs->backing_store = smw->simple_menu.backing_store;
00364 }
00365 else
00366 *mask &= ~CWBackingStore;
00367
00368 (*superclass->core_class.realize) (w, mask, attrs);
00369 }
00370
00371
00372
00373
00374
00375
00376
00377 static void
00378 Resize(w)
00379 Widget w;
00380 {
00381 SimpleMenuWidget smw = (SimpleMenuWidget) w;
00382 SmeObject * entry;
00383
00384 if ( !XtIsRealized(w) ) return;
00385
00386 ForAllChildren(smw, entry)
00387 if (XtIsManaged( (Widget) *entry))
00388 (*entry)->rectangle.width = smw->core.width;
00389
00390 Redisplay(w, (XEvent *) NULL, (Region) NULL);
00391 }
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402 static Boolean
00403 SetValues(current, request, new, args, num_args)
00404 Widget current, request, new;
00405 ArgList args;
00406 Cardinal *num_args;
00407 {
00408 SimpleMenuWidget smw_old = (SimpleMenuWidget) current;
00409 SimpleMenuWidget smw_new = (SimpleMenuWidget) new;
00410 Boolean ret_val = FALSE, layout = FALSE;
00411
00412 if (!XtIsRealized(current)) return(FALSE);
00413
00414 if (!smw_new->simple_menu.recursive_set_values) {
00415 if (smw_new->core.width != smw_old->core.width) {
00416 smw_new->simple_menu.menu_width = (smw_new->core.width != 0);
00417 layout = TRUE;
00418 }
00419 if (smw_new->core.height != smw_old->core.height) {
00420 smw_new->simple_menu.menu_height = (smw_new->core.height != 0);
00421 layout = TRUE;
00422 }
00423 }
00424
00425 if (smw_old->simple_menu.cursor != smw_new->simple_menu.cursor)
00426 XDefineCursor(XtDisplay(new),
00427 XtWindow(new), smw_new->simple_menu.cursor);
00428
00429 if (smw_old->simple_menu.label_string !=smw_new->simple_menu.label_string)
00430 if (smw_new->simple_menu.label_string == NULL)
00431 XtDestroyWidget((Widget) smw_old->simple_menu.label);
00432 else if (smw_old->simple_menu.label_string == NULL)
00433 CreateLabel(new);
00434 else {
00435 Arg arglist[1];
00436
00437 XtSetArg(arglist[0], XtNlabel, smw_new->simple_menu.label_string);
00438 XtSetValues((Widget) smw_new->simple_menu.label, arglist, ONE);
00439 }
00440
00441 if (smw_old->simple_menu.label_class != smw_new->simple_menu.label_class)
00442 XtAppWarning(XtWidgetToApplicationContext(new),
00443 "No Dynamic class change of the SimpleMenu Label.");
00444
00445 if ((smw_old->simple_menu.top_margin != smw_new->simple_menu.top_margin) ||
00446 (smw_old->simple_menu.bottom_margin !=
00447 smw_new->simple_menu.bottom_margin) ) {
00448 layout = TRUE;
00449 ret_val = TRUE;
00450 }
00451
00452 if (layout)
00453 Layout(new, (Dimension *)NULL, (Dimension *)NULL);
00454
00455 return(ret_val);
00456 }
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473 static Boolean
00474 SetValuesHook(w, arglist, num_args)
00475 Widget w;
00476 ArgList arglist;
00477 Cardinal *num_args;
00478 {
00479 Cardinal i;
00480 Dimension width, height;
00481
00482 width = w->core.width;
00483 height = w->core.height;
00484
00485 for ( i = 0 ; i < *num_args ; i++) {
00486 if ( streq(arglist[i].name, XtNwidth) )
00487 width = (Dimension) arglist[i].value;
00488 if ( streq(arglist[i].name, XtNheight) )
00489 height = (Dimension) arglist[i].value;
00490 }
00491
00492 if ((width != w->core.width) || (height != w->core.height))
00493 MakeSetValuesRequest(w, width, height);
00494 return(FALSE);
00495 }
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511 static XtGeometryResult
00512 GeometryManager(w, request, reply)
00513 Widget w;
00514 XtWidgetGeometry * request, * reply;
00515 {
00516 SimpleMenuWidget smw = (SimpleMenuWidget) XtParent(w);
00517 SmeObject entry = (SmeObject) w;
00518 XtGeometryMask mode = request->request_mode;
00519 XtGeometryResult answer;
00520 Dimension old_height, old_width;
00521
00522 if ( !(mode & CWWidth) && !(mode & CWHeight) )
00523 return(XtGeometryNo);
00524
00525 reply->width = request->width;
00526 reply->height = request->height;
00527
00528 old_width = entry->rectangle.width;
00529 old_height = entry->rectangle.height;
00530
00531 Layout(w, &(reply->width), &(reply->height) );
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542 if ( (reply->width == request->width) &&
00543 (reply->height == request->height) ) {
00544
00545 if ( mode & XtCWQueryOnly ) {
00546 entry->rectangle.width = old_width;
00547 entry->rectangle.height = old_height;
00548 }
00549 else {
00550 Layout(( Widget) smw, (Dimension *)NULL, (Dimension *)NULL);
00551 }
00552 answer = XtGeometryDone;
00553 }
00554 else {
00555 entry->rectangle.width = old_width;
00556 entry->rectangle.height = old_height;
00557
00558 if ( ((reply->width == request->width) && !(mode & CWHeight)) ||
00559 ((reply->height == request->height) && !(mode & CWWidth)) ||
00560 ((reply->width == request->width) &&
00561 (reply->height == request->height)) )
00562 answer = XtGeometryNo;
00563 else {
00564 answer = XtGeometryAlmost;
00565 reply->request_mode = 0;
00566 if (reply->width != request->width)
00567 reply->request_mode |= CWWidth;
00568 if (reply->height != request->height)
00569 reply->request_mode |= CWHeight;
00570 }
00571 }
00572 return(answer);
00573 }
00574
00575
00576
00577
00578
00579
00580
00581 static void
00582 ChangeManaged(w)
00583 Widget w;
00584 {
00585 Layout(w, (Dimension *)NULL, (Dimension *)NULL);
00586 }
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607 static void
00608 PositionMenuAction(w, event, params, num_params)
00609 Widget w;
00610 XEvent * event;
00611 String * params;
00612 Cardinal * num_params;
00613 {
00614 Widget menu;
00615 XPoint loc;
00616
00617 if (*num_params != 1) {
00618 char error_buf[BUFSIZ];
00619 (void) sprintf(error_buf, "%s %s",
00620 "Xaw - SimpleMenuWidget: position menu action expects only one",
00621 "parameter which is the name of the menu.");
00622 XtAppWarning(XtWidgetToApplicationContext(w), error_buf);
00623 return;
00624 }
00625
00626 if ( (menu = FindMenu(w, params[0])) == NULL) {
00627 char error_buf[BUFSIZ];
00628 (void) sprintf(error_buf, "%s '%s'",
00629 "Xaw - SimpleMenuWidget: could not find menu named: ", params[0]);
00630 XtAppWarning(XtWidgetToApplicationContext(w), error_buf);
00631 return;
00632 }
00633
00634 switch (event->type) {
00635 case ButtonPress:
00636 case ButtonRelease:
00637 loc.x = event->xbutton.x_root;
00638 loc.y = event->xbutton.y_root;
00639 PositionMenu(menu, &loc);
00640 break;
00641 case EnterNotify:
00642 case LeaveNotify:
00643 loc.x = event->xcrossing.x_root;
00644 loc.y = event->xcrossing.y_root;
00645 PositionMenu(menu, &loc);
00646 break;
00647 case MotionNotify:
00648 loc.x = event->xmotion.x_root;
00649 loc.y = event->xmotion.y_root;
00650 PositionMenu(menu, &loc);
00651 break;
00652 default:
00653 PositionMenu(menu, (XPoint *)NULL);
00654 break;
00655 }
00656 }
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673 static void
00674 Unhighlight(w, event, params, num_params)
00675 Widget w;
00676 XEvent * event;
00677 String * params;
00678 Cardinal * num_params;
00679 {
00680 SimpleMenuWidget smw = (SimpleMenuWidget) w;
00681 SmeObject entry = smw->simple_menu.entry_set;
00682 SmeObjectClass class;
00683
00684 if ( entry == NULL) return;
00685
00686 smw->simple_menu.entry_set = NULL;
00687 class = (SmeObjectClass) entry->object.widget_class;
00688 (class->sme_class.unhighlight) ( (Widget) entry);
00689 }
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700 static void
00701 Highlight(w, event, params, num_params)
00702 Widget w;
00703 XEvent * event;
00704 String * params;
00705 Cardinal * num_params;
00706 {
00707 SimpleMenuWidget smw = (SimpleMenuWidget) w;
00708 SmeObject entry;
00709 SmeObjectClass class;
00710
00711 if ( !XtIsSensitive(w) ) return;
00712
00713 entry = GetEventEntry(w, event);
00714
00715 if (entry == smw->simple_menu.entry_set) return;
00716
00717 Unhighlight(w, event, params, num_params);
00718
00719 if (entry == NULL) return;
00720
00721 if ( !XtIsSensitive( (Widget) entry)) {
00722 smw->simple_menu.entry_set = NULL;
00723 return;
00724 }
00725
00726 smw->simple_menu.entry_set = entry;
00727 class = (SmeObjectClass) entry->object.widget_class;
00728
00729 (class->sme_class.highlight) ( (Widget) entry);
00730 }
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741 static void
00742 Notify(w, event, params, num_params)
00743 Widget w;
00744 XEvent * event;
00745 String * params;
00746 Cardinal * num_params;
00747 {
00748 SimpleMenuWidget smw = (SimpleMenuWidget) w;
00749 SmeObject entry = smw->simple_menu.entry_set;
00750 SmeObjectClass class;
00751
00752 if ( (entry == NULL) || !XtIsSensitive((Widget) entry ) ) return;
00753
00754 class = (SmeObjectClass) entry->object.widget_class;
00755 (class->sme_class.notify)( (Widget) entry );
00756 }
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770 void
00771 #if NeedFunctionPrototypes
00772 XawSimpleMenuAddGlobalActions(XtAppContext app_con)
00773 #else
00774 XawSimpleMenuAddGlobalActions(app_con)
00775 XtAppContext app_con;
00776 #endif
00777 {
00778 XtInitializeWidgetClass(simpleMenuWidgetClass);
00779 XmuCallInitializers( app_con );
00780 }
00781
00782
00783
00784
00785
00786
00787
00788
00789 Widget
00790 #if NeedFunctionPrototypes
00791 XawSimpleMenuGetActiveEntry(Widget w)
00792 #else
00793 XawSimpleMenuGetActiveEntry(w)
00794 Widget w;
00795 #endif
00796 {
00797 SimpleMenuWidget smw = (SimpleMenuWidget) w;
00798
00799 return( (Widget) smw->simple_menu.entry_set);
00800 }
00801
00802
00803
00804
00805
00806
00807
00808 void
00809 #if NeedFunctionPrototypes
00810 XawSimpleMenuClearActiveEntry(Widget w)
00811 #else
00812 XawSimpleMenuClearActiveEntry(w)
00813 Widget w;
00814 #endif
00815 {
00816 SimpleMenuWidget smw = (SimpleMenuWidget) w;
00817
00818 smw->simple_menu.entry_set = NULL;
00819 }
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836 static void
00837 CreateLabel(w)
00838 Widget w;
00839 {
00840 SimpleMenuWidget smw = (SimpleMenuWidget) w;
00841 Widget * child, * next_child;
00842 int i;
00843 Arg args[2];
00844
00845 if ( (smw->simple_menu.label_string == NULL) ||
00846 (smw->simple_menu.label != NULL) ) {
00847 char error_buf[BUFSIZ];
00848
00849 (void) sprintf(error_buf, "Xaw Simple Menu Widget: %s or %s, %s",
00850 "label string is NULL", "label already exists",
00851 "no label is being created.");
00852 XtAppWarning(XtWidgetToApplicationContext(w), error_buf);
00853 return;
00854 }
00855
00856 XtSetArg(args[0], XtNlabel, smw->simple_menu.label_string);
00857 XtSetArg(args[1], XtNjustify, XtJustifyCenter);
00858 smw->simple_menu.label = (SmeObject)
00859 XtCreateManagedWidget("menuLabel",
00860 smw->simple_menu.label_class, w,
00861 args, TWO);
00862
00863 next_child = NULL;
00864 for (child = smw->composite.children + smw->composite.num_children,
00865 i = smw->composite.num_children ; i > 0 ; i--, child--) {
00866 if (next_child != NULL)
00867 *next_child = *child;
00868 next_child = child;
00869 }
00870 *child = (Widget) smw->simple_menu.label;
00871 }
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890 static void
00891 Layout(w, width_ret, height_ret)
00892 Widget w;
00893 Dimension *width_ret, *height_ret;
00894 {
00895 SmeObject current_entry, *entry;
00896 SimpleMenuWidget smw;
00897 Dimension width, height;
00898 Boolean do_layout = ((height_ret == NULL) || (width_ret == NULL));
00899 Boolean allow_change_size;
00900 height = 0;
00901
00902 if ( XtIsSubclass(w, simpleMenuWidgetClass) ) {
00903 smw = (SimpleMenuWidget) w;
00904 current_entry = NULL;
00905 }
00906 else {
00907 smw = (SimpleMenuWidget) XtParent(w);
00908 current_entry = (SmeObject) w;
00909 }
00910
00911 allow_change_size = (!XtIsRealized((Widget)smw) ||
00912 (smw->shell.allow_shell_resize));
00913
00914 if ( smw->simple_menu.menu_height )
00915 height = smw->core.height;
00916 else
00917 if (do_layout) {
00918 height = smw->simple_menu.top_margin;
00919 ForAllChildren(smw, entry) {
00920 if (!XtIsManaged( (Widget) *entry)) continue;
00921
00922 if ( (smw->simple_menu.row_height != 0) &&
00923 (*entry != smw->simple_menu.label) )
00924 (*entry)->rectangle.height = smw->simple_menu.row_height;
00925
00926 (*entry)->rectangle.y = height;
00927 (*entry)->rectangle.x = 0;
00928 height += (*entry)->rectangle.height;
00929 }
00930 height += smw->simple_menu.bottom_margin;
00931 }
00932 else {
00933 if ((smw->simple_menu.row_height != 0) &&
00934 (current_entry != smw->simple_menu.label) )
00935 height = smw->simple_menu.row_height;
00936 }
00937
00938 if (smw->simple_menu.menu_width)
00939 width = smw->core.width;
00940 else if ( allow_change_size )
00941 width = GetMenuWidth((Widget) smw, (Widget) current_entry);
00942 else
00943 width = smw->core.width;
00944
00945 if (do_layout) {
00946 ForAllChildren(smw, entry)
00947 if (XtIsManaged( (Widget) *entry))
00948 (*entry)->rectangle.width = width;
00949
00950 if (allow_change_size)
00951 MakeSetValuesRequest((Widget) smw, width, height);
00952 }
00953 else {
00954 *width_ret = width;
00955 if (height != 0)
00956 *height_ret = height;
00957 }
00958 }
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969 static void
00970 AddPositionAction(app_con, data)
00971 XtAppContext app_con;
00972 XPointer data;
00973 {
00974 static XtActionsRec pos_action[] = {
00975 { "XawPositionSimpleMenu", PositionMenuAction },
00976 };
00977
00978 XtAppAddActions(app_con, pos_action, XtNumber(pos_action));
00979 }
00980
00981
00982
00983
00984
00985
00986
00987
00988 static Widget
00989 FindMenu(widget, name)
00990 Widget widget;
00991 String name;
00992 {
00993 Widget w, menu;
00994
00995 for ( w = widget ; w != NULL ; w = XtParent(w) )
00996 if ( (menu = XtNameToWidget(w, name)) != NULL )
00997 return(menu);
00998 return(NULL);
00999 }
01000
01001
01002
01003
01004
01005
01006
01007
01008 static void
01009 PositionMenu(w, location)
01010 Widget w;
01011 XPoint * location;
01012 {
01013 SimpleMenuWidget smw = (SimpleMenuWidget) w;
01014 SmeObject entry;
01015 XPoint t_point;
01016
01017 if (location == NULL) {
01018 Window junk1, junk2;
01019 int root_x, root_y, junkX, junkY;
01020 unsigned int junkM;
01021
01022 location = &t_point;
01023 if (XQueryPointer(XtDisplay(w), XtWindow(w), &junk1, &junk2,
01024 &root_x, &root_y, &junkX, &junkY, &junkM) == FALSE) {
01025 char error_buf[BUFSIZ];
01026 (void) sprintf(error_buf, "%s %s", "Xaw Simple Menu Widget:",
01027 "Could not find location of mouse pointer");
01028 XtAppWarning(XtWidgetToApplicationContext(w), error_buf);
01029 return;
01030 }
01031 location->x = (short) root_x;
01032 location->y = (short) root_y;
01033 }
01034
01035
01036
01037
01038
01039 XtRealizeWidget(w);
01040
01041 location->x -= (Position) w->core.width/2;
01042
01043 if (smw->simple_menu.popup_entry == NULL)
01044 entry = smw->simple_menu.label;
01045 else
01046 entry = smw->simple_menu.popup_entry;
01047
01048 if (entry != NULL)
01049 location->y -= entry->rectangle.y + entry->rectangle.height/2;
01050
01051 MoveMenu(w, (Position) location->x, (Position) location->y);
01052 }
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062 static void
01063 MoveMenu(w, x, y)
01064 Widget w;
01065 Position x, y;
01066 {
01067 Arg arglist[2];
01068 Cardinal num_args = 0;
01069 SimpleMenuWidget smw = (SimpleMenuWidget) w;
01070
01071 if (smw->simple_menu.menu_on_screen) {
01072 int width = w->core.width + 2 * w->core.border_width;
01073 int height = w->core.height + 2 * w->core.border_width;
01074
01075 if (x >= 0) {
01076 int scr_width = WidthOfScreen(XtScreen(w));
01077 if (x + width > scr_width)
01078 x = scr_width - width;
01079 }
01080 if (x < 0)
01081 x = 0;
01082
01083 if (y >= 0) {
01084 int scr_height = HeightOfScreen(XtScreen(w));
01085 if (y + height > scr_height)
01086 y = scr_height - height;
01087 }
01088 if (y < 0)
01089 y = 0;
01090 }
01091
01092 XtSetArg(arglist[num_args], XtNx, x); num_args++;
01093 XtSetArg(arglist[num_args], XtNy, y); num_args++;
01094 XtSetValues(w, arglist, num_args);
01095 }
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106 static void
01107 ChangeCursorOnGrab(w, junk, garbage)
01108 Widget w;
01109 XtPointer junk, garbage;
01110 {
01111 SimpleMenuWidget smw = (SimpleMenuWidget) w;
01112
01113
01114
01115
01116
01117
01118
01119 XChangeActivePointerGrab(XtDisplay(w), ButtonPressMask|ButtonReleaseMask,
01120 smw->simple_menu.cursor,
01121 XtLastTimestampProcessed(XtDisplay(w)));
01122 }
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132 static void
01133 MakeSetValuesRequest(w, width, height)
01134 Widget w;
01135 Dimension width, height;
01136 {
01137 SimpleMenuWidget smw = (SimpleMenuWidget) w;
01138 Arg arglist[2];
01139 Cardinal num_args = (Cardinal) 0;
01140
01141 if ( !smw->simple_menu.recursive_set_values ) {
01142 if ( (smw->core.width != width) || (smw->core.height != height) ) {
01143 smw->simple_menu.recursive_set_values = TRUE;
01144 XtSetArg(arglist[num_args], XtNwidth, width); num_args++;
01145 XtSetArg(arglist[num_args], XtNheight, height); num_args++;
01146 XtSetValues(w, arglist, num_args);
01147 }
01148 else if (XtIsRealized( (Widget) smw))
01149 Redisplay((Widget) smw, (XEvent *) NULL, (Region) NULL);
01150 }
01151 smw->simple_menu.recursive_set_values = FALSE;
01152 }
01153
01154
01155
01156
01157
01158
01159
01160 static Dimension
01161 GetMenuWidth(w, w_ent)
01162 Widget w, w_ent;
01163 {
01164 SmeObject cur_entry = (SmeObject) w_ent;
01165 SimpleMenuWidget smw = (SimpleMenuWidget) w;
01166 Dimension width, widest = (Dimension) 0;
01167 SmeObject * entry;
01168
01169 if ( smw->simple_menu.menu_width )
01170 return(smw->core.width);
01171
01172 ForAllChildren(smw, entry) {
01173 XtWidgetGeometry preferred;
01174
01175 if (!XtIsManaged( (Widget) *entry)) continue;
01176
01177 if (*entry != cur_entry) {
01178 XtQueryGeometry((Widget) *entry, (XtWidgetGeometry *)NULL, &preferred);
01179
01180 if (preferred.request_mode & CWWidth)
01181 width = preferred.width;
01182 else
01183 width = (*entry)->rectangle.width;
01184 }
01185 else
01186 width = (*entry)->rectangle.width;
01187
01188 if ( width > widest )
01189 widest = width;
01190 }
01191
01192 return(widest);
01193 }
01194
01195
01196
01197
01198
01199
01200
01201 static Dimension
01202 GetMenuHeight(w)
01203 Widget w;
01204 {
01205 SimpleMenuWidget smw = (SimpleMenuWidget) w;
01206 SmeObject * entry;
01207 Dimension height;
01208
01209 if (smw->simple_menu.menu_height)
01210 return(smw->core.height);
01211
01212 height = smw->simple_menu.top_margin + smw->simple_menu.bottom_margin;
01213
01214 if (smw->simple_menu.row_height == 0) {
01215 ForAllChildren(smw, entry)
01216 if (XtIsManaged ((Widget) *entry))
01217 height += (*entry)->rectangle.height;
01218 } else
01219 height += smw->simple_menu.row_height * smw->composite.num_children;
01220
01221 return(height);
01222 }
01223
01224
01225
01226
01227
01228
01229
01230
01231 static SmeObject
01232 GetEventEntry(w, event)
01233 Widget w;
01234 XEvent * event;
01235 {
01236 Position x_loc = 0, y_loc = 0;
01237 SimpleMenuWidget smw = (SimpleMenuWidget) w;
01238 SmeObject * entry;
01239
01240 switch (event->type) {
01241 case MotionNotify:
01242 x_loc = event->xmotion.x;
01243 y_loc = event->xmotion.y;
01244 break;
01245 case EnterNotify:
01246 case LeaveNotify:
01247 x_loc = event->xcrossing.x;
01248 y_loc = event->xcrossing.y;
01249 break;
01250 case ButtonPress:
01251 case ButtonRelease:
01252 x_loc = event->xbutton.x;
01253 y_loc = event->xbutton.y;
01254 break;
01255 default:
01256 XtAppError(XtWidgetToApplicationContext(w),
01257 "Unknown event type in GetEventEntry().");
01258 break;
01259 }
01260
01261 if ( (x_loc < 0) || (x_loc >= (int)smw->core.width) || (y_loc < 0) ||
01262 (y_loc >= (int)smw->core.height) )
01263 return(NULL);
01264
01265 ForAllChildren(smw, entry) {
01266 if (!XtIsManaged ((Widget) *entry)) continue;
01267
01268 if ( ((*entry)->rectangle.y < y_loc) &&
01269 ((*entry)->rectangle.y + (int) (*entry)->rectangle.height > y_loc) )
01270 if ( *entry == smw->simple_menu.label )
01271 return(NULL);
01272 else
01273 return(*entry);
01274 }
01275
01276 return(NULL);
01277 }