v12i058: olvwm - Open Look Virtual Window Manager, Part02/16

Scott Oaks - Sun Consulting NYC sdo at soliado.East.Sun.COM
Mon Apr 29 03:29:02 AEST 1991


Submitted-by: sdo at soliado.East.Sun.COM (Scott Oaks - Sun Consulting NYC)
Posting-number: Volume 12, Issue 58
Archive-name: olvwm/part02

#! /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 2 (of 16)."
# Contents:  LEGAL_NOTICE Select.c defaults.c group.c st.c winbusy.c
#   winnofoc.c winresize.c
# Wrapped by sdo at piccolo on Fri Apr 26 17:31:02 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'LEGAL_NOTICE' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'LEGAL_NOTICE'\"
else
echo shar: Extracting \"'LEGAL_NOTICE'\" \(4995 characters\)
sed "s/^X//" >'LEGAL_NOTICE' <<'END_OF_FILE'
This code is based on the OLWM code distributed with X11R4.  In addition,
I looked heavily at the public versions of tvtwm (though none of that code
is included directly, and hence the copyright notice from Solboure is
included more for safety than anything else).
X
X	NOTICE TO USER: The source code, including the glyphs or icons 
X	forming a par of the OPEN LOOK TM Graphic User Interface, on this 
X	tape and in these files is copyrighted under U.S. and international
X	laws. Sun Microsystems, Inc. of Mountain View, California owns
X	the copyright and has design patents pending on many of the icons. 
X	AT&T is the owner of the OPEN LOOK trademark associated with the
X	materials on this tape. Users and possessors of this source code 
X	are hereby granted a nonexclusive, royalty-free copyright and 
X	design patent license to use this code in individual and 
X	commercial software. A royalty-free, nonexclusive trademark
X	license to refer to the code and output as "OPEN LOOK" compatible 
X	is available from AT&T if, and only if, the appearance of the 
X	icons or glyphs is not changed in any manner except as absolutely
X	necessary to accommodate the standard resolution of the screen or
X	other output device, the code and output is not changed except as 
X	authorized herein, and the code and output is validated by AT&T. 
X	Bigelow & Holmes is the owner of the Lucida (R) trademark for the
X	fonts and bit-mapped images associated with the materials on this 
X	tape. Users are granted a royalty-free, nonexclusive license to use
X	the trademark only to identify the fonts and bit-mapped images if, 
X	and only if, the fonts and bit-mapped images are not modified in any
X	way by the user. 
X
X
X	Any use of this source code must include, in the user documentation 
X	and internal comments to the code, notices to the end user as  
X	follows:
X
X
X	(c) Copyright 1989 Sun Microsystems, Inc. Sun design patents
X	pending in the U.S. and foreign countries. OPEN LOOK is a 
X	trademark of AT&T. Used by written permission of the owners.
X
X
X 	(c) Copyright Bigelow & Holmes 1986, 1985. Lucida is a registered 
X	trademark of Bigelow & Holmes. Permission to use the Lucida 
X	trademark is hereby granted only in association with the images 
X	and fonts described in this file.
X
X
X
X	SUN MICROSYSTEMS, INC., AT&T, AND BIGELOW & HOLMES 
X	MAKE NO REPRESENTATIONS ABOUT THE SUITABILITY OF
X 	THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" 
X	WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. 
X	SUN  MICROSYSTEMS, INC., AT&T AND BIGELOW  & HOLMES, 
X	SEVERALLY AND INDIVIDUALLY, DISCLAIM ALL WARRANTIES 
X	WITH REGARD TO THIS SOURCE CODE, INCLUDING ALL IMPLIED
X	WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
X	PARTICULAR PURPOSE. IN NO EVENT SHALL SUN MICROSYSTEMS,
X	INC., AT&T OR BIGELOW & HOLMES BE LIABLE FOR ANY
X	SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
X	OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA 	
X	OR PROFITS, WHETHER IN AN ACTION OF  CONTRACT, NEGLIGENCE
X	OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
X	WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.
X
X/*****************************************************************************/
X/**               Copyright 1990 by Solbourne Computer Inc.                 **/
X/**                          Longmont, Colorado                             **/
X/**                                                                         **/
X/**                           All Rights Reserved                           **/
X/**                                                                         **/
X/**    Permission to use, copy, modify, and distribute this software and    **/
X/**    its documentation  for  any  purpose  and  without  fee is hereby    **/
X/**    granted, provided that the above copyright notice appear  in  all    **/
X/**    copies and that both  that  copyright  notice  and  this  permis-    **/
X/**    sion  notice appear in supporting  documentation,  and  that  the    **/
X/**    name of Solbourne not be used in advertising                         **/
X/**    in publicity pertaining to distribution of the  software  without    **/
X/**    specific, written prior permission.                                  **/
X/**                                                                         **/
X/**    SOLBOURNE COMPUTER INC. DISCLAIMS ALL WARRANTIES WITH REGARD         **/
X/**    TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES  OF  MERCHANT-    **/
X/**    ABILITY  AND  FITNESS,  IN  NO  EVENT SHALL SOLBOURNE                **/
X/**    BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL  DAM-           **/
X/**    AGES OR  ANY DAMAGES WHATSOEVER  RESULTING FROM LOSS OF USE, DATA    **/
X/**    OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER    **/
X/**    TORTIOUS ACTION, ARISING OUT OF OR IN  CONNECTION  WITH  THE  USE    **/
X/**    OR PERFORMANCE OF THIS SOFTWARE.                                     **/
X/*****************************************************************************/
END_OF_FILE
if test 4995 -ne `wc -c <'LEGAL_NOTICE'`; then
    echo shar: \"'LEGAL_NOTICE'\" unpacked with wrong size!
