DataMuseum.dkPresents historical artifacts from the history of: Rational R1000/400 Tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Rational R1000/400 Tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - downloadIndex: ┃ T r ┃
Length: 51171 (0xc7e3) Types: TextFile Names: »ratmenu.c«
└─⟦5f3412b64⟧ Bits:30000745 8mm tape, Rational 1000, ENVIRONMENT 12_6_5 TOOLS └─ ⟦91c658230⟧ »DATA« └─⟦5d656759a⟧ └─⟦34224b4fb⟧ └─ ⟦this⟧ »./ratmenu.c« └─⟦5f3412b64⟧ Bits:30000745 8mm tape, Rational 1000, ENVIRONMENT 12_6_5 TOOLS └─ ⟦91c658230⟧ »DATA« └─⟦5d656759a⟧ └─⟦50f09e4e4⟧ └─ ⟦this⟧ »./ratmenu.c« └─⟦5f3412b64⟧ Bits:30000745 8mm tape, Rational 1000, ENVIRONMENT 12_6_5 TOOLS └─ ⟦91c658230⟧ »DATA« └─⟦5d656759a⟧ └─⟦610eb0a19⟧ └─ ⟦this⟧ »./ratmenu.c« └─⟦5f3412b64⟧ Bits:30000745 8mm tape, Rational 1000, ENVIRONMENT 12_6_5 TOOLS └─ ⟦91c658230⟧ »DATA« └─⟦5d656759a⟧ └─⟦8fb0c967c⟧ └─⟦d10a02448⟧ Bits:30000409 8mm tape, Rational 1000, ENVIRONMENT, D_12_7_3 └─ ⟦fc9b38f02⟧ »DATA« └─⟦8e9e227a9⟧ └─⟦8fb0c967c⟧ └─ ⟦this⟧ »ratmenu.c« └─⟦5f3412b64⟧ Bits:30000745 8mm tape, Rational 1000, ENVIRONMENT 12_6_5 TOOLS └─ ⟦91c658230⟧ »DATA« └─⟦5d656759a⟧ └─⟦afaca67b5⟧ └─⟦d10a02448⟧ Bits:30000409 8mm tape, Rational 1000, ENVIRONMENT, D_12_7_3 └─ ⟦fc9b38f02⟧ »DATA« └─⟦8e9e227a9⟧ └─⟦afaca67b5⟧ └─ ⟦this⟧ »./ratmenu.c« └─⟦5f3412b64⟧ Bits:30000745 8mm tape, Rational 1000, ENVIRONMENT 12_6_5 TOOLS └─ ⟦91c658230⟧ »DATA« └─⟦5d656759a⟧ └─⟦d97085656⟧ └─ ⟦this⟧ »./ratmenu.c«
#include <stdio.h> #include <ctype.h> #include <setjmp.h> #include <X11/Xlib.h> #include <X11/StringDefs.h> #include <X11/IntrinsicP.h> #include "RMCommand.h" #include "RMForm.h" #include <X11/Shell.h> #include <X11/Xos.h> #include "ratmenu.h" #include "RMShellP.h" #include "RMLabelP.h" #include "RMSubP.h" #include <X11/cursorfont.h> #include <X11/Xatom.h> #define XK_MISCELLANY #define XK_LATIN1 #include <X11/keysymdef.h> #include "ptyx.h" #include "data.h" #include "menu.h" \f /****************************************************************************** * Package State ******************************************************************************/ #ifdef RIOS #undef strcpy #endif extern char *strcpy(); extern int default_menuBorder; extern int default_menuPad; static int defZero = 0; static String defNullString = NULL; static Boolean defTrue = TRUE; static Boolean defFalse = FALSE; #define MAXMENUDEPTH 4 static Cursor MainCursor; static int MenuDepth = -1; static Widget DaddyMenu[MAXMENUDEPTH]; static Widget ChildMenu[MAXMENUDEPTH]; static KeySym MenuPick [MAXMENUDEPTH]; static Boolean ActionsRegistered = FALSE; Widget RatMenu = NULL; RatMenuDefaultsType RatMenuDefaults; Window RatMenuTransientFor = 0; char RatMenuDontWarp[] = "DontWarp"; char RatMenuDontMove[] = "DontMove"; char *RatMenuDontMoveWarp[] = { RatMenuDontMove, RatMenuDontWarp }; #define offset(fld) XtOffset(RatMenuDefaultsType*,fld) XtResource RatMenuResourceList[] = { {"envMenuFile", "EnvMenuFile", XtRString, sizeof(char*), offset(env_menu_file), XtRString, (caddr_t)NULL}, {"itemBorder", "ItemBorder", XtRInt, sizeof(int), offset(item_border_width), XtRInt, (caddr_t)&defZero}, {"menuLabels", "MenuLabels", XtRBoolean, sizeof(Boolean), offset(want_menu_labels), XtRBoolean, (caddr_t)&defTrue}, {"menuSpace", "MenuSpace", XtRInt, sizeof(int), offset(item_pad), XtRInt, (caddr_t)&default_menuPad}, {"permanent", "Permanent", XtRBoolean, sizeof(Boolean), offset(permanent), XtRBoolean, (caddr_t)&defFalse}, {"subBorder", "SubBorder", XtRInt, sizeof(int), offset(sub_border_width), XtRInt, (caddr_t)&defZero}, {"subDistance", "SubDistance", XtRInt, sizeof(int), offset(sub_horiz_distance), XtRInt, (caddr_t)&default_menuPad}, {"submenuLabels", "SubmenuLabels", XtRBoolean, sizeof(Boolean), offset(want_submenu_labels), XtRBoolean, (caddr_t)&defTrue}, {"subSlide", "SubSlide", XtRBoolean, sizeof(Boolean), offset(slide_subs), XtRBoolean, (caddr_t)&defFalse}, {"warp", "Warp", XtRBoolean, sizeof(Boolean), offset(warp), XtRBoolean, (caddr_t)&defTrue}, }; int Size_RatMenuResourceList = XtNumber(RatMenuResourceList); #undef offset extern void AddRatItem(); extern void RationalMenuInit(); static void NotifyRatMenu(); extern void SubupRatMenu(); extern void SubdownRatMenu(); static PickRatMenuCallback(); extern void PopupRatMenu(); extern void PopdownRatMenu(); static void NoOp(); static void KeyRatMenu(); extern void PopdownRatMenuChain(); static void DropSubsRatMenu(); static void UnmappedRatMenu(); void spit(); #define SETARG( XtN, XtV ) XtSetArg( args[argi], XtN, XtV ); argi++ #define CALLBACK( XtN, XtV ) Callback[++cbi].callback = (XtCallbackProc)XtN; \ Callback[ cbi].closure =(caddr_t)XtV /*--When we pop up a menu we try to put it's x/y coordinates at this offset * back from the event's coordinates. */ #define XPOPUP 5 #define YPOPUP 5 \f void InitRatCursor() /****************************************************************************** * InitRatCursor - This started out simply making sure that the menu cursor * was properly defined before we created the Rational menu(s); now however we * make sure that we've retrieved the full set of resources specific to the * Rational menu(s). ******************************************************************************/ { static char DidThisOnce = FALSE; extern Menu Menu_Default; extern Cursor Menu_DefaultCursor; extern void InitMenu(); /*--If the menu cursor hasn't been given, make a default one. */ if (!DidThisOnce) { InitMenu( xterm_name ); } DidThisOnce = TRUE; if(!Menu_Default.menuCursor) { if(!Menu_DefaultCursor) { Menu_DefaultCursor = XCreateFontCursor(term->screen.display, XC_left_ptr); } Menu_Default.menuCursor = Menu_DefaultCursor; } /*--Get the Rational menu resources. */ /* Now done in main.c at startup. * * XtGetSubresources( (Widget)term, (caddr_t)&RatMenuDefaults, "menu", "Menu", * RatMenuResourceList, XtNumber(RatMenuResourceList), * NULL, 0 ); */ /*--Fill in stuff from the term. */ RatMenuDefaults.background = term->core.background_pixel; RatMenuDefaults.border_pixel = term->core.border_pixel; RatMenuDefaults.foreground = term->screen.foreground; RatMenuDefaults.font = Menu_Default.menuFontInfo; RatMenuDefaults.menu_border_width = Menu_Default.menuBorderWidth; RatMenuDefaults.menu_whitespace = Menu_Default.menuItemPad; } /* InitRatCursor */ \f Boolean RatMenuMapped( w ) Widget w; /****************************************************************************** * RatMenuMapped - Returns true if a shell exists and thinks it is mapped. ******************************************************************************/ { if (w == NULL) { return FALSE; } if (!XtIsSubclass( w, ratMenuShellWidgetClass )) { fprintf( stderr, "RatMenuMapped: widget not RatMenuShell [%s]\n", w->core.widget_class->core_class.class_name ); exit(1); } return ((RatMenuShellWidget)w)->ratmenu.mapped; } /* RatMenuMapped */ \f void RatMenuPermanent( move ) Boolean move; /****************************************************************************** * RatMenuPermanent - Control for permanent menus. Map or unmap the menu * as appropriate to the current state of the world. Our parameter tells us * whether or not a remap is allowed to move the menu. A creation always * moves the menu. ******************************************************************************/ { char *what[1]; Cardinal count; /*--Make sure the menu exists. If we have to create it then we are free to * move it. */ if (RatMenu == NULL) { RationalMenuInit( (Widget)term ); move = TRUE; /*--If menu already exists then change the override flag to correspond to the * permanency. Ie. We want window managers to be able (or not to be able) * to play with the placement of the window. */ } else { Arg args[5]; int argi = 0; SETARG( XtNoverrideRedirect, !RatMenuDefaults.permanent ); SETARG( XtNinput, !RatMenuDefaults.permanent ); XtSetValues( RatMenu, args, (Cardinal)argi ); if (RatMenuDefaults.permanent && XtIsRealized(RatMenu)) { XSetTransientForHint( XtDisplay(RatMenu), XtWindow(RatMenu), RatMenuTransientFor ); } } /*--Make sure that the menu is up or down as appropriate. If it is a permanent * menu then it must be/go up. Otherwise it must be/go down. */ if (RatMenuDefaults.permanent && term->misc.rational) { DropSubsRatMenu( (Widget)RatMenu, (XEvent*)NULL, (char**)NULL, (Cardinal*)NULL ); if (move || !XtIsRealized(RatMenu)) { what[0] = RatMenuDontWarp; count = 1; PopupRatMenu( RatMenu, (XEvent*)NULL, &what[0], &count ); } else { count = 2; PopupRatMenu( RatMenu, (XEvent*)NULL, RatMenuDontMoveWarp, &count ); } } else if (RatMenuMapped(RatMenu)) { count = 0; PopdownRatMenuChain( RatMenu, (XEvent*)NULL, (char**)NULL, &count ); } } /* RatMenuPermanent */ \f Widget StartAnyRatMenu( rmname, label, toplevel, cursor, menupick, cmdpick, submenu ) String rmname; /* resource name of the menu to create */ String label; /* label for the menu when visible to user */ Widget toplevel; /* the true top-level shell of application */ Cursor cursor; /* None or the cursor to use within the menu */ KeySym menupick; /* KeySym to use when picking submenu items */ KeySym cmdpick; /* KeySym to use when submenu picked itself */ Boolean submenu; /* TRUE if this is a sub-menu */ /****************************************************************************** * StartAnyRatMenu - Begin a new Rational Menu. Create a Popup shell * and set the menu label. Set up for adding items to the menu. ******************************************************************************/ { int argi; Arg args[20]; Widget TheMenu; static char shellactions[] = "<Unmap>: RatMenuUnmapped()"; static char actions[] = "<Btn2Up>: RatMenuPopdownChain()\n\ <Btn2Down>: noop()\n\ <Key>: RatMenuKey()\n\ <EnterWindow>:RatMenuDropSubs()\n"; /*--This is a new menu. Create his outermost DaddyMenu. */ if (++MenuDepth == 0) { MainCursor = cursor; } argi = 0; SETARG( XtNtitle, label ); SETARG( XtNcursor, cursor ); SETARG( XtNmenuDepth, MenuDepth ); SETARG( XtNsubMenu, submenu ); SETARG( XtNmenuPick, menupick ); SETARG( XtNcmdPick, cmdpick ); SETARG( XtNoverrideRedirect, submenu | !RatMenuDefaults.permanent ); SETARG( XtNinput, TRUE ); SETARG( XtNborderPixmap, XtGrayPixmap(XtScreen(toplevel)) ); SETARG( XtNborderWidth, RatMenuDefaults.menu_border_width ); SETARG( XtNbackground, RatMenuDefaults.background ); SETARG( XtNborderColor, RatMenuDefaults.border_pixel ); SETARG( XtNgeometry, NULL ); /* Under no circumstances let user set * the geometry value for menus! */ SETARG( XtNtranslations, XtParseTranslationTable( shellactions ) ); TheMenu = XtCreatePopupShell( rmname, ratMenuShellWidgetClass, toplevel, args, argi ); /*--Create the form that occupies the Shell. */ argi = 0; SETARG( XtNdefaultDistance, RatMenuDefaults.menu_whitespace ); SETARG( XtNbackground, RatMenuDefaults.background ); SETARG( XtNborderColor, RatMenuDefaults.border_pixel ); SETARG( XtNtranslations, XtParseTranslationTable( actions ) ); DaddyMenu[MenuDepth] = XtCreateManagedWidget( "Form", RMformWidgetClass, TheMenu, args, argi ); XtSetKeyboardFocus( TheMenu, DaddyMenu[MenuDepth] ); /*--Create the label that goes at the top of the menu; he is inverse video * of whatever video we are using; he may be reverse-reverse-vide. */ if (((!submenu && RatMenuDefaults.want_menu_labels) || ( submenu && RatMenuDefaults.want_submenu_labels)) && label != NULL && label[0] != '\000') { argi = 0; SETARG( XtNlabel, label ); SETARG( XtNcursor, None ); SETARG( XtNborderWidth, RatMenuDefaults.item_border_width ); SETARG( XtNbackground, term->screen.foreground ); SETARG( XtNborderColor, (RatMenuDefaults.border_pixel == RatMenuDefaults.background ? RatMenuDefaults.foreground : RatMenuDefaults.border_pixel ) ); SETARG( XtNforeground, RatMenuDefaults.background ); SETARG( XtNfont, RatMenuDefaults.font ); SETARG( XtNtranslations, XtParseTranslationTable( actions ) ); ChildMenu[MenuDepth] = XtCreateManagedWidget( "Label", ratMenuLabelWidgetClass, DaddyMenu[MenuDepth], args, argi ); } else { ChildMenu[MenuDepth] = NULL; } return TheMenu; } /* StartAnyRatMenu */ \f Widget StartRatMenu( rmname, label, toplevel, cursor ) String rmname; /* resource name of the menu to create */ String label; /* label for menu when visible to the user */ Widget toplevel; /* the true top-level shell of application */ Cursor cursor; /* None or the cursor to use within the menu */ /****************************************************************************** * StartRatMenu - Begin a new Rational Menu. Create the outermost Popup shell * and set the menu label. Set up for adding items to the menu. ******************************************************************************/ { /*--Check MenuDepth */ if (MenuDepth >= 0) { fprintf( stderr, "ratmenu: Menu already started?\n" ); exit(1); } /*--Set up action tables we will need. */ if (!ActionsRegistered) { XtActionsRec RatActions[20]; int rai; ActionsRegistered = TRUE; rai = 0; RatActions[rai].string = "RatMenuPopdown"; RatActions[rai].proc = (XtActionProc)PopdownRatMenu; rai++; RatActions[rai].string = "RatMenuPopup"; RatActions[rai].proc = (XtActionProc)PopupRatMenu; rai++; RatActions[rai].string = "RatMenuPopdownChain"; RatActions[rai].proc = (XtActionProc)PopdownRatMenuChain; rai++; RatActions[rai].string = "RatMenuUnmapped"; RatActions[rai].proc = (XtActionProc)UnmappedRatMenu; rai++; RatActions[rai].string = "noop"; RatActions[rai].proc = (XtActionProc)NoOp; rai++; RatActions[rai].string = "RatMenuNotify"; RatActions[rai].proc = (XtActionProc)NotifyRatMenu; rai++; RatActions[rai].string = "RatMenuDropSubs"; RatActions[rai].proc = (XtActionProc)DropSubsRatMenu; rai++; RatActions[rai].string = "RatMenuSubup"; RatActions[rai].proc = (XtActionProc)SubupRatMenu; rai++; RatActions[rai].string = "RatMenuSubdown"; RatActions[rai].proc = (XtActionProc)SubdownRatMenu; rai++; RatActions[rai].string = "RatMenuKey"; RatActions[rai].proc = (XtActionProc)KeyRatMenu; rai++; XtAddActions( &RatActions[0], rai ); } /*--Set up the menu. */ return StartAnyRatMenu( rmname, label, toplevel, cursor, (KeySym)0, (KeySym)0, FALSE); } /* StartRatMenu */ \f Widget StartRatSubMenu( itemname, menurmname, menulabel, menupick, cmdpick, cursor ) String itemname; /* name of the item to go in outer menu */ String menurmname; /* resource name of the menu to create */ String menulabel; /* label to go at top of the menu */ KeySym menupick; /* KeySym used when a sub-item is picked */ KeySym cmdpick; /* KeySym used when we are picked; or NoSymbol */ Cursor cursor; /* None or the cursor to use within the menu */ /****************************************************************************** * StartRatSubMenu - Begin a new Rational SubMenu. Create the Popup shell * and set the menu label. Set up for adding items to the menu. ******************************************************************************/ { Widget Daddy = DaddyMenu[MenuDepth]; Widget Child = ChildMenu[MenuDepth]; Widget SubMenu; int argi; Arg args[20]; Widget item; static char item_translat[] = "<EnterWindow>:highlight() RatMenuDropSubs()\n\ <LeaveWindow>:unhighlight()"; /*--Check MenuDepth */ if (MenuDepth < 0) { fprintf( stderr, "ratmenu: No menu started?\n" ); exit(1); } /*--If we are a command pickable submenu then create a RatItem; otherwise * just create a more or less normal label. */ if (cmdpick != NoSymbol) { AddRatItem( menurmname, itemname, cmdpick ); item = ChildMenu[MenuDepth]; /*--Set up the textual menu entry; it just has text and it has few actions * which completely replaces the standard set (not just overrides a few). */ } else { argi = 0; if (Child) { SETARG( XtNfromVert, Child ); SETARG( XtNvertDistance, RatMenuDefaults.item_pad ); } SETARG( XtNcursor, None ); SETARG( XtNlabel, itemname ); SETARG( XtNtranslations, XtParseTranslationTable( item_translat ) ); SETARG( XtNborderWidth, RatMenuDefaults.item_border_width ); SETARG( XtNbackground, RatMenuDefaults.background ); SETARG( XtNborderColor, RatMenuDefaults.border_pixel ); SETARG( XtNforeground, RatMenuDefaults.foreground ); SETARG( XtNfont, RatMenuDefaults.font ); SETARG( XtNjustify, XtJustifyLeft ); item = XtCreateManagedWidget( menurmname, RMcommandWidgetClass, Daddy, args, argi ); ChildMenu[MenuDepth] = item; } /*--Create the submenu. */ if (cursor == None) { SubMenu = StartAnyRatMenu( menurmname, menulabel, Daddy->core.parent, MainCursor, menupick, cmdpick, TRUE ); } else { SubMenu = StartAnyRatMenu( menurmname, menulabel, Daddy->core.parent, cursor, menupick, cmdpick, TRUE ); } /*--Set up the arrow menu entry; it pops up the SubMenu when it is entered. * Once again we completely replace the translation table for this widget. */ argi = 0; if (Child) { SETARG( XtNfromVert, Child ); SETARG( XtNvertDistance, RatMenuDefaults.item_pad ); } SETARG( XtNfromHoriz, item ); SETARG( XtNhorizDistance, RatMenuDefaults.sub_horiz_distance ); SETARG( XtNsubMenu, SubMenu ); SETARG( XtNcursor, None ); SETARG( XtNlabel, "=>" ); SETARG( XtNborderWidth, RatMenuDefaults.sub_border_width ); SETARG( XtNbackground, RatMenuDefaults.background ); SETARG( XtNborderColor, RatMenuDefaults.border_pixel ); SETARG( XtNforeground, RatMenuDefaults.foreground ); SETARG( XtNfont, RatMenuDefaults.font ); (void) XtCreateManagedWidget( itemname, ratMenuSubWidgetClass, Daddy, args, argi ); /*--Return the SubMenu to our caller. */ return SubMenu; } /* StartRatSubMenu */ \f void AddRatItem( rmname, label, menupick ) String rmname; /* resource name of the item to add */ String label; /* Label to put on the menu */ KeySym menupick; /* MenuPick character when item picked */ /****************************************************************************** * AddRatItem - Called to add a selectable item to a menu or a submenu. * The item will be labelled with Name and it will send a menupick character * when selected by any Btn up. ******************************************************************************/ { int argi; Arg args[20]; int cbi; XtCallbackRec Callback[2]; Widget item; static char PickTransl[] = "<EnterWindow>:highlight() RatMenuDropSubs()\n\ <Btn1Down>: noop()\n\ <Btn1Up>: RatMenuNotify()\n\ <Btn3Down>: noop()\n\ <Btn3Up>: RatMenuNotify()\n\ <Btn2Down>: noop()\n\ <Btn2Up>: RatMenuNotify() RatMenuPopdownChain()"; cbi = -1; CALLBACK( PickRatMenuCallback, menupick ); CALLBACK( NULL, NULL ); argi = 0; if (ChildMenu[MenuDepth]) { SETARG( XtNfromVert, ChildMenu[MenuDepth] ); SETARG( XtNvertDistance, RatMenuDefaults.item_pad ); } SETARG( XtNcursor, None ); SETARG( XtNcallback, &Callback[0] ); SETARG( XtNlabel, label ); SETARG( XtNborderWidth, RatMenuDefaults.item_border_width ); SETARG( XtNbackground, RatMenuDefaults.background ); SETARG( XtNborderColor, RatMenuDefaults.border_pixel ); SETARG( XtNforeground, RatMenuDefaults.foreground ); SETARG( XtNfont, RatMenuDefaults.font ); SETARG( XtNjustify, XtJustifyLeft ); item = XtCreateManagedWidget( rmname, RMcommandWidgetClass, DaddyMenu[MenuDepth], args, argi ); ChildMenu[MenuDepth] = item; XtOverrideTranslations( item, XtParseTranslationTable( PickTransl ) ); } /* AddRatItem */ \f void FinishAnyRatMenu() /****************************************************************************** * FinishRatMenu - Finish up a Rational Menu. Tidy up. ******************************************************************************/ { /*--We are now one less in MenuDepth. */ MenuDepth--; } /* FinishAnyRatMenu */ \f void FinishRatMenu() /****************************************************************************** * FinishRatMenu - Finish up the outermost Rational Menu. Tidy up. ******************************************************************************/ { /*--Check MenuDepth */ if (MenuDepth != 0) { fprintf( stderr, "ratmenu: MenuDepth != 0?\n" ); exit(1); } for (MenuDepth = MAXMENUDEPTH; MenuDepth > 0; ) { DaddyMenu[--MenuDepth] = NULL; } /*--Finish up the menu. */ FinishAnyRatMenu(); } /* FinishRatMenu */ \f void FinishRatSubMenu() /****************************************************************************** * FinishRatSubMenu - Finish up any Rational SubMenu. Tidy up. ******************************************************************************/ { /*--Check MenuDepth */ if (MenuDepth <= 0) { fprintf( stderr, "ratmenu: MenuDepth <= 0?\n" ); exit(1); } /*--Finish up the menu. */ FinishAnyRatMenu(); } /* FinishRatSubMenu */ \f void PopupRatMenu( w, event, params, num_params ) Widget w; XEvent *event; String *params; Cardinal *num_params; /****************************************************************************** * PopupRatMenu - Called to popup any RatMenuShell. * Allowed params: * "DontMove" - don't move the menu from whereever it is * "DontWarp" - don't warp pointer to the menu * Menus now have permanence. * - event != NULL - we are doing a normal button loaded popup; however, if * a main menu is mapped then don't move it, just raise it up. * - event == NULL - we are forcing the menu to be mapped; check params for * RatMenuDontWarp/Move, they tell us to move/not-move the menu * and to warp/not-warp the pointer to it afterwards. ******************************************************************************/ { RatMenuShellWidget rw = (RatMenuShellWidget)w; Boolean just_realized; Position x,y; Dimension wid,hei; Position dx,dy; Position x_root, y_root; Boolean warp = RatMenuDefaults.warp; Boolean move = TRUE; Boolean permanent = FALSE; int i; /*--Are we really what we think we are? */ if (!XtIsSubclass( w, ratMenuShellWidgetClass )) { fprintf( stderr, "PopupRatMenu: widget not RatMenuShell [%s]\n", XtClass(w)->core_class.class_name ); exit(1); } /*--Make sure that we are realized and have a window and such. */ if (!XtIsRealized(w)) { XtRealizeWidget( w ); just_realized = TRUE; if (!rw->ratmenu.submenu) { (void)XGetTransientForHint( XtDisplay(rw), XtWindow(rw), &RatMenuTransientFor ); if (RatMenuDefaults.permanent) { XDeleteProperty( XtDisplay(rw), XtWindow(rw), XA_WM_TRANSIENT_FOR ); } } } else { just_realized = FALSE; } /*--Check our params. Don't warp if told not to. Don't move if told not to * or if we are mapped and a main menu. */ if (params != NULL) { for (i = (int)*num_params-1; i >= 0; i--) { if (strcmp( params[i], RatMenuDontMove ) == 0) { move = FALSE; } else if (strcmp( params[i], RatMenuDontWarp ) == 0) { warp = FALSE; } } } if (!rw->ratmenu.submenu && RatMenuDefaults.permanent) { permanent = TRUE; } if (!rw->ratmenu.submenu && rw->ratmenu.mapped) { move = FALSE; } /*--Figure the x/y coords for popup menu. We don't want the cursor to move * if it doesn't have to but we also don't want the menu to be half on/off * the screen. Try to place the menu so that the cursor is "just" inside * the upper left corner. */ if (permanent) { #ifndef XTTRANSLATECOORDS_FIXED /* XtTranslateCoords has bugs when the user uses uwm to move * menus; use the XLib function. */ int tmpx,tmpy; Window tmpchild; /*--Pop him up at the right side of the VT100 widget. */ XTranslateCoordinates( XtDisplay(term), XtWindow(XtParent(term)), RootWindowOfScreen(XtScreen(term)), 0, 0, &tmpx, &tmpy, &tmpchild ); /*--The term has no border width but the shell surrounding the term * may well have non-zero border width; adjust for that. */ x_root = tmpx + term->core.parent->core.width + term->core.parent->core.border_width; y_root = tmpy - term->core.parent->core.border_width; x_root += XPOPUP; y_root += YPOPUP; #else /*--Pop him up at the right side of the VT100 widget. */ XtTranslateCoords( (Widget)term, (Position)0, (Position)0, &x_root, &y_root ); /*--The term has no border width but the shell surrounding the term * may well have non-zero border width; adjust for that. */ x_root += term->core.parent->core.width + term->core.parent->core.border_width; y_root += -term->core.parent->core.border_width; x_root += XPOPUP; y_root += YPOPUP; #endif } else { switch (event->type) { case ButtonPress : case ButtonRelease : x_root = event->xbutton.x_root; y_root = event->xbutton.y_root; break; case EnterNotify : case LeaveNotify : { int tmpx,tmpy; Window tmpchild; Window win; Widget sm; win = event->xcrossing.window; sm = XtWindowToWidget( XtDisplay(term), win ); /* XtTranslateCoords has bugs when the user uses uwm to move * menus; use the XLib function. */ XTranslateCoordinates( XtDisplay(term), win, RootWindowOfScreen(XtScreen(term)), (int) -sm->core.border_width, (int) -sm->core.border_width, &tmpx, &tmpy, &tmpchild ); x_root = tmpx + XPOPUP; y_root = tmpy + YPOPUP; if (!rw->ratmenu.submenu) { move = TRUE; } } break; default: fprintf( stderr, "PopupRatMenu: event not Button or Enter/Leave?\n" ); exit(1); } } x = x_root; dx = 0; if (x > XPOPUP) { x -= XPOPUP; dx = XPOPUP; } y = y_root; dy = 0; if (y > YPOPUP) { y -= YPOPUP; dy = YPOPUP; } /*--Don't let popup fall off screen */ wid = rw->core.width + (rw->core.border_width << 1); hei = rw->core.height + (rw->core.border_width << 1); if (x+wid > XtScreen(rw)->width) { x = XtScreen(rw)->width - wid; } if (y+hei > XtScreen(rw)->height) { y = XtScreen(rw)->height - hei; } /*--Get the menu positioned correctly. */ if (just_realized) { XSizeHints hints; if (XGetNormalHints( XtDisplay(w), XtWindow(w), &hints )) { hints.flags |= USPosition; } else { hints.flags = USPosition; } hints.x = x; hints.y = y; XSetNormalHints( XtDisplay(w), XtWindow(w), &hints ); } if (move) { XtMoveWidget( rw, x, y ); } /*--Pop the menu and record the fact. */ XtPopup( rw, XtGrabNone ); { XWindowAttributes wa; do { XGetWindowAttributes( XtDisplay(rw), XtWindow(rw), &wa ); } while (wa.map_state == IsUnmapped); } XUngrabPointer( XtDisplay(rw), CurrentTime ); rw->ratmenu.mapped = TRUE; /* In our opinion; he is mapped. */ rw->ratmenu.permanent = permanent; /*--Set up the MenuDepth and the DaddyMenu entry so that we know who's up * and thus we know what to transmit when the menu pick is done. */ if (!rw->ratmenu.submenu) { for (wid = MAXMENUDEPTH-1; wid > 0; wid--) { DaddyMenu[wid] = NULL; } } MenuDepth = rw->ratmenu.menu_depth; DaddyMenu[MenuDepth] = w; MenuPick[MenuDepth] = rw->ratmenu.menu_pick; /*--Move pointer to be at start of menu. */ x += dx; y += dy; if (warp) { XWarpPointer( XtDisplay(rw), None, DefaultRootWindow(XtDisplay(rw)), 0, 0, 0, 0, x, y ); } } /* PopupRatMenu */ \f /*ARGSUSED*/ void PopdownRatMenu( w, event, params, num_params ) Widget w; XEvent *event; String *params; Cardinal *num_params; /****************************************************************************** * PopdownRatMenu - Called to popdown any RatMenuShell. ******************************************************************************/ { RatMenuShellWidget rw = (RatMenuShellWidget)w; /*--Are we really what we think we are? */ if (!XtIsSubclass( w, ratMenuShellWidgetClass )) { fprintf( stderr, "PopdownRatMenu: widget not RatMenuShell [%s]\n", XtClass(w)->core_class.class_name ); exit(1); } /*--Popdown the menu. */ if (rw->ratmenu.submenu || /* sumenus always go down */ !rw->ratmenu.permanent || /* we weren't permanent anyway */ !RatMenuDefaults.permanent || /* permanent mode is off now */ !term->misc.rational) { /* rational mode is off now */ XtPopdown( w ); DaddyMenu[rw->ratmenu.menu_depth] = NULL; rw->ratmenu.mapped = FALSE; rw->ratmenu.permanent = FALSE; } } /* PopdownRatMenu */ \f Boolean FoundALeave; Boolean LookingForLeaves( dpy, event, window ) Display *dpy; XEvent *event; char *window; /****************************************************************************** * Search the entire event queue for a Leave that leaves the window in question. * Never actually remove anything; we don't want to change the order of events * we just want to know "Am I about to Leave?". ******************************************************************************/ { if (FoundALeave) { /* optimize a speed-up */ } else if (event->xany.type == LeaveNotify && event->xcrossing.window == *(Window*)window) { /*--The answer is yes. */ FoundALeave = TRUE; } return FALSE; } /* LookingForLeaves */ \f Boolean SimultaneousLeave( window ) Window window; /****************************************************************************** * Try to reduce submenu flicker when the user drags the mouse quickly over * a bunch of RatMenuSub's (ie. drags faster than we can respond; too bad * there isn't a way to do a passive grab on the pointer on EnterNotify). * Sync with the server. If there is now a Leave that corresponds to our * Enter (same window) then do nothing. ******************************************************************************/ { XEvent ev; XSync( XtDisplay(term), FALSE ); FoundALeave = FALSE; (void)XCheckIfEvent( XtDisplay(term), &ev, LookingForLeaves, (char*)&window ); return FoundALeave; } /* SimultaneousLeave */ \f /*ARGSUSED*/ void SubupRatMenu( w, event, params, num_params ) Widget w; XEvent *event; String *params; Cardinal *num_params; /****************************************************************************** * SubupRatMenu - Called by the translation manager to pop up a submenu. ******************************************************************************/ { register Widget SubMenu; /*--Are we really what we think we are? */ if (!XtIsSubclass( w, ratMenuSubWidgetClass )) { fprintf( stderr, "SubupRatMenu: widget not RatMenuSub [%s]\n", XtClass(w)->core_class.class_name ); exit(1); } /*--For all parents up to the main menu; do they all think that they are * mapped? (The server may think they are mapped (and thus give them an * enter event) even though we think they are unmapped.) */ SubMenu = w; while ((SubMenu = XtParent(SubMenu)) != NULL) { if (XtIsSubclass( SubMenu, ratMenuShellWidgetClass )) { if (!((RatMenuShellWidget)SubMenu)->ratmenu.mapped) { return; } if (!((RatMenuShellWidget)SubMenu)->ratmenu.submenu) { break; } } } /*--Ignore Enters where we are just somebody's ancestor getting a Virtual * entry. */ if (event && event->xany.type == EnterNotify) { if (event->xcrossing.detail == NotifyVirtual || event->xcrossing.detail == NotifyNonlinearVirtual) { return; } /*--If we are an Enter event then see if there is already a Leave event * around. The Toolkit doesn't compress Enter/Leave pairs unless they * are exactly adjacent in the queue. Not much chance of that when either * a) there are multiple ancestors/inferiors getting Virtual/Nonlinear * enter/leaves along with us or b) when pointer motion is also being * reported. */ if (SimultaneousLeave( event->xcrossing.window )) { return; } } /*--Redo the coordinates as we enter menu arrows. */ if (event->type == EnterNotify || event->type == LeaveNotify) { Position x,y; XtTranslateCoords( w, XPOPUP-w->core.border_width, YPOPUP-w->core.border_width, &x, &y ); ((XCrossingEvent*)event)->x_root = x; ((XCrossingEvent*)event)->y_root = y; } /*--Get the SubMenu and drop anything that is at or below its level. */ SubMenu = ((RatMenuSubWidget)w)->ratmenusub.submenu; DropSubsRatMenu( SubMenu, (XEvent*)NULL, (char**)NULL, (Cardinal*)NULL ); /*--Pop up the sub menu. */ if (!((RatMenuShellWidget)SubMenu)->ratmenu.mapped) { PopupRatMenu( SubMenu, event, params, num_params ); } } /* SubupRatMenu */ \f #ifdef RIOS /*ARGSUSED*/ static void AixBugFix( w ) Widget w; /****************************************************************************** * AixBugFix - Called when a submenu (or a main menu) is <Unmap>ed. We go * through all managed children and we do an Unhighlight on them if they are * an RMCommand type of object. This fixes a bug in the AIX X server where that * server forgets to send <Leave> events to subwindows of a window that gets * unmapped. ******************************************************************************/ { WidgetList children; Cardinal num_children; Cardinal i; if (!XtIsComposite(w)) { return; } children = ((CompositeWidget)w)->composite.children; num_children = ((CompositeWidget)w)->composite.num_children; for (i = 0; i < num_children; ++i) { if (XtIsSubclass( children[i], RMformWidgetClass )) { AixBugFix( children[i] ); } else if (XtIsSubclass( children[i], RMcommandWidgetClass )) { extern void AixBugUnhighlight(); AixBugUnhighlight( children[i] ); } } } /* AixBugFix */ #endif /* RIOS */ \f /*ARGSUSED*/ void SubdownRatMenu( w, event, params, num_params ) Widget w; XEvent *event; String *params; Cardinal *num_params; /****************************************************************************** * SubdownRatMenu - Called by the translation manager to pop down a submenu. ******************************************************************************/ { PopdownRatMenu( ((RatMenuSubWidget)w)->ratmenusub.submenu, event, params, num_params ); } /* SubdownRatMenu */ \f /*ARGSUSED*/ static void DropSubsRatMenu( w, event, params, num_params ) Widget w; XEvent *event; String *params; Cardinal *num_params; /****************************************************************************** * DropSubsRatMenu - Called when we enter a main menu. Remove any mapped * submenus. ******************************************************************************/ { XEvent ev; int i; int menu_depth; /*--Are we really what we think we are? */ if (!XtIsSubclass( w, ratMenuShellWidgetClass )) { Widget w2 = XtParent(w); while (w2 != NULL && !XtIsSubclass( w2, ratMenuShellWidgetClass )) { w2 = XtParent(w2); } if (w2 == NULL) { fprintf( stderr, "DropSubsRatMenu: widget not RatMenuShell [%s]\n", XtClass(w)->core_class.class_name ); exit(1); } w = w2; } /*--Drop any submenus that are at or below our level and which aren't us. */ menu_depth = ((RatMenuShellWidget)w)->ratmenu.menu_depth; MenuDepth = menu_depth; for ( i = MAXMENUDEPTH-1; i > menu_depth; i--) { if (DaddyMenu[i] != NULL) { PopdownRatMenu( DaddyMenu[i], event, params, num_params ); } } if (DaddyMenu[menu_depth] != NULL && DaddyMenu[menu_depth] != w) { PopdownRatMenu( DaddyMenu[menu_depth], event, params, num_params ); MenuDepth--; } } /* DropSubsRatMenu */ \f /*ARGSUSED*/ void PopdownRatMenuChain( w, event, params, num_params ) Widget w; XEvent *event; String *params; Cardinal *num_params; /****************************************************************************** * PopdownRatMenuChain - Called to popdown any RatMenuShell and all of its * parents. ******************************************************************************/ { int menu_depth; /*--If we are permanent and if the event is a button release then igore it. */ if (RatMenuDefaults.permanent && term->misc.rational && (event == NULL || event->xany.type == ButtonRelease)) { return; } /*--Recursively Popdown every shell until we get to a non-submenu. */ for (menu_depth = 0; menu_depth < MAXMENUDEPTH; menu_depth++){ if (DaddyMenu[menu_depth] != NULL) { PopdownRatMenu( DaddyMenu[menu_depth], event, params, num_params ); } } } /* PopdownRatMenuChain */ \f /* ARGSUSED */ static void NotifyRatMenu( w, event, params, num_params ) Widget w; XEvent *event; String *params; /* unused */ Cardinal *num_params; /* unused */ { if (event->type == EnterNotify || ((event->type == ButtonPress || event->type == ButtonRelease) && ((XButtonEvent*)event)->button == Button3)) { XtCallCallbacks( w, XtNcallback, (caddr_t)TRUE ); } else { XtCallCallbacks( w, XtNcallback, (caddr_t) FALSE ); } if (event->xany.type == ButtonPress) { XAllowEvents( XtDisplay(w), SyncPointer, event->xbutton.time ); } else { XAllowEvents( XtDisplay(w), AsyncPointer, event->xbutton.time ); } } /* NotifyRatMenu */ \f /* ARGSUSED */ static void UnmappedRatMenu( w, event, params, num_params ) Widget w; XEvent *event; String *params; /* unused */ Cardinal *num_params; /* unused */ /****************************************************************************** * If we get an UNMAP notificiation then either the menu was in its popup mode * (!permanent) or else the user must have had his window mananager unmap the * Rational Menu (permanent). In the latter case we will reset our permanent * flag. ******************************************************************************/ { #ifdef RIOS AixBugFix( w ); #endif if (w != RatMenu || !RatMenuDefaults.permanent) { return; } RatMenuDefaults.permanent = FALSE; RatMenuPermanent( FALSE ); } /* UnmappedRatMenu */ \f /*ARGSUSED*/ static void KeyRatMenu( w, event, params, num_params ) Widget w; XEvent *event; String *params; Cardinal *num_params; /****************************************************************************** * Send keys back to RXI when they are struck over a menu. ******************************************************************************/ { extern void HandleKeyPressed(); HandleKeyPressed( w, event, params, num_params ); XAllowEvents( XtDisplay(w), AsyncKeyboard, event->xkey.time ); } /* KeyRatMenu */ \f /*ARGSUSED*/ static void NoOp( w, event, params, num_params ) Widget w; XEvent *event; String *params; Cardinal *num_params; /****************************************************************************** * No-Operation for Translation lists. ******************************************************************************/ { /* translation manager has a bug whereby you can't override some action with * an empty action so we must have a noop action to help us out. */ if (params != NULL && *num_params > 0) { fprintf( stderr, "NoOp: [%s]\n", params[0] ); } if (event->xany.type == ButtonPress) { XAllowEvents( XtDisplay(w), SyncPointer, event->xbutton.time ); } } /* NoOp */ \f /*ARGSUSED*/ static PickRatMenuCallback( w, client_data, call_data ) Widget w; char *client_data; caddr_t call_data; /****************************************************************************** * PickRatMenuCallback - Called when Button2 goes up over a menu item or when * Button1 goes down over a menu item. Transmit the menu pick to the pty. ******************************************************************************/ { char buf[MAXMENUDEPTH*4+16]; register char *bp = &buf[0]; register KeySym ks; register int i; /*--Stuff the current menu_pick into the MenuPick list and then transmit. */ MenuDepth++; MenuPick[MenuDepth] = (KeySym)client_data; /*--See if we are Button3; we do a Prompt_For in that case */ if (call_data) { /* Button3 - Do MenuPick MenuPick */ *bp++ = MOUSE_PREFIX; *bp++ = MENU_PICK; *bp++ = MOUSE_PREFIX; *bp++ = MENU_PICK; } /*--Check the last MenuPick key. See if it is a special key. */ switch (MenuPick[MenuDepth]) { case MENU_JOB_KILL : case MENU_JOB_DISABLE : case MENU_DEBUG_STOP : ks = MenuPick[MenuDepth]; DoRChar( bp, ks ); break; /*--Normal picks come here. */ default : *bp++ = (char)MOUSE_PREFIX; /* Any Button - Do MenuPick <btns> */ *bp++ = (char)MENU_PICK; for (i = 1; i <= MenuDepth; i++) { ks = MenuPick[i]; DoRChar( bp, ks ); } break; } MenuDepth--; (void)v_write( term->screen.respond, buf, bp-buf ); } /* PickRatMenuCallback */ \f /* print out the name of a widget; NOTE: no \n printed so printout is not * flushed until our caller does one. */ void spit(w) Widget w; { if (w == NULL) return; spit( w->core.parent ); fprintf( stderr, ".%s", w->core.name ); } \f void RatMenuUserItems( user ) SubMenuRes *user; /****************************************************************************** * Starting with these user items and submenus; and they might be empty; add * item0..item9 to the current (sub)menu. Then for each menu0..menu9 add a new * submenu and recurse on that submenu.ratmenu.user as the new user. This * instantiates the user menu items. ******************************************************************************/ { char *buf; int i; RatMenuShellWidget SubMenu; char SubMenuName[6]; KeySym ks; /*--Loop over all items and sub-menus for this widget. We install the items * and the sub-menus in order 0..9. */ strcpy( SubMenuName, "menuN" ); for (i = 0; i < XtNumber(user->item); i++) { /*--Check each of the itemN's and see if it gets added. We add this one if * it exists and if the corresponding menuN entry is empty. */ if (user->menu[i] == NULL || user->menu[i][0] == '\000') { /* no menu entry */ if (user->item[i] != NULL && /* enter an item */ user->item[i][0] != '\000') { buf = (char*)XtMalloc( strlen(user->item[i] ) + 2 ); buf[0] = '*'; /* All user items are pickable; mark with * */ strcpy( &buf[1], user->item[i] ); AddRatItem( buf, buf, (KeySym)(XK_0+i) ); } /*--We have a menuN entry. See if it is itself an item or whether it is just * a sub-menu. */ } else { SubMenuName[4] = '0' + i; /*--Selectable sub-menus have names that start with '*' and non-selectable * names start with ' '. */ if (user->item[i] != NULL && user->item[i][0] != '\000') { buf = (char*)XtMalloc( strlen(user->item[i] ) + 2 ); buf[0] = '*'; strcpy( &buf[1], user->item[i] ); ks = XStringToKeysym(user->menu[i]); } else { buf = (char*)XtMalloc( strlen(user->menu[i] ) + 2 ); buf[0] = ' '; strcpy( &buf[1], user->menu[i] ); ks = NoSymbol; } /*--Create the sub-menu and all of it's sub-entries. */ SubMenu = (RatMenuShellWidget) StartRatSubMenu( buf, SubMenuName, buf, (KeySym)(XK_0+i), ks, None ); RatMenuUserItems( &SubMenu->ratmenu.user ); FinishRatSubMenu(); } } } /* RatMenuUserItems */ \f KeySym OurStrToKeysym( str ) char *str; /****************************************************************************** * Convert from a string, eg. "XK_A", to a KeySym value. ******************************************************************************/ { if (strncmp( str, "XK_", 3 ) == 0) { str += 3; } else if (strncmp( str, "MENU_", 5 ) == 0) { if (strcmp( str, "MENU_JOB_KILL" ) == 0) return MENU_JOB_KILL; if (strcmp( str, "MENU_JOB_DISABLE" ) == 0) return MENU_JOB_DISABLE; if (strcmp( str, "MENU_DEBUG_STOP" ) == 0) return MENU_DEBUG_STOP; if (strcmp( str, "MENU_RETURN" ) == 0) return MENU_RETURN; return NoSymbol; } return XStringToKeysym( str ); } /* OurStrToKeysym */ \f typedef struct _Define_Name { struct _Define_Name *Next; Boolean On; char Name[1]; } Define_Name_Rec, *Define_Name; #define Define_Name_NULL ((Define_Name)0) #define new_Define_Name(Name_Length) \ ((Define_Name)XtMalloc( (Cardinal)(sizeof(Define_Name_Rec) + Name_Length) )) \f void RationalMenuInit( toplevel ) Widget toplevel; /****************************************************************************** * Called when the user has requested the Rational Environment menu for the * first time. We read the descriptor file, build the menu structure, and * return to our caller who will do the actual window mapping and such. ******************************************************************************/ { Define_Name Defines = Define_Name_NULL; FILE *file; int menu_depth = 0; char buff[128]; char name[128]; char pick1[128]; char pick2[128]; int val; int cnt; int eol; char *ptr; int On_Depth = 0; int Off_Depth = 0; /*--Locate and open the RXI_Env_Menu file. If we can't find it or can't * open it then create an "empty" menu containing only user menu items. */ InitRatCursor(); if (RatMenuDefaults.env_menu_file == NULL) { static char Error_Null[] = "No RXI_Env_Menu file specified."; fprintf( stderr, "No Rational Environment menu filename resource.\n"); ptr = Error_Null; goto Make_Fake_Menu; } file = fopen( RatMenuDefaults.env_menu_file, "r" ); if (file == (FILE*)NULL) { static char Error_Item[] = "Could not find RXI_Env_Menu?"; /*--Open failed. Tell the user and create an empty menu. */ fprintf( stderr, "Could not open the RXI_Env_Menu file: %s\n", RatMenuDefaults.env_menu_file ); fprintf( stderr, "No Rational Environment menus will be available.\n"); perror( "fopen error was" ); ptr = Error_Item; goto Make_Fake_Menu; } /*--Loop reading from the file until we hit EOF or until we decide to give * up for some reason. */ while (fgets( buff, sizeof(buff), file ) != NULL && buff[0] != '\000') { /*--Skip any leading whitespace on the line (so we can tell the difference * between empty lines and lines that have uninterpretable garbage. * Lines beginning with / or * are comment lines. */ ptr = &buff[0]; while (*ptr != '\000' && *ptr <= ' ') { ++ptr; } if (*ptr == '\000' || *ptr == '*' || *ptr == '/') { continue; } /*--Watch out for #if FOO lines. */ if (*ptr == '#' || Off_Depth > 0) { cnt = sscanf( ptr, "#if %s", name ); if (cnt == 1) { Define_Name N; if (Off_Depth > 0) { ++Off_Depth; continue; } for (N = Defines; N != Define_Name_NULL; N = N->Next) { if (strcmp( &N->Name[0], &name[0] ) == 0) { break; } } if (N == Define_Name_NULL) { fprintf( stderr, "Don't recognize #if %s\n", name ); goto Bad_Line; } if (N->On) { ++On_Depth; continue; } ++Off_Depth; continue; } /*--Watch out for #endif lines. */ cnt = sscanf( ptr, "#endi%[f]", name ); if (cnt == 1) { if (Off_Depth) { --Off_Depth; continue; } if (On_Depth) { --On_Depth; continue; } fprintf( stderr, "Found #endif with no matching #if?\n" ); goto Bad_Line; } /*--If we are in a turned-off #if then don't check any further. */ if (Off_Depth > 0) { continue; } /*--Watch out for #define lines. */ cnt = sscanf( ptr, "#define %s %d", &name[0], &val ); if (cnt == 2) { Define_Name N; N = new_Define_Name( strlen(name) ); strcpy( &N->Name[0], &name[0] ); N->On = val != 0; N->Next = Defines; Defines = N; continue; } } /*--Watch for the line that begins the whole menu. */ if (*ptr == 'B') { cnt = sscanf( ptr, "BEGIN_MAIN_MENU(\"%[^\"]", name ); if (cnt == 1) { ptr = XtNewString( name ); MenuDepth = -1; RatMenu = StartRatMenu( "env", ptr, toplevel, Menu_Default.menuCursor ); RatMenuUserItems(&((RatMenuShellWidget)RatMenu)->ratmenu.user); ++menu_depth; continue; } } /*--Watch for the line that begins a simple sub-menu. */ if (*ptr == 'S') { cnt = sscanf( ptr, "SUBM ( \"%[^\"]\",\ %[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_]", name, pick1 ); if (cnt == 2) { val = OurStrToKeysym( pick1 ); if (val == NoSymbol) { fprintf( stderr, "XK_ key symbol name invalid: %s", buff ); goto Bad_Line; } ptr = XtNewString( name ); (void)StartRatSubMenu( ptr, ptr, ptr, (KeySym)val, NoSymbol, None ); ++menu_depth; continue; } /*--Watch for the line that begins an executable sub-menu. */ cnt = sscanf( ptr, "SUBB ( \"%[^\"]\",\ %[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_],\ %[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_]", name, pick1, pick2 ); if (cnt == 3) { val = OurStrToKeysym( pick1 ); if (val == NoSymbol) { fprintf( stderr, "XK_%s key symbol name invalid: %s", pick1, buff ); goto Bad_Line; } cnt = OurStrToKeysym( pick2 ); if (val == NoSymbol) { fprintf( stderr, "XK_%s key symbol name invalid: %s", pick2, buff ); goto Bad_Line; } ptr = XtNewString( name ); (void)StartRatSubMenu( ptr, ptr, ptr, (KeySym)val, (KeySym)cnt, None ); ++menu_depth; continue; } } /*--Watch for ITEM lines that indicate items in menus. */ if (*ptr == 'I') { cnt = sscanf( ptr, "ITEM ( \"%[^\"]\",\ %[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_]", name, pick1 ); if (cnt == 2) { val = OurStrToKeysym( pick1 ); if (val == NoSymbol) { fprintf( stderr, "XK_%s key symbol name invalid: %s", pick1, buff ); goto Bad_Line; } ptr = XtNewString( name ); AddRatItem( ptr, ptr, (KeySym)val ); continue; } } /*--Watch for lines that end sub-menus. */ if (*ptr == 'E') { cnt = sscanf( ptr, "ENDM %[(] %[)]", pick1, pick2 ); if (cnt == 2) { if (menu_depth <= 0) { fprintf( stderr, "Found ENDM with no SUBM or SUBB preceeding?\n" ); goto Bad_Line; } --menu_depth; FinishRatSubMenu(); continue; } /*--Watch for the line that ends the whole menu. */ cnt = sscanf( ptr, "END_MAIN_MENU %[(] %[)]", pick1, pick2 ); if (cnt == 2) { if (menu_depth > 1) { break; } if (menu_depth == 0) { fprintf( stderr, "Found END_MAIN_MENU with no BEGIN_MAIN_MENU preceeding?\n" ); goto Bad_Line; } FinishRatMenu(); menu_depth = 0; break; } } /*--Report any lines that don't make sense. */ fprintf( stderr, "Do not know how to do: %s", buff ); Bad_Line : fprintf( stderr, "In menu file: %s\n", RatMenuDefaults.env_menu_file ); } /*--Close the file. We are done with it. */ if (menu_depth > 1) { fprintf( stderr, "%d ENDM's are missing?\n", menu_depth-1 ); fprintf( stderr, "In menu file: %s\n", RatMenuDefaults.env_menu_file ); for ( ; menu_depth > 1; --menu_depth) { FinishRatSubMenu(); } } if (menu_depth > 0) { FinishRatMenu(); fprintf( stderr, "Missing END_MAIN_MENU?\n" ); fprintf( stderr, "In menu file: %s\n", RatMenuDefaults.env_menu_file ); } fclose( file ); { Define_Name N; while ((N = Defines) != Define_Name_NULL) { Defines = N->Next; XtFree( N ); } } if (RatMenu != 0) { return; } /*--We get here if there is some catastrophic error; like the file was empty.*/ ptr = "RXI_Env_Menu file was empty?"; Make_Fake_Menu: RatMenu = StartRatMenu( "env", "Environment", toplevel, Menu_Default.menuCursor ); RatMenuUserItems( &((RatMenuShellWidget)RatMenu)->ratmenu.user ); AddRatItem( ptr, ptr, XK_equal ); FinishRatMenu(); return; } /* RationalMenuInit */