|
|
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 m
Length: 39892 (0x9bd4)
Types: TextFile
Names: »menu.c«
└─⟦5f3412b64⟧ Bits:30000745 8mm tape, Rational 1000, ENVIRONMENT 12_6_5 TOOLS
└─⟦91c658230⟧ »DATA«
└─⟦5d656759a⟧
└─⟦34224b4fb⟧
└─⟦this⟧ »./menu.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⟧ »./menu.c«
#ifdef SCCS
static char sccsid[]="@(#)menu.c 1.7 Stellar 87/10/16";
#endif
/*
* $XConsortium: menu.c,v 1.10 88/10/05 11:16:29 jim Exp $
*/
#include <X11/copyright.h>
/*
* Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
*
* All Rights Reserved
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of Digital Equipment
* Corporation not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior permission.
*
*
* DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
* DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
* ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
* WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/StringDefs.h>
#include <X11/Intrinsic.h>
#include <X11/Shell.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/cursorfont.h>
#include "menu.h"
#include <setjmp.h>
#ifdef hpux
#undef SIGCHLD
#include <sys/signal.h>
#else
#include <signal.h>
#endif
#include "ptyx.h"
#include "data.h"
#ifdef RIOS
#include <signal.h>
#endif /* RIOS */
#ifndef lint
static char rcs_id[] = "$XConsortium: menu.c,v 1.10 88/10/05 11:16:29 jim Exp $";
#endif lint
#define DEFMENUBORDER 2
#define DEFMENUPAD 3
#define XOR(a,b) ((a&(~b)) | ((~a)&b))
#define SetStateFlags(item) item->itemFlags = (item->itemFlags &\
~(itemStateMask | itemChanged)) |\
((item->itemFlags & itemSetMask) >>\
itemSetMaskShift)
static char Check_MarkBits[] = {
0x00, 0x01, 0x80, 0x01, 0xc0, 0x00, 0x60, 0x00,
0x31, 0x00, 0x1b, 0x00, 0x0e, 0x00, 0x04, 0x00
};
static GC MenuGC, MenuInverseGC, MenuInvertGC, MenuGrayGC;
static int gotGCs = FALSE;
Pixmap Gray_Tile, Check_Normal_Tile, Check_Inverse_Tile, Check_Tile;
Menu Menu_Default;
Cursor Menu_DefaultCursor;
char *Menu_DefaultFont;
int default_menuBorder = DEFMENUBORDER;
int default_menuPad = DEFMENUPAD;
static XtResource resourceList[] = {
{"menuBorder", "MenuBorder", XtRInt, sizeof(int),
XtOffset (Menu *, menuBorderWidth), XtRInt, (caddr_t)&default_menuBorder},
{"menuPad", "MenuPad", XtRInt, sizeof(int),
XtOffset (Menu *, menuItemPad), XtRInt, (caddr_t) &default_menuPad}
};
static Draw_Item();
static Draw_Menu();
static Map_Menu();
static Move_Menu();
static Recalc_Menu();
/*
* AddMenuItem() adds a menu item to an existing menu, at the end of the
* list, which are number sequentially from zero. The menuitem index is
* return, or -1 if failed.
*/
AddMenuItem(menu, text)
register Menu *menu;
register char *text;
{
register MenuItem *menuitem, **next;
register int i;
extern char *malloc();
if(!menu || !text || (menuitem = (MenuItem *)malloc(sizeof(MenuItem)))
== (MenuItem *)0)
return(-1);
bzero((char *)menuitem, sizeof(MenuItem));
menuitem->itemText = text;
menuitem->itemTextLength = strlen(text);
for(i = 0, next = &menu->menuItems ; *next ; i++)
next = &(*next)->nextItem;
*next = menuitem;
menu->menuFlags |= menuChanged;
return(i);
}
void InitMenu(name)
register char *name;
{
register XtermWidget xw = term;
register char *cp;
static int didthisonce = FALSE;
Display *dpy = XtDisplay(xw);
Pixel background = xw->core.background_pixel;
Pixel foreground = xw->screen.foreground;
if (didthisonce) return;
didthisonce = TRUE;
/*
* If the gray tile hasn't been set up, do it now.
*/
if(!Gray_Tile)
Gray_Tile = XtGrayPixmap(XtScreen(xw));
if (!Check_Tile) {
extern Pixmap Make_tile();
Check_Normal_Tile =
Make_tile(checkMarkWidth, checkMarkHeight,
Check_MarkBits, foreground, background,
(unsigned int)DefaultDepth(dpy,DefaultScreen(dpy)));
Check_Inverse_Tile =
Make_tile(checkMarkWidth, checkMarkHeight,
Check_MarkBits, background, foreground,
(unsigned int)DefaultDepth(dpy,DefaultScreen(dpy)));
Check_Tile = Check_Normal_Tile;
}
Menu_Default.menuFlags = menuChanged;
Menu_Default.menuInitialItem = -1;
XtGetSubresources((Widget)xw, (caddr_t)&Menu_Default, "menu", "Menu",
resourceList, XtNumber(resourceList), NULL, 0);
Menu_Default.menuFontInfo = vt100_resource.f_m;
if (Menu_Default.menuFontInfo == NULL) {
if (xw->screen.fnt_norm) {
Menu_Default.menuFontInfo = xw->screen.fnt_norm;
MenugcFontMask = VTgcFontMask;
} else {
Display *dpy = XtDisplay (xw);
Menu_Default.menuFontInfo =
XQueryFont (dpy, DefaultGC (dpy, DefaultScreen (dpy))->gid);
MenugcFontMask = 0;
}
}
};
/*
* ItemFlags returns the state of item "n" of the menu.
*/
ItemFlags(menu, n)
register Menu *menu;
register int n;
{
register MenuItem *item;
if(!menu || !menu->menuItems || n < 0)
return(-1);
for(item = menu->menuItems ; n > 0 ; n--)
if(!(item = item->nextItem))
return(0);
return((item->itemFlags & itemSetMask) >> itemSetMaskShift);
}
/*
* ItemText changes the text of item "n" of the menu.
*/
ItemText(menu, n, text)
register Menu *menu;
register int n;
char *text;
{
register MenuItem *item;
if(!menu || !menu->menuItems || n < 0 || !text)
return(0);
for(item = menu->menuItems ; n > 0 ; n--)
if(!(item = item->nextItem))
return(0);
item->itemText = text;
menu->menuFlags |= menuChanged;
return(1);
}
/*
* NewMenu() returns a pointer to an initialized new Menu structure, or NULL
* if failed.
*
* The Menu structure _menuDefault contains the default menu settings.
*/
Menu *NewMenu (name)
char *name;
{
register Menu *menu;
register XtermWidget xw = term;
XGCValues xgc;
extern char *malloc();
extern XFontStruct *XLoadQueryFont();
register Display *dpy = XtDisplay(xw);
Pixel background = xw->core.background_pixel;
Pixel foreground = xw->screen.foreground;
/*
* If the GrayTile hasn't been defined, InitMenu() was never
* run, so exit.
*/
if(!Gray_Tile)
return((Menu *)0);
/*
* Allocate the memory for the menu structure.
*/
if((menu = (Menu *)malloc(sizeof(Menu))) == (Menu *)0)
return((Menu *)0);
/*
* Initialize to default values.
*/
*menu = Menu_Default;
/*
* If the menu cursor hasn't been given, make a default one.
*/
if(!menu->menuCursor) {
if(!Menu_DefaultCursor) {
if(!(Menu_DefaultCursor =
XCreateFontCursor(dpy, XC_left_ptr)))
return((Menu *)0);
}
menu->menuCursor = Menu_DefaultCursor;
}
/*
* Initialze the default background and border pixmaps and foreground
* and background colors (black and white).
*/
menu->menuFgColor = foreground;
menu->menuBgColor = background;
if(!gotGCs) {
xgc.foreground = menu->menuFgColor;
xgc.function = GXinvert;
xgc.plane_mask = XOR(menu->menuFgColor, menu->menuBgColor);
MenuInvertGC = XCreateGC(dpy, DefaultRootWindow(dpy),
GCForeground+GCFunction+GCPlaneMask, &xgc);
xgc.foreground = menu->menuFgColor;
xgc.background = menu->menuBgColor;
xgc.font = menu->menuFontInfo->fid;
xgc.function = GXcopy;
xgc.fill_style = FillSolid;
MenuGC = XCreateGC(dpy, DefaultRootWindow(dpy),
MenugcFontMask+GCForeground+GCBackground+GCFunction+GCFillStyle,
&xgc);
xgc.foreground = menu->menuBgColor;
xgc.background = menu->menuFgColor;
xgc.font = menu->menuFontInfo->fid;
xgc.function = GXcopy;
xgc.fill_style = FillSolid;
MenuInverseGC = XCreateGC(dpy, DefaultRootWindow(dpy),
MenugcFontMask+GCForeground+GCBackground+GCFunction+GCFillStyle,
&xgc);
xgc.foreground = menu->menuFgColor;
xgc.background = menu->menuBgColor;
xgc.function = GXcopy;
xgc.stipple = Gray_Tile;
xgc.fill_style = FillStippled;
MenuGrayGC = XCreateGC(dpy, DefaultRootWindow(dpy),
GCStipple+GCFillStyle+MenugcFontMask
+GCForeground+GCBackground+GCFunction,
&xgc);
gotGCs = TRUE;
}
/*
* Set the menu title. If name is NULL or is an empty string, no
* title will be displayed.
*/
if(name && *name) {
menu->menuTitleLength = strlen(menu->menuTitle = name);
menu->menuTitleWidth = XTextWidth(menu->menuFontInfo, name,
menu->menuTitleLength);
menu->menuItemTop = menu->menuFontInfo->ascent +
menu->menuFontInfo->descent + 2 * menu->menuItemPad + 1;
} else
menu->menuTitleLength = menu->menuTitleWidth =
menu->menuItemTop = 0;
return(menu);
}
/*
* SetItemCheck sets the check state of item "n" of the menu to "state".
*/
SetItemCheck(menu, n, state)
register Menu *menu;
register int n;
int state;
{
register MenuItem *item;
if(!menu || !menu->menuItems || n < 0)
return(0);
for(item = menu->menuItems ; n > 0 ; n--)
if(!(item = item->nextItem))
return(0);
if(state)
item->itemFlags |= itemSetChecked;
else
item->itemFlags &= ~itemSetChecked;
if(((item->itemFlags & itemSetMask) >> itemSetMaskShift) !=
(item->itemFlags & itemStateMask)) {
item->itemFlags |= itemChanged;
menu->menuFlags |= menuItemChanged;
} else
item->itemFlags &= ~itemChanged;
return(1);
}
/*
* SetItemDisable sets the disable state of item "n" of the menu to "state".
*/
SetItemDisable(menu, n, state)
register Menu *menu;
register int n;
int state;
{
register MenuItem *item;
if(!menu || !menu->menuItems || n < 0)
return(0);
for(item = menu->menuItems ; n > 0 ; n--)
if(!(item = item->nextItem))
return(0);
if(state)
item->itemFlags |= itemSetDisabled;
else
item->itemFlags &= ~itemSetDisabled;
if(((item->itemFlags & itemSetMask) >> itemSetMaskShift) !=
(item->itemFlags & itemStateMask)) {
item->itemFlags |= itemChanged;
menu->menuFlags |= menuItemChanged;
} else
item->itemFlags &= ~itemChanged;
return(1);
}
static Menu *menu;
static MenuItem *item;
static int i;
static MenuItem *hilited_item;
static int drawn;
static int changed;
int y, n, hilited_y, hilited_n, in_window;
static MenuItem *Mouse_InItem(), *Y_InItem();
static Unmap_Menu();
/*ARGSUSED*/
void MenuExposeWindow(w, closure, event)
Widget w;
caddr_t closure;
XEvent *event;
{
register XtermWidget xw = (XtermWidget) w;
/*
* If we have a saved pixmap, display it. Otherwise
* redraw the menu and save it away.
*/
if (event->type == NoExpose) return;
Draw_Menu(menu);
/*
* If the menu has changed in any way and we want to
* save the menu, throw away any existing save menu
* image and make a new one.
*/
XFlush(XtDisplay(xw));
/*
* See which item the cursor may currently be in. If
* it is in a non-disabled item, hilite it.
*/
if(hilited_item = Mouse_InItem(menu, &hilited_y, &hilited_n))
XFillRectangle(XtDisplay(xw), menu->menuWindow,
MenuInvertGC, 0, hilited_y,
(unsigned int)menu->menuWidth,
(unsigned int)hilited_item->itemHeight);
drawn++;
}
/*ARGSUSED*/
void MenuMouseMoved(w, closure, event)
Widget w;
caddr_t closure;
XMotionEvent *event;
{
register XtermWidget xw = (XtermWidget) w;
if(!drawn || !in_window)
return;
/*
* See which item the cursor may currently be in. If
* the item has changed, unhilite the old one and
* then hilited the new one.
*/
y = event->y;
if((item = Y_InItem(menu, &y, &n)) != hilited_item) {
if(hilited_item)
XFillRectangle(XtDisplay(xw), menu->menuWindow,
MenuInvertGC, 0, hilited_y,
(unsigned int)menu->menuWidth,
(unsigned int)hilited_item->itemHeight);
if(hilited_item = item) {
XFillRectangle(XtDisplay(xw), menu->menuWindow,
MenuInvertGC, 0,
hilited_y = y,
(unsigned int)menu->menuWidth,
(unsigned int)item->itemHeight);
hilited_n = n;
}
}
}
/*ARGSUSED*/
void MenuEnterWindow(w, closure, event)
Widget w;
caddr_t closure;
XEvent *event;
{
in_window = TRUE;
MenuMouseMoved(w, closure, (XMotionEvent*)event);
}
/*ARGSUSED*/
void MenuLeaveWindow(w, closure, event)
Widget w;
caddr_t closure;
XEvent *event;
{
register XtermWidget xw = (XtermWidget) w;
if(!drawn)
return;
/*
* Unhilite any window that is currently hilited.
*/
if(hilited_item) {
XFillRectangle(XtDisplay(xw), menu->menuWindow,
MenuInvertGC, 0, hilited_y,
(unsigned int)menu->menuWidth,
(unsigned int)hilited_item->itemHeight);
hilited_item = (MenuItem *)0;
}
in_window = FALSE;
}
int menu_grab = FALSE;
/*ARGSUSED*/
void MenuButtonReleased(w, closure, event)
Widget w;
caddr_t closure;
XButtonEvent *event;
{
register XtermWidget xw = (XtermWidget) w;
extern FinishModeMenu();
/*
* return the index number of any selected menu
* item.
*/
if (! AllButtonsUp(event->state, event->button))
return;
XUngrabPointer(XtDisplay(xw), CurrentTime);
menu_grab = FALSE;
if(in_window) {
y = event->y;
if((item = Y_InItem(menu, &y, &n)) != hilited_item) {
if(hilited_item)
XFillRectangle(XtDisplay(xw), menu->menuWindow,
MenuInvertGC, 0,
hilited_y,
(unsigned int)menu->menuWidth,
(unsigned int)hilited_item->itemHeight);
if(hilited_item = item) {
XFillRectangle(XtDisplay(xw), menu->menuWindow,
MenuInvertGC, 0,
hilited_y = y,
(unsigned int)menu->menuWidth,
(unsigned int)hilited_item->itemHeight);
hilited_n = n;
}
}
}
XFlush(XtDisplay(xw));
menu->menuFlags &= ~(menuChanged | menuItemChanged);
Unmap_Menu(menu);
drawn = 0;
if(hilited_item)
FinishModeMenu(menu->menuInitialItem = hilited_n,
event->time);
else
FinishModeMenu(-1, event->time);
}
/*
* TrackMenu does most of the work of displaying the menu and tracking the
* mouse.
*/
TrackMenu(lmenu, event)
register Menu *lmenu;
register XButtonPressedEvent *event;
{
register XtermWidget xw = term;
XButtonReleasedEvent ev;
XSetWindowAttributes attr;
menu = lmenu;
hilited_item = (MenuItem *)0;
/*
* Check that things are reasonable.
*/
if(!menu || !event || !menu->menuItems || event->type != ButtonPress)
return(-1);
/*
* Set the changed flag and clear the menu changed flags.
*/
changed = menu->menuFlags & (menuChanged | menuItemChanged);
/*
* If the entire menu has changed, throw away any saved pixmap and
* then call RecalcMenu().
*/
if(changed & menuChanged) {
if(!Recalc_Menu(menu))
return(-1);
changed &= ~menuItemChanged;
}
/*
* Now if the window was never created, go ahead and make it. Otherwise
* if the menu has changed, resize the window.
*/
if(!menu->menuWindow) {
#define SETARG( XtN, XtV ) XtSetArg( args[argi], XtN, XtV ); argi++
Arg args[2];
int argi = 0;
SETARG( XtNgeometry, NULL ); /* Never let user set this. */
#undef SETARG
menu->menuWidget =
XtCreatePopupShell ("Xterm Menu", transientShellWidgetClass, xw,
args, (Cardinal)argi);
XtResizeWidget (menu->menuWidget,
menu->menuWidth, menu->menuHeight,
menu->menuBorderWidth);
XtRealizeWidget (menu->menuWidget);
menu->menuWindow = XtWindow (menu->menuWidget);
attr.override_redirect = True;
attr.border_pixmap = XtGrayPixmap(XtScreen(xw));
attr.background_pixel = menu->menuBgColor;
attr.cursor = menu->menuCursor;
attr.save_under = True;
XChangeWindowAttributes (XtDisplay(xw), menu->menuWindow,
(CWBorderPixmap | CWBackPixel |
CWOverrideRedirect | CWCursor |
CWSaveUnder), &attr);
XtAddEventHandler(menu->menuWidget, ExposureMask, FALSE,
MenuExposeWindow, (caddr_t)NULL);
XtAddEventHandler(menu->menuWidget, EnterWindowMask, FALSE,
MenuEnterWindow, (caddr_t)NULL);
XtAddEventHandler(menu->menuWidget, LeaveWindowMask, FALSE,
MenuLeaveWindow, (caddr_t)NULL);
XtAddEventHandler(menu->menuWidget, PointerMotionMask, FALSE,
MenuMouseMoved, (caddr_t)NULL);
XtAddEventHandler(menu->menuWidget, ButtonReleaseMask, FALSE,
MenuButtonReleased, (caddr_t)NULL);
} else if(changed & menuChanged)
XtResizeWidget(menu->menuWidget, menu->menuWidth, menu->menuHeight,
menu->menuBorderWidth);
/*
* Figure out where the menu is supposed to go, from the initial button
* press, and move the window there. Then map the menu.
*/
if(!Move_Menu(menu, event) || !Map_Menu(menu))
return(-1);
in_window = TRUE;
XGrabPointer(XtDisplay(xw), menu->menuWindow, FALSE,
EnterWindowMask | LeaveWindowMask | PointerMotionMask
| ButtonReleaseMask | ButtonPressMask,
GrabModeAsync, GrabModeAsync, None,
menu->menuCursor, CurrentTime);
return 0;
}
/*
* Recalculate all of the various menu and item variables.
*/
static Recalc_Menu(menu)
register Menu *menu;
{
register MenuItem *item;
register int max, height, fontheight;
/*
* We must have already gotten the menu font.
*/
if(!menu->menuFontInfo)
return(0);
/*
* Initialize the various max width variables.
*/
fontheight = menu->menuFontInfo->ascent + menu->menuFontInfo->descent;
height = menu->menuItemTop;
menu->menuMaxTextWidth = menu->menuTitleWidth;
/*
* The item height is the maximum of the font height and the
* checkbox height.
*/
max = fontheight;
if(checkMarkHeight > max)
max = checkMarkHeight;
/*
* Go through the menu item list.
*/
for(item = menu->menuItems ; item ; item = item->nextItem) {
/*
* If the item text is a single dash, we assume this is
* a line separator and treat it special.
*/
if(XStrCmp(item->itemText, "-") == 0)
height += (item->itemHeight = lineSeparatorHeight);
else {
height += (item->itemHeight = max);
/*
* Check the text width with the max value stored in
* menu.
*/
if((item->itemTextWidth = XTextWidth(
menu->menuFontInfo, item->itemText,
strlen(item->itemText))) > menu->menuMaxTextWidth)
menu->menuMaxTextWidth = item->itemTextWidth;
}
/*
* If the itemChanged flag is set, set the state bits.
*/
if(item->itemFlags & itemChanged) {
item->itemFlags = (item->itemFlags & ~itemStateMask) |
((item->itemFlags & itemSetMask) >> itemSetMaskShift);
item->itemFlags &= ~itemChanged;
}
}
/*
* Set the menu height and then set the menu width.
*/
menu->menuHeight = height;
menu->menuWidth = 3 * menu->menuItemPad + menu->menuMaxTextWidth +
checkMarkWidth;
return(1);
}
/*
* Figure out where to popup the menu, relative to the where the button was
* pressed.
*/
static Move_Menu(menu, ev)
register Menu *menu;
XButtonPressedEvent *ev;
{
register int n, x, y;
register XtermWidget xw = term;
int total_width;
/*
* Try to popup the menu so that the cursor is centered within the
* width of the menu, but compensate if that would run it outside
* the display area.
*/
total_width = menu->menuWidth + 2 * menu->menuBorderWidth;
if((x = ev->x_root - total_width / 2) < 0)
x = 0;
else if(x + total_width > DisplayWidth(XtDisplay(xw),
DefaultScreen(XtDisplay(xw))))
x = DisplayWidth(XtDisplay(xw),
DefaultScreen(XtDisplay(xw))) - total_width;
/*
* If the menu extends above outside of the display, warp
* the mouse vertically so the menu will all show up.
*/
if((y = ev->y_root) < 0) {
/* don't bother warping pointer
XWarpPointer(XtDisplay(xw), None,
DefaultRootWindow(XtDisplay(xw)), 0, 0, 0, 0, ev->x_root,
0);
*/
y = 0;
} else if((n = y + menu->menuHeight + 2 * menu->menuBorderWidth -
DisplayHeight(XtDisplay(xw), DefaultScreen(XtDisplay(xw)))) > 0) {
/* don't bother warping pointer
XWarpPointer(XtDisplay(xw), None,
DefaultRootWindow(XtDisplay(xw)), 0, 0, 0, 0, ev->x_root,
ev->y_root - n);
*/
y -= n;
}
XtMoveWidget(menu->menuWidget, x, y);
return(1);
}
/*
* Map the menu window.
*/
static Map_Menu(menu)
register Menu *menu;
{
register XtermWidget xw = term;
/*
* Actually map the window.
*/
XRaiseWindow (XtDisplay(xw), menu->menuWindow);
XtPopup (menu->menuWidget, XtGrabNone);
menu->menuFlags |= menuMapped;
return(1);
}
/*
* Draw the entire menu in the blank window.
*/
static Draw_Menu(menu)
register Menu *menu;
{
register MenuItem *item;
register int top = menu->menuItemTop;
register int x = menu->menuItemPad;
register int dim;
register XtermWidget xw = term;
/*
* If we have a menu title, draw it first, centered and hilited.
*/
if(menu->menuTitleLength) {
XFillRectangle(XtDisplay(xw), menu->menuWindow,
MenuGC, 0, 0,
(unsigned int)menu->menuWidth,
(unsigned int)top - 1);
XDrawImageString(XtDisplay(xw), menu->menuWindow,
MenuInverseGC, (menu->menuWidth -
menu->menuTitleWidth) / 2,
menu->menuItemPad+menu->menuFontInfo->ascent,
menu->menuTitle, menu->menuTitleLength);
}
/*
* For each item in the list, first draw any check mark and then
* draw the rest of it.
*/
for(item = menu->menuItems ; item ; item = item->nextItem) {
SetStateFlags(item);
dim = (item->itemFlags & itemDisabled);
/*
* Draw the check mark, possibly dimmed, wherever is necessary.
*/
if(item->itemFlags & itemChecked) {
XCopyArea(XtDisplay(xw),
Check_Tile, menu->menuWindow,
dim ? MenuGrayGC : MenuGC,
0, 0, checkMarkWidth, checkMarkHeight, x,
top + (item->itemHeight - checkMarkHeight) / 2);
}
/*
* Draw the item, possibly dimmed.
*/
Draw_Item(menu, item, top, dim);
top += item->itemHeight;
}
}
/*
* Modify the item at vertical position y. This routine is table driven and
* the state and set bits are each 2 bits long, contiguous, the least
* significant bits in the flag word and with the state bits in bits 0 & 1.
*/
#define drawCheck 0x10
#define removeCheck 0x08
#define dimCheck 0x04
#define drawItem 0x02
#define dimItem 0x01
static char Modify_Table[] = {
0x00, 0x02, 0x08, 0x0a, 0x01, 0x00, 0x09, 0x08,
0x10, 0x12, 0x00, 0x12, 0x15, 0x14, 0x05, 0x00
};
#if 0
* static Modify_Item(menu, item, top)
* register Menu *menu;
* register MenuItem *item;
* int top;
* {
* register int x = menu->menuItemPad;
* register int y;
* register int center = top + item->itemHeight / 2;
* register int func = Modify_Table[item->itemFlags &
* (itemStateMask | itemSetMask)];
* register XtermWidget xw = term;
*
* /*
* * If we really won't be making a change, return.
* */
* if(func == 0)
* return;
* /*
* * Draw the check mark if needed, possibly dimmed.
* */
* y = center - (checkMarkHeight / 2);
* if(func & (drawCheck | dimCheck))
* XCopyArea(XtDisplay(xw),
* Check_Tile, menu->menuWindow,
* (func & dimCheck) ? MenuGrayGC : MenuGC,
* 0, 0, checkMarkWidth, checkMarkHeight, x,
* y = top + (item->itemHeight - checkMarkHeight) / 2);
* /*
* * Remove the check mark if needed.
* */
* if(func & removeCheck)
* XClearArea(XtDisplay(xw), menu->menuWindow,
* x, y, checkMarkWidth, checkMarkHeight, FALSE);
* /*
* * Call Draw_Item if we need to draw or dim the item.
* */
* if((x = func & dimItem) || (func & drawItem))
* Draw_Item(menu, item, top, x);
* /*
* * Update state flags.
* */
* SetStateFlags(item);
* }
#endif /* 0 */
/*
* Draw the item (less check mark) at vertical position y.
* Dim the item if "dim" is set.
*/
static Draw_Item(menu, item, y, dim)
register Menu *menu;
register MenuItem *item;
register int y;
int dim;
{
register int x = 2 * menu->menuItemPad + checkMarkWidth;
register int center = y + item->itemHeight / 2;
register XtermWidget xw = term;
/*
* If the item text is a single dash, draw a separating line.
*/
if(XStrCmp(item->itemText, "-") == 0) {
XDrawLine(XtDisplay(xw), menu->menuWindow, MenuGC,
0, center, menu->menuWidth, center);
return;
}
/*
* Draw and/or dim the text, centered vertically.
*/
y = center -
((menu->menuFontInfo->ascent + menu->menuFontInfo->descent)/ 2);
if(dim) {
XDrawString(XtDisplay(xw), menu->menuWindow, MenuGrayGC,
x, y+menu->menuFontInfo->ascent,
item->itemText, item->itemTextLength);
} else
XDrawImageString(XtDisplay(xw), menu->menuWindow,
MenuGC, x, y+menu->menuFontInfo->ascent,
item->itemText, item->itemTextLength);
}
/*
* Determine which enabled menu item the mouse is currently in. Return the
* top position of this item and its item number. Set inwindow to whether
* we are or not.
*/
static MenuItem *Mouse_InItem(menu, top, n)
register Menu *menu;
int *top, *n;
{
int x, y, rootx, rooty;
unsigned int mask;
Window subw, root;
static MenuItem *Y_InItem();
register XtermWidget xw = term;
/*
* Find out where the mouse is. If its not in the menu window,
* return NULL.
*/
XQueryPointer(XtDisplay(xw), menu->menuWindow,
&root, &subw, &rootx, &rooty, &x, &y, &mask);
if((x <0) || (y < 0) ||
(x > menu->menuWidth) || (y > menu->menuHeight)) {
return((MenuItem *)0);
}
/*
* Call Y_InItem().
*/
*top = y;
return(Y_InItem(menu, top, n));
}
/*
* Return which enabled item the locator is in. Also return the
* top position of this item and its item number. Initial y passed
* in top.
*/
static MenuItem *Y_InItem(menu, top, n)
register Menu *menu;
int *top, *n;
{
register MenuItem *item;
register int t, i;
register int y = *top;
/*
* Go through the item list. "t" is the vertical position of the
* current item and "i" is its item number.
*/
t = menu->menuItemTop;
/*
* If the mouse is before the first item, return.
*/
if(y < t)
return((MenuItem *)0);
for(i = 0, item = menu->menuItems ; item ; i++, item = item->nextItem) {
/*
* If the y coordinate is within this menu item, then return.
* But don't return disable items.
*/
if(t + item->itemHeight > y) {
if(item->itemFlags & itemDisabled)
return((MenuItem *)0);
*top = t;
*n = i;
return(item);
}
t += item->itemHeight;
}
/*
* Should never get here.
*/
return((MenuItem *)0);
}
/*
* Unmap_Menu() unmaps a menu, if it is currently mapped.
*/
static Unmap_Menu(menu)
register Menu *menu;
{
register int i;
/* register XtermWidget xw = term; */
if(!menu || !(menu->menuFlags & menuMapped))
return;
XtPopdown (menu->menuWidget);
menu->menuFlags &= ~menuMapped;
}
MenuResetGCs (bgp, fgp)
Pixel *bgp, *fgp;
{
register XtermWidget xw = term;
Display *dpy = XtDisplay (xw);
XGCValues xgc;
*bgp = xw->core.background_pixel;
*fgp = xw->screen.foreground;
if (MenuInvertGC) {
xgc.foreground = *fgp;
xgc.plane_mask = XOR(*fgp, *bgp);
XChangeGC (dpy, MenuInvertGC, (GCForeground | GCPlaneMask), &xgc);
}
if (MenuGC) {
xgc.foreground = *fgp;
xgc.background = *bgp;
XChangeGC (dpy, MenuGC, (GCForeground | GCBackground), &xgc);
}
if (MenuInverseGC) {
xgc.foreground = *bgp;
xgc.background = *fgp;
XChangeGC (dpy, MenuInverseGC, (GCForeground | GCBackground), &xgc);
}
if (MenuGrayGC) {
xgc.foreground = *fgp;
xgc.background = *bgp;
xgc.function = *fgp ? GXor : GXand;
XChangeGC (dpy, MenuGrayGC,
(GCForeground | GCBackground | GCFunction), &xgc);
}
if (Check_Tile) {
Check_Tile = ((Check_Tile == Check_Normal_Tile) ? Check_Inverse_Tile :
Check_Normal_Tile);
}
return;
}
\f
static void do_securekbd(), do_allowsends(), do_visualbell(), do_logging(),
do_redraw(), /* do_suspend(), do_continue(), do_interrupt(), do_hangup(), */
/* do_terminate(), do_kill(), */ do_quit(), do_scrollbar(), do_jumpscroll(),
do_reversevideo(), do_autowrap(), do_reversewrap(), do_autolinefeed(),
do_appcursor(), do_appkeypad(), do_scrollkey(), do_scrollttyoutput(),
do_allow132(), do_cursesemul(), do_marginbell(),
do_altscreen(), do_softreset(), do_hardreset();
static void handle_send_signal (gw, sig)
Widget gw;
int sig;
{
register TScreen *screen = &term->screen;
if (screen->pid > 1) killpg (screen->pid, sig);
}
/*
* action routines
*/
void DoSecureKeyboard (time)
Time time;
{
do_securekbd ( NULL, NULL);
}
static void do_securekbd (closure, data)
caddr_t closure, data;
{
register TScreen *screen = &term->screen;
Time time = CurrentTime; /* XXX - wrong */
if (screen->grabbedKbd) {
XUngrabKeyboard (screen->display, time);
ReverseVideo (term);
screen->grabbedKbd = FALSE;
} else {
if (XGrabKeyboard (screen->display, term->core.parent->core.window,
True, GrabModeAsync, GrabModeAsync, time)
!= GrabSuccess) {
XBell (screen->display, 100);
} else {
ReverseVideo (term);
screen->grabbedKbd = TRUE;
}
}
}
static void do_allowsends (gw, closure, data)
Widget gw;
caddr_t closure, data;
{
register TScreen *screen = &term->screen;
screen->allowSendEvents = !screen->allowSendEvents;
}
static void do_visualbell (gw, closure, data)
Widget gw;
caddr_t closure, data;
{
register TScreen *screen = &term->screen;
screen->visualbell = !screen->visualbell;
}
static void do_logging (gw, closure, data)
Widget gw;
caddr_t closure, data;
{
register TScreen *screen = &term->screen;
if (screen->logging) {
CloseLog (screen);
} else {
StartLog (screen);
}
}
static void do_redraw (gw, closure, data)
Widget gw;
caddr_t closure, data;
{
Redraw ();
}
/*
* The following cases use the pid instead of the process group so that we
* don't get hosed by programs that change their process group
*/
#if 0
* static void do_suspend (gw, closure, data)
* Widget gw;
* caddr_t closure, data;
* {
* #ifdef SIGTSTP
* handle_send_signal (gw, SIGTSTP);
* #endif
* }
*
*
* static void do_continue (gw, closure, data)
* Widget gw;
* caddr_t closure, data;
* {
* #ifdef SIGCONT
* handle_send_signal (gw, SIGCONT);
* #endif
* }
*
*
* static void do_interrupt (gw, closure, data)
* Widget gw;
* caddr_t closure, data;
* {
* handle_send_signal (gw, SIGINT);
* }
*
*
* static void do_hangup (gw, closure, data)
* Widget gw;
* caddr_t closure, data;
* {
* handle_send_signal (gw, SIGHUP);
* }
*
*
* static void do_terminate (gw, closure, data)
* Widget gw;
* caddr_t closure, data;
* {
* handle_send_signal (gw, SIGTERM);
* }
*
*
* static void do_kill (gw, closure, data)
* Widget gw;
* caddr_t closure, data;
* {
* handle_send_signal (gw, SIGKILL);
* }
*
#endif /* 0 */
static void do_quit (gw, closure, data)
Widget gw;
caddr_t closure, data;
{
Cleanup (0);
}
/*
* vt menu callbacks
*/
static void do_scrollbar (gw, closure, data)
Widget gw;
caddr_t closure, data;
{
register TScreen *screen = &term->screen;
if (screen->scrollbar) {
ScrollBarOff (screen);
} else {
ScrollBarOn (term, FALSE, FALSE);
}
}
static void do_jumpscroll (gw, closure, data)
Widget gw;
caddr_t closure, data;
{
register TScreen *screen = &term->screen;
term->flags ^= SMOOTHSCROLL;
if (term->flags & SMOOTHSCROLL) {
screen->jumpscroll = FALSE;
if (screen->scroll_amt) FlushScroll(screen);
} else {
screen->jumpscroll = TRUE;
}
}
static void do_reversevideo (gw, closure, data)
Widget gw;
caddr_t closure, data;
{
term->flags ^= REVERSE_VIDEO;
ReverseVideo (term);
}
static void do_autowrap (gw, closure, data)
Widget gw;
caddr_t closure, data;
{
term->flags ^= WRAPAROUND;
}
static void do_reversewrap (gw, closure, data)
Widget gw;
caddr_t closure, data;
{
term->flags ^= REVERSEWRAP;
}
static void do_autolinefeed (gw, closure, data)
Widget gw;
caddr_t closure, data;
{
term->flags ^= LINEFEED;
}
static void do_appcursor (gw, closure, data)
Widget gw;
caddr_t closure, data;
{
term->keyboard.flags ^= CURSOR_APL;
}
static void do_appkeypad (gw, closure, data)
Widget gw;
caddr_t closure, data;
{
term->keyboard.flags ^= KYPD_APL;
}
static void do_scrollkey (gw, closure, data)
Widget gw;
caddr_t closure, data;
{
register TScreen *screen = &term->screen;
screen->scrollkey = !screen->scrollkey;
}
static void do_scrollttyoutput (gw, closure, data)
Widget gw;
caddr_t closure, data;
{
register TScreen *screen = &term->screen;
screen->scrollttyoutput = !screen->scrollttyoutput;
}
static void do_allow132 (gw, closure, data)
Widget gw;
caddr_t closure, data;
{
register TScreen *screen = &term->screen;
screen->c132 = !screen->c132;
}
static void do_cursesemul (gw, closure, data)
Widget gw;
caddr_t closure, data;
{
register TScreen *screen = &term->screen;
screen->curses = !screen->curses;
}
static void do_marginbell (gw, closure, data)
Widget gw;
caddr_t closure, data;
{
register TScreen *screen = &term->screen;
if (!(screen->marginbell = !screen->marginbell)) screen->bellarmed = -1;
}
static void do_altscreen (gw, closure, data)
Widget gw;
caddr_t closure, data;
{
/* do nothing for now; eventually, will want to flip screen */
}
static void do_softreset (gw, closure, data)
Widget gw;
caddr_t closure, data;
{
VTReset (FALSE);
}
static void do_hardreset (gw, closure, data)
Widget gw;
caddr_t closure, data;
{
VTReset (TRUE);
}
/*
* public handler routines
*/
static void handle_toggle (proc, var, params, nparams, w, closure, data)
void (*proc)();
int var;
String *params;
Cardinal nparams;
Widget w;
caddr_t closure, data;
{
int dir = -2;
switch (nparams) {
case 0:
dir = -1;
case 1:
if (XmuCompareISOLatin1 (params[0], "on") == 0) dir = 1;
else if (XmuCompareISOLatin1 (params[0], "off") == 0) dir = 0;
else if (XmuCompareISOLatin1 (params[0], "toggle") == 0) dir = -1;
}
switch (dir) {
case -2:
Bell();
break;
case -1:
(*proc) (w, closure, data);
break;
case 0:
if (var) (*proc) (w, closure, data);
else Bell();
break;
case 1:
if (!var) (*proc) (w, closure, data);
else Bell();
break;
}
return;
}
void HandleAllowSends(w, event, params, param_count)
Widget w;
XEvent *event;
String *params;
Cardinal *param_count;
{
handle_toggle (do_allowsends, (int) term->screen.allowSendEvents,
params, *param_count, w, NULL, NULL);
}
void HandleVisualBell(w, event, params, param_count)
Widget w;
XEvent *event;
String *params;
Cardinal *param_count;
{
handle_toggle (do_visualbell, (int) term->screen.visualbell,
params, *param_count, w, NULL, NULL);
}
void HandleLogging(w, event, params, param_count)
Widget w;
XEvent *event;
String *params;
Cardinal *param_count;
{
handle_toggle (do_logging, (int) term->screen.logging,
params, *param_count, w, NULL, NULL);
}
void HandleRedraw(w, event, params, param_count)
Widget w;
XEvent *event;
String *params;
Cardinal *param_count;
{
do_redraw(w, NULL, NULL);
}
void HandleSendSignal(w, event, params, param_count)
Widget w;
XEvent *event;
String *params;
Cardinal *param_count;
{
static struct sigtab {
char *name;
int sig;
} signals[] = {
#ifdef SIGTSTP
{ "suspend", SIGTSTP },
{ "tstp", SIGTSTP },
#endif
#ifdef SIGCONT
{ "cont", SIGCONT },
#endif
{ "int", SIGINT },
{ "hup", SIGHUP },
{ "term", SIGTERM },
{ "kill", SIGKILL },
{ NULL, 0 },
};
if (*param_count == 1) {
struct sigtab *st;
for (st = signals; st->name; st++) {
if (XmuCompareISOLatin1 (st->name, params[0]) == 0) {
handle_send_signal (w, st->sig);
return;
}
}
/* one could allow numeric values, but that would be a security hole */
}
Bell();
}
void HandleQuit(w, event, params, param_count)
Widget w;
XEvent *event;
String *params;
Cardinal *param_count;
{
do_quit(w, NULL, NULL);
}
void HandleScrollbar(w, event, params, param_count)
Widget w;
XEvent *event;
String *params;
Cardinal *param_count;
{
handle_toggle (do_scrollbar, (int) term->screen.scrollbar,
params, *param_count, w, NULL, NULL);
}
void HandleJumpscroll(w, event, params, param_count)
Widget w;
XEvent *event;
String *params;
Cardinal *param_count;
{
handle_toggle (do_jumpscroll, (int) term->screen.jumpscroll,
params, *param_count, w, NULL, NULL);
}
void HandleReverseVideo(w, event, params, param_count)
Widget w;
XEvent *event;
String *params;
Cardinal *param_count;
{
handle_toggle (do_reversevideo, (int) (term->flags & REVERSE_VIDEO),
params, *param_count, w, NULL, NULL);
}
void HandleAutoWrap(w, event, params, param_count)
Widget w;
XEvent *event;
String *params;
Cardinal *param_count;
{
handle_toggle (do_autowrap, (int) (term->flags & WRAPAROUND),
params, *param_count, w, NULL, NULL);
}
void HandleReverseWrap(w, event, params, param_count)
Widget w;
XEvent *event;
String *params;
Cardinal *param_count;
{
handle_toggle (do_reversewrap, (int) (term->flags & REVERSEWRAP),
params, *param_count, w, NULL, NULL);
}
void HandleAutoLineFeed(w, event, params, param_count)
Widget w;
XEvent *event;
String *params;
Cardinal *param_count;
{
handle_toggle (do_autolinefeed, (int) (term->flags & LINEFEED),
params, *param_count, w, NULL, NULL);
}
void HandleAppCursor(w, event, params, param_count)
Widget w;
XEvent *event;
String *params;
Cardinal *param_count;
{
handle_toggle (do_appcursor, (int) (term->keyboard.flags & CURSOR_APL),
params, *param_count, w, NULL, NULL);
}
void HandleAppKeypad(w, event, params, param_count)
Widget w;
XEvent *event;
String *params;
Cardinal *param_count;
{
handle_toggle (do_appkeypad, (int) (term->keyboard.flags & KYPD_APL),
params, *param_count, w, NULL, NULL);
}
void HandleScrollKey(w, event, params, param_count)
Widget w;
XEvent *event;
String *params;
Cardinal *param_count;
{
handle_toggle (do_scrollkey, (int) term->screen.scrollkey,
params, *param_count, w, NULL, NULL);
}
void HandleScrollTtyOutput(w, event, params, param_count)
Widget w;
XEvent *event;
String *params;
Cardinal *param_count;
{
handle_toggle (do_scrollttyoutput, (int) term->screen.scrollttyoutput,
params, *param_count, w, NULL, NULL);
}
void HandleAllow132(w, event, params, param_count)
Widget w;
XEvent *event;
String *params;
Cardinal *param_count;
{
handle_toggle (do_allow132, (int) term->screen.c132,
params, *param_count, w, NULL, NULL);
}
void HandleCursesEmul(w, event, params, param_count)
Widget w;
XEvent *event;
String *params;
Cardinal *param_count;
{
handle_toggle (do_cursesemul, (int) term->screen.curses,
params, *param_count, w, NULL, NULL);
}
void HandleMarginBell(w, event, params, param_count)
Widget w;
XEvent *event;
String *params;
Cardinal *param_count;
{
handle_toggle (do_marginbell, (int) term->screen.marginbell,
params, *param_count, w, NULL, NULL);
}
void HandleAltScreen(w, event, params, param_count)
Widget w;
XEvent *event;
String *params;
Cardinal *param_count;
{
/* eventually want to see if sensitive or not */
handle_toggle (do_altscreen, (int) term->screen.alternate,
params, *param_count, w, NULL, NULL);
}
void HandleSoftReset(w, event, params, param_count)
Widget w;
XEvent *event;
String *params;
Cardinal *param_count;
{
do_softreset(w, NULL, NULL);
}
void HandleHardReset(w, event, params, param_count)
Widget w;
XEvent *event;
String *params;
Cardinal *param_count;
{
do_hardreset(w, NULL, NULL);
}