fi
# end of 'LEGAL_NOTICE'
fi
if test -f 'Select.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Select.c'\"
else
echo shar: Extracting \"'Select.c'\" \(7325 characters\)
sed "s/^X//" >'Select.c' <<'END_OF_FILE'
X/*
X *      (c) Copyright 1989 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[] = "@(#)Select.c	1.2 olvwm version 3/30/91";
X
X/*
X * Based on
static	char	sccsid[] = "@(#) Select.c 25.2 90/04/17 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
X#include "olwm.h"
X#include "win.h"
X#include "list.h"
X
static List *selectList = NULL_LIST;
X
Time SelectionTime;
X
X/* Externals */
extern Atom	AtomLength;
extern Atom	AtomListLength;
extern Atom	AtomTargets;
extern Atom	AtomTimestamp;
extern Atom AtomOlwmTimestamp;
X
X/*
X * IsSelected -- returns boolean telling whether or not client is selected.
X *
X * Input:
X *
X *	cli	- client which might be on selection list.
X *
X * Output:
X *
X *	Returns True if the client cli is on the selection list.
X *	Returns False if it is not.
X *
X * Globals:
X *
X *	selectList	- The list of selected windows.
X */
Bool
IsSelected(cli)
Client *cli;
X{
X	return cli->isSelected;
X}
X
X
X/*
X * AddSelection -- add this client to the selection list if it is not 
X *	already present.  This routine also tells the server it is the current 
X *	XA_PRIMARY selection owner.
X *
X * Input:
X *
X *	cli	- The client we are adding to the selectList.
X *
X * Output:
X *
X *	None.
X *
X * Globals:
X *
X *	selectList	- The list of selected windows.
X *	The current selection owner in the server is also adjusted.
X */
int
AddSelection(cli, timestamp)
Client *cli;
Time timestamp;
X{
X	List *l = selectList;
X	Client *tc;
X
X	if (selectList == NULL_LIST)
X	{
X		/* Tell the server that we are now the 
X		 * current selection owner.
X		 * We really only need to call this 
X		 * if this is the first window
X		 * in the SelectList.  Calling this sends the
X		 * previous owner of the XA_PRIMARY selection 
X		 * a SelectionClear event, unless the previous 
X		 * owner was us already.
X	 	 */
X		XSetSelectionOwner(cli->dpy, XA_PRIMARY, 
X				   RootWindow(cli->dpy, cli->screen),
X				   timestamp);
X	}
X	else
X	{
X		/* First look to see if window is already listed. */
X		for(tc = ListEnum(&l); tc != NULL; tc = ListEnum(&l))
X		{
X			if (tc == cli)
X				return;
X		}
X	}
X
X	/* If we get here the window wasn't already in the list. */
X	selectList = ListCons(cli,selectList);
X	cli->isSelected = True;
X
X	/* Tell the window it is selected. */
X	WinCallSelect(cli, True);
X	SelectionTime = timestamp;
X}
X
X/*
X * RemoveSelection -- de-select the window
X *
X * Purpose:
X * 	This routine will remove an entry from the SelectList.
X * Input:
X *
X *	winInfo	- The window we are removing from the SelectList.
X *
X * Output:
X *	Returns True if client was deselected; false if the
X *	client was not already selected.
X *
X * Globals:
X *
X *	selectList	- The list of selected windows.
X */
Bool
RemoveSelection(cli)
Client *cli;
X{
X	List **l;
X
X	for (l = &selectList ; *l != NULL; l = &((*l)->next))
X	{
X		if ((*l)->value == cli)
X		{
X			ListDestroyCell(l);
X			cli->isSelected = False;
X			WinCallSelect(cli,False);
X			return True;
X		}
X	}
X	return False;
X}
X
X
X
X/*
X * ToggleSelection -- if the winInfo is already selected, then de-select it.
X *	If not, then select it.
X *	Returns whether it is selected or not.
X */
Bool
ToggleSelection(cli, timestamp)
Client *cli;
Time timestamp;
X{
X
X	/* If already present, we want to deselect. */
X	if (RemoveSelection(cli))
X		return False;
X	else
X	{
X		AddSelection(cli, timestamp);
X		return True;
X	}
X}
X
X
X/*
X * ClearSelections -- clear the selection list
X */
void
ClearSelections(dpy)
Display	*dpy;
X{
X	List *l;
X	Client *cli;
X
X	l = selectList;
X	for(cli = ListEnum(&l); cli != NULL; cli = ListEnum(&l))
X	{
X		cli->isSelected = False;
X		WinCallSelect(cli,False);
X	}
X	ListDestroy(selectList);
X	selectList = NULL_LIST;
X}
X
X/*
X * EnumSelections --- enumerate the selected client structures.  
X *	Pass NULL to begin enumeration; any non-NULL value thereafter
X *	will continue enumeration where it left off.  This function
X *	uses static data, so only one enumeration can happen at any
X *	given time.
X *	Returns NULL when list is exhausted.
X */
Client *
XEnumSelections(foo)
void *foo;
X{
X	static List *l;
X	Client *ct;
X
X	if (foo == NULL)
X		l = selectList;
X
X	if (l != NULL)
X	{
X		ct = l->value;
X		l = l->next;
X		return ct;
X	}
X	return NULL;
X}
X
X/*
X * SelectionResponse
X * Respond to a selection request in the manner specified by the ICCCM.
X * If we understand the target, write the appropriate property and send the 
X * event.  If we don't understand the target, just send the event.
X */
void
SelectionResponse(request)
X    XSelectionRequestEvent *request;
X{
X    XSelectionEvent response;
X    unsigned long data[10]; /* longer than anything actually passed */
X    unsigned long *wdata;
X    int format, nelements, i;
X    Bool accepted = True;
X    Atom type;
X    Client *cli;
X
X    response.type = SelectionNotify;
X    response.serial = request->serial;
X    response.requestor = request->requestor;
X    response.selection = request->selection;
X    response.time = request->time;
X
X    if ( request->property == None ) {
X	/*
X	 * The requestor is obsolete, because the property field should always 
X	 * contain the destination property.  Use the target atom to name this 
X	 * property, per the suggestion in ICCCM section 2.2.
X	 */
X	request->property = request->target;
X    }
X
X    /*
X     * REMIND: We don't support MULTIPLE yet.
X     */
X    if ( request->target == AtomTargets ) {
X	data[0] = AtomTargets;
X	data[1] = AtomTimestamp;
X	data[2] = AtomListLength;
X	data[3] = XA_DRAWABLE;
X	data[4] = AtomLength;
X	type = XA_ATOM;
X	format = 32;
X	nelements = 5;
X	wdata = data;
X    } else if ( request->target == AtomTimestamp ) {
X	data[0] = SelectionTime;
X	type = XA_INTEGER;
X	format = 32;
X	nelements = 1;
X	wdata = data;
X    } else if ( request->target == AtomListLength ) {
X	data[0] = ListCount(selectList);
X	type = XA_INTEGER;
X	format = 32;
X	nelements = 1;
X	wdata = data;
X    } else if ( request->target == XA_DRAWABLE ) {
X	nelements = ListCount(selectList);
X	wdata = (unsigned long *)MemCalloc(nelements,sizeof(unsigned long));
X	cli = NULL;
X	i = 0;
X	while (cli = EnumSelections(cli))
X	    wdata[i++] = PANEWINOFCLIENT(cli);
X	type = XA_DRAWABLE;
X	format = 32;
X    } else if ( request->target == AtomLength ) {
X	data[0] = ListCount(selectList)*sizeof(long);
X	type = XA_INTEGER;
X	format = 32;
X	nelements = 1;
X	wdata = data;
X    } else {
X	accepted = False;
X    }
X
X    if ( accepted ) {
X	XChangeProperty(request->display,request->requestor,request->property,
X			type, format, PropModeReplace, wdata, nelements);
X	response.target = request->target;
X	response.property = request->property;
X    } else {
X	response.target = None;
X	response.property = None;
X    }
X
X    XSendEvent(request->display, request->requestor, False,
X	       NoEventMask, &response);
X}
X
X/* TimeFresh -- get a fresh timestamp from the server
X */
Time
TimeFresh(win)
WinGeneric *win;
X{
X	XEvent e;
X	Time timestamp;
X
X	XChangeProperty(win->core.client->dpy, win->core.self,
X		AtomOlwmTimestamp, XA_INTEGER,
X		32, PropModeReplace, win, 0);
X	XSync(win->core.client->dpy,0);
X	if (XCheckTypedWindowEvent(win->core.client->dpy, win->core.self,
X	    PropertyNotify, &e))
X		timestamp = e.xproperty.time;
X	else
X		timestamp = CurrentTime;
X
X	return timestamp;
X}
END_OF_FILE
if test 7325 -ne `wc -c <'Select.c'`; then
    echo shar: \"'Select.c'\" unpacked with wrong size!
