|
|
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 - metrics - downloadIndex: T r
Length: 51662 (0xc9ce)
Types: TextFile
Names: »ratmenu.c«
└─⟦d10a02448⟧ Bits:30000409 8mm tape, Rational 1000, ENVIRONMENT, D_12_7_3
└─⟦fc9b38f02⟧ »DATA«
└─⟦8e9e227a9⟧
└─⟦0b3b13f5b⟧
└─⟦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;
extern Pixmap XtGrayPixmap ();
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 the window isn't the main menu window then we don't care. */
if (w != RatMenu || !RatMenuDefaults.permanent) { return; }
/*--If our main window also is now unmapped then we've merely been iconified
* and we don't want to change the permanent flag. */
{ XWindowAttributes wa;
XGetWindowAttributes( XtDisplay(term), XtWindow(term), &wa );
if (wa.map_state == IsUnmapped) { return; }
}
/*--Our menu was, presumably, unmapped by user action via the window manager.
* This cancels permanence. */
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 */