[comp.sources.x] v03i021: Ardent Window Manager, Patchlevel 9, Part05/12

mikew@wyse.wyse.com (Mike Wexler) (02/21/89)

Submitted-by: kmw@ardent (Ken Wallich)  
Posting-number: Volume 3, Issue 21
Archive-name: awm2/part05

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 5 (of 12)."
# Contents:  Pause.c awm.h menus/track_menu.c
# Wrapped by mikew@wyse on Fri Feb 17 10:50:23 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Pause.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Pause.c'\"
else
echo shar: Extracting \"'Pause.c'\" \(3003 characters\)
sed "s/^X//" >'Pause.c' <<'END_OF_FILE'
X
X
X
X#ifndef lint
Xstatic char *rcsid_Pause_c = "$Header: /usr/graph2/X11.3/contrib/windowmgrs/awm/RCS/Pause.c,v 1.2 89/02/07 21:23:15 jkh Exp $";
X#endif	lint
X
X#include "X11/copyright.h"
X/*
X *
X * Copyright 1987, 1988 by Ardent Computer Corporation, Sunnyvale, Ca.
X *
X * Copyright 1987 by Jordan Hubbard.
X *
X *
X *                         All Rights Reserved
X *
X * Permission to use, copy, modify, and distribute this software and its
X * documentation for any purpose and without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and that
X * both that copyright notice and this permission notice appear in
X * supporting documentation, and that the name of Ardent Computer
X * Corporation or Jordan Hubbard not be used in advertising or publicity
X * pertaining to distribution of the software without specific, written
X * prior permission.
X *
X */
X
X/*
X * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
X *
X *                         All Rights Reserved
X *
X * Permission to use, copy, modify, and distribute this software and its
X * documentation for any purpose and without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and that
X * both that copyright notice and this permission notice appear in
X * supporting documentation, and that the name of Digital Equipment
X * Corporation not be used in advertising or publicity pertaining to
X * distribution of the software without specific, written prior permission.
X *
X *
X * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
X * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
X * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
X * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
X * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
X * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
X * SOFTWARE.
X */
X
X
X
X/*
X * MODIFICATION HISTORY
X *
X * 000 -- M. Gancarz, DEC Ultrix Engineering Group
X * 001 -- Loretta Guarino Reid, DEC Ultrix Engineering Group,
X *  Western Software Lab. Convert to X11.
X * 002 -- Jordan Hubbard, Ardent Computer
X *  Changes for awm.
X */
X
X#include "awm.h"
X
X/*ARGSUSED*/
XBoolean Pause(window, mask, button, x, y)
XWindow window;                          /* Event window. */
Xint mask;                               /* Button/key mask. */
Xint button;                           /* Button event detail. */
Xint x, y;                               /* Event mouse position. */
X{
X    Entry("Pause")
X
X    XGrabServer(dpy);
X    Leave(FALSE)
X}
X
X/*ARGSUSED*/
XBoolean Continue(window, mask, button, x, y)
XWindow window;                          /* Event window. */
Xint mask;                               /* Button/key mask. */
Xint button;                           /* Button event detail. */
Xint x, y;                               /* Event mouse position. */
X{
X    Entry("Continue")
X
X    XUngrabServer(dpy);
X    Leave(FALSE)
X}
END_OF_FILE
if test 3003 -ne `wc -c <'Pause.c'`; then
    echo shar: \"'Pause.c'\" unpacked with wrong size!