fi
# end of 'Select.c'
fi
if test -f 'defaults.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'defaults.c'\"
else
echo shar: Extracting \"'defaults.c'\" \(4894 characters\)
sed "s/^X//" >'defaults.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[] = "@(#)defaults.c	1.2 olvwm version 3/30/91";
X/*
X * Based on
static	char	sccsid[] = "@(#) defaults.c 25.2 90/05/16 Crucible";
X *
X */
X
X#include <ctype.h>
X#include <errno.h>
X#include <stdio.h>
X#include <strings.h>
X#include <sys/file.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
char	*getenv();
X
X#include "olwm.h"
X#include "defaults.h"
X#include "globals.h"
X#include "resources.h"
X
extern	char	*ProgramName;
X
extern	XrmDatabase	OlwmDB;
X
X/* private data */
static void parseResourceDefaults();
static void parseApplicationDefaults();
X
X/* 
X * GetDefaults - Set up global OlwmDB with built-in default values.
X *		Then, initialize all the appropriate olwm variables
X *		using the information in the OlwmDB
X */
void
GetDefaults(dpy, commandlineDB)
Display		*dpy;
XXrmDatabase	commandlineDB;
X{
X	/* put resource settings from default files into global OlwmDB */
X	parseApplicationDefaults();
X	parseResourceDefaults( dpy );
X
X	/* merge command line options last into global OlwmDB
X	 * notice that commandlineDB is destroyed by this call!
X	 */
X	if ( commandlineDB != NULL )
X		(void) XrmMergeDatabases( commandlineDB, &OlwmDB );
X
X	SetAllDBValues( dpy );
X}
X
X
X/* 
X * parseApplicationDefaults - get resource settings from application 
X *	default file
X */
static void
parseApplicationDefaults()
X{
X	XrmDatabase	applicationDB = NULL;
X	char		filename[1024];
X        char            *openWinPath;
X	Bool		notFound = False;
X
X        /* look for application default file */
X	if ( (openWinPath = getenv( "OPENWINHOME" )) != NULL )
X	{
X		(void) strcpy( filename, openWinPath );
X		(void) strcat( filename, "/lib/app-defaults/" );
X		(void) strcat( filename, ProgramName );
X		if ( access( filename, R_OK ) != 0 )
X			notFound = True;
X	}
X        else
X		notFound = True;
X
X	if ( notFound )
X	{
X        	(void) strcpy( filename, "/usr/lib/X11/app-defaults/" );
X		(void) strcat( filename, ProgramName );
X	}
X
X        applicationDB = XrmGetFileDatabase( filename );
X	if ( applicationDB != NULL )
X        	(void) XrmMergeDatabases( applicationDB, &OlwmDB );
X}
X
X/* 
X * parseResourceDefaults - get resource settings from default user locations.
X *	Look first for server property - if it's there, use it alone.
X *	If it's not there, look for XENVIRONMENT file and use it.
X *	If still no luck, use $HOME/.Xdefaults.
X */
static void
parseResourceDefaults( dpy )
Display	*dpy;
X{
X	XrmDatabase	serverDB = NULL, homeDB = NULL;
X	char		filename[1024];
X	unsigned long	nitems, remain;
X	char		*resourceString;
X	char		*environmentFile;
X
X	/*  look for xrdb/server specified defaults */
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) && (nitems != 0))
X	{
X		serverDB = XrmGetStringDatabase( resourceString );
X		(void) XrmMergeDatabases( serverDB, &OlwmDB );
X		XFree( resourceString );
X		return;
X	}
X
X	/* if unsuccessful, look for user defaults: 
X	 * first try XENVIRONMENT, next in $HOME/.Xdefaults 
X	 */
X	if ( ( (environmentFile = getenv( "XENVIRONMENT" )) == NULL )
X	     || ( access( environmentFile, R_OK ) != 0 ) )
X	{
X		if ( (environmentFile = getenv( "HOME" )) != NULL )
X		{
X			(void) strcpy( filename, environmentFile );
X			(void) strcat( filename, "/" );
X			(void) strcat( filename, ".Xdefaults" );
X			environmentFile = filename;
X		}
X	}
X	if ( environmentFile != NULL )
X	{
X		homeDB = XrmGetFileDatabase( environmentFile );
X		(void) XrmMergeDatabases( homeDB, &OlwmDB );
X	}
X	return;
X}
X
X
X/*
X * SetAllDBValues - read all the resources from the OlwmDB and
X *	set the appropriate olwm variables
X */
void
SetAllDBValues(dpy)
Display	*dpy;
X{
X	char			name[MAX_NAME];
X	char			class[MAX_CLASS];
X	XrmRepresentation	repType;
X	XrmValue        	value;
X	int             	ii;
X
X	/* find out if ProgramName is the name tag, or if the user
X	 * has specified something else
X	 *
X	 * NOTICE that this was already done once in main() (for commandline
X	 * arg only), is it possible to change in a resource specification?
X	 */
X	(void) SetNameTag( dpy, RM_PREFIX, NULL, False );
X
X	/*  loop through all resources, except RM_DISPLAY and RM_PREFIX */
X	for ( ii = 0 ; ii < RM_ENTRYEND ; ii++ )
X	{
X		if ( ii == RM_DISPLAY || ii == RM_PREFIX )
X			continue;
X
X		MakeRMName( name, ii );
X		MakeRMClass( class, ii );
X		if ( XrmGetResource( OlwmDB, name, class, &repType, &value ) )
X			RMTable[ii].setFunc( dpy, ii, value.addr, False );
X		else
X			RMTable[ii].setFunc( dpy, ii, NULL, False );
X	}
X}
END_OF_FILE
if test 4894 -ne `wc -c <'defaults.c'`; then
    echo shar: \"'defaults.c'\" unpacked with wrong size!
