v12i061: olvwm - Open Look Virtual Window Manager, Part05/16
Scott Oaks - Sun Consulting NYC
sdo at soliado.East.Sun.COM
Mon Apr 29 03:29:33 AEST 1991
Submitted-by: sdo at soliado.East.Sun.COM (Scott Oaks - Sun Consulting NYC)
Posting-number: Volume 12, Issue 61
Archive-name: olvwm/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 16)."
# Contents: Notice.c winmenu.c winroot.c
# Wrapped by sdo at piccolo on Fri Apr 26 17:31:05 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Notice.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Notice.c'\"
else
echo shar: Extracting \"'Notice.c'\" \(14629 characters\)
sed "s/^X//" >'Notice.c' <<'END_OF_FILE'
X/*
X * (c) Copyright 1989, 1990 Sun Microsystems, Inc. Sun design patents
X * pending in the U.S. and foreign countries. See LEGAL_NOTICE
X * file for terms of the license.
X *
X * Written for Sun Microsystems by Crucible, Santa Cruz, CA.
X */
X
static char sccsid[] = "@(#) Notice.c 25.6 90/05/22 Crucible";
X
X#include <errno.h>
X#include <stdio.h>
X#include <X11/Xos.h>
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include <olgx/olgx.h>
X
X#include "olwm.h"
X#include "notice.h"
X#include "globals.h"
X
extern Graphics_info *olgx_gistext;
extern Graphics_info *olgx_gisbutton;
X
extern int PointInRect();
X
X#define NOTICE_EVENT_MASK ( ButtonPressMask | ButtonReleaseMask \
X | PointerMotionMask | KeyPressMask )
X#define NOTICE_ATTR_MASK ( CWBorderPixel | CWBackPixel | CWSaveUnder )
X
X/* difference between inside beveled box and outside beveled box */
X#define BORDER_WIDTH 5
X#define MIN_BOX_SIDE ( 15 + BORDER_WIDTH ) /* betw side & text */
X#define MIN_BOX_TOP ( 15 + BORDER_WIDTH ) /* betw top & text */
X#define MIN_BOX_BOTTOM ( 15 + BORDER_WIDTH ) /* betw bot & text */
X#define MIN_BUTTON_SPACE 15 /* space between buttons */
X#define MIN_BUTTON_VSPACE 15 /* space above buttons */
X#define MIN_STRING_VSPACE 5 /* space above/below strings */
X
typedef struct {
X int x;
X int y;
X unsigned int width; /* space taken up by text */
X unsigned int fullWidth; /* width including endcaps */
X} noticeButtonDetails;
X
typedef struct {
X Display *dpy;
X Window window;
X unsigned int buttonHeight;
X unsigned int fontHeight;
X unsigned int boxHeight;
X unsigned int boxWidth;
X int x;
X int y;
X int totalButtonWidth;
X noticeButtonDetails *buttonInfo;
X} noticeBoxDetails;
X
static void calculateBoxDimensions();
static void drawNoticeBox();
static int noticeEventLoop();
X
X/*
X * NoticeBox -- pop up a box which forces the user to answer
X * a question using the buttons
X *
X * Arguments:
X * dpy - pointer to current display
X * screen - index to current screen
X * noticeBox - pointer to NoticeBox structure:
X * numButtons (number of buttons)
X * defaultButton (index into buttonText for mouse warp)
X * buttonText (array of strings for button text)
X * numStrings (number of descriptive strings)
X * stringText (array of strings for description)
X * boxX (box origin (-1 =use default/centered))
X * boxY (box origin (-1 =use default/centered))
X *
X * Default placement of the box is centered in the display
X * Returns -1 on failure (0 for 0th button, 1 for 1st button, etc.)
X */
int
UseNoticeBox( dpy, screen, noticeBox )
Display *dpy;
int screen;
NoticeBox *noticeBox;
X{
X XSetWindowAttributes attributes;
X int buttonSelected;
X noticeBoxDetails boxDetails;
X int pointerX, pointerY;
X int dummyInt;
X Window dummyWin;
X int ii;
X int defaultButton;
X
X /* set up window attributes structure */
X attributes.border_pixel = GRV.Bg2Color;
X attributes.background_pixel = GRV.Bg1Color;
X attributes.save_under = True;
X
X /* set up initial elements of boxDetails structure */
X boxDetails.dpy = dpy;
X boxDetails.buttonInfo =
X (noticeButtonDetails *)MemAlloc( noticeBox->numButtons
X * (unsigned int)sizeof(noticeButtonDetails) );
X
X /* figure out size to make window and where to put it */
X calculateBoxDimensions( screen, noticeBox, &boxDetails );
X
X /* create window */
X boxDetails.window = XCreateWindow( dpy,
X RootWindow(dpy,
X DefaultScreen(dpy)),
X boxDetails.x, boxDetails.y,
X boxDetails.boxWidth,
X boxDetails.boxHeight, 0,
X DefaultDepth(dpy, DefaultScreen(dpy)),
X InputOutput, CopyFromParent,
X NOTICE_ATTR_MASK,
X &attributes );
X
X /* grab server and map window so box can be drawn here */
X XGrabServer( dpy );
X XMapRaised( dpy, boxDetails.window );
X
X /* only beep if beeps are selected */
X if (GRV.Beep != BeepNever)
X XBell(dpy,100);
X
X drawNoticeBox( noticeBox, &boxDetails );
X
X /* save current mouse position */
X XQueryPointer( dpy, RootWindow(dpy, DefaultScreen(dpy)),
X &dummyWin, &dummyWin,
X &pointerX, &pointerY,
X &dummyInt, &dummyInt, &dummyInt );
X
X /* warp pointer to default button */
X defaultButton = noticeBox->defaultButton;
X if (GRV.PopupJumpCursor)
X XWarpPointer( dpy, None, boxDetails.window, 0, 0, 0, 0,
X boxDetails.buttonInfo[defaultButton].x
X + boxDetails.buttonInfo[defaultButton].fullWidth/2,
X boxDetails.buttonInfo[defaultButton].y
X + boxDetails.buttonHeight/2 );
X
X XSelectInput( dpy, boxDetails.window, NOTICE_EVENT_MASK );
X buttonSelected = noticeEventLoop( noticeBox, &boxDetails );
X
X /* put the pointer back where we got it */
X /* REMIND we need to test to see if the pointer is still within the
X * default button */
X if (GRV.PopupJumpCursor)
X XWarpPointer( dpy, None, RootWindow(dpy, DefaultScreen(dpy)),
X 0, 0, 0, 0, pointerX, pointerY );
X
X /* free up the server as soon as we're done with it */
X XUngrabServer( dpy );
X
X /* destroy window */
X XDestroyWindow( dpy, boxDetails.window );
X MemFree( boxDetails.buttonInfo );
X return( buttonSelected );
X}
X
X/*
X * noticeEventLoop -- watch for events while in notice box
X *
X */
static int
noticeEventLoop( noticeBox, details )
NoticeBox *noticeBox;
noticeBoxDetails *details;
X{
X XEvent event;
X Bool done = False;
X int buttonSelected = -1;
X int buttonDown = -1;
X Bool buttonDrawnDown = False;
X int ii;
X int buttonState; /* OLGX_NORMAL or OLGX_DEFAULT */
X int keyboardGrabbed = False;
X
X /* take control until we get an answer */
X /* REMIND: we're assuming the pointer can be grabbed,
X * since we were successfully called from some menu
X * REMIND: we may want to change the pointer during the grab
X */
X XGrabPointer( details->dpy, details->window, False,
X NOTICE_EVENT_MASK,
X GrabModeAsync, GrabModeAsync,
X None, None, CurrentTime );
X
X /* REMIND: need to check return, in case someone else has
X * grabbed the keyboard (what to do then? just XGrabKey(),
X * or ignore keypress events?)
X */
X keyboardGrabbed = ( GrabSuccess == XGrabKeyboard(
X details->dpy, details->window,
X False, GrabModeAsync,
X GrabModeAsync, CurrentTime ) );
X
X while ( !done )
X {
X XNextEvent( details->dpy, &event );
X
X /*
X * Discard synthetic events
X *
X * This event loop is only interested in user events, so we
X * don't even bother checking to see if this event is a mouse
X * or keyboard event.
X */
X if (event.xany.send_event)
X continue;
X
X switch (event.type)
X {
X case ButtonPress:
X /* first check to see if we're even in the notice box */
X if ( !PointInRect( event.xbutton.x,
X event.xbutton.y,
X 0, 0,
X details->boxWidth,
X details->boxHeight ) )
X break;
X
X /* if on one of the notice buttons, depress it */
X for ( ii = 0 ; ii < noticeBox->numButtons ; ii++ )
X {
X if ( PointInRect( event.xbutton.x,
X event.xbutton.y,
X details->buttonInfo[ii].x,
X details->buttonInfo[ii].y,
X details->buttonInfo[ii].fullWidth,
X details->buttonHeight ) )
X {
X buttonDown = ii;
X buttonDrawnDown = True;
X olgx_draw_button( olgx_gisbutton,
X details->window,
X details->buttonInfo[ii].x,
X details->buttonInfo[ii].y,
X details->buttonInfo[ii].fullWidth, 0,
X noticeBox->buttonText[ii],
X OLGX_INVOKED );
X break;
X }
X }
X break;
X
X case ButtonRelease:
X /* only a depressed button can be selected */
X if ( PointInRect( event.xbutton.x,
X event.xbutton.y,
X details->buttonInfo[buttonDown].x,
X details->buttonInfo[buttonDown].y,
X details->buttonInfo[buttonDown].fullWidth,
X details->buttonHeight ) )
X {
X buttonSelected = buttonDown;
X done = True;
X }
X
X if (!done)
X {
X buttonDown = -1;
X buttonDrawnDown = False;
X }
X
X break;
X
X case MotionNotify:
X /* check state of buttons */
X if ( buttonDown < 0 )
X break;
X
X if ( PointInRect( event.xbutton.x,
X event.xbutton.y,
X details->buttonInfo[buttonDown].x,
X details->buttonInfo[buttonDown].y,
X details->buttonInfo[buttonDown].fullWidth,
X details->buttonHeight ) )
X {
X /* Moved within button down at start of motion.
X * If the button was is drawn undepressed,
X * make it go down.
X */
X if ( !buttonDrawnDown )
X {
X olgx_draw_button( olgx_gisbutton,
X details->window,
X details->buttonInfo[buttonDown].x,
X details->buttonInfo[buttonDown].y,
X details->buttonInfo[buttonDown].fullWidth, 0,
X noticeBox->buttonText[buttonDown],
X OLGX_INVOKED );
X
X buttonDrawnDown = True;
X }
X }
X else
X {
X /* Moved out of button that was down at start.
X * If the button was previously drawn down,
X * draw it undepressed.
X */
X if ( buttonDrawnDown )
X {
X /* check if needs "default" indicator */
X if ( noticeBox->defaultButton == buttonDown )
X buttonState = OLGX_DEFAULT;
X else
X buttonState = OLGX_NORMAL;
X
X olgx_draw_button( olgx_gisbutton,
X details->window,
X details->buttonInfo[buttonDown].x,
X details->buttonInfo[buttonDown].y,
X details->buttonInfo[buttonDown].fullWidth,
X 0, noticeBox->buttonText[buttonDown],
X buttonState | OLGX_ERASE );
X
X buttonDrawnDown = False;
X }
X }
X
X break;
X
X case KeyPress:
X if (keyboardGrabbed &&
X event.xkey.keycode == GRV.ConfirmKey.keycode )
X {
X buttonSelected = noticeBox->defaultButton;
X done = True;
X }
X
X break;
X
X default:
X break;
X }
X }
X
X /* release control */
X XUngrabPointer( details->dpy, CurrentTime );
X if ( keyboardGrabbed )
X XUngrabKeyboard( details->dpy, CurrentTime );
X XFlush( details->dpy );
X
X return( buttonSelected);
X}
X
X/*
X * calculateBoxDimensions -- determine size of box needed, etc. based on
X * information passed in in noticeBox structure. Return
X * values in boxDetails structure.
X */
static void
calculateBoxDimensions( screen, noticeBox, boxDetails )
int screen;
NoticeBox *noticeBox;
noticeBoxDetails *boxDetails;
X{
X unsigned int displayWidth, displayHeight;
X int longestStringLength = 0;
X int totalButtonWidth = 0;
X int ii;
X
X boxDetails->fontHeight = GRV.TextFontInfo->ascent +
X GRV.TextFontInfo->descent;
X
X /* calculate the width of the text which appears inside the button */
X for ( ii = 0 ; ii < noticeBox->numButtons ; ii++ )
X {
X boxDetails->buttonInfo[ii].width =
X XTextWidth( GRV.ButtonFontInfo,
X noticeBox->buttonText[ii],
X strlen(noticeBox->buttonText[ii]) );
X boxDetails->buttonInfo[ii].fullWidth =
X boxDetails->buttonInfo[ii].width
X + 2 * ButtonEndcap_Width(olgx_gisbutton);
X }
X
X /* add together widths of all the buttons */
X for ( ii = 0 ; ii < noticeBox->numButtons ; ii++ )
X totalButtonWidth += boxDetails->buttonInfo[ii].fullWidth;
X boxDetails->totalButtonWidth = totalButtonWidth;
X
X /* figure out which descriptive string is longest */
X for ( ii = 0 ; ii < noticeBox->numStrings ; ii++ )
X longestStringLength =
X MAX( longestStringLength,
X XTextWidth( GRV.TextFontInfo,
X noticeBox->stringText[ii],
X strlen(noticeBox->stringText[ii]) ) );
X
X /*
X * REMIND: this calculation assumes all the buttons are
X * on the same line
X */
X boxDetails->boxWidth = 2 * MIN_BOX_SIDE
X + MAX( longestStringLength,
X totalButtonWidth +
X /* amount of space between all the buttons */
X MIN_BUTTON_SPACE * (noticeBox->numButtons - 1) );
X
X boxDetails->buttonHeight = Button_Height(olgx_gisbutton);
X
X boxDetails->boxHeight = MIN_BOX_TOP + MIN_BOX_BOTTOM
X + ( noticeBox->numStrings * boxDetails->fontHeight )
X /* amount of space vertically between all the strings */
X + ( (noticeBox->numStrings - 1) * MIN_STRING_VSPACE )
X + MIN_BUTTON_VSPACE + boxDetails->buttonHeight;
X
X displayWidth = DisplayWidth( boxDetails->dpy, screen );
X displayHeight = DisplayHeight( boxDetails->dpy, screen );
X
X /* if not set, create default "origin" for box: centered */
X boxDetails->x = ( noticeBox->boxX == -1 )
X ? (int)( displayWidth - boxDetails->boxWidth )/2
X : noticeBox->boxX ;
X boxDetails->y = ( noticeBox->boxY == -1 )
X ? (int)( displayHeight - boxDetails->boxHeight )/2
X : noticeBox->boxY ;
X
X}
X
X/*
X * drawNoticeBox -- draw box outline, strings, and buttons using information
X * in noticeBox and boxDetails structures which are passed in.
X * Location of buttons (x, y) are set in boxDetails structure
X * for use later (mouse warping, determining pointer position).
X */
static void
drawNoticeBox( noticeBox, boxDetails )
NoticeBox *noticeBox;
noticeBoxDetails *boxDetails;
X{
X int ii;
X int buttonX, buttonY;
X int buttonState; /* OLGX_NORMAL or OLGX_DEFAULT */
X
X /* draw beveled box */
X olgx_draw_box( olgx_gistext, boxDetails->window, 0, 0,
X boxDetails->boxWidth, boxDetails->boxHeight,
X OLGX_NORMAL, True );
X
X olgx_draw_box( olgx_gistext, boxDetails->window,
X BORDER_WIDTH, BORDER_WIDTH,
X boxDetails->boxWidth - 2 * BORDER_WIDTH,
X boxDetails->boxHeight - 2 * BORDER_WIDTH,
X OLGX_NORMAL, True );
X
X /* draw descriptive text
X * REMIND: all strings are along the left edge (MIN_BOX_SIDE)
X */
X for ( ii = 0 ; ii < noticeBox->numStrings ; ii++ )
X olgx_draw_text( olgx_gistext, boxDetails->window,
X noticeBox->stringText[ii], MIN_BOX_SIDE,
X /* need to move each line further down the screen */
X MIN_BOX_TOP + GRV.TextFontInfo->ascent * ( ii + 1 )
X + ( MIN_STRING_VSPACE * ii ),
X 0, False, OLGX_NORMAL );
X
X /* put buttons in - notice that it's a single row */
X /* row of buttons should be centered within available space,
X * assuming MIN_BUTTON_SPACE between each of the them
X */
X buttonX = ( boxDetails->boxWidth - (boxDetails->totalButtonWidth
X + MIN_BUTTON_SPACE * (noticeBox->numButtons - 1)) )/2;
X /* this calculates from the bottom of the box */
X buttonY = ( boxDetails->boxHeight -
X ( MIN_BOX_BOTTOM + boxDetails->buttonHeight ) );
X for ( ii = 0 ; ii < noticeBox->numButtons ; ii++ )
X {
X if ( noticeBox->defaultButton == ii )
X buttonState = OLGX_DEFAULT;
X else
X buttonState = OLGX_NORMAL;
X
X /* save button's x, y values for use later */
X boxDetails->buttonInfo[ii].x = buttonX;
X boxDetails->buttonInfo[ii].y = buttonY;
X
X olgx_draw_button( olgx_gisbutton, boxDetails->window,
X buttonX, buttonY,
X boxDetails->buttonInfo[ii].fullWidth, 0,
X noticeBox->buttonText[ii],
X buttonState );
X
X /* set up buttonX for next button */
X buttonX = buttonX + boxDetails->buttonInfo[ii].fullWidth
X + MIN_BUTTON_SPACE;
X }
X}
END_OF_FILE
if test 14629 -ne `wc -c <'Notice.c'`; then
echo shar: \"'Notice.c'\" unpacked with wrong size!
fi
# end of 'Notice.c'
fi
if test -f 'winmenu.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'winmenu.c'\"
else
echo shar: Extracting \"'winmenu.c'\" \(13410 characters\)
sed "s/^X//" >'winmenu.c' <<'END_OF_FILE'
X/*
X * (c) Copyright 1989, 1990 Sun Microsystems, Inc. Sun design patents
X * pending in the U.S. and foreign countries. See LEGAL_NOTICE
X * file for terms of the license.
X *
X * Written for Sun Microsystems by Crucible, Santa Cruz, CA.
X */
X
static char sccsid[] = "@(#)winmenu.c 1.2 olvwm version 3/30/91";
X
X/*
X * Based on
static char sccsid[] = "@(#) winmenu.c 25.4 90/05/18 Crucible";
X *
X */
X
X#include <errno.h>
X#include <stdio.h>
X#include <X11/Xos.h>
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include <X11/Xatom.h>
X#include <olgx/olgx.h>
X#include "mem.h"
X#include "olwm.h"
X#include "win.h"
X#include "menu.h"
X#include "globals.h"
X
X/***************************************************************************
X* global data
X***************************************************************************/
X
extern Atom AtomDecorAdd;
extern Atom AtomDecorHeader;
extern Atom AtomDecorPin;
extern Atom AtomDeleteWindow;
extern Atom AtomMenuLimited;
extern Atom AtomProtocols;
extern Atom AtomPushpinState;
extern Atom AtomWinAttr;
extern Atom AtomWTOther;
X
extern Window NoFocusWin;
X
X/***************************************************************************
X* private data
X***************************************************************************/
X
X/* function vector for menu windows */
static ClassMenu classMenu;
X
static int bindex_last; /* set to last menu button pressed; cleared
X * when button released or a submenu is
X * brought up */
X
X/*
X * after_info_t
X *
X * REMIND this is an abomination. This structure simply holds the arguments
X * for the "afterProcessing" function, which should get called when a pop-up
X * menu is finished tracking. Unfortunately, the architecture of this pinned
X * menu system assumes that popping up a menu is synchronous, when in fact it
X * just installs an event interposer and returns immediately. The solution is
X * to pass along this information as a closure and have the information passed
X * back by the menu "sync" function.
X */
X
typedef struct {
X Display *dpy;
X Menu *menu;
X WinMenu *winInfo;
X int bindex;
X} after_info_t;
X
static after_info_t afterInfo;
X
X/***************************************************************************
X* private functions
X***************************************************************************/
X
static void
afterProcessing(dpy, menu, winInfo, bindex)
Display *dpy;
Menu *menu;
WinMenu *winInfo;
int bindex;
X{
X unsigned long nItems, remain;
X long *pinState;
X
X /* unhighlight button */
X if ((bindex >= 0) && (bindex < menu->buttonCount))
X SetButton(dpy, menu, bindex, False);
X
X /* if our push-pin is out then we should go away */
X pinState = GetWindowProperty(dpy, winInfo->core.self, AtomPushpinState,
X 0L, LONG_LENGTH(long), XA_INTEGER, 0, &nItems, &remain);
X
X if (pinState != NULL)
X {
X if (*pinState == PIN_OUT) /* pin is out */
X {
X /* make our window die */
X ClientKill(winInfo->core.client,False);
X }
X XFree(pinState);
X }
X}
X
X
static void
afterProcWrapper( i )
X after_info_t *i;
X{
X afterProcessing( i->dpy, i->menu, i->winInfo, i->bindex );
X}
X
X/* pressButton -- a user has moved the pointer in such a way that a
X * button should be pressed (that is, highlighted, ready for
X * activation. If any other button is pressed, unpress that button
X * along the way.
X */
static int
pressButton(dpy, menu, winInfo, event, bindex, mbutton)
Display *dpy;
Menu *menu;
WinMenu *winInfo;
XXEvent *event;
int bindex;
int mbutton;
X{
X if ((mbutton == MB_MENU) || (mbutton = MB_SELECT))
X {
X SetButton(dpy, menu, bindex, True);
X
X if ((menu->buttons[bindex].stacked == True) &&
X (menu->buttons[bindex].action.submenu != NULL) &&
X (mbutton == MB_MENU))
X {
X afterInfo.dpy = dpy;
X afterInfo.menu = menu;
X afterInfo.winInfo = winInfo;
X afterInfo.bindex = bindex;
X MenuShowSync(dpy, winInfo,
X (Menu *)(menu->buttons[bindex].action.submenu),
X event, afterProcWrapper, &afterInfo);
X }
X }
X}
X
X
X
X/* findButton - find the button corresponding to an x,y position
X * modifies the x,y position to the correct popup location
X * for cascaded menus.
X * returns: button index or -1 if button not found
X */
static int
findButton(menu, ex, ey, winInfo)
Menu *menu;
int *ex, *ey;
WinMenu *winInfo;
X{
X int bindex;
X
X /* figure out if the button press is in a button */
X for (bindex=0; bindex < menu->buttonCount; bindex++)
X {
X if (PointInRect(*ex, *ey,
X menu->buttons[bindex].activeX,
X menu->buttons[bindex].activeY,
X menu->buttons[bindex].activeW,
X menu->buttons[bindex].activeH))
X {
X WinRootPos(winInfo, ex, ey);
X *ex += menu->buttons[bindex].activeX +
X menu->buttons[bindex].activeW;
X *ey += menu->buttons[bindex].activeY;
X return bindex;
X }
X }
X return -1;
X}
X
X
X/***************************************************************************
X* private event functions
X***************************************************************************/
X
X/*
X * eventButtonPress - a button has gone down.
X */
static int
eventButtonPress(dpy, event, winInfo)
Display *dpy;
XXEvent *event;
WinMenu *winInfo;
X{
X Menu *menu = (Menu *)(winInfo->menu);
X int bindex;
X int ex, ey;
X
X ex = event->xbutton.x;
X ey = event->xbutton.y;
X bindex = findButton(menu, &ex, &ey, winInfo);
X bindex_last = bindex;
X if (bindex != -1)
X pressButton(dpy, menu, winInfo, event, bindex, MouseButton(dpy,event));
X}
X
X/*
X * eventButtonRelease - a button has gone up
X */
static int
eventButtonRelease(dpy, event, winInfo)
Display *dpy;
XXEvent *event;
WinMenu *winInfo;
X{
X Menu *menu = (Menu *)(winInfo->menu);
X int bindex;
X int ex, ey;
X
X ex = event->xbutton.x;
X ey = event->xbutton.y;
X
X if (MouseButton(dpy,event) == MB_ADJUST)
X return;
X
X bindex = findButton(menu, &ex, &ey, winInfo);
X
X /* Make sure that the button under the ButtonRelease is the
X * same one that the ButtonPress went down on.
X */
X if ((bindex == bindex_last) &&
X (bindex_last >= 0) &&
X (bindex_last < menu->buttonCount))
X ExecButtonAction(dpy,winInfo,menu,bindex,True);
X
X afterProcessing(dpy,menu,winInfo,bindex_last);
X}
X
X/*
X * eventClientMessage - handle a DELETE_WINDOW message.
X */
static int
eventClientMessage(dpy, event, winInfo)
Display *dpy;
XXEvent *event;
WinMenu *winInfo;
X{
X if ((event->xclient.message_type == AtomProtocols) &&
X (event->xclient.data.l[0] == AtomDeleteWindow))
X {
X DestroyClient(winInfo->core.client);
X }
X}
X
X/*
X * eventPropertyNotify - the main window manager has changed a property on
X * our pane; handle the property.
X */
static int
eventPropertyNotify(dpy, event, winInfo)
Display *dpy;
XXEvent *event;
WinMenu *winInfo;
X{
X ClientDistributeProperty(winInfo->core.client, event);
X}
X
X
X/*
X * drawMenu -- draw the menu window
X */
X/*ARGSUSED*/ /* dpy arg will be used when multiple Displays supported */
static int
drawMenu(dpy, winInfo)
Display *dpy;
WinMenu *winInfo;
X{
X DrawMenu(dpy, winInfo->menu);
X}
X
X
X/*
X * DestroyMenu -- destroy the menu window resources and free any allocated
X * data.
X */
static int
destroyMenu(dpy, winInfo)
Display *dpy;
WinMenu *winInfo;
X{
X /* free our data and throw away window */
X ((Menu *)winInfo->menu)->originalMenu->currentlyDisplayed = False;
X MemFree(winInfo->menu);
X XUndefineCursor(dpy, winInfo->core.self);
X XDestroyWindow(dpy, winInfo->core.self);
X WIUninstallInfo(winInfo->core.self);
X MemFree(winInfo);
X}
X
X/*
X * focusselectMenu - the focus or selection state has changed
X */
static int
focusselectMenu(dpy, winInfo, selected)
Display *dpy;
WinMenu *winInfo;
Bool selected;
X{
X (WinFunc(winInfo,core.drawfunc))(dpy, winInfo);
X}
X
X/*
X * newconfigMenu - recomputes the size of the menu window
X * Note that menus don't change size, so this is a no-op.
X */
static int
newconfigMenu(win, pxcre)
WinMenu *win;
XXConfigureRequestEvent *pxcre;
X{
X return win->core.dirtyconfig;
X}
X
X/* menuSetParent -- callback during creation. Since menus are internally-
X * created windows we must fix up certain fields that are only available
X * after the window is mapped.
X */
static int
menuSetParent(w,cli,par)
WinMenu *w;
Client *cli;
WinGenericFrame *par;
X{
X w->core.client = cli;
X WinAddChild(par,w);
X XReparentWindow(cli->dpy, w->core.self, par->core.self, w->core.x, w->core.y);
X par->fcore.panewin = (WinGenericPane *)w;
X}
X
X
X/***************************************************************************
X* global functions
X***************************************************************************/
X
X/*
X * MakeMenu -- create the pinned menu's menu window (around which we'll put
X * a frame). The window is mapped during the transition to normal
X * state.
X */
WinMenu *
MakeMenu(dpy, junkwindow, menu, idx)
Display *dpy;
WinGeneric *junkwindow;
Menu *menu;
int idx;
X{
X WinMenu *w;
X Window win;
X unsigned long valuemask;
X XSetWindowAttributes attributes;
X Menu *originalMenu;
X Atom atomList[3];
X NewXSizeHints sizeHints;
X XWMHints wmHints;
X
X /* save a pointer to the menu we're putting in the window.
X * We will duplicate the structure later on and set the
X * currentlyDisplayed flag in the original.
X */
X originalMenu = menu;
X
X /* create the associated structure */
X w = MemNew(WinMenu);
X w->class = &classMenu;
X w->core.kind = WIN_MENU;
X w->core.children = NULL;
X w->core.x = menu->x;
X w->core.y = menu->y;
X w->core.width = menu->width;
X w->core.height = menu->height - menu->titleHeight;
X w->core.dirtyconfig = CWX|CWY|CWWidth|CWHeight;
X w->core.exposures = NULL;
X
X /* create the actual window */
X attributes.event_mask = ButtonReleaseMask | ButtonPressMask |
X ExposureMask | PropertyChangeMask;
X attributes.background_pixel = GRV.Bg1Color;
X attributes.cursor = GRV.MenuPointer;
X valuemask = CWEventMask | CWBackPixel | CWCursor;
X
X win = XCreateWindow(dpy, RootWindow(dpy, DefaultScreen(dpy)),
X w->core.x, w->core.y,
X w->core.width, w->core.height,
X 0,
X DefaultDepth(dpy, DefaultScreen(dpy)),
X InputOutput,
X DefaultVisual(dpy, DefaultScreen(dpy)),
X valuemask,
X &attributes);
X w->core.self = win;
X
X /* register the window */
X WIInstallInfo(w);
X
X /* first we set the properties defining what kind of OpenLook window it is */
X atomList[0] = AtomWTOther;
X atomList[1] = AtomMenuLimited;
X atomList[2] = (Atom) PIN_IN;
X XChangeProperty(dpy, win, AtomWinAttr, AtomWinAttr,
X 32, PropModeReplace, (unsigned char *)atomList, 3);
X
X /* add a push-pin */
X atomList[0] = AtomDecorPin;
X atomList[1] = AtomDecorHeader;
X XChangeProperty(dpy, win, AtomDecorAdd, XA_ATOM,
X 32, PropModeReplace, (unsigned char *)atomList, 2);
X
X /* set protocols */
X atomList[0] = AtomDeleteWindow;
X XChangeProperty(dpy, win, AtomProtocols, XA_ATOM,
X 32, PropModeReplace, (unsigned char *)atomList, 1);
X
X /* now set the size hints */
X sizeHints.flags = USPosition | USSize;
X XChangeProperty(dpy, win, XA_WM_NORMAL_HINTS, XA_WM_SIZE_HINTS,
X 32, PropModeReplace, (unsigned char *)&sizeHints,
X sizeof(NewXSizeHints)/sizeof(long));
X
X /* and the wmHints */
X wmHints.flags = InputHint | StateHint | WindowGroupHint;
X wmHints.initial_state = NormalState;
X wmHints.input = False;
X /*
X * REMIND this is hack to make StateNew think we're a dependent
X * follower, and thus not iconify us.
X */
X wmHints.window_group = NoFocusWin;
X
X XChangeProperty(dpy, win, XA_WM_HINTS, XA_WM_HINTS,
X 32, PropModeReplace, (unsigned char *)&wmHints,
X sizeof(XWMHints)/sizeof(long));
X
X XStoreName(dpy, win, menu->title);
X
X /* create a private, duplicate menu structure */
X w->menu = (void *)MemNew(Menu);
X *(Menu *)(w->menu) = *menu;
X menu = (Menu *)(w->menu);
X menu->originalMenu = originalMenu;
X originalMenu->currentlyDisplayed = True;
X menu->title = NULL;
X menu->x = menu->y = 0;
X menu->titleHeight = menu->titleWidth = 0;
X menu->height = w->core.height;
X menu->window = win;
X
X StateNew(dpy, win, False, w);
X
X return w;
X}
X
void
MenuInit(dpy)
Display *dpy;
X{
X classMenu.core.kind = WIN_MENU;
X classMenu.core.xevents[ButtonPress] = eventButtonPress;
X classMenu.core.xevents[ButtonRelease] = eventButtonRelease;
X classMenu.core.xevents[ClientMessage] = eventClientMessage;
X classMenu.core.xevents[PropertyNotify] = eventPropertyNotify;
X classMenu.core.xevents[Expose] = WinEventExpose;
X classMenu.core.focusfunc = focusselectMenu;
X classMenu.core.drawfunc = drawMenu;
X classMenu.core.destroyfunc = destroyMenu;
X classMenu.core.selectfunc = focusselectMenu;
X classMenu.core.newconfigfunc = newconfigMenu;
X classMenu.core.newposfunc = WinNewPosFunc;
X classMenu.core.setconfigfunc = WinSetConfigFunc;
X classMenu.core.createcallback = menuSetParent;
X classMenu.core.heightfunc = NULL;
X classMenu.core.widthfunc = NULL;
X classMenu.pcore.setsizefunc = NULL;
X
X}
END_OF_FILE
if test 13410 -ne `wc -c <'winmenu.c'`; then
echo shar: \"'winmenu.c'\" unpacked with wrong size!
fi
# end of 'winmenu.c'
fi
if test -f 'winroot.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'winroot.c'\"
else
echo shar: Extracting \"'winroot.c'\" \(14250 characters\)
sed "s/^X//" >'winroot.c' <<'END_OF_FILE'
X/*
X * (c) Copyright 1989, 1990 Sun Microsystems, Inc. Sun design patents
X * pending in the U.S. and foreign countries. See LEGAL_NOTICE
X * file for terms of the license.
X *
X * Written for Sun Microsystems by Crucible, Santa Cruz, CA.
X */
X
static char sccsid[] = "@(#)winroot.c 1.2 olvwm version 3/30/91";
X
X/*
X * Based on
static char sccsid[] = "@(#) winroot.c 25.8 90/05/22 Crucible";
X *
X */
X
X#include <errno.h>
X#include <stdio.h>
X#include <X11/Xos.h>
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include <X11/Xatom.h>
X#include <X11/Xresource.h>
X#include <olgx/olgx.h>
X#include "mem.h"
X#include "olwm.h"
X#include "win.h"
X#include "menu.h"
X#include "globals.h"
X#include "group.h"
X
X/***************************************************************************
X* global data
X***************************************************************************/
X
extern Menu *RootMenu;
extern Window NoFocusWin;
extern Time SelectionTime;
X
X/***************************************************************************
X* private data
X***************************************************************************/
X
static int lastButton;
static XEvent buttonPressEvent;
static ClassRoot classRoot;
X
X/***************************************************************************
X* private functions
X***************************************************************************/
X
static void
redistributeKeystroke( dpy, e )
Display *dpy;
XXEvent *e;
X{
X XKeyEvent *ke = (XKeyEvent *) e;
X Window childwin, dstwin, srcwin;
X int srcx, srcy, dstx, dsty;
X static Bool pressreceived = False;
X static XKeyEvent pressevent;
X
X if ( ke->type == KeyPress ) {
X if ( pressreceived == False ) {
X srcwin = ke->window;
X dstwin = ke->window;
X srcx = ke->x;
X srcy = ke->y;
X while (1) {
X XTranslateCoordinates( dpy, srcwin, dstwin, srcx, srcy,
X &dstx, &dsty, &childwin );
X if ( childwin == None )
X break;
X srcx = dstx;
X srcy = dsty;
X srcwin = dstwin;
X dstwin = childwin;
X }
X pressevent = *ke;
X pressevent.x = dstx;
X pressevent.y = dsty;
X pressevent.window = dstwin;
X pressevent.subwindow = None;
X pressreceived = True;
X }
X } else {
X if ( pressreceived == True ) {
X#ifdef notdef
X XUngrabKeyboard( dpy, pressevent.time );
X#endif /* notdef */
X XSendEvent( dpy, pressevent.window, True,
X KeyPressMask, &pressevent );
X XTranslateCoordinates( dpy, ke->window, pressevent.window,
X ke->x, ke->y, &dstx, &dsty, &childwin );
X ke->x = dstx;
X ke->y = dsty;
X ke->window = pressevent.window;
X ke->subwindow = None;
X XSendEvent( dpy, pressevent.window, True, KeyPressMask, ke );
X }
X pressreceived = False;
X }
X}
X
X
static Bool
matchKeystrokeToSpec(event,spec)
X XEvent *event;
X KeySpec *spec;
X{
X return (spec->keycode == event->xkey.keycode &&
X (spec->modmask == AnyModifier ||
X spec->modmask == event->xkey.state));
X}
X
X
static void
rootKeystroke(dpy,pEvent)
Display *dpy;
XXEvent *pEvent;
X{
X Window child;
X WinGeneric *childInfo;
X Client *childClient;
X Bool samescreen;
X int destX, destY;
X
X samescreen = XTranslateCoordinates(dpy,
X DefaultRootWindow(dpy), DefaultRootWindow(dpy),
X pEvent->xkey.x, pEvent->xkey.y, &destX, &destY, &child );
X
X if (!samescreen)
X return;
X
X if (pEvent->type == KeyPress && child != None &&
X matchKeystrokeToSpec(pEvent, &(GRV.FrontKey))) {
X XWindowChanges xwc;
X xwc.stack_mode = Opposite;
X XConfigureWindow( dpy, child, CWStackMode, &xwc );
X childInfo = WIGetInfo(child);
X childClient = childInfo->core.client;
X if (childClient && childClient->virtualWindow) {
X XConfigureWindow(dpy, childClient->virtualWindow, CWStackMode, &xwc);
X }
X } else if (matchKeystrokeToSpec(pEvent, &(GRV.HelpKey))) {
X redistributeKeystroke( dpy, pEvent );
X } else if (pEvent->type == KeyPress && child != None &&
X matchKeystrokeToSpec(pEvent, &(GRV.OpenKey))) {
X childInfo = WIGetInfo(child);
X if ( childInfo ) {
X childClient = childInfo->core.client;
X if (childClient != NULL)
X {
X if ( childClient->wmState == IconicState ) {
X StateIconNorm(childClient);
X } else {
X /* check for base vs. popup window */
X if (childClient->groupmask == GROUP_DEPENDENT) {
X /*
X * REMIND: passing (Menu *)NULL is bogus.
X * Also, should pass DA_THIS instead of 0.
X */
X DismissAction(dpy,childInfo,(Menu *)NULL,0,False);
X } else {
X StateNormIcon(childClient);
X }
X }
X }
X }
X } else if (pEvent->type == KeyPress &&
X matchKeystrokeToSpec(pEvent, &(GRV.ColorLockKey))) {
X InstallPointerColormap(dpy, pEvent->xkey.root, pEvent->xkey.x_root,
X pEvent->xkey.y_root, True);
X } else if (pEvent->type == KeyPress &&
X matchKeystrokeToSpec(pEvent, &(GRV.ColorUnlockKey))) {
X UnlockColormap(dpy);
X }
X}
X
X
static void
rootProperty( dpy, pEvent )
Display *dpy;
XXEvent *pEvent;
X{
X unsigned long nitems, remain;
X char *resourceString;
X XrmDatabase serverDB;
X
X /* make sure that the property was the one we care about and
X * changed (as opposed to deleted)
X */
X if ( (pEvent->xproperty.atom != XA_RESOURCE_MANAGER)
X || (pEvent->xproperty.state != PropertyNewValue) )
X return;
X
X resourceString = GetWindowProperty(dpy, RootWindow(dpy, DefaultScreen(dpy)),
X XA_RESOURCE_MANAGER, 0L, 100000000L,
X /* REMIND what should the length really be ? */
X XA_STRING, 0, &nitems, &remain);
X if (resourceString != NULL)
X {
X serverDB = XrmGetStringDatabase( resourceString );
X UpdateDBValues( dpy, serverDB );
X XFree( resourceString );
X }
X}
X
X
X/*
X * eventEnterNotify - the pointer has entered the root window
X */
static int
eventEnterNotify(dpy, pEvent, winInfo)
Display *dpy;
XXEvent *pEvent;
WinRoot *winInfo;
X{
X ColorWindowCrossing(dpy, pEvent, winInfo);
X}
X
X/*
X * eventConfigureRequest - a client wants to change configuration
X */
static int
eventConfigureRequest(dpy, pEvent, winInfo)
Display *dpy;
XXEvent *pEvent;
WinRoot *winInfo;
X{
X#define ConfEvent (pEvent->xconfigurerequest)
X if ((winInfo = WIGetInfo(ConfEvent.window)) == NULL)
X {
X /* we don't know about this window, so let it go */
X ClientConfigure(NULL,NULL,pEvent);
X }
X else /* OBSOLETE: if (ConfEvent.value_mask & (CWX | CWY | CWWidth | CWHeight)) */
X {
X /* configure the window and its frame */
X ClientConfigure(winInfo->core.client,winInfo,pEvent);
X }
X /* REMIND doesn't handle stacking or border width yet */
X}
X
X/*
X * eventMapRequest - a new client is mapping
X */
static int
eventMapRequest(dpy, pEvent, winInfo)
Display *dpy;
XXEvent *pEvent;
WinRoot *winInfo;
X{
X#define MapEvent (pEvent->xmap)
X StateNew(dpy, MapEvent.window, False, NULL);
X}
X
X/*
X * eventMotionNotify - the pointer is moving
X */
static int
eventMotionNotify(dpy, pEvent, winInfo)
Display *dpy;
XXEvent *pEvent;
WinRoot *winInfo;
X{
X short boxX, boxY, boxW, boxH;
X clientInBoxClosure cibclosure;
X Time timestamp;
X
X if (!pEvent->xmotion.same_screen)
X return;
X
X /* If the user hasn't moved more than the threshold
X * amount, break out of here. REMIND Also, if we get a
X * MotionNotify event with no buttons down, we ignore it.
X * Ideally this shouldn't happen, but some areas of the code
X * still leave the pointer grabbed even after all the buttons
X * have gone up.
X */
X if ((ABS(pEvent->xmotion.x - buttonPressEvent.xbutton.x) <
X GRV.MoveThreshold) &&
X (ABS(pEvent->xmotion.y - buttonPressEvent.xbutton.y) <
X GRV.MoveThreshold))
X return;
X if (pEvent->xmotion.state == 0)
X return;
X
X switch(lastButton)
X {
X case MB_SELECT:
X ClearSelections(dpy);
X
X /* need to trace a bounding box */
X if (TraceBoundingBox(dpy, &buttonPressEvent,
X &boxX, &boxY, &boxW, &boxH, ×tamp))
X {
X /* select all frames or icons in the box */
X cibclosure.dpy = dpy;
X cibclosure.func = AddSelection;
X cibclosure.bx = boxX;
X cibclosure.by = boxY;
X cibclosure.bw = boxW;
X cibclosure.bh = boxH;
X cibclosure.timestamp = timestamp;
X ListApply(ActiveClientList, ClientInBox, &cibclosure);
X }
X break;
X
X case MB_ADJUST:
X /* bounding box with toggles */
X if (TraceBoundingBox(dpy, &buttonPressEvent,
X &boxX, &boxY, &boxW, &boxH, ×tamp))
X {
X cibclosure.dpy = dpy;
X cibclosure.func = ToggleSelection;
X cibclosure.bx = boxX;
X cibclosure.by = boxY;
X cibclosure.bw = boxW;
X cibclosure.bh = boxH;
X cibclosure.timestamp = timestamp;
X ListApply(ActiveClientList, ClientInBox, &cibclosure);
X }
X break;
X }
X}
X
X/*
X * eventButtonRelease - handle a click
X */
static int
eventButtonRelease(dpy, pEvent, winInfo)
Display *dpy;
XXEvent *pEvent;
WinRoot *winInfo;
X{
X /* This only happens if we did NOT get a motion notify
X * after the last button press.
X */
X if (MouseButton(dpy, pEvent) == MB_SELECT)
X {
X /* Clear the selection list. */
X ClearSelections(dpy);
X
X /* Set the input focus to the root window. */
X XSetInputFocus(dpy, NoFocusWin, RevertToPointerRoot,
X pEvent->xbutton.time);
X
X /* Tell the server that we are now the current
X * selection owner. This might be necessary if
X * the user had selected some text in an xterm
X * and wants to unselect it. S/he does this by
X * clicking in the root window.
X */
X XSetSelectionOwner(dpy, XA_PRIMARY,
X RootWindow(dpy, DefaultScreen(dpy)),
X pEvent->xbutton.time);
X SelectionTime = pEvent->xbutton.time;
X }
X}
X
X/*
X * eventButtonPress - record a button press
X */
static int
eventButtonPress(dpy, pEvent, winInfo)
Display *dpy;
XXEvent *pEvent;
WinRoot *winInfo;
X{
X buttonPressEvent = *pEvent;
X
X /* set lastButton */
X if ((lastButton = MouseButton(dpy, pEvent)) == MB_MENU)
X {
X /* bring up menu for root */
X MenuShow(dpy, winInfo, RootMenu, pEvent);
X }
X}
X
X/*
X * eventSelectionNotify - someone else has asked for the selection value
X */
static int
eventSelectionNotify(dpy, pEvent, winInfo)
Display *dpy;
XXEvent *pEvent;
WinRoot *winInfo;
X{
X /* We get this event from the owner of the selection
X * if we had made a XConvertSelection call. At the
X * moment we never make a XConvertSelction call
X * so we don't have to worry about a SelectionNotify
X * event. An XCovertSelection call is used to get
X * the current selection.
X */
X}
X
X/*
X * eventSelectionRequest - someone else has asked for the selection value
X */
static int
eventSelectionRequest(dpy, pEvent, winInfo)
Display *dpy;
XXEvent *pEvent;
WinRoot *winInfo;
X{
X SelectionResponse((XSelectionRequestEvent *)pEvent);
X}
X
X/*
X * eventSelectionClear - someone else has asked to be the selection owner
X */
static int
eventSelectionClear(dpy, pEvent, winInfo)
Display *dpy;
XXEvent *pEvent;
WinRoot *winInfo;
X{
X /*
X * Someone else has asked to be the selection owner.
X * Clear our list of selected windows.
X */
X ClearSelections(dpy);
X}
X
X/*
X * eventKeyPressRelease - a keystroke has happened in the root window
X */
static int
eventKeyPressRelease(dpy, pEvent, winInfo)
Display *dpy;
XXEvent *pEvent;
WinRoot *winInfo;
X{
X rootKeystroke( dpy, pEvent );
X}
X
X/*
X * eventPropertyNotify - a root property has changed
X */
static int
eventPropertyNotify(dpy, pEvent, winInfo)
Display *dpy;
XXEvent *pEvent;
WinRoot *winInfo;
X{
X rootProperty( dpy, pEvent );
X}
X
X/*
X * eventUnmapNotify - an unreparented pane is going away
X */
static int
eventUnmapNotify(dpy, pEvent, winInfo)
Display *dpy;
XXEvent *pEvent;
WinRoot *winInfo;
X{
X WinGeneric *wg;
X
X wg = WIGetInfo(pEvent->xunmap.window);
X if (wg != NULL)
X {
X StateWithdrawn(wg->core.client);
X }
X}
X
X#ifdef NOTDEF
X/*
X * drawRoot -- draw the root window
X */
X/*ARGSUSED*/ /* dpy arg will be used when multiple Displays supported */
static int
drawRoot(dpy, winInfo)
Display *dpy;
WinGeneric *winInfo;
X{
X}
X
X/*
X * DestroyRoot -- destroy the root window resources and free any allocated
X * data.
X */
static int
destroyRoot(dpy, winInfo)
Display *dpy;
WinGeneric *winInfo;
X{
X /* free our data and throw away window */
X WIUninstallInfo(winInfo->core.self);
X MemFree(winInfo);
X}
X#endif
X
X/***************************************************************************
X* global functions
X***************************************************************************/
X
X/*
X * MakeRoot -- create the root window. Return a WinGeneric structure.
X */
WinGeneric *
MakeRoot(dpy, par)
Display *dpy;
WinGeneric *par; /* ignored */
X{
X XWindowAttributes attr;
X WinRoot *w;
X Window win;
X
X win = RootWindow(dpy, DefaultScreen(dpy));
X
X if (XGetWindowAttributes(dpy, win, &attr) == 0) {
X ErrorGeneral("could not get attributes of root window");
X /*NOTREACHED*/
X }
X
X /* create the associated structure */
X w = MemNew(WinRoot);
X w->core.self = win;
X w->class = &classRoot;
X w->core.kind = WIN_ROOT;
X w->core.parent = NULL;
X w->core.children = NULL;
X w->core.client = NULL;
X w->core.x = 0;
X w->core.y = 0;
X w->core.width = attr.width;
X w->core.height = attr.height;
X w->core.dirtyconfig = False;
X w->core.colormap = attr.colormap;
X w->core.exposures = NULL;
X
X /* register the window */
X WIInstallInfo(w);
X
X return w;
X}
X
void
RootInit(dpy)
Display *dpy;
X{
X classRoot.core.kind = WIN_ROOT;
X classRoot.core.xevents[ConfigureRequest] = eventConfigureRequest;
X classRoot.core.xevents[EnterNotify] = eventEnterNotify;
X classRoot.core.xevents[MapRequest] = eventMapRequest;
X classRoot.core.xevents[MotionNotify] = eventMotionNotify;
X classRoot.core.xevents[ButtonRelease] = eventButtonRelease;
X classRoot.core.xevents[ButtonPress] = eventButtonPress;
X classRoot.core.xevents[SelectionNotify] = eventSelectionNotify;
X classRoot.core.xevents[SelectionRequest] = eventSelectionRequest;
X classRoot.core.xevents[SelectionClear] = eventSelectionClear;
X classRoot.core.xevents[KeyPress] = eventKeyPressRelease;
X classRoot.core.xevents[KeyRelease] = eventKeyPressRelease;
X classRoot.core.xevents[PropertyNotify] = eventPropertyNotify;
X classRoot.core.xevents[UnmapNotify] = eventUnmapNotify;
X classRoot.core.focusfunc = NULL;
X classRoot.core.drawfunc = NULL;
X classRoot.core.destroyfunc = NULL;
X classRoot.core.selectfunc = NULL;
X classRoot.core.newconfigfunc = NULL;
X classRoot.core.newposfunc = NULL;
X classRoot.core.setconfigfunc = NULL;
X classRoot.core.createcallback = NULL;
X classRoot.core.heightfunc = NULL;
X classRoot.core.widthfunc = NULL;
X}
END_OF_FILE
if test 14250 -ne `wc -c <'winroot.c'`; then
echo shar: \"'winroot.c'\" unpacked with wrong size!
fi
# end of 'winroot.c'
fi
echo shar: End of archive 5 \(of 16\).
cp /dev/null ark5isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 16 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
--
Dan Heller
O'Reilly && Associates Z-Code Software Comp-sources-x:
Senior Writer President comp-sources.x at uunet.uu.net
argv at ora.com argv at zipcode.com
More information about the Comp.sources.x
mailing list