fi
# end of 'Pause.c'
fi
if test -f 'awm.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'awm.h'\"
else
echo shar: Extracting \"'awm.h'\" \(22317 characters\)
sed "s/^X//" >'awm.h' <<'END_OF_FILE'
X#ifndef lint
Xstatic char *rcsid_awm_h = "$Header: /usr/graph2/X11.3/contrib/windowmgrs/awm/RCS/awm.h,v 1.2 89/02/07 21:24:27 jkh Exp $";
X#endif  lint
X
X#include <X11/copyright.h>
X/*
X *
X * Copyright 1987, 1988 by Ardent Computer Corporation, Sunnyvale, Ca.
X *
X * Copyright 1987 by Jordan Hubbard.
X *
X *
X *                         All Rights Reserved
X *
X * Permission to use, copy, modify, and distribute this software and its
X * documentation for any purpose and without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and that
X * both that copyright notice and this permission notice appear in
X * supporting documentation, and that the name of Ardent Computer
X * Corporation or Jordan Hubbard not be used in advertising or publicity
X * pertaining to distribution of the software without specific, written
X * prior permission.
X *
X */
X
X/*
X * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
X *
X *                         All Rights Reserved
X *
X * Permission to use, copy, modify, and distribute this software and its
X * documentation for any purpose and without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and that
X * both that copyright notice and this permission notice appear in
X * supporting documentation, and that the name of Digital Equipment
X * Corporation not be used in advertising or publicity pertaining to
X * distribution of the software without specific, written prior permission.
X *
X *
X * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
X * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
X * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
X * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
X * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
X * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
X * SOFTWARE.
X */
X
X 
X 
X/*
X * MODIFICATION HISTORY
X *
X * 000 -- M. Gancarz, DEC Ultrix Engineering Group
X * 001 -- R. Kittell, DEC Storage A/D May 19, 1986
X *  Added global vars for warp options.
X * 002 -- Loretta Guarino Reid, DEC Ultrix Engineering Group,
X *  Western Software Lab, Port to X11
X * 003 -- Jordan Hubbard, Ardent Computer
X *  Many additional declarations for awm.
X * 1.3 -- Support for WM_STATE (Mike Wexler)
X */
X 
X#ifndef AWM_INCLUDE
X#define AWM_INCLUDE
X#include <errno.h>
X#include <stdio.h>
X#include <X11/Intrinsic.h>
X#include <X11/Xatom.h>
X
X#include "menus/rtlmenu.h"
X#include "support.h"
X 
X#define MIN(x, y)	((x) <= (y) ? (x) : (y))
X#define MAX(x, y)	((x) >= (y) ? (x) : (y))
X#define VOLUME_PERCENTAGE(x)	((x)*14) 
X#define ModMask 0xFF
X#define ButtonMask(b)	(((b)==Button1) ? Button1Mask : \
X			  (((b)==Button2) ? Button2Mask : Button3Mask))
X
X#define DEF_DELTA		1
X#define DEF_FUNC		GXcopy
X#define DEF_ICON_BORDER_WIDTH 	2
X#define DEF_ICON_PAD		4
X#define DEF_POP_BORDER_WIDTH 	2
X#define DEF_POP_PAD		4
X#define DEF_MENU_BORDER_WIDTH 	2
X#define DEF_MENU_PAD		4
X#define DEF_GADGET_PAD		3
X#define DEF_GADGET_BORDER	1
X#define DEF_TITLE_PAD		2
X#define DEF_VOLUME		4
X#define DEF_PUSH		5
X#define DEF_BCONTEXT_WIDTH	0
X#define DEF_RAISE_DELAY		100	/* milliseconds */
X#define DEF_MAX_COLORS		0	/* 0 means take as many as we can */
X#ifndef DEF_BCONTEXT_CURSOR
X#define DEF_BCONTEXT_CURSOR	XC_plus
X#endif	DEF_BCONTEXT_CURSOR
X#ifndef	DEF_TITLE_CURSOR
X#define DEF_TITLE_CURSOR	XC_left_ptr
X#endif	DEF_TITLE_CURSOR
X#ifndef	NAME
X#define NAME			"awm"
X#endif	NAME
X#ifndef CLASS
X#define	CLASS			"Wm"
X#endif	CLASS
X#ifndef	DEF_FONT
X#define	DEF_FONT		"fixed"
X#endif	DEF_FONT
X#ifndef	DEF_TITLE_FONT
X#define	DEF_TITLE_FONT		"8x13"
X#endif	DEF_TITLE_FONT
X#ifndef	DEF_ICON_FONT
X#define	DEF_ICON_FONT		"8x13"
X#endif	DEF_ICON_FONT
X#ifndef	DEF_POPUP_FONT
X#define	DEF_POPUP_FONT		"9x15"
X#endif	DEF_POPUP_FONT
X#ifndef	DEF_GADGET_FONT
X#define DEF_GADGET_FONT		"fixed"
X#endif	DEF_GADGET_FONT
X#ifndef	DEF_MENU_FONT
X#define	DEF_MENU_FONT		"8x13"
X#endif	DEF_MENU_FONT
X#ifndef	DEF_BOLD_FONT
X#define	DEF_BOLD_FONT		"8x13bold"
X#endif	DEF_BOLD_FONT
X#define DEF_MENU_DELTA		20
X#ifndef DEF_NAME
X#define DEF_NAME		"NoName" /* for clients w/no name */
X#endif
X
X#define INIT_PTEXT		{'0', '0', '0', 'x', '0', '0', '0'}
X
X#ifndef TEMPFILE
X#define TEMPFILE		"/tmp/awm.XXXXXX"
X#endif	TEMPFILE
X
X#define CURSOR_WIDTH		16
X#define CURSOR_HEIGHT		16
X 
X#define MAX_ZAP_VECTORS		8
X#define MAX_BOX_VECTORS		20
X 
X#define DRAW_WIDTH		0 	/* use fastest hardware draw */
X#define DRAW_VALUE		0xfd
X#define DRAW_FUNC		GXxor
X#define DRAW_PLANES		1
X
X#define NOCOLOR			-1
X
X/*
X * The first BITS_USED bits of the mask are used to define the most generic
X * types. All other bits are free for storing peripheral information.
X * For now, we use the extra bits to specify which gadget(s) are bound
X * to an action. MAX_GADGETS depends on BITS_USED to determine the maximum
X * number of gadgets possible. If you add a new context type, be sure to
X * increment BITS_USED.
X */
X#define ROOT			0x1
X#define WINDOW			0x2
X#define ICON			0x4
X#define TITLE			0x8
X#define BORDER			0x10
X#define GADGET			0x20
X
X#define BITS_USED		6
X
X/* Window states */
X#define ST_WINDOW	0x1
X#define ST_ICON		0x2
X#define ST_PLACED	0x4
X#define ST_DECORATED	0x8
X
X#define DECORATED(a) (a && (a->state & ST_DECORATED))
X
X/* Window attributes */
X#define AT_NONE		0x0
X#define AT_TITLE	0x1
X#define AT_GADGETS	0x2
X#define AT_RAISE	0x4
X#define AT_BORDER	0x8
X#define AT_INPUT	0x10
X#define AT_ICONLABEL	0x20
X
X/*
X * Gadgets aren't the sort of embellishments that one uses in quantitity
X * (unless one is designing a truly odd interface), so we keep the information
X * in an array instead of using the usual linked list. MAX_GADGETS is a derived
X * macro (see BITS_USED) that is used to determine the size of the
X * Array.
X *
X */
X#define MAX_GADGETS		((sizeof(int) * 8) - BITS_USED)
X
X#ifndef FAILURE
X#define FAILURE	0
X#endif	FAILURE
X
X#define NAME_LEN		256L	/* Maximum length string names */
X#define EVENTMASK		(ButtonPressMask | ButtonReleaseMask)
X
X
X#define DrawBox() XDrawSegments(dpy, RootWindow(dpy, scr),DrawGC,box,num_vectors)
X#define DrawZap() XDrawSegments(dpy, RootWindow(dpy, scr),DrawGC,zap,num_vectors)
X
X#define gray_width 16
X#define gray_height 16
Xextern char gray_bits[];
X
X#define solid_width 16
X#define solid_height 16
Xextern char solid_bits[];
X 
X#define xlogo32_width 32
X#define xlogo32_height 32
Xextern char xlogo32_bits[];
X
X/*
X * All one needs to know about an awm managed window.. (so far...)
X */
X#ifdef WMSTATE
X#define WithdrawState	0
X#define NormalState	1
X#define IconicState	3
X
Xtypedef struct {
X  int state;
X  Window icon;
X} WM_STATE;
X
Xextern Atom wm_state_atom;
X#endif /* WMSTATE */
X
X
Xtypedef struct _awminfo {
X     Window title, client, frame, icon;	/* Associated windows */
X     Window *gadgets;			/* associated gadgets */
X     char *name;			/* The formatted window name */
X     Boolean own;			/* Do we own the icon window? */
X     Pixmap back, bold, iconPixmap;	/* background, bold and icon pix */
X     Pixmap BC_back, BC_bold;		/* BC back and bold pixmaps */
X#ifdef RAINBOW
X     /* Per window versions of the globals colours */
X     Pixmap grayPixmap, solidPixmap;
X     Pixmap iBackPixmap;
X     Pixel foreColor, backColor;
X     Pixel iBorder;
X     Pixel iBackground, iForeground;
X     Pixel iTextForeground, iTextBackground;
X#endif
X     unsigned int border_width;		/* original border width */
X     int state;				/* The state of the window */
X     int attrs;				/* Window "attributes" */
X     GC winGC;				/* GC at proper depth for window */
X#ifdef WMSTATE
X     WM_STATE wm_state;
X#endif /* WMSTATE */
X} AwmInfo, *AwmInfoPtr;
X
X/*
X * This whole section has changed substantially. Basically, since all the
X * variables have vanished into the resource manager, the keyword table
X * only needs to keep track of function pointers, boolean pointers and
X * "special" keywords like menu and gagdet. Since some things are still
X * modifiable from menus (only booleans, currently, though this will change),
X * we keep these in the keyword table even though
X * they're no longer directly modifable from the .awmrc
X */
X
X/*
X * Keyword table entry.
X */
Xtypedef struct _keyword {
X     char *name;
X     int type;
X     Boolean *bptr;
X     Boolean (*fptr)();
X} Keyword;
X
X/*
X * Keyword table type entry.
X */
X#define IsFunction	1
X#define IsMenuMap	2
X#define IsMenu		3
X#define IsDownFunction	4
X#define IsParser	5
X#define IsQuitFunction	6
X#define IsGadget	7
X#define IsBoolean	8
X#define IsAction	9
X
X/*
X * Button/key binding type.
X */
Xtypedef struct _binding {
X    struct _binding *next;
X    int context;
X    unsigned int mask;
X    int button;
X    Boolean (*func)();
X    char *menuname;
X    RTLMenu menu;
X} Binding;
X 
X/*
X * Key expression type.
X */
Xtypedef struct _keyexpr {
X    char *name;
X    int mask;
X} KeyExpr;
X 
X/*
X * Context expression type.
X */
Xtypedef struct _contexpr {
X    char *name;
X    int mask;
X} ContExpr;
X
X/*
X * Button modifier type.
X */
Xtypedef struct _buttonmodifier {
X    char *name;
X    int mask;
X} ButtonModifier;
X
X/*
X * Gravity expression type.
X */
Xtypedef struct _gravityexpr {
X     char *name;
X     int mask;
X} GravityExpr;
X
X/*
X * Button modifier mask definitions.
X * bits 13 and 14 unused in key masks, according to X.h
X * steal bit 15, since we don't use AnyModifier
X */
X
X#define DeltaMotion	(1<<13)
X#define ButtonUp	(1<<14)
X#define ButtonDown	AnyModifier
X#define ButtonMods	DeltaMotion+ButtonUp+ButtonDown
X
X/* 
X * Button and mask redefinitions, for X11
X */
X#define LeftMask 	Button1Mask
X#define MiddleMask 	Button2Mask
X#define RightMask 	Button3Mask
X#define LeftButton	Button1
X#define MiddleButton	Button2
X#define RightButton	Button3
X
X/*
X * Declaration specific information for gadgets. This defines only gadget
X * types, not the actual gadgets. The pixmap member is only used if a pixmap
X * is being displayed. Gravity and offset are purely optional.
X */
X
X#define NoGadgetGravity		0
X#define LeftGadgetGravity	1
X#define RightGadgetGravity	2
X#define CenterGadgetGravity	3
X
Xtypedef struct _gadgetdecl {	/*   Declaration (type) information */
X     unsigned char *name;	/* Either text label or pixmap file name */
X     unsigned char *data;	/* If pixmap file, this is the data from it */
X     char *forecolor;		/* foreground color for pixmap */
X     char *backcolor;		/* background color for pixmap */
X     XFontStruct *fontInfo;	/* font for text */
X     int high, wide;		/* width and height of pixmap or text */
X     int gravity;		/* stick to the left or right? */
X     int offset;		/* offset from previous item */
X} GadgetDecl;
X
X/*
X * MenuInfo data type.
X */
Xtypedef struct _menuinfo {
X    char *name;			/* Name of this menu. */
X    char *pixmapname;		/* Name of label pixmap (opt) */
X    RTLMenu menu;		/* RTL menu handle for destroy */
X    struct _actionline *line;	/* Linked list of menu items. */
X} MenuInfo;
X 
X/*
X * Action Line data type.
X */
Xtypedef struct _actionline {
X    struct _actionline *next;	/* Pointer to next line. */
X    char *name;			/* Name of this line. */
X    char *pixmapname;		/* Name of the backing pixmap (opt) */
X    int type;			/* IsShellCommand, IsText, IsTextNL... */
X    RTLMenuItem item;		/* RTL item handle */
X    char *text;			/* Text string to be acted upon. */
X    Boolean (*func)();		/* Window manager function to be invoked. */
X} ActionLine;
X 
X/*
X * ActionLine->type definitions.
X */
X#define IsShellCommand		1
X#define IsText			2
X#define IsTextNL		3
X#define IsUwmFunction		4
X#define IsMenuFunction		5
X#define IsImmFunction		6	/* Immediate (context-less) function. */
X#define IsVar			7	/* we're setting a boolean variable */
X 
X/*
X * Menu Link data type.  Used by the parser when creating a linked list
X * of menus. 
X */
Xtypedef struct _menulink {
X    struct _menulink *next;	/* Pointer to next MenuLink. */
X    struct _menuinfo *menu;	/* Pointer to the menu in this link. */
X} MenuLink;
X
X/*
X * External variable definitions.
X */
Xextern int errno;
Xextern Window Pop;		/* Pop-up dimension display window. */
Xextern Window Frozen;		/* Contains window id of "gridded" window. */
Xextern XFontStruct *IFontInfo;	/* Icon text font information. */
Xextern XFontStruct *PFontInfo;	/* Pop-up text font information. */
Xextern XFontStruct *TFontInfo;	/* Title text font information. */
Xextern XFontStruct *TFontBoldInfo;/* Title text (bold) font information. */
Xextern XFontStruct *GFontInfo; /* Gadget box text font */
Xextern XFontStruct *MFontInfo;	/* Menu font */
Xextern XFontStruct *MBoldFontInfo;/* Menu bold font */
Xextern Pixmap GrayPixmap;	/* Gray pixmap. */
Xextern Pixmap SolidPixmap;
Xextern Pixmap IBackPixmap;	/* Icon window background pixmap. */
Xextern Pixmap IDefPixmap;	/* Icon pixmap for twm style icons */
Xextern char *BForeground;	/* Border Context (pixmap) foreground pixel */
Xextern char *BBackground;	/* Border Context (pixmap) background pixel */
Xextern char *WBorder;		/* Window border pixel */
Xextern char *TTextForeground;	/* Title text foreground pixel */
Xextern char *TTextBackground;	/* Title text background pixel */
Xextern char *TForeground;	/* Title (pixmap) foreground pixel */
Xextern char *TBackground;	/* Title (pixmap) background pixel */
Xextern char *Foreground;	/* default forground color (text) */
Xextern char *Background;	/* default background color (text) */
Xextern Pixel IBorder;		/* Icon window border pixel. */
Xextern Pixel ITextForeground;	/* Icon window text forground color. */
Xextern Pixel ITextBackground;	/* Icon window text background color. */
Xextern Pixel IForeground;	/* Icon pixmap foreground color */
Xextern Pixel IBackground;	/* Icon pixmap background color */
Xextern Pixel PForeground;	/* Pop-up window forground color. */
Xextern Pixel PBackground;	/* Pop-up window background color. */
Xextern Pixel PBorder;		/* Pop-Up Window border pixel. */
Xextern Pixel ForeColor;		/* default foreground color */
Xextern Pixel BackColor;		/* default background color */
Xextern Pixel MBorder;		/* Menu border color */
Xextern Pixel MForeground;	/* Menu foreground color */
Xextern Pixel MBackground;	/* Menu background color */
Xextern Cursor ArrowCrossCursor; /* Arrow cross cursor. */
Xextern Cursor TextCursor;	/* Text cursor used in icon windows. */
Xextern Cursor IconCursor;	/* Icon Cursor. */
Xextern Cursor LeftButtonCursor;	/* Left button main cursor. */
Xextern Cursor MiddleButtonCursor;/* Middle button main cursor. */
Xextern Cursor RightButtonCursor;/* Right button main cursor. */
Xextern Cursor TargetCursor;	/* Target (select-a-window) cursor. */
Xextern Cursor TitleCursor;	/* Title bar cursor */
Xextern Cursor FrameCursor;	/* Frame cursor */
Xextern Cursor GumbyCursor;	/* Used in icons if not type-in   */
Xextern unsigned int GadgetBorder;	/* Width of gadget borders */
Xextern int ScreenWidth;		/* Display screen width. */
Xextern int ScreenHeight;	/* Display screen height. */
Xextern int TitleHeight;		/* Height in pixels of title bar(s) */
Xextern int titleHeight;		/* Derived height of title bar(s) */
Xextern int gadgetHeight;	/* Height of highest gadget */
Xextern int NameOffset;		/* Offset for window name */
Xextern int IBorderWidth;	/* Icon window border width. */
Xextern int PWidth;		/* Pop-up window width (including borders). */
Xextern int PHeight;		/* Pop-up window height (including borders). */
Xextern unsigned int PBorderWidth;	/* Pop-up window border width. */
Xextern int PPadding;		/* Pop-up window padding. */
Xextern int Delta;		/* Mouse movement slop. */
Xextern int HIconPad;		/* Icon horizontal padding. */
Xextern int VIconPad;		/* Icon vertical padding. */
Xextern int Pushval;		/* Number of pixels to push window by. */
Xextern int BContext;		/* Width of border context area in pixels */
Xextern int RaiseDelay;		/* Delay in milliseconds before autoraising windows */
Xextern int Volume;		/* Audible alarm volume. */
Xextern int NumGadgets;		/* Number of gadgets used */
Xextern int GadgetPad;		/* Padding between gadgets */
Xextern int TitlePad;		/* Title text padding */
Xextern int status;		/* Routine return status. */
Xextern int MPad;		/* menu padding */
Xextern int MDelta;		/* Menu subitem delta */
Xextern int MBorderWidth;	/* Menu border width */
Xextern int MItemBorder;		/* Menu item border width */
Xextern unsigned int BCursor;	/* Border context cursor */
Xextern unsigned int TCursor;	/* Title context cursor */
Xextern MenuLink *Menus;		/* Linked list of menus. */
Xextern GC  IconGC;		/* graphics context for icon */
Xextern GC  PopGC;		/* graphics context for pop */
Xextern GC  DrawGC;		/* graphics context for zap */
X
Xextern Boolean Autoraise;	/* Raise window on input focus? */
Xextern Boolean Autoselect;	/* Warp mouse to default menu selection? */
Xextern Boolean Borders;		/* Display border context areas? */
Xextern Boolean ConstrainResize;	/* Don't resize until pointer leaves window */
Xextern Boolean Freeze;		/* Freeze server during move/resize? */
Xextern Boolean Grid;		/* Should the m/r box contain a 9 seg. grid. */
Xextern Boolean Hilite;		/* Should we highlight titles on focus? */
Xextern Boolean BorderHilite;	/* Should we highlight borders on focus? */
Xextern Boolean FrameFocus;	/* Should frame be considered part of window */
Xextern Boolean ShowName;	/* Display names in title bars */
Xextern Boolean NWindow;		/* Normalize windows? */
Xextern Boolean NIcon;		/* Normalize icons? */
Xextern Boolean RootResizeBox;	/* Should resize box obscure window? */
Xextern Boolean InstallColormap;	/* Install colormap for clients? */
Xextern Boolean Push;		/* Relative=TRUE, Absolute=FALSE. */
Xextern Boolean ResizeRelative;	/* Relative=TRUE, Absolute=FALSE. */
Xextern Boolean Reverse;		/* Reverse video? */
Xextern Boolean SaveUnder;	/* Save unders? */
Xextern Boolean Snatched;	/* We're in the middle of an no-highlight/raise op */
Xextern Boolean Titles;		/* Title bars on windows? */
Xextern Boolean IconLabels;	/* Labels on pixmap icons? (twm style) */
Xextern Boolean ILabelTop;	/* label top of icon? */
Xextern Boolean PushDown;	/* Down=TRUE, Up=FALSE */
Xextern Boolean UseGadgets;	/* Gadget boxes in title bars? */
Xextern Boolean Wall;		/* Don't allow windows past edges of screen */
Xextern Boolean WarpOnRaise;	/* Warp to upper right corner on raise. */
Xextern Boolean WarpOnIconify;   /* Warp to icon center on iconify. */
Xextern Boolean WarpOnDeIconify; /* Warp to upper right corner on de-iconify. */
Xextern Boolean Zap;		/* Should the the zap effect be used. */
Xextern Boolean FocusSetByUser;  /* True if f.focus called */
Xextern Boolean FocusSetByWM;	/* True if awm set the focus */
X 
Xextern char PText[];		/* Pop-up window dummy text. */
Xextern int PTextSize;		/* Pop-up window dummy text size. */
X
Xextern int Lineno;		/* Line count for parser. */
Xextern Boolean Startup_File_Error; /* Startup file error flag. */
Xextern char Startup_File[];	/* Startup file name. */
Xextern char *IFontName;		/* Icon font name. */
Xextern char *PFontName;		/* Pop-up font name. */
Xextern char *TFontName;		/* Title font name. */
Xextern char *GFontName;		/* Gadget font name */
Xextern char *TFontBoldName;	/* Bold Title font name. */
Xextern char *TBoldPixmapName;	/* Title (highlighted) pixmap file */
Xextern char *TBackPixmapData;	/* Bitmap data file title background */
Xextern char *TBoldPixmapData;	/* ditto, except highlighted */
Xextern char *BBackPixmapData;	/* Border Context area background pixmap data */
Xextern char *BBoldPixmapData;	/* Border Context bold pixmap data */
Xextern char *awmPath;		/* Pathlist for pixmap files */
Xextern char **Argv;		/* Pointer to command line parameters. */
Xextern char **Environ;		/* Pointer to environment. */
X 
Xextern char *DefaultBindings[];	/* Default bindings string array. */
Xextern Keyword KeywordTable[];	/* Keyword lookup table. */
Xextern Binding *Blist;		/* Button/key bindings list. */
Xextern KeyExpr KeyExprTbl[];	/* Key expression table. */
Xextern ContExpr ContExprTbl[];	/* Context expression table. */
Xextern ButtonModifier ButtModTbl[];/* Button modifier table. */
Xextern GravityExpr GravityExprTbl[]; /* Gravity expression table. */
X
Xextern GadgetDecl **Gadgets;	/* Gadgets declared. See gram.y */
Xextern int scr;
Xextern Display *dpy;		/* Display info pointer. */
X 
X#ifdef PROFIL
Xint ptrap();
X#endif
X 
X/*
X * External routine typing.
X */
Xextern Boolean Beep();
Xextern Boolean CircleDown();
Xextern Boolean CircleUp();
Xextern Boolean Continue();
Xextern Boolean Focus();
Xextern Boolean UnFocus();
Xextern Boolean GetButton();
Xextern Boolean Iconify();
Xextern Boolean Lower();
Xextern Boolean DoMenu();
Xextern Boolean DoAction();
Xextern Boolean Lock();
Xextern Boolean Move();
Xextern Boolean MoveOpaque();
Xextern Boolean Neaten();
Xextern Boolean NewIconify();
Xextern Boolean Pause();
Xextern Boolean ShoveDown();
Xextern Boolean ShoveLeft();
Xextern Boolean ShoveRight();
Xextern Boolean ShoveUp();
Xextern Boolean Quit();
Xextern Boolean Raise();
Xextern Boolean Redraw();
Xextern Boolean Refresh();
Xextern Boolean ResetBindings();
Xextern Boolean ResetMenus();
Xextern Boolean ResetGadgets();
Xextern Boolean Resize();
Xextern Boolean Restart();
Xextern Boolean FDecorate();
Xextern Boolean FNoDecorate();
Xextern Boolean DestroyClient();
Xextern Boolean GetBoolRes();
Xextern Boolean ConfigureWindow();
Xextern int StoreCursors();
Xextern int StoreBox();
Xextern int StoreTitleBox();
Xextern int StoreGridBox();
Xextern int StoreTitleGridBox();
Xextern int StoreZap();
Xextern int Error();
Xextern int XError();
Xextern int GetIntRes();
Xextern Window Reparent(), Decorate();
Xextern unsigned char *expand_metachars();
Xextern char *stash();
Xextern char *GetIconName();
Xextern char *expand_from_path();
Xextern char *GetStringRes();
Xextern char *GetPixmapDataRes();
Xextern Pixmap GetPixmapRes();
Xextern Pixel GetColorRes();
Xextern Pixel GetPixel();
Xextern XFontStruct *GetFontRes();
Xextern Drawable GetPixmapFromCache();
Xextern AwmInfoPtr GetAwmInfo();
Xextern AwmInfoPtr RegisterWindow();
Xextern AwmInfoPtr IsTitled();
Xextern AwmInfoPtr IsGadgetWin();
X
Xextern void Init_Titles(), Init_Frames();
Xextern void NoDecorate();
Xextern void PaintTitle();
Xextern void SetBorderPixmaps();
Xextern void FreePixmapFromCache();
X
X#ifdef	NEATEN
X#define DEFAULT_ABS_MIN		64
X#define SEPARATION		2
X#define DEF_PRIMARY_PLACEMENT	"Top"
X#define DEF_SECONDARY_PLACEMENT	"Left"
X
Xextern int AbsMinWidth;
Xextern int AbsMinHeight;
Xextern Boolean RetainSize;
Xextern Boolean KeepOpen;
Xextern Boolean Fill;
Xextern Boolean UsePriorities;
Xextern Boolean FixTopOfStack;
Xextern char *PrimaryIconPlacement;
Xextern char *SecondaryIconPlacement;
X#endif	NEATEN
X#endif AWM_INCLUDE
END_OF_FILE
if test 22317 -ne `wc -c <'awm.h'`; then
    echo shar: \"'awm.h'\" unpacked with wrong size!