fi
# end of 'defaults.c'
fi
if test -f 'group.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'group.c'\"
else
echo shar: Extracting \"'group.c'\" \(6681 characters\)
sed "s/^X//" >'group.c' <<'END_OF_FILE'
X/*
X *      (c) Copyright 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[] = "@(#)group.c	1.2 olvwm version 3/30/91";
X
X/*
X * Based on
X @(#) group.c 1.2 90/04/10 Crucible 
X *
X */
X
X#include <stdio.h>
X#include <X11/Xos.h>
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include "mem.h"
X#include "st.h"
X#include "olwm.h"
X#include "win.h"
X#include "list.h"
X#include "group.h"
X
X/***************************************************************************
X* Local data
X***************************************************************************/
X
static st_table *groupHashTable;
X
X/***************************************************************************
X* Local functions
X***************************************************************************/
X
X/* groupFindList -- find a client in a list of clients; return a given
X * value if found or 0 otherwise.  If passed a pointer to a List **, set that.
X */
static unsigned int
groupFindList(plist, cli, retlist, retval)
List **plist;
Client *cli;
List ***retlist;
unsigned int retval;
X{
X	if ((cli == NULL) || (*plist == NULL))
X	{
X		if (retlist != NULL)
X			*retlist = NULL;
X		return 0;
X	}
X
X	if ((*plist)->value == cli)
X	{
X		if (retlist != NULL)
X			*retlist = plist;
X		return retval;
X	}
X	return groupFindList(&((*plist)->next), cli, retlist, retval);
X}
X
X
X/* groupFindCli -- find a client in a group.  Return a mask indicating
X * which category of client the client was found in, if any; if a list
X * pointer is passed in, return a pointer to a List * in that parameters
X * (presumably for list deletion).
X */
static unsigned int
groupFindCli(group, cli, ppList)
Group *group;
Client *cli;
List ***ppList;
X{
X    unsigned int retmask;
X    List **retlist;
X    Bool found;
X    Client *clitest;
X
X    if (cli == group->leader)
X    {
X        retmask = GROUP_LEADER;
X    }
X    else
X    {
X	if ((retmask = groupFindList(&(group->dependents), cli, ppList, 
X	  GROUP_DEPENDENT)) == 0)
X	    retmask = groupFindList(&(group->independents), cli, ppList, 
X		GROUP_INDEPENDENT);
X    }
X    return retmask;
X}
X
X/* groupCompare -- utility function to compare two group id's
X */
static int
groupCompare(g1,g2)
register char *g1, *g2;
X{
X	return ((GroupID)g1) - ((GroupID)g2);
X}
X
X/* groupHash -- hash function for group id lookup table 
X */
static int
groupHash(g1, modulus)
register char *g1;
register int modulus;
X{
X	return ((GroupID)g1)%modulus;
X}
X
X/* groupInsert -- put a group structure into the lookup table
X */
static void
groupInsert(group)
Group *group;
X{
X	st_insert(groupHashTable, (int)group->groupid, (char *)group);
X}
X
X/* groupDelete -- remove a group structure from the lookup table
X */
static Bool
groupDelete(grpid)
GroupID grpid;
X{
X	Group *oldGrp;
X	GroupID tmpGrp = grpid;
X	GroupID *tmpGrpPtr = &tmpGrp;
X
X	return st_delete(groupHashTable, (char *)tmpGrpPtr, (char *)&oldGrp);
X}
X
X/***************************************************************************
X* Global functions
X***************************************************************************/
X
X/*
X * GroupInit -- initialises the hash table used to map group id's to
X * 	group structures.
X */
void 
GroupInit()
X{
X	groupHashTable = st_init_table(groupCompare, groupHash);
X}
X
X
X/* GroupApply -- applies a function to each part of the group identified 
X * in the mask; as with any apply function, when the function returns
X * a non-NULL value application stops and that value is returned.
X */
void *
GroupApply(grpid, func, closure, mask)
GroupID grpid;
GroupFunc func;
void *closure;
unsigned int mask;
X{
X	Group *group;
X	void *res = NULL;
X
X	group = GroupLookup(grpid);
X	if (group == NULL)
X		return NULL;
X
X	if ((mask & GROUP_LEADER) && (group->leader != NULL))
X	{
X		res = (func)(group->leader, closure);
X	}
X
X	if ((mask & GROUP_DEPENDENT) && (group->dependents != NULL) && 
X	    (res == NULL))
X	{
X		res = ListApply(group->dependents,func,closure);
X	}
X
X	if ((mask & GROUP_INDEPENDENT) && (group->independents != NULL) && 
X	    (res == NULL))
X	{
X		res = ListApply(group->independents,func,closure);
X	}
X
X	return res;
X}
X
X/* GroupLookup -- given a GroupID, returns the associated group structure, 
X * or NULL if there is none.
X */
Group *
GroupLookup(group)
GroupID group;
X{
X	Group *tmp = NULL;
X
X	st_lookup(groupHashTable, group, &tmp);
X	return tmp;
X}
X
X/* GroupAdd -- adds a client to the named group, creating the group if need be.
X * The kind of client is specified in the mask field.  Returns True
X * if the client was successfully added.
X */
Bool 
GroupAdd(grpid, cli, mask)
GroupID grpid;
Client *cli;
unsigned int mask;
X{
X	Group *group;
X	unsigned int currmask;
X
X	group = GroupLookup(grpid);
X	if (group == NULL)
X	{
X		group = MemNew(Group);
X		group->groupid = grpid;
X		groupInsert(group);
X		currmask = 0;
X	}
X	else
X	{
X		currmask = groupFindCli(group, cli, NULL);
X	}
X	
X	if (mask & GROUP_LEADER)
X	{
X		if ((currmask == 0) || (group->leader == cli))
X		{
X			group->leader = cli;
X			return True;
X		}
X		else
X			return False;
X	}
X	else if (mask & GROUP_DEPENDENT)
X	{
X		if (currmask != 0)
X			return False;
X		group->dependents = ListCons(cli,group->dependents);
X	}
X	else if (mask & GROUP_INDEPENDENT)
X	{
X		if (currmask != 0)
X			return False;
X		group->independents = ListCons(cli,group->independents);
X	}
X}
X
X/* GroupRemove -- removes a client from the group.  If the group becomes empty
X * it is deleted.  Returns True if the client was successfully deleted.
X */
Bool 
GroupRemove(grpid,cli)
GroupID grpid;
Client *cli;
X{
X	Group *group;
X	unsigned int mask;
X	List **plist;
X
X	group = GroupLookup(grpid);
X	if (group == NULL)
X		return False;
X
X	mask = groupFindCli(group, cli, &plist);
X	if (mask == GROUP_LEADER)
X	{
X		group->leader = NULL;
X	}
X	else if ((mask == GROUP_DEPENDENT) || (mask == GROUP_INDEPENDENT))
X	{
X		ListDestroyCell(plist);
X	}
X	else
X	{
X		return False;
X	}
X	if ((group->leader == NULL) && (group->dependents == NULL) && 
X	    (group->independents == NULL))
X	{
X		groupDelete(group->groupid);
X		MemFree(group);
X	}
X	return True;
X}
X
X
X/* GroupIsLeader -- returns whether a particular client is leader of a group
X *	If the group hasn't been registered yet, assume that this client is 
X *	its leader.
X */
Bool
GroupIsLeader(grpid, cli)
GroupID grpid;
Client *cli;
X{
X    Group *group;
X
X    group = GroupLookup(grpid);
X    if (group == NULL)
X        return True;
X    return (group->leader == cli);
X}
X
X
X/* GroupLeader -- returns the leader of a group
X */
Client *
GroupLeader(grpid)
GroupID grpid;
X{
X	Group *group;
X
X	group = GroupLookup(grpid);
X	if (group == NULL)
X		return NULL;
X	else
X		return group->leader;
X}
END_OF_FILE
if test 6681 -ne `wc -c <'group.c'`; then
    echo shar: \"'group.c'\" unpacked with wrong size!
fi
# end of 'group.c'
fi
if test -f 'st.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'st.c'\"
else
echo shar: Extracting \"'st.c'\" \(8170 characters\)
sed "s/^X//" >'st.c' <<'END_OF_FILE'
X/* This is a general purpose hash table package written by Peter Moore @ UCB. */
X
static	char	sccsid[] = "@(#) st.c 25.2 90/05/01 Crucible";
X#ifndef lint
static char *rcsid = "$Header: $";
X#endif
X
X#include <stdio.h>
X#include "st.h"
X#include "mem.h"
X
X
X#define max(a,b) ((a) > (b) ? (a) : (b))
X#define nil(type) ((type *) 0)
X#define alloc(type) (type *)MemAlloc((unsigned)sizeof(type))
X#define Calloc(n,s) (char *)MemCalloc((n),(s))
X
X    /*
X     * DEFAULT_MAX_DENSITY is the default for the largest we allow the
X     * average number of items per bin before increasing the number of
X     * bins
X     *
X     * DEFAULT_INIT_TABLE_SIZE is the default for the number of bins
X     * allocated initially
X     *
X     * DEFAULT_GROW_FACTOR is the amount the hash table is expanded after
X     * the density has reached max_density
X     */
X
X#define EQUAL(func, x, y) \
X    ((func == ST_NUMCMP) ? ((x) == (y)) : ((*func)((x), (y)) == 0))
X
X/*#define do_hash(key, table) (*table->hash)(key, table->num_bins)*/
X
X#define do_hash(key, table)\
X    ((table->hash == ST_PTRHASH) ? (((int) (key) >> 2) % table->num_bins) :\
X	(table->hash == ST_NUMHASH) ? ((int) (key) % table->num_bins) :\
X	(*table->hash)((key), table->num_bins))
X
st_table *st_init_table_with_params(compare, hash, size, density, grow_factor,
X				    reorder_flag)
int (*compare)();
int (*hash)();
int size;
int density;
double grow_factor;
int reorder_flag;
X{
X    st_table *new;
X
X    new = alloc(st_table);
X    new->compare = compare;
X    new->hash = hash;
X    new->num_entries = 0;
X    new->max_density = density;
X    new->grow_factor = grow_factor;
X    new->reorder_flag = reorder_flag;
X    new->num_bins = size;
X    new->bins = 
X	(st_table_entry **) Calloc((unsigned)size, sizeof(st_table_entry *));
X    return new;
X}
X
st_table *st_init_table(compare, hash)
int (*compare)();
int (*hash)();
X{
X    return st_init_table_with_params(compare, hash, ST_DEFAULT_INIT_TABLE_SIZE,
X				     ST_DEFAULT_MAX_DENSITY,
X				     ST_DEFAULT_GROW_FACTOR,
X				     ST_DEFAULT_REORDER_FLAG);
X}
X			    
st_free_table(table)
st_table *table;
X{
X    register st_table_entry *ptr, *next;
X    int i;
X
X    for(i = 0; i < table->num_bins ; i++) {
X	ptr = table->bins[i];
X	while (ptr != nil(st_table_entry)) {
X	    next = ptr->next;
X	    free((char *) ptr);
X	    ptr = next;
X	}
X    }
X    free((char *) table->bins);
X    free((char *) table);
X}
X
X#define PTR_NOT_EQUAL(table, ptr, key)\
X(ptr != nil(st_table_entry) && !EQUAL(table->compare, key, (ptr)->key))
X
X#define FIND_ENTRY(table, ptr, hashval)\
ptr = (table)->bins[hashval];\
if (PTR_NOT_EQUAL(table, ptr, key)) {\
X    while (PTR_NOT_EQUAL(table, ptr->next, key)) {\
X	ptr = ptr->next;\
X    }\
X    if (ptr->next != nil(st_table_entry) && (table)->reorder_flag) {\
X	st_table_entry *_tmp = (ptr)->next;\
X	(ptr)->next = (ptr)->next->next;\
X	_tmp->next = (table)->bins[hashval];\
X	(table)->bins[hashval] = _tmp;\
X	ptr = _tmp;\
X    } else {\
X	ptr = ptr->next;\
X    }\
X}
X	
st_lookup(table, key, value)
st_table *table;
register char *key;
char **value;
X{
X    int hash_val;
X    register st_table_entry *ptr;
X
X    hash_val = do_hash(key, table);
X
X    FIND_ENTRY(table, ptr, hash_val);
X    
X    if (ptr == nil(st_table_entry)) {
X	return 0;
X    } else {
X	if (value != nil(char *))  *value = ptr->record; 
X	return 1;
X    }
X}
X
X#define ADD_DIRECT(table, key, value, hash_val, new)\
X{\
X    if (table->num_entries/table->num_bins > table->max_density) {\
X	rehash(table);\
X	hash_val = do_hash(key,table);\
X    }\
X    \
X    new = alloc(st_table_entry);\
X    \
X    new->key = key;\
X    new->record = value;\
X    new->next = table->bins[hash_val];\
X    table->bins[hash_val] = new;\
X    table->num_entries++;\
X}
X
st_insert(table, key, value)
register st_table *table;
register char *key;
char *value;
X{
X    int hash_val;
X    st_table_entry *new;
X    register st_table_entry *ptr;
X
X    hash_val = do_hash(key, table);
X
X    FIND_ENTRY(table, ptr, hash_val);
X
X    if (ptr == nil(st_table_entry)) {
X	ADD_DIRECT(table,key,value,hash_val,new);
X	return 0;
X    } else {
X	ptr->record = value;
X	return 1;
X    }
X}
X
st_add_direct(table, key, value)
st_table *table;
char *key;
char *value;
X{
X    int hash_val;
X    st_table_entry *new;
X    
X    hash_val = do_hash(key, table);
X    ADD_DIRECT(table, key, value, hash_val, new);
X}
X
st_find_or_add(table, key, slot)
st_table *table;
char *key;
char ***slot;
X{
X    int hash_val;
X    st_table_entry *new, *ptr;
X
X    hash_val = do_hash(key, table);
X
X    FIND_ENTRY(table, ptr, hash_val);
X
X    if (ptr == nil(st_table_entry)) {
X	ADD_DIRECT(table, key, (char *)0, hash_val, new)
X	if (slot != nil(char **)) *slot = &new->record;
X	return 0;
X    } else {
X	if (slot != nil(char **)) *slot = &ptr->record;
X	return 1;
X    }
X}
X
static rehash(table)
register st_table *table;
X{
X    register st_table_entry *ptr, *next, **old_bins = table->bins;
X    int i, old_num_bins = table->num_bins, hash_val;
X
X    table->num_bins = table->grow_factor*old_num_bins;
X    
X    if (table->num_bins%2 == 0) {
X	table->num_bins += 1;
X    }
X    
X    table->num_entries = 0;
X    table->bins = 
X      (st_table_entry **) Calloc((unsigned) table->num_bins,
X	    sizeof(st_table_entry *));
X
X    for(i = 0; i < old_num_bins ; i++) {
X	ptr = old_bins[i];
X	while (ptr != nil(st_table_entry)) {
X	    next = ptr->next;
X	    hash_val = do_hash(ptr->key, table);
X	    ptr->next = table->bins[hash_val];
X	    table->bins[hash_val] = ptr;
X	    table->num_entries++;
X	    ptr = next;
X	}
X    }
X    free((char *) old_bins);
X}
X
st_table *st_copy(old_table)
st_table *old_table;
X{
X    st_table *new_table;
X    st_table_entry *ptr, *new;
X    int i, num_bins = old_table->num_bins;
X
X    new_table = alloc(st_table);
X    if (new_table == nil(st_table)) {
X	return nil(st_table);
X    }
X    
X    *new_table = *old_table;
X    new_table->bins = 
X      (st_table_entry **) Calloc((unsigned) num_bins, sizeof(st_table_entry *));
X    
X    if (new_table->bins == nil(st_table_entry *)) {
X	free((char *) new_table);
X	return nil(st_table);
X    }
X
X    for(i = 0; i < num_bins ; i++) {
X	new_table->bins[i] = nil(st_table_entry);
X	ptr = old_table->bins[i];
X	while (ptr != nil(st_table_entry)) {
X	    new = alloc(st_table_entry);
X	    if (new == nil(st_table_entry)) {
X		free((char *) new_table->bins);
X		free((char *) new_table);
X		return nil(st_table);
X	    }
X	    *new = *ptr;
X	    new->next = new_table->bins[i];
X	    new_table->bins[i] = new;
X	    ptr = ptr->next;
X	}
X    }
X    return new_table;
X}
X
st_delete(table, key, value)
register st_table *table;
register char **key;
char **value;
X{
X    int hash_val;
X    st_table_entry *tmp;
X    register st_table_entry *ptr;
X
X    hash_val = do_hash(*key, table);
X
X    ptr = table->bins[hash_val];
X
X    if (ptr == nil(st_table_entry)) {
X	*value = nil(char);
X	return 0;
X    }
X
X    if (EQUAL(table->compare, *key, ptr->key)) {
X	table->bins[hash_val] = ptr->next;
X	table->num_entries--;
X	if (value != nil(char *)) *value = ptr->record;
X	*key = ptr->key;
X	free((char *) ptr);
X	return 1;
X    }
X
X    for(; ptr->next != nil(st_table_entry); ptr = ptr->next) {
X	if (EQUAL(table->compare, ptr->next->key, *key)) {
X	    tmp = ptr->next;
X	    ptr->next = ptr->next->next;
X	    if (value != nil(char *)) *value = tmp->record;
X	    *key = tmp->key;
X	    free((char *) tmp);
X	    return 1;
X	}
X    }
X
X    return 0;
X}
X
st_foreach(table, func, arg)
st_table *table;
enum st_retval (*func)();
char *arg;
X{
X    st_table_entry *ptr, *last, *tmp;
X    enum st_retval retval;
X    int i;
X
X    for(i = 0; i < table->num_bins; i++) {
X	last = nil(st_table_entry);
X	for(ptr = table->bins[i]; ptr != nil(st_table_entry);) {
X	    retval = (*func)(ptr->key, ptr->record, arg);
X	    switch (retval) {
X	    case ST_CONTINUE:
X		last = ptr;
X		ptr = ptr->next;
X		break;
X	    case ST_STOP:
X		return;
X	    case ST_DELETE:
X		tmp = ptr;
X		if (last == nil(st_table_entry)) {
X		    table->bins[i] = ptr->next;
X		} else {
X		    last->next = ptr->next;
X		}
X		ptr = ptr->next;
X		free((char *) tmp);
X	    }
X	}
X    }
X}
X
st_strhash(string, modulus)
register char *string;
int modulus;
X{
X    register int val = 0;
X    register int c;
X    
X    while ((c = *string++) != '\0') {
X	val = val*997 + c;
X    }
X
X    return ((val < 0) ? -val : val)%modulus;
X}
END_OF_FILE
if test 8170 -ne `wc -c <'st.c'`; then
    echo shar: \"'st.c'\" unpacked with wrong size!