fi
# end of 'awm.h'
fi
if test -f 'menus/track_menu.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'menus/track_menu.c'\"
else
echo shar: Extracting \"'menus/track_menu.c'\" \(26567 characters\)
sed "s/^X//" >'menus/track_menu.c' <<'END_OF_FILE'
X
X#ifndef lint
X     static char sccs_id[] = "@(#)track_menu.c	2.1 12/16/87  Siemens Corporate Research and Support, Inc.";
X#endif
X
X
X#include "X11/copyright.h"
X
X/* 
X  RTL Menu Package Version 1.0
X  by Joe Camaratta and Mike Berman, Siemens RTL, Princeton NJ, 1987
X  
X  track_menu.c: bring up menus and track the mouse
X  */
X
X/*
X *
X * Copyright 1987, 1988 by Ardent Computer Corporation, Sunnyvale, Ca.
X *
X * Copyright 1987 by Jordan Hubbard.
X *
X *
X *                         All Rights Reserved
X *
X * Permission to use, copy, modify, and distribute this software and its
X * documentation for any purpose and without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and that
X * both that copyright notice and this permission notice appear in
X * supporting documentation, and that the name of Ardent Computer
X * Corporation or Jordan Hubbard not be used in advertising or publicity
X * pertaining to distribution of the software without specific, written
X * prior permission.
X *
X */
X
X
X/*
X  
X  Copyright 1987 by
X  Siemens Corporate Research and Support, Inc., Princeton, New Jersey
X  
X  Permission to use, copy, modify, and distribute this software
X  and its documentation for any purpose and without fee is
X  hereby granted, provided that the above copyright notice
X  appear in all copies and that both that copyright notice and
X  this permission notice appear in supporting documentation, and
X  that the name of Siemens not be used in advertising or
X  publicity pertaining to distribution of the software without
X  specific, written prior permission.  Siemens makes no
X  representations about the suitability of this software for any
X  purpose.  It is provided "as is" without express or implied
X  warranty.
X  
X  */
X
X/*
X * The menu package will break if you don't define this, but
X * it's there in case you want to see just how and where the
X * "eventstack" stuff is used and, if necessary, replace it.
X */
X#define SAVE_EVENTS
X
X
X#include <stdio.h>
X#include "X11/Xlib.h"
X#include "X11/cursorfont.h"
X#include "arrow_icon.h"
X#include "null_icon.h"
X#include "menu.h"
X#include "menu.def.h"
X#include "menu.ext.h"
X#include "dbug.h"
X#ifdef SAVE_EVENTS
X#include "eventstack.h"
X#endif
X
X#define MIN(x,y) (((x) <= (y))? x:y)
X#define MAX(x,y) (((x) >= (y))? x:y)
X
X#define CLICK_TIME 290 /* in milliseconds */
X
X#define CursorLockMask (ButtonReleaseMask | ExposureMask)
X
X/* Event macros */
X
X#define EventGetXCoord(rep) ((rep).xmotion.x)
X#define EventGetYCoord(rep) ((rep).xmotion.y)
X#define EventType(rep) ((rep).type)
X#define EventXWindow(rep) ((rep).xcrossing.window)
X#define EventXTime(rep) ((rep).xcrossing.time)
X#define EventXMode(rep) ((rep).xcrossing.mode)
X#define EventXRootX(rep) ((rep).xcrossing.x_root)
X#define EventXRootY(rep) ((rep).xcrossing.y_root)
X#define EventXDetail(rep) ((rep).xcrossing.detail)
X#define EventMWindow(rep) ((rep).xmotion.window)
X#define EventMTime(rep) ((rep).xmotion.time)
X#define EventButton(rep) ((rep).xbutton.button)
X#define EventBWindow(rep) ((rep).xbutton.window)
X#define EventBTime(rep) ((rep).xbutton.time)
X#define EventEX(rep) ((rep).xexpose.x)
X#define EventEY(rep) ((rep).xexpose.y)
X#define EventEWidth(rep) ((rep).xexpose.width)
X#define EventEHeight(rep) ((rep).xexpose.height)
X#define PointerEvent(rep) \
X     ((EventType(rep) == ButtonPress) || \
X      (EventType(rep) == ButtonRelease) || \
X      (EventType(rep) == MotionNotify) || \
X      (EventType(rep) == EnterNotify) || \
X      (EventType(rep) == LeaveNotify) || \
X      (EventType(rep) == FocusIn) || \
X      (EventType(rep) == FocusOut))
X#define KeyEvent(rep) \
X     ((EventType(rep) == KeyPress) || (EventType(rep) == KeyRelease))
X/* Possible states for the state machine */
Xtypedef enum
X{
X     Initial,      /* Inside a submenu, but not any item */
X     CheckTrigger, /* Inside an item that has submenu, checking for pullright */
X     Leaf,         /* Inside an item with no submenu */
X     Exit,         /* Preparing to exit */
X     LevelControl  /* Not in any submenu, waiting to enter something */
X     } State;
X
XState InitialState(), CheckTriggerState(), LeafState(), LevelControlState(),
X     GetItemState();
XBoolean EventNotSignificant(), PushSubmenu();
X
Xvoid OutputEvent(), GetNextSignificantEvent(), PopSubmenu(), 
X     Highlight(), Unhighlight(), DisplayInitialMenus(), LockCursor(),
X     TossExtraMoves(), UnlockCursor();
X
Xvoid ProcessExposeEvents();
X
Xvoid SaveTest();
X
XMenuItem *MenuGetItem();
XMenu *MenuGetMenu();
X
X/* global state variables */
X
Xstatic MenuItem *current_item;
Xstatic Menu *current_menu;
Xstatic Window root_window;
Xextern Display *dpy;
Xextern int scr;
Xstatic int level;            /* submenu level */
Xstatic Time button_time;     /* time button press invoked */
Xstatic Cursor wait_cursor = None;  /* empty cursor for lock state */
Xstatic Boolean click_allowed;
Xstatic Boolean lock_event_mask, unlock_event_mask;
X
Xextern Boolean Autoselect;
Xextern int MDelta;
X
X#ifdef SAVE_EVENTS
Xstatic struct Ev_q *ev_save = 0;
X#endif
X
X
XMenuItem *TrackMenu(root_menu, root_x, root_y, 
X		    init_button, root, buttime)
XMenu *root_menu;    /* Pointer to root menu requested to pop up   */
Xint root_x, root_y; /* Position to start menu                     */
Xint init_button;    /* The # of button used to pop up menu        */
XWindow root;        /* Window label for parent of menu            */
XTime buttime;       /* timestamp for button (or 0, if CLICK == 0) */
X{
X     State CurrentState = LevelControl;
X     XEvent Event_Reply;
X     int open_x;
X     Boolean selected = FALSE;
X     MenuItem *selected_item;
X     
X     Entry("TrackMenu")
X     
X     /* Initialize globals */
X     
X     button_time = buttime;
X     root_window = root;
X     level = 0;
X     current_menu = root_menu;
X     click_allowed = (TestOptionFlag(current_menu, clickokay))? TRUE : FALSE;
X     unlock_event_mask = (TestOptionFlag(current_menu, savebits))?
X	  MenuEventMask : (MenuEventMask | ExposureMask);
X     lock_event_mask = (TestOptionFlag(current_menu, savebits))?
X	  CursorLockMask : (CursorLockMask | ExposureMask);
X     
X     /* If not already done, set up the null cursor for lock state */
X     if (wait_cursor == None)
X     {
X	  Pixmap wc_pixmap;
X	  XColor fg, bg;
X	  
X	  wc_pixmap = XCreateBitmapFromData (dpy, root_window,
X					     null_icon_bits,
X					     null_icon_width, null_icon_height);
X	  wait_cursor = XCreatePixmapCursor (dpy, wc_pixmap, wc_pixmap,
X					     &fg, &bg, 1, 1);
X     }
X     
X     
X     /* Block all other action by grabbing the server */
X     /*    XGrabServer (dpy); */
X     /* Don't think we need to grab the server... so for now, we won't */
X     
X#ifdef SAVE_EVENTS     
X     /* Get the present state, so it can be restored later */
X     /* Any events on the queue when we start get saved now, restored later */
X     SaveEvents (dpy, &ev_save, ~(unsigned long) ButtonReleaseMask);
X#endif
X     
X     LockCursor(root_window);
X     if (!(current_item =
X	   Display_Menu(current_menu, NULLMENU, root_x, root_y)))
X     {
X	  CurrentState = Exit;
X     }
X     /*
X      * First item is a label and autoselect is on, so we want
X      * to push on to the first "real" item.
X      */
X     if (ItemIsDeaf(current_item) && Autoselect)
X	  current_item = current_item->nextItem;
X     LockCursor(ItemWindow(current_item));
X     open_x = root_x;
X     
X     /* Push to appropriate previous item, if any */
X     while (MenuHasInitialItem(current_menu) && (CurrentState != Exit))
X     {
X	  current_item = GetInitialItem(current_menu);
X	  ClearInitialItem(current_menu);
X	  
X	  /* if the initial item can't be selected, take first in list */
X	  if (ItemIsNull(current_item) || ItemIsDisabled(current_item))
X	  {
X	       current_item = MenuItems(current_menu);
X	       break;
X	  }
X	  else if (ItemIsLeaf(current_item)) /* then we're done */
X	       break;
X	  else
X	  {
X	       open_x += ItemGetArrowPosition(current_item);
X	       if (!ItemIsDeaf(current_item))
X		    Highlight(current_item);
X	       TossExtraMoves(ItemWindow(current_item));
X	       (void)PushSubmenu(open_x);
X	  }
X     }
X     ProcessExposeEvents();
X     if (CurrentState != Exit)
X	  CurrentState = (ItemIsLeaf(current_item)) ? Leaf : CheckTrigger;
X     if (!ItemIsDeaf(current_item))
X	  Highlight(current_item);
X     XSync (dpy, 0);  /* get release click, if it's in queue */
X#ifdef SAVE_EVENTS
X     DisposeEvents(dpy, (PointerMotionMask | EnterWindowMask |
X			 LeaveWindowMask | ExposureMask));
X#endif
X     LockCursor(ItemWindow(current_item));
X     PlacePointer(current_menu,current_item); 
X     UnlockCursor();
X     	
X     /* State Machine */
X     
X     while (CurrentState != Exit)
X     {
X	  GetNextSignificantEvent(&Event_Reply, init_button);
X	  switch (CurrentState)
X	  {
X	  case LevelControl:
X	       CurrentState = LevelControlState(Event_Reply);
X	       break;
X	  case Initial:
X	       CurrentState = InitialState(Event_Reply);
X	       break;
X	  case CheckTrigger:
X	       CurrentState = CheckTriggerState(Event_Reply);
X	       break;
X	  case Leaf:
X	       CurrentState = LeafState(Event_Reply, &selected);
X	       break;
X	  default:
X	       Retch("(RTLmenu) YOW! Unknown State! (%d)\n",
X		     CurrentState);
X	       CurrentState = Exit;
X	       break;
X	  }
X     }
X     /* Clean up and exit */
X     
X     selected_item = (selected)? current_item : NULLITEM;
X     while (level)
X     {
X	  if (selected)
X	       SetInitialItem(current_menu, current_item);
X	  PopSubmenu();
X     }
X     if (selected)
X     {
X	  SetInitialItem(current_menu, current_item);
X     }
X     
X     Undisplay_Menu(current_menu);
X     UnlockCursor();
X     XUngrabPointer(dpy, CurrentTime);
X     
X     /* Throw out any left over events from menu world */
X     /*    if (TestOptionFlag(current_menu, savebits)) {
X	   XSync(dpy,1); 
X	   XUngrabServer(dpy, CurrentTime);  add this if grab added! 
X	   }
X	   else
X	   XSync(dpy,0);*/
X     
X     /* Push back any events that were lying around when menus started */
X     
X     XFlush(dpy);
X#ifdef SAVE_EVENTS
X     DisposeEvents(dpy, (PointerMotionMask | EnterWindowMask |
X			 LeaveWindowMask | ExposureMask));
X     RestoreEvents(dpy, &ev_save);
X#endif
X     Leave(selected_item)
X}
X
X/* Used for debugging */
X
Xvoid OutputEvent(Event_Reply)
XXEvent Event_Reply;
X{
X     Entry("OutputEvent")
X
X     switch (EventType(Event_Reply))
X     {
X     case ButtonPress:
X     case ButtonRelease:
X	  DBUG_5("RTLmenu","Button Press/Release, button %d on window %d at time %d\n",
X		 EventButton(Event_Reply), EventBWindow(Event_Reply), 
X		 EventBTime(Event_Reply));
X	  break;
X     case MotionNotify:
X	  DBUG_5("RTLmenu","Motion Notify on window %d at time %d, x=%d\n", 
X		 EventMWindow(Event_Reply), EventMTime(Event_Reply),
X		 EventGetXCoord(Event_Reply));
X	  break;
X     case EnterNotify:
X	  DBUG_4("RTLmenu","Enter Notify on window %d at time %d\n",
X		 EventXWindow(Event_Reply), EventXTime(Event_Reply));
X	  break;
X     case LeaveNotify:
X	  DBUG_4("RTLmenu","Leave Notify on window %d at time %d\n",
X		 EventXWindow(Event_Reply), EventXTime(Event_Reply));
X	  break;
X     default:
X	  DBUG_3("RTLmenu","Unexpected event type %d\n", EventType(Event_Reply));
X	  break;
X     }
X     Leave_void
X}
X
Xstatic Boolean locked = FALSE;
X
X/* Lock the cursor: make it disappear, and ignore events it generates.  */
X/* Optionally, confine it to a single window.                           */
X/* (Using "None" for confine_window doesn't confine it.    )            */
Xvoid LockCursor(confine_window)
XWindow confine_window;
X{
X     int result;
X     
X     Entry("LockCursor")
X     
X     locked = TRUE;
X     result = XGrabPointer(dpy,
X			   RootWindow(dpy, MenuScreen(current_menu)),
X			   True, lock_event_mask, GrabModeSync, 
X			   GrabModeAsync, confine_window,
X			   wait_cursor, CurrentTime);
X     DBUG_3("RTLmenu","Lock Cursor grab = %d\n",result);
X     Leave_void
X}
X
X/* Unlock (and unconfine) the cursor.  If cursor lock is not set,    */
X/* this does nothing.                                                */
X
Xvoid UnlockCursor()
X{
X     int result;
X     
X     Entry("UnlockCursor")
X     
X     if (locked)
X     {
X	  locked = FALSE;
X	  result = XGrabPointer(dpy, 
X				RootWindow(dpy, MenuScreen(current_menu)),
X				True,  unlock_event_mask,
X				GrabModeAsync, GrabModeAsync, None,
X				MenuCursor(current_menu), CurrentTime);
X	  DBUG_3("RTLmenu","Unlock Cursor grab = %d\n",result);	    
X     }
X     Leave_void
X}
X
X/* Keep getting the X events, until finding one that may be interesting */
X/* to the operation of the state machine. */
X
Xvoid GetNextSignificantEvent(Event_Reply,init_button)
XXEvent *Event_Reply;
Xint init_button;		/* the button that initiated the menu */
X{
X     XEvent Next_Event_Reply;
X     Boolean InsignificantEvent = True;
X     
X     Entry("GetNextSignificantEvent")
X     
X     /* Loop as long as any of a number of "insignificant" events */
X     /* are found; when the event no longer matches one of the tests, */
X     /* it is assumed to be "significant" and returned.*/
X     do
X     {
X	  XNextEvent(dpy, Event_Reply);
X	  DBUG_EXECUTE("RTLmenu", OutputEvent(*Event_Reply));
X	  
X	  /* If this event is an "enter", check whether there is a   */
X	  /* "leave" for the same window already in the queue,       */
X	  /* immediately following it; if so, throw them both out    */
X	  /* and get the next event                                  */
X	  /* NOTE: might try to look further ahead, but this is      */
X	  /* tricky because other events might intervene.            */
X	  
X	  if ((EventType(*Event_Reply) == EnterNotify) &&
X	      (EventXMode(*Event_Reply) == NotifyNormal) &&
X	      (QLength(dpy) > 0) &&
X	      (MenuGetMenu(current_menu, EventXWindow(*Event_Reply))
X	       != current_menu))
X	  {
X	       XPeekEvent(dpy, &Next_Event_Reply);
X	       if ((EventType(Next_Event_Reply) == LeaveNotify) &&
X		   (EventXMode(Next_Event_Reply) == NotifyNormal) &&
X		   (EventXWindow(Next_Event_Reply) == EventXWindow(*Event_Reply)))
X	       {
X		    DBUG_2("RTLmenu","TOSS: Enter/leave pair.\n");
X		    XNextEvent(dpy, Event_Reply);
X		    XNextEvent(dpy, Event_Reply);
X	       }
X	  }
X#ifdef SAVE_EVENTS
X	  if (EventNotSignificant(*Event_Reply, init_button))
X	  {
X	       if (!(PointerEvent(*Event_Reply) || KeyEvent(*Event_Reply)
X		     || EventType(*Event_Reply) == Expose))
X	       {
X		    /* might be significant elsewhere -- save it for later */
X		    AddEventToStore(&ev_save, *Event_Reply);
X	       }
X	  }
X	  else
X#else
X	       if (!EventNotSignificant(*Event_Reply, init_button))
X#endif
X		    InsignificantEvent = FALSE;
X     }
X     while (InsignificantEvent);
X     
X     DBUG_2("RTLmenu","--->");
X     Leave_void
X}
X
X/* Check whether the event matches one of the events considered */
X/* "not significant".*/
XBoolean EventNotSignificant(Event_Reply, init_button)
XXEvent Event_Reply;
Xint init_button;
X{
X     Entry("EventNotSignificant")
X
X     /* Insignificant if not in following list */
X     Leave(!((EventType(Event_Reply) == ButtonRelease) ||
X	       (EventType(Event_Reply) == ButtonPress) ||
X	       (EventType(Event_Reply) == MotionNotify) ||
X	       (EventType(Event_Reply) == EnterNotify) ||
X	       (EventType(Event_Reply) == Expose) ||
X	       (EventType(Event_Reply) == LeaveNotify))
X	     ||
X	     /* Insignificant if leave or enter is not "Normal"  */
X	     (((EventType(Event_Reply) == LeaveNotify) ||
X	       (EventType(Event_Reply) == EnterNotify)) &&
X	      (EventXMode(Event_Reply) != NotifyNormal))
X	     ||
X	     /* Insignificant if hit button other than initial one */
X	     ((EventType(Event_Reply) == ButtonRelease) &&
X	      (EventButton(Event_Reply) != init_button))
X	     ||
X	     /* Insignificant if tail end of a click -- and clicks allowed */
X	     (click_allowed &&
X	      (EventType(Event_Reply) == ButtonRelease) &&
X	      (EventBTime(Event_Reply) - button_time < CLICK_TIME))
X	     )
X}
X
XState LevelControlState(rep)
XXEvent rep;
X{
X     State next_state;
X     Menu *entered_menu;
X     MenuItem *entered_item;
X     
X     Entry("LevelControlState")
X     switch (EventType(rep))
X     {
X     case MotionNotify:
X     case LeaveNotify: 
X	  next_state = LevelControl; /* loop back to this state */
X	  break;
X     case EnterNotify:
X	  /* Decide whether we've entered a menu window or item window */
X	  entered_menu = MenuGetMenu(current_menu, EventXWindow(rep));
X	  entered_item = MenuGetItem(current_menu,EventXWindow(rep));
X	  
X	  if ((MenuIsNull(entered_menu)) && (ItemIsNull(entered_item)))
X	       /* Must be some other window; carry on */
X	       next_state = LevelControl;
X	  else if (!ItemIsNull(entered_item) &&
X		   MenuIsDisplayed(ItemMenu(entered_item)))
X	  {
X	       /* we entered an item, but not a window. This should only happen */
X	       /* when we stayed in the parent of the current submenu.  So,     */
X	       /* Pop that submenu and get to the item.                         */
X	       if (level)
X	       {
X		    LockCursor(ItemWindow(entered_item));
X		    PopSubmenu();
X		    ProcessExposeEvents();
X		    UnlockCursor();
X		    current_item = entered_item;
X		    Highlight(current_item);
X		    next_state = GetItemState(rep);
X	       }
X	       else
X	       { 
X		    Retch("(RTLmenu) Tried to pop the root menu...\n");
X		    next_state = Exit;
X	       }
X	  }
X	  
X	  else if (!MenuIsNull(entered_menu)&&
X		   MenuIsDisplayed(entered_menu))
X	  {
X	       /* entered a menu that is displayed */
X	       while ((current_menu != entered_menu) && level)
X		    /* drop down the menu that was entered */
X		    PopSubmenu();
X	       ProcessExposeEvents();
X	       UnlockCursor();
X	       if (current_menu == entered_menu)
X		    next_state = Initial;
X	       else
X	       {
X		    next_state = Exit;
X		    Retch("(RTLmenu) Couldn't find the menu I entered!!\n");
X	       }
X	  }
X	  else 
X	       next_state = LevelControl;
X	  break;
X     case ButtonRelease:
X	  next_state = Exit;
X	  break;
X     default:
X	  Retch("RTLmenu","YOW! Unexpected event! (%d)\n", rep.type);
X	  next_state = Exit;
X	  break;
X     }
X     Leave(next_state)
X}
X
X/* Figure out the status of the item we've just entered */
XState GetItemState(rep)
XXEvent rep;
X{
X     int open_x;
X     State next_state;
X     
X     Entry("GetItemState")
X     if (ItemIsNull(current_item))
X     {
X	  Retch("(RTLmenu) null current item!");
X	  next_state = Exit;
X     }
X     else if (MenuIsNull(current_menu))
X     {
X	  Retch("(RTLmenu) null current menu!");
X	  next_state = Exit;
X     }
X     else if (ItemIsLeaf(current_item))
X     {
X	  if (MenuHasInitialItem(current_menu))
X	       ClearInitialItem(current_menu);
X	  next_state = Leaf;
X     }
X     else if (EventGetXCoord(rep) >= (int)(ItemGetArrowPosition(current_item) - 4))
X     {
X	  /* entered item in "auto pop-up zone", i.e., over pull-right arrow. */
X	  LockCursor(ItemWindow(current_item));
X	  TossExtraMoves(ItemWindow(current_item));
X	  if (PushSubmenu(EventXRootX(rep)))
X	  {
X	       LockCursor(ItemWindow(current_item));
X	       PlacePointer(current_menu, current_item); 
X	       next_state = Initial;
X	       ProcessExposeEvents();
X	  }
X	  else
X	       next_state = CheckTrigger;
X	  UnlockCursor();
X     }
X     else if (MenuHasInitialItem(current_menu))
X     {
X	  /* Entered menu has initial item -- move to it */
X	  DBUG_2("RTLmenu","Pushing for initial item.");
X	  current_item = GetInitialItem(current_menu);
X	  open_x = ItemGetArrowPosition(current_item) +
X	       EventXRootX(rep);	    
X	  ClearInitialItem(current_menu);
X	  LockCursor(ItemWindow(current_item));
X	  if (PushSubmenu(open_x))
X	  {
X	       ProcessExposeEvents();
X	       LockCursor(ItemWindow(current_item));
X	       PlacePointer(current_menu, current_item); 
X	       next_state = Initial;
X	  }
X	  UnlockCursor();
X     }
X     else /* parent pull */
X	  next_state = CheckTrigger;
X     Leave(next_state)
X}
X
XState InitialState( rep)
XXEvent rep;
X{
X     State next_state;
X     
X     Entry("Initial")
X     switch (EventType(rep))
X     {
X     case EnterNotify:
X	  if (MenuIsNull(current_menu))
X	  {
X	       Retch("(RTLmenu) null current menu!?!?");
X	       next_state = Exit;
X	  }
X	  else if (EventXDetail(rep) == NotifyInferior)
X	       next_state = Initial;
X	  else
X	  {
X	       current_item = MenuGetItem(current_menu, EventXWindow(rep));
X	       if (ItemIsNull(current_item))
X	       {
X		    /* Retch("(RTLmenu) Window entered not an item!\n"); */
X		    next_state = Initial;
X	       }
X	       else
X	       {
X		    Highlight(current_item);
X		    next_state = GetItemState(rep);
X	       }
X	  }
X	  break;
X     case LeaveNotify:
X	  /* Decide whether we're actually leaving      */
X	  /* this menu for another submenu or the root, */
X	  /* or going into an item.                     */
X	  next_state = (EventXDetail(rep) == NotifyInferior)?
X	       Initial : LevelControl;
X	  break;
X     case ButtonRelease:
X	  next_state = Exit;
X	  break;
X     case MotionNotify:
X	  next_state = Initial;
X	  break;
X     default:
X	  Retch("(RTLmenu) YOW! Unexpected event! (%d)\n", rep.type);
X	  next_state = Exit;
X	  break;
X     }
X     Leave(next_state)
X}
X
X#define NotSet -1
X/* Look to see if pull-right is requested */
XState CheckTriggerState(rep)
XXEvent rep;
X{
X     State next_state = CheckTrigger;
X     static int Trigger = NotSet;
X     static int OldX, NewX, childX, button;
X     
X     Entry("CheckTrigger")
X     if (MenuIsNull(current_menu) || ItemIsNull(current_item))
X     {
X	  Retch("(RTLmenu) Null menu or item...");
X	  next_state = Exit;
X	  goto exit;
X     }
X     if (Trigger == NotSet) /* set it */
X     {
X	  Trigger = MIN(EventGetXCoord(rep) + MenuDelta(current_menu),
X			ItemGetArrowPosition(current_item));
X	  NewX = NotSet;
X     }
X     switch (EventType(rep))
X     {
X     case LeaveNotify:
X	  next_state = Initial;
X	  Unhighlight(MenuGetItem(current_menu, EventXWindow(rep)));
X	  Trigger = NotSet;
X	  break;
X     case ButtonRelease:
X	  next_state = Exit;
X	  Trigger = NotSet;
X	  break;
X	  
X     case ButtonPress:
X	  button = rep.xbutton.button;
X	  while (TRUE) {
X	       XNextEvent(dpy, &rep);
X	       if (rep.type == ButtonRelease &&
X		   rep.xbutton.button == button)
X		    break;
X	  }
X	  next_state = CheckTrigger;
X	  childX = TestOptionFlag(current_menu, fixedchild) ?
X	       (MenuX(current_menu) + ItemGetArrowPosition(current_item)) :
X		    EventXRootX(rep);
X	  Trigger = NotSet;
X	  if (PushSubmenu(childX))
X	  {
X	       next_state = LevelControl;
X	       ProcessExposeEvents();
X	       LockCursor(ItemWindow(current_item));
X	       PlacePointer(current_menu, current_item);
X	  }
X	  UnlockCursor();
X	  break;
X
X     case MotionNotify:
X	  next_state = CheckTrigger;
X	  OldX = NewX;
X	  NewX = EventGetXCoord(rep);
X	  if (NewX >= Trigger)
X	  {
X	       LockCursor(ItemWindow(current_item));
X	       childX = TestOptionFlag(current_menu, fixedchild)?
X		    (MenuX(current_menu) + ItemGetArrowPosition(current_item)):
X			 EventXRootX(rep);
X	       Trigger = NotSet;
X	       if (PushSubmenu(childX))
X	       {
X		    next_state = LevelControl;
X		    ProcessExposeEvents();
X		    LockCursor(ItemWindow(current_item));
X		    PlacePointer(current_menu, current_item); 
X	       }
X	       UnlockCursor();
X	  }
X	  else if (NewX < OldX) /* reverse motion */
X	       Trigger = MIN(Trigger, NewX + MenuDelta(current_menu));
X	  break;
X
X     default:
X	  Retch("(RTLmenu) YOW! Unexpected event!\n");
X	  next_state = Exit;
X	  break;
X     }
X exit:
X     Leave(next_state)
X}
X
XState LeafState(rep,selected)
XXEvent rep;
XBoolean *selected;
X{
X     State next_state;
X     
X     Entry("LeafState")
X     switch(EventType(rep))
X     {
X     case LeaveNotify:
X	  Unhighlight(MenuGetItem(current_menu, EventXWindow(rep)));
X	  next_state = Initial;
X	  break;
X	  
X     case ButtonRelease:
X	  *selected = TRUE;
X	  next_state = Exit;
X	  break;
X     
X     case ButtonPress:
X     case EnterNotify:
X     case MotionNotify: /* if events set right, this never happens */
X	  next_state = Leaf;
X	  break;
X	  
X     default:
X	  Retch("(RTLMenu) YOW! Unexpected event! (%d)\n",
X		rep.type);
X	  next_state = Exit;
X	  break;
X     }
X     Leave(next_state)
X}
X
XBoolean PushSubmenu(x)
Xint x;
X{
X     int y;
X     Boolean pushed;
X     MenuItem *new_current_item;
X     
X     Entry("PushSubmenu")
X
X     if (ItemIsNull(current_item))
X     {
X	  Retch("(RTLMenu) Can't push from null item.\n");
X	  pushed = FALSE;
X     }
X     else if (MenuIsNull(ItemSubmenu(current_item)))
X     {
X	  Retch("(RTLmenu) Null submenu.\n");
X	  pushed = FALSE;
X     }	
X     else if (ItemIsNull(MenuItems(ItemSubmenu(current_item))))
X	  /* submenu has no items -- don't push, but not an error */
X	  pushed = FALSE;
X     else
X     {
X	  y =  ItemGetMiddleY(current_item);
X	  ++level;
X	  
X	  if (new_current_item =
X	      Display_Menu(ItemSubmenu(current_item), current_menu, x, y))
X	  {
X	       XFlush(dpy);
X	       current_menu = ItemSubmenu(current_item);
X	       current_item = new_current_item;
X	       if (ItemIsDeaf(current_item) && Autoselect)
X		    current_item = current_item->nextItem;
X	       pushed = TRUE;
X	  }
X	  else
X	  {
X	       Retch("(RTLmenu) Display_Menu failed!\n");
X	       pushed = FALSE;
X	  }
X     }
X     Leave(pushed)
X}
X
Xvoid PopSubmenu()
X{
X     Menu *parent;
X     MenuItem *item;
X     
X     Entry("PopSubmenu")
X     --level;
X     parent = current_menu->parentMenu;
X     Undisplay_Menu(current_menu);
X     current_menu = parent;
X     if (!MenuIsNull(current_menu))
X     {
X	  item = MenuItemHighlighted(current_menu);
X	  if (!ItemIsNull(item))
X	  {
X	       current_item = item;
X	  }
X     }
X     
X     Leave_void
X}
X
Xvoid Highlight(item)
XMenuItem *item;
X{
X     MenuItem *old_highlight;
X     
X     Entry("Highlight")
X     
X     old_highlight = MenuItemHighlighted(current_menu);
X     if ((item != old_highlight) && /* else, already highlighted */
X	 (!ItemIsNull(item)))
X     {
X	  if (!ItemIsNull(old_highlight) && !ItemIsDeaf(item))
X	       Unhighlight(old_highlight); 
X	  SetHighlightItem(ItemMenu(item), item);
X	  Draw_Item(ItemMenu(item), item);
X     }
X     Leave_void
X}
X
Xvoid Unhighlight(item)
XMenuItem *item;
X{
X     Entry("Unhighlight")
X     if (!ItemIsNull(item))
X     {
X	  if (MenuItemHighlighted(current_menu) == item)
X	  {
X	       ResetHighlightItem(ItemMenu(item));
X	       Draw_Item(ItemMenu(item), item);
X	  }
X     }
X     Leave_void
X}
X
Xvoid TossExtraMoves(window)
XWindow window;
X{
X     XEvent ev;
X     
X     Entry("TossExtraMoves")
X     while (XCheckTypedWindowEvent(dpy, window, MotionNotify, &ev))
X	  DBUG_2("RTLmenu","Tossing extra motion.\n");
X     Leave_void
X}
X
X
Xvoid ProcessExposeEvents()
X{
X     MenuItem *item;
X     XEvent ev;
X     
X     Entry("ProcessExposeEvents")
X
X     XSync(dpy,0);
X     while (XCheckTypedEvent(dpy, Expose, &ev))
X     {
X	  item = MenuGetItem(current_menu, EventXWindow(ev));
X	  if (!ItemIsNull(item))
X	       Draw_Item(ItemMenu(item), item);
X     }
X     Leave_void
X}
END_OF_FILE
if test 26567 -ne `wc -c <'menus/track_menu.c'`; then
    echo shar: \"'menus/track_menu.c'\" unpacked with wrong size!
fi
# end of 'menus/track_menu.c'
fi
echo shar: End of archive 5 \(of 12\).
cp /dev/null ark5isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 12 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Mike Wexler(wyse!mikew)    Phone: (408)433-1000 x1330
Moderator of comp.sources.x