fi
# end of 'st.c'
fi
if test -f 'winbusy.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'winbusy.c'\"
else
echo shar: Extracting \"'winbusy.c'\" \(5598 characters\)
sed "s/^X//" >'winbusy.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[] = "@(#) winbusy.c 25.4 90/05/22 Crucible";
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 "globals.h"
X
X/***************************************************************************
X* global data
X***************************************************************************/
X
X/***************************************************************************
X* private data
X***************************************************************************/
X
static ClassBusy classBusy;
static Bool busyDisabled = True;
X
X/***************************************************************************
X* private functions
X***************************************************************************/
X
X/*
X * DestroyBusy -- destroy the busy window resources and free any allocated
X *	data.
X */
static int
destroyBusy(dpy, winInfo)
Display	*dpy;
WinBusy *winInfo;
X{
X	/* free our data and throw away window */
X	XUndefineCursor(dpy, winInfo->core.self);
X	WinRemoveChild(winInfo->core.parent,winInfo);
X	XDestroyWindow(dpy, winInfo->core.self);
X	WIUninstallInfo(winInfo->core.self);
X	MemFree(winInfo);
X}
X
X
X/*
X * widthfuncBusy - recomputes the height of the busy window
X */
int
widthfuncBusy(win, pxcre)
WinBusy *win;
XXConfigureRequestEvent *pxcre;
X{
X	WinGenericFrame *frame = (WinGenericFrame *)win->core.parent;
X	return frame->fcore.panewin->core.width;
X}
X
X/*
X * heightfuncBusy - recomputes the height of the busy window
X */
int
heightfuncBusy(win, pxcre)
WinBusy *win;
XXConfigureRequestEvent *pxcre;
X{
X	WinGenericFrame *frame = (WinGenericFrame *)win->core.parent;
X	return frame->fcore.panewin->core.height;
X}
X
X
X/*
X *
X * REMIND
X * 
X * Busy windows are effectively "turned off" by the static Bool busyDisabled.
X * The reason for this is that having a busy window on the screen over the
X * application's window will prevent that application from receiving drag-n-
X * drop messages properly.  When busyDisabled is set, the following newconfig,
X * newpos, and setconfig functions prevent the busy window from changing from
X * its initial state.  The initial state is set in MakeBusy, which makes the 
X * busy window very small and above the upper left corner of the frame window.
X */
X
static int
newConfigBusy(winInfo, pxcre)
X    WinBusy *winInfo;
X    XConfigureRequestEvent *pxcre;
X{
X    if (busyDisabled)
X	return 0;
X    else
X	return WinNewConfigFunc(winInfo, pxcre);
X}
X
X
static int
newPosBusy(winInfo, x, y)
X    WinBusy *winInfo;
X    int x, y;
X{
X    if (busyDisabled)
X	return 0;
X    else
X	return WinNewPosFunc(winInfo, x, y);
X}
X
X
static int
setConfigBusy(dpy, winInfo)
X    Display *dpy;
X    WinBusy *winInfo;
X{
X    if (busyDisabled)
X	return 0;
X    else
X	return WinSetConfigFunc(dpy, winInfo);
X}
X
X
X
X/***************************************************************************
X* global functions
X***************************************************************************/
X
X/*
X * MakeBusy  -- create the busy window.  The Busy window is exactly the
X *	same size as its parent and gets all keyboard and pointer events
X *	for the frame.  The parent is assumed to be a frame.
X */
WinBusy *
MakeBusy(dpy, par)
Display	*dpy;
WinGenericFrame *par;
X{
X	WinBusy *w;
X	Window win;
X        unsigned long valuemask;
X        XSetWindowAttributes attributes;
X
X	/* create the associated structure */
X	w = MemNew(WinBusy);
X	w->core.kind = WIN_BUSY;
X	w->class = &classBusy;
X	WinAddChild(par,w);
X	w->core.children = NULL;
X	w->core.client = par->core.client;
X	if (busyDisabled) {
X	    w->core.x = -10;
X	    w->core.y = -10;
X	    w->core.width = 1;
X	    w->core.height = 1;
X	} else {
X	    w->core.x = par->fcore.panewin->core.x;	
X	    w->core.y = par->fcore.panewin->core.y;
X	    w->core.width = par->fcore.panewin->core.width;
X	    w->core.height = par->fcore.panewin->core.height;
X	}
X	w->core.dirtyconfig = CWX | CWY | CWWidth | CWHeight;
X	w->core.exposures = NULL;
X	w->isFocus = False;
X
X	/* create the window */
X        attributes.event_mask = ButtonReleaseMask | ButtonPressMask | 
X	    KeyPressMask;
X	attributes.cursor = GRV.BusyPointer;
X        valuemask = CWEventMask | CWCursor;
X        win = XCreateWindow(dpy, par->core.self,
X                        w->core.x, w->core.y,
X			w->core.width, w->core.height,
X                        0,
X			CopyFromParent,
X			InputOnly,
X                        CopyFromParent,
X                        valuemask,
X                        &attributes);
X
X	/* fill out remaining fields */
X	w->core.self = win;
X	WIInstallInfo(w);
X        XMapRaised(dpy, win);
X
X	return w;
X}
X
void
BusyInit(dpy)
Display *dpy;
X{
X	classBusy.core.kind = WIN_BUSY;
X	classBusy.core.xevents[ButtonPress] = NoFocusEventBeep;
X	classBusy.core.xevents[ButtonRelease] = NoFocusEventBeep;
X	classBusy.core.xevents[KeyPress] = NoFocusEventBeep;
X	classBusy.core.xevents[KeyRelease] = NoFocusEventBeep;
X	classBusy.core.focusfunc = NULL;
X	classBusy.core.drawfunc = NULL;
X	classBusy.core.destroyfunc = destroyBusy;
X	classBusy.core.selectfunc = NULL;
X	classBusy.core.newconfigfunc = newConfigBusy;
X	classBusy.core.newposfunc = newPosBusy;
X	classBusy.core.setconfigfunc = setConfigBusy;
X	classBusy.core.createcallback = NULL;
X	classBusy.core.heightfunc = heightfuncBusy;
X	classBusy.core.widthfunc = widthfuncBusy;
X}
END_OF_FILE
if test 5598 -ne `wc -c <'winbusy.c'`; then
    echo shar: \"'winbusy.c'\" unpacked with wrong size!
fi
# end of 'winbusy.c'
fi
if test -f 'winnofoc.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'winnofoc.c'\"
else
echo shar: Extracting \"'winnofoc.c'\" \(5257 characters\)
sed "s/^X//" >'winnofoc.c' <<'END_OF_FILE'
X/*
X *      (c) Copyright 1989 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[] = "@(#)winnofoc.c	1.2 olvwm version 3/30/91";
X
X/*
X * Based on
static	char	sccsid[] = "@(#) winnofoc.c 25.6 90/05/23 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 "globals.h"
X
extern unsigned int FindModifierMask();
extern Bool FocusIndeterminate;
extern Atom AtomProtocols;
extern Atom AtomTakeFocus;
X
X/***************************************************************************
X* global data
X***************************************************************************/
X
Window NoFocusWin = NULL;
X
X/***************************************************************************
X* private data
X***************************************************************************/
X
static ClassNoFocus classNoFocus;
X
X/***************************************************************************
X* private functions
X***************************************************************************/
X
X/*
X * DestroyNoFocus -- destroy the no-focus window and free any allocated
X *	data.
X */
static int
destroyNoFocus(dpy, winInfo)
Display	*dpy;
WinGeneric *winInfo;
X{
X	/* free our data and throw away window */
X	XDestroyWindow(dpy, winInfo->core.self);
X	WIUninstallInfo(winInfo->core.self);
X	MemFree(winInfo);
X}
X
X
X/*
X * eventClientMessage - handle WM_TAKE_FOCUS messages.
X */
static int
eventClientMessage(dpy, event, winInfo)
X    Display *dpy;
X    XEvent *event;
X    WinNoFocus *winInfo;
X{
X    if (FocusIndeterminate &&
X	event->xclient.message_type == AtomProtocols &&
X	event->xclient.data.l[0] == AtomTakeFocus) {
X	    XSetInputFocus(dpy, NoFocusWin,
X			   RevertToPointerRoot,
X			   event->xclient.data.l[1]);
X	    FocusIndeterminate = False;
X    }
X}
X
X
X/***************************************************************************
X* global functions
X***************************************************************************/
X
X/*
X * MakeNoFocus  -- create the no-focus windows to a window. Return a 
X * WinGeneric structure.
X */
WinGeneric *
MakeNoFocus(dpy, par)
Display	*dpy;
WinGeneric *par;
X{
X	XSetWindowAttributes attributes;
X	WinNoFocus *w;
X
X	/* create the window */
X	attributes.event_mask = KeyPressMask;
X	attributes.override_redirect = True;
X	NoFocusWin = XCreateWindow(dpy, par->core.self,
X			 -10, -10,
X			 10, 10	,
X			 0,
X			 0,
X			 InputOnly,
X			 CopyFromParent,
X			 CWEventMask | CWOverrideRedirect,
X			 &attributes);
X	XMapWindow(dpy, NoFocusWin);
X
X	/* create the associated structure */
X	w = MemNew(WinNoFocus);
X	w->core.self = NoFocusWin;
X	w->core.kind = WIN_NOFOCUS;
X	w->class = &classNoFocus;
X	w->core.parent = par;
X	w->core.children = NULL;
X	w->core.client = NULL;
X	w->core.x = -10;
X	w->core.y = -10;
X	w->core.width = 10;
X	w->core.height = 10;
X	w->core.dirtyconfig = False;
X	w->core.exposures = NULL;
X
X	/* register the window */
X	WIInstallInfo(w);
X
X	return w;
X}
X
X
void
NoFocusInit(dpy)
Display *dpy;
X{
X	classNoFocus.core.kind = WIN_NOFOCUS;
X	classNoFocus.core.xevents[ButtonPress] = NoFocusEventBeep;
X	classNoFocus.core.xevents[ButtonRelease] = NoFocusEventBeep;
X	classNoFocus.core.xevents[KeyPress] = NoFocusEventBeep;
X	classNoFocus.core.xevents[KeyRelease] = NoFocusEventBeep;
X	classNoFocus.core.xevents[ClientMessage] = eventClientMessage;
X	classNoFocus.core.focusfunc = NULL;
X	classNoFocus.core.drawfunc = NULL;
X	classNoFocus.core.destroyfunc = destroyNoFocus;
X	classNoFocus.core.selectfunc = NULL;
X	classNoFocus.core.newconfigfunc = NULL;
X	classNoFocus.core.newposfunc = NULL;
X	classNoFocus.core.setconfigfunc = NULL;
X	classNoFocus.core.createcallback = NULL;
X	classNoFocus.core.heightfunc = NULL;
X	classNoFocus.core.widthfunc = NULL;
X}
X
void
NoFocusTakeFocus(dpy,evtime)
Display *dpy;
Time evtime;
X{
X	XSetInputFocus(dpy, NoFocusWin, RevertToParent, evtime);
X}
X
X/*
X * NoFocusEventBeep -- beep on keyboard/mouse events for the no-focus window
X *	Also used by busy windows
X */
int
NoFocusEventBeep(dpy, event, winInfo)
Display	*dpy;
XXEvent	*event;
WinGeneric *winInfo;
X{
X        XEvent dummy;
X
X	if (FindModifierMask(event->xkey.keycode) != 0)
X		return;
X
X        XSync(dpy,0);
X        /*
X         * Discard pending keyboard and mouse events on this
X         * window, and then beep once.
X         */
X        while (XCheckTypedWindowEvent(dpy,winInfo->core.self,
X                                      KeyPress,&dummy))
X            ;
X        while (XCheckTypedWindowEvent(dpy,winInfo->core.self,
X                                      KeyRelease,&dummy))
X            ;
X        while (XCheckTypedWindowEvent(dpy,winInfo->core.self,
X                                      ButtonPress,&dummy))
X            ;
X        while (XCheckTypedWindowEvent(dpy,winInfo->core.self,
X                                      ButtonRelease,&dummy))
X            ;
X	if (winInfo->core.self == NoFocusWin && GRV.ArrowInRoot &&
X				CheckVDMMove(dpy, event))
X	    return;
X	if (GRV.Beep == BeepAlways)
X            XBell(dpy, 100);
X}
X
END_OF_FILE
if test 5257 -ne `wc -c <'winnofoc.c'`; then
    echo shar: \"'winnofoc.c'\" unpacked with wrong size!
fi
# end of 'winnofoc.c'
fi
if test -f 'winresize.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'winresize.c'\"
else
echo shar: Extracting \"'winresize.c'\" \(7625 characters\)
sed "s/^X//" >'winresize.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[] = "@(#) winresize.c 25.8 90/05/21 Crucible";
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 "globals.h"
X
X/***************************************************************************
X* global data
X***************************************************************************/
X
extern Graphics_info *olgx_gisnormal;
extern int Resize_width, Resize_height;
extern GC DrawBusyGC, DrawSelectedGC, DrawBackgroundGC;
X
X/***************************************************************************
X* private data
X***************************************************************************/
X
static int whicholgx[] = {OLGX_UPPER_LEFT, OLGX_UPPER_RIGHT, 
X	OLGX_LOWER_LEFT, OLGX_LOWER_RIGHT};
static int whichgrav[] = {NorthWestGravity, NorthEastGravity, 
X	SouthWestGravity, SouthEastGravity};
X
static ClassResize classResize;
X
X/***************************************************************************
X* private functions
X***************************************************************************/
X
X/* 
X * eventButtonPress - handle button press events on the resize window 
X */
static int
eventButtonPress(dpy, event, winInfo)
Display	*dpy;
XXEvent	*event;
WinResize	*winInfo;
X{
X        if (MouseButton(dpy, event) != MB_SELECT)
X                return;
X
X	/* draw depressed corner */
X	winInfo->depressed = True;
X        (WinFunc(winInfo,core.drawfunc))(dpy,winInfo);
X
X	/* resize function will eat button release */
X        UserResizeWin(winInfo->core.client, winInfo->which, event);
X
X        /* put corner back */
X	winInfo->depressed = False;
X        (WinFunc(winInfo,core.drawfunc))(dpy,winInfo);
X}
X
X
X/*
X * drawResize -- draw the resize window
X */
X/*ARGSUSED*/	/* dpy arg will be used when multiple Displays supported */
static int
drawResize(dpy, winInfo)
Display	*dpy;
WinResize *winInfo;
X{
X	WhichResize which = winInfo->which;
X
X	if ((which == upright) || (which == upleft))
X	{
X	    if (winInfo->core.client->isBusy) {
X		XFillRectangle(dpy,winInfo->core.self,DrawBackgroundGC,
X		    (which==upleft)?(ResizeArm_Width(olgx_gisnormal)):(0),
X		    ResizeArm_Height(olgx_gisnormal), 
X		    winInfo->core.width-ResizeArm_Width(olgx_gisnormal),
X		    winInfo->core.height-ResizeArm_Height(olgx_gisnormal));
X		XFillRectangle(dpy,winInfo->core.self,DrawBusyGC,
X		    (which==upleft)?(ResizeArm_Width(olgx_gisnormal)):(0),
X		    ResizeArm_Height(olgx_gisnormal), 
X		    winInfo->core.width-ResizeArm_Width(olgx_gisnormal),
X		    winInfo->core.height-ResizeArm_Height(olgx_gisnormal));
X	    } else if ((winInfo->core.client->isFocus) && (!GRV.FocusFollowsMouse))
X	    {
X		if (GRV.F3dUsed)
X		{
X		    olgx_draw_box(olgx_gisnormal, winInfo->core.self,
X		        (which==upleft)?(ResizeArm_Width(olgx_gisnormal)):(-2),
X		        ResizeArm_Height(olgx_gisnormal), 
X		        winInfo->core.width-ResizeArm_Width(olgx_gisnormal)+2,
X		        winInfo->core.height-ResizeArm_Height(olgx_gisnormal)+2,
X			OLGX_INVOKED, True);
X		}
X		else
X		{
X		    XFillRectangle(dpy,winInfo->core.self,DrawSelectedGC,
X		        (which==upleft)?(ResizeArm_Width(olgx_gisnormal)):(0),
X		        ResizeArm_Height(olgx_gisnormal), 
X		        winInfo->core.width-ResizeArm_Width(olgx_gisnormal),
X		        winInfo->core.height-ResizeArm_Height(olgx_gisnormal));
X		}
X	    }
X	    else
X	    {
X		XFillRectangle(dpy,winInfo->core.self,DrawBackgroundGC,
X		    (which==upleft)?(ResizeArm_Width(olgx_gisnormal)):(0),
X		    ResizeArm_Height(olgx_gisnormal), 
X		    winInfo->core.width-ResizeArm_Width(olgx_gisnormal),
X		    winInfo->core.height-ResizeArm_Height(olgx_gisnormal));
X	    }
X	} else {
X	    XFillRectangle(dpy, winInfo->core.self, DrawBackgroundGC,
X		(which==lowleft) ? (ResizeArm_Width(olgx_gisnormal)) : 0, 0,
X		winInfo->core.width-ResizeArm_Width(olgx_gisnormal),
X		winInfo->core.height-ResizeArm_Height(olgx_gisnormal));
X	}
X	olgx_draw_resize_corner(olgx_gisnormal, winInfo->core.self, 0, 0,
X		whicholgx[winInfo->which],
X		(winInfo->depressed)?(OLGX_INVOKED):(OLGX_NORMAL));
X}
X
X
X/*
X * DestroyResize -- destroy the resize window resources and free any allocated
X *	data.
X */
static int
destroyResize(dpy, winInfo)
Display	*dpy;
WinGeneric *winInfo;
X{
X	/* free our data and throw away window */
X	XUndefineCursor(dpy, winInfo->core.self);
X	XDestroyWindow(dpy, winInfo->core.self);
X	WIUninstallInfo(winInfo->core.self);
X	MemFree(winInfo);
X}
X
X/* 
X * focusselectResize - the focus or selection state has changed
X */
static int
focusResize(dpy, winInfo, selected)
Display *dpy;
WinResize *winInfo;
Bool selected;
X{
X	(WinFunc(winInfo,core.drawfunc))(dpy, winInfo);
X}
X
X/*
X * widthfuncResize - recomputes the width of the resize window
X */
static int 
widthfuncResize(win, pxcre)
WinResize *win;
XXConfigureRequestEvent *pxcre;
X{
X	return Resize_width;
X}
X
X/*
X * heightfuncResize - recomputes the width of the resize window
X */
static int 
heightfuncResize(win, pxcre)
WinResize *win;
XXConfigureRequestEvent *pxcre;
X{
X	return Resize_height;
X}
X
X/***************************************************************************
X* global functions
X***************************************************************************/
X
X/*
X * MakeResize  -- create the resize window. Return a WinGeneric structure.
X */
WinResize *
MakeResize(dpy, par, which, x, y)
Display	*dpy;
WinGeneric *par;
WhichResize which;
int x,y;
X{
X	WinResize *w;
X	Window win;
X        unsigned long valuemask;
X        XSetWindowAttributes attributes;
X
X        attributes.event_mask = ButtonPressMask | ExposureMask;
X        attributes.win_gravity = whichgrav[which];
X	attributes.cursor = GRV.ResizePointer;
X        valuemask = CWEventMask | CWWinGravity | CWCursor;
X
X        win = XCreateWindow(dpy, par->core.self,
X                         x, y,
X                         Resize_width, Resize_height,
X                         0,
X                         DefaultDepth(dpy, DefaultScreen(dpy)),
X                         CopyFromParent,
X                         DefaultVisual(dpy, DefaultScreen(dpy)),
X                         valuemask,
X                         &attributes);
X
X	/* create the associated structure */
X	w = MemNew(WinResize);
X	w->core.self = win;
X	w->class = &classResize;
X	w->core.kind = WIN_RESIZE;
X	WinAddChild(par,w);
X	w->core.children = NULL;
X	w->core.client = par->core.client;
X	w->core.x = x;	
X	w->core.y = y;
X	w->core.width = Resize_width;
X	w->core.height = Resize_height;
X	w->core.dirtyconfig = CWX | CWY | CWWidth | CWHeight;
X	w->core.exposures = NULL;
X	w->which = which;
X
X	/* register the window */
X	WIInstallInfo(w);
X
X        XMapRaised(dpy, win);
X
X	return w;
X}
X
X
X/* ResizeInit -- initialise values for the resize class 
X */
void
ResizeInit(dpy)
Display *dpy;
X{
X	classResize.core.kind = WIN_RESIZE;
X	classResize.core.xevents[Expose] = WinEventExpose;
X	classResize.core.xevents[ButtonPress] = eventButtonPress;
X	classResize.core.focusfunc= focusResize;
X	classResize.core.drawfunc= drawResize;
X	classResize.core.destroyfunc = destroyResize;
X	classResize.core.selectfunc = NULL;
X	classResize.core.newconfigfunc = WinNewConfigFunc;
X	classResize.core.newposfunc = WinNewPosFunc;
X	classResize.core.setconfigfunc = WinSetConfigFunc;
X	classResize.core.createcallback = NULL;
X	classResize.core.heightfunc = heightfuncResize;
X	classResize.core.widthfunc = widthfuncResize;
X}
END_OF_FILE
if test 7625 -ne `wc -c <'winresize.c'`; then
    echo shar: \"'winresize.c'\" unpacked with wrong size!
fi
# end of 'winresize.c'
fi
echo shar: End of archive 2 \(of 16\).
cp /dev/null ark2isdone
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