[comp.sources.x] v09i002: TWM with a virtual root window, Part01/09

toml@marvin.Solbourne.COM (Tom LaStrange) (08/30/90)

Submitted-by: toml@marvin.Solbourne.COM (Tom LaStrange)
Posting-number: Volume 9, Issue 2
Archive-name: tvtwm/part01

This is yet another, different implementation of the Virtual Desktop
concept for twm.  I call this version tvtwm (Tom's Virtual twm).  It is
based on the R4 version of twm with up to fix-14 installed.  This
implementation is modeled after swm (Solbourne Window Manager) and
includes the very nice ability to move windows into and out of the
panner.  It should be noted that none of this code came from the vtwm
implementation.  If you have problems and/or patches you can email me
at the address at:
    toml@marvin.Solbourne.COM (Tom LaStrange)

#! /bin/sh
# This is a shell archive, meaning:
# 1.  Remove everything above the #! /bin/sh line.
# 2.  Save the resulting test in a file
# 3.  Execute the file with /bin/sh (not csh) to create the files:
#
#CHANGES
#Imakefile
#README
#README.tvtwm
#add_window.c
#add_window.h
#cursor.c
#patchlevel.h
#siconify.bm
#
# Created by toml () on Wed Aug 29 08:43:23 MDT 1990
#
if test -f 'CHANGES'
then
    echo shar: will not over-write existing file "CHANGES"
else
echo extracting "CHANGES"
sed 's/^X//' >CHANGES <<'SHAR_EOF'
XThis directory is new since R3.
SHAR_EOF
if test 32 -ne "`wc -c < CHANGES`"
then
    echo shar: error transmitting "CHANGES" '(should have been 32 characters)'
fi
fi
if test -f 'Imakefile'
then
    echo shar: will not over-write existing file "Imakefile"
else
echo extracting "Imakefile"
sed 's/^X//' >Imakefile <<'SHAR_EOF'
X/**/#
X/**/#Here is an Imakefile for twm.  It depends on having TWMDIR defined
X/**/#in Imake.tmpl.  I like to use Imakefiles for everything, and I am sure
X/**/#other people do also, so perhaps you could do us all a favor and
X/**/#distribute this one.
X/**/#
X
X         YFLAGS = -d
X        DEPLIBS = $(DEPXMULIB) $(DEPEXTENSIONLIB) $(DEPXLIB)
XLOCAL_LIBRARIES = $(XMULIB) $(EXTENSIONLIB) $(XLIB)
X       LINTLIBS = $(LINTXMU) $(LINTEXTENSIONLIB) $(LINTXLIB)
X        DEFINES = ExtensionDefines $(SIGNAL_DEFINES)
X
X           SRCS = gram.c lex.c deftwmrc.c add_window.c gc.c list.c twm.c \
X		parse.c menus.c events.c resize.c util.c version.c iconmgr.c \
X		cursor.c icons.c vdt.c move.c
X
X           OBJS = gram.o lex.o deftwmrc.o add_window.o gc.o list.o twm.o \
X		parse.o menus.o events.o resize.o util.o version.o iconmgr.o \
X		cursor.o icons.o vdt.o move.o
X
XAllTarget(tvtwm)
X
XSpecialObjectRule(parse.o, ,'-DSYSTEM_INIT_FILE="'$(TWMDIR)'/system.twmrc"')
X#if !HasPutenv
XSpecialObjectRule(util.o, ,-DNOPUTENV)
X#endif
X
Xdepend:: lex.c gram.c deftwmrc.c 
X
XComplexProgramTarget(tvtwm)
XMakeDirectories(install,$(TWMDIR))
XInstallNonExec(system.twmrc, $(TWMDIR))
X
Xgram.h gram.c: gram.y
X	yacc $(YFLAGS) gram.y
X	$(MV) y.tab.c gram.c
X	$(MV) y.tab.h gram.h
X
Xclean::
X	$(RM) y.tab.h y.tab.c lex.yy.c gram.h gram.c lex.c deftwmrc.c 
X
Xdeftwmrc.c:  system.twmrc
X	$(RM) $@
X	echo '/* ' >>$@
X	echo ' * This file is generated automatically from the default' >>$@
X	echo ' * twm bindings file system.twmrc by the twm Imakefile.' >>$@
X	echo ' */' >>$@
X	echo '' >>$@
X	echo 'char *defTwmrc[] = {' >>$@
X	sed -e '/^#/d' -e 's/"/\\"/g' -e 's/^/    "/' -e 's/$$/",/' \
X		system.twmrc >>$@
X	echo '    (char *) 0 };' >>$@
X
SHAR_EOF
if test 1683 -ne "`wc -c < Imakefile`"
then
    echo shar: error transmitting "Imakefile" '(should have been 1683 characters)'
fi
fi
if test -f 'README'
then
    echo shar: will not over-write existing file "README"
else
echo extracting "README"
sed 's/^X//' >README <<'SHAR_EOF'
XTo save Tom LaStrange from being blaimed for any of the massive numbers of
Xchanges that have been done to twm since gave up control of it, the name "twm"
Xnow stands for "Tab Window Manager" (try the SqueezeTitle option to see why). 
X
X
SHAR_EOF
if test 235 -ne "`wc -c < README`"
then
    echo shar: error transmitting "README" '(should have been 235 characters)'
fi
fi
if test -f 'README.tvtwm'
then
    echo shar: will not over-write existing file "README.tvtwm"
else
echo extracting "README.tvtwm"
sed 's/^X//' >README.tvtwm <<'SHAR_EOF'
XFor those of you like me who want to try software before reading
Xthe instructions, all you have to do to get started is add a single
Xline to your .twmrc file.  Something like this:
X
X  VirtualDesktop "3000x2000"
X
XNow for the verbose description:
X
XThis is yet another, different implementation of the Virtual Desktop
Xconcept for twm.  I call this version tvtwm (Tom's Virtual twm).  It is
Xbased on the R4 version of twm with up to fix-14 installed.  This
Ximplementation is modeled after swm (Solbourne Window Manager) and
Xincludes the very nice ability to move windows into and out of the
Xpanner.  It should be noted that none of this code came from the vtwm
Ximplementation.  If you have problems and/or patches you can email me
Xat the address at the end of this file.
X
XIf we look at different implementations of the Virtual Desktop, I think
Xwe can relate them to soft drinks:
X
Xswm   - Classic Coke  "The Real Thing"
Xtvtwm - Diet Coke     "Same as Coke but not as sweet"
Xvtwm  - Diet Pepsi    "Not as sweet as Coke, some people may
X		       prefer it to any flavor of Coke"
X
XThere are pros and cons to the vtwm and swm/tvtwm implementations.  Most
Xrevolve around whether or not to use an additional window for the
Xscrolling desktop or to simply move windows around on the actual
Xroot window.
X
Xvtwm moves windows on the actual root window, swm/tvtwm use an
Xadditional window to perform the scrolling.
X
XPros:
X  vtwm    Simple to implement.
X          Programs like xsetroot continue to work.
X
X  tvtwm   Half the network traffic when the desktop scrolls,
X	    only a ConfigureNotify event has to be sent.
X	  Faster scrolling of the desktop.
X	  Desktop background image will actually scroll.
X	  Opens the door for possible multiple Virtual Desktop
X	    windows.
XCons:
X  vtwm	  Twice as much network traffic when the desktop scrolls,
X	    each window has to be moved and then a ConfigureNotify
X	    event must be sent.
X	  Slower scrolling of the desktop.
X	  Desktop background image does not scroll.
X
X  tvtwm	  Programs like xsetroot no longer work, additional work
X	    needs to be done to find the Virtual Desktop window.
X	  Programs that attempt to find the size of the window
X	    manager decoration may fail if the traverse the window
X	    tree until they run into the actual root window.
X
XThe ICCCM states that more work needs to be done in the area of
Xvirtual root windows, so there isn't any clear answer on the right
Xway to implement this feature.  Having said that, let me describe
Xhow I've butchered the code, what currently doesn't work, what would
Xbe nice if it worked, etc.
X
X1. First a description of how the panner works.  Basically,
X   mouse button 1 allows you to change your position in the
X   desktop.  Mouse button 2 allows you to drag any of the
X   small "virtual" windows.  During a window move operation
X   you can move the pointer into and out of the panner.
X   Resizing the panner will of course resize the desktop.
X
X2. I completely re-wrote the window move code.  In menus.c I 
X   simply commented out the window move code that is there and
X   didn't touch any code related to window moves in events.c.
X   The new window move code is in a new file called move.c.
X
X3. Because of the new window move code, I have not looked at 
X   or implemented the MoveOpaque feature.  With the Virtual Desktop
X   enabled, users typically won't want to use MoveOpaque anyway 
X   because it's not as clean to move into and out of the panner.
X   The constrained move and DontMoveOff functionality is also
X   missing.
X
X4. Rather than the f.nail and "NailedDown" features of vtwm, tvtwm
X   uses the same terminology as swm.  In tvtwm, windows that do
X   not move when the desktop is panned are called "sticky" windows.
X   There is a command called f.stick and a "Sticky" list of windows
X   that will be sticky when started.  Also, a side effect/feature
X   of the way sticky windows are impemented means that sticky
X   windows will always be on top of non-sticky windows.  The sticky-ness
X   of a window is remembered during an f.restart if RestartPreviousState
X   is set.
X
X5. USPosition vs. PPosition - When a window has USPosition hints
X   set, the window will be positioned at that exact pixel location.
X   When PPosition hints are set, the window will be positioned at 
X   the pixel location plus the current offset of the Virtual Desktop.
X   For example, if the desktop has been panned to +200+500 and 
X   a window is mapped with PPosition +100+100, the window will be
X   positioned at +300+600 on the desktop.
X
X6. How does the icon gravity stuff work in relation to different areas
X   of the Virtual Desktop?  I don't know, and I don't really have the
X   time to look into the problem.  It might be nice to have seperate icon
X   regions in different quadrants of the Virtual Desktop.  If you use
X   icon managers and make them sticky then you don't have any problems.
X
X7. The small "virtual" windows in the panner will have the same color
X   as their corresponding window titlebars and icons have.
X
X8. The initialization files .tvtwmrc.<screen number> and .tvtwmrc will
X   be attempted before .twmrc.<screen number> .twmrc.
X
X
XNew Variables:
X
XVirtualDesktop "WIDTHxHEIGHT"
X  This variable simply specified the initial size of the Virtual Desktop.
X  Specifying this variable enables the Virtual Desktop feature.
X  Why didn't I use the same syntax as vtwm and also specify the panner
X  scale and geometry?  I don't know, lazy I guess.
X
XVirtualDesktopBackgroundPixmap "filename"
X  The pixmap image to display as the background of the Virtual Desktop window.
X
XVirtualDesktopBackground "color"
X  The background color of the VirtualDesktop window.  If
X  VirtualDesktopBackgroundPixmap is not set, the VirtualDesktop will have a
X  solid background of this color.
X
XVirtualDesktopForeground "color"
X  This color is only used if VirtualDesktopBackgroundPixmap is set.
X
XPannerGeometry "+-X+-Y"
X  Specifies the geometry at which the panner is to be placed.  The
X  default is "-0-0".
X
XPannerState "state"
X  This specifies the initial state of the panner.  Possible values
X  include "withdrawn", "iconic", and "normal".  The default state
X  is "normal".
X
XPannerScale scale
X  This specifies the scale of the panner.  The default number is 20.
X
XPannerBackgroundPixmap "filename"
X  The pixmap image to display as the background of the panner window.
X
XPannerBackground "color"
X  The background color of the panner window.  If PannerBackgroundPixmap
X  is not set, the panner will have a solid background of this color.
X
XPannerForeground "color"
X  This color is only used if PannerBackgroundPixmap is set.
X
XSticky { window list }
X  A list of windows that will come up in a sticky state.
X
XNew Commands:
X
Xf.panner	- toggle making the panner visible
Xf.scrollhome	- scroll the desktop to 0,0
Xf.scrollup	- scroll the desktop up one screenful
Xf.scrolldown	- scroll the desktop down one screenful
Xf.scrollleft	- scroll the desktop left on screenful
Xf.scrollright	- scroll the desktop right on screenful
Xf.panup		- same as f.scrollup
Xf.pandown	- same as f.scrolldown
Xf.panleft	- same as f.scrollleft
Xf.panright	- same as f.scrollright
Xf.stick		- toggle making a window sticky or not
X
X
XA version of xsetroot, called ssetroot has been included as an
Xexample of how to find the Virtual Desktop window.
X
X--
XTom LaStrange
X
XSolbourne Computer Inc.    ARPA: toml@Solbourne.COM
X1900 Pike Rd.              UUCP: ...!{boulder,sun}!stan!toml
XLongmont, CO  80501
SHAR_EOF
if test 7424 -ne "`wc -c < README.tvtwm`"
then
    echo shar: error transmitting "README.tvtwm" '(should have been 7424 characters)'
fi
fi
if test -f 'add_window.c'
then
    echo shar: will not over-write existing file "add_window.c"
else
echo extracting "add_window.c"
sed 's/^X//' >add_window.c <<'SHAR_EOF'
X/*****************************************************************************/
X/**       Copyright 1988 by Evans & Sutherland Computer Corporation,        **/
X/**                          Salt Lake City, Utah                           **/
X/**  Portions Copyright 1989 by the Massachusetts Institute of Technology   **/
X/**                        Cambridge, Massachusetts                         **/
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/**    names of Evans & Sutherland and M.I.T. not be used in advertising    **/
X/**    in publicity pertaining to distribution of the  software  without    **/
X/**    specific, written prior permission.                                  **/
X/**                                                                         **/
X/**    EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD    **/
X/**    TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES  OF  MERCHANT-    **/
X/**    ABILITY  AND  FITNESS,  IN  NO  EVENT SHALL EVANS & SUTHERLAND OR    **/
X/**    M.I.T. 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/*****************************************************************************/
X
X
X/**********************************************************************
X *
X * $XConsortium: add_window.c,v 1.140 90/03/23 11:42:33 jim Exp $
X *
X * Add a new window, put the titlbar and other stuff around
X * the window
X *
X * 31-Mar-88 Tom LaStrange        Initial Version.
X *
X **********************************************************************/
X
X#if !defined(lint) && !defined(SABER)
Xstatic char RCSinfo[]=
X"$XConsortium: add_window.c,v 1.140 90/03/23 11:42:33 jim Exp $";
X#endif
X
X#include <stdio.h>
X#include "twm.h"
X#include <X11/Xatom.h>
X#include "add_window.h"
X#include "util.h"
X#include "resize.h"
X#include "parse.h"
X#include "list.h"
X#include "events.h"
X#include "menus.h"
X#include "screen.h"
X#include "iconmgr.h"
X#include "move.h"
X
X#define gray_width 2
X#define gray_height 2
Xstatic char gray_bits[] = {
X   0x02, 0x01};
X
Xextern int FromVirtualDesktop;
X
Xint AddingX;
Xint AddingY;
Xint AddingW;
Xint AddingH;
X
Xstatic int PlaceX = 50;
Xstatic int PlaceY = 50;
Xstatic void CreateWindowTitlebarButtons();
Xstatic void getTWM_FLAGS();
X
Xchar NoName[] = "Untitled"; /* name if no name is specified */
X
X
X/************************************************************************
X *
X *  Procedure:
X *	GetGravityOffsets - map gravity to (x,y) offset signs for adding
X *		to x and y when window is mapped to get proper placement.
X * 
X ************************************************************************
X */
X
XGetGravityOffsets (tmp, xp, yp)
X    TwmWindow *tmp;			/* window from which to get gravity */
X    int *xp, *yp;			/* return values */
X{
X    static struct _gravity_offset {
X	int x, y;
X    } gravity_offsets[11] = {
X	{  0,  0 },			/* ForgetGravity */
X	{ -1, -1 },			/* NorthWestGravity */
X	{  0, -1 },			/* NorthGravity */
X	{  1, -1 },			/* NorthEastGravity */
X	{ -1,  0 },			/* WestGravity */
X	{  0,  0 },			/* CenterGravity */
X	{  1,  0 },			/* EastGravity */
X	{ -1,  1 },			/* SouthWestGravity */
X	{  0,  1 },			/* SouthGravity */
X	{  1,  1 },			/* SouthEastGravity */
X	{  0,  0 },			/* StaticGravity */
X    };
X    register int g = ((tmp->hints.flags & PWinGravity) 
X		      ? tmp->hints.win_gravity : NorthWestGravity);
X
X    if (g < ForgetGravity || g > StaticGravity) {
X	*xp = *yp = 0;
X    } else {
X	*xp = gravity_offsets[g].x;
X	*yp = gravity_offsets[g].y;
X    }
X}
X
X
X
X
X/***********************************************************************
X *
X *  Procedure:
X *	AddWindow - add a new window to the twm list
X *
X *  Returned Value:
X *	(TwmWindow *) - pointer to the TwmWindow structure
X *
X *  Inputs:
X *	w	- the window id of the window to add
X *	iconm	- flag to tell if this is an icon manager window
X *	iconp	- pointer to icon manager struct
X *
X ***********************************************************************
X */
X
XTwmWindow *
XAddWindow(w, iconm, iconp)
XWindow w;
Xint iconm;
XIconMgr *iconp;
X{
X    TwmWindow *tmp_win;			/* new twm window structure */
X    int stat;
X    XEvent event;
X    unsigned long valuemask;		/* mask for create windows */
X    XSetWindowAttributes attributes;	/* attributes for create windows */
X    int width, height;			/* tmp variable */
X    Atom actual_type;
X    int actual_format;
X    unsigned long nitems, bytesafter;
X    int ask_user;		/* don't know where to put the window */
X    long supplied = 0;
X    int gravx, gravy;			/* gravity signs for positioning */
X    int namelen;
X    int bw2;
X    int cancel;				/* cancel flag for window move */
X    int tmpX;				/* temp variable */
X    int saveDelta;			/* save the Scr->MoveDelta */
X
X#ifdef DEBUG
X    fprintf(stderr, "AddWindow: w = 0x%x\n", w);
X#endif
X
X    /* allocate space for the twm window */
X    tmp_win = (TwmWindow *)calloc(1, sizeof(TwmWindow));
X    tmp_win->w = w;
X    tmp_win->zoomed = ZOOM_NONE;
X    tmp_win->iconmgr = iconm;
X    tmp_win->iconmgrp = iconp;
X    tmp_win->cmaps.number_cwins = 0;
X
X    XSelectInput(dpy, tmp_win->w, PropertyChangeMask);
X    XGetWindowAttributes(dpy, tmp_win->w, &tmp_win->attr);
X    XFetchName(dpy, tmp_win->w, &tmp_win->name);
X    tmp_win->class = NoClass;
X    XGetClassHint(dpy, tmp_win->w, &tmp_win->class);
X    FetchWmProtocols (tmp_win);
X    FetchWmColormapWindows (tmp_win);
X
X    /*
X     * do initial clip; should look at window gravity
X     */
X    if (tmp_win->attr.width > Scr->MaxWindowWidth)
X      tmp_win->attr.width = Scr->MaxWindowWidth;
X    if (tmp_win->attr.height > Scr->MaxWindowHeight)
X      tmp_win->attr.height = Scr->MaxWindowHeight;
X
X    tmp_win->wmhints = XGetWMHints(dpy, tmp_win->w);
X    if (tmp_win->wmhints && (tmp_win->wmhints->flags & WindowGroupHint))
X	tmp_win->group = tmp_win->wmhints->window_group;
X    else
X	tmp_win->group = NULL;
X
X    if (!XGetWMNormalHints (dpy, tmp_win->w, &tmp_win->hints, &supplied))
X      tmp_win->hints.flags = 0;
X
X    /*
X     * The July 27, 1988 draft of the ICCCM ignores the size and position
X     * fields in the WM_NORMAL_HINTS property.
X     */
X
X    tmp_win->transient = Transient(tmp_win->w);
X    /*
X     * Don't bother user if:
X     * 
X     *     o  the window is a transient, or
X     * 
X     *     o  a USPosition was requested, or
X     * 
X     *     o  a PPosition was requested and UsePPosition is ON or
X     *        NON_ZERO if the window is at other than (0,0)
X     */
X    ask_user = TRUE;
X    if (tmp_win->transient || 
X	(tmp_win->hints.flags & USPosition) ||
X        ((tmp_win->hints.flags & PPosition) && Scr->UsePPosition &&
X	 (Scr->UsePPosition == PPOS_ON || 
X	  tmp_win->attr.x != 0 || tmp_win->attr.y != 0)))
X      ask_user = FALSE;
X
X    if (tmp_win->name == NULL)
X	tmp_win->name = NoName;
X    if (tmp_win->class.res_name == NULL)
X    	tmp_win->class.res_name = NoName;
X    if (tmp_win->class.res_class == NULL)
X    	tmp_win->class.res_class = NoName;
X
X    tmp_win->full_name = tmp_win->name;
X    namelen = strlen (tmp_win->name);
X
X    if (RestartPreviousState)
X	getTWM_FLAGS(tmp_win->w, &tmp_win->flags);
X
X    if (Scr->VirtualDesktop) {
X	tmp_win->sticky = 
X	    (short)LookInList(Scr->StickyL, tmp_win->full_name, &tmp_win->class);
X	if (tmp_win->w == Scr->Panner)
X	    tmp_win->sticky = True;
X
X	if (RestartPreviousState) {
X	    if (tmp_win->flags & TWM_FLAGS_STICKY)
X		tmp_win->sticky = True;
X	}
X    }
X
X    /* set flags for twm restart */
X    SetTWM_FLAGS(tmp_win);
X
X    tmp_win->highlight = Scr->Highlight && 
X	(!(short)LookInList(Scr->NoHighlight, tmp_win->full_name, 
X	    &tmp_win->class));
X
X    tmp_win->stackmode = Scr->StackMode &&
X	(!(short)LookInList(Scr->NoStackModeL, tmp_win->full_name, 
X	    &tmp_win->class));
X
X    tmp_win->titlehighlight = Scr->TitleHighlight && 
X	(!(short)LookInList(Scr->NoTitleHighlight, tmp_win->full_name, 
X	    &tmp_win->class));
X
X    tmp_win->auto_raise = (short)LookInList(Scr->AutoRaise, tmp_win->full_name,
X					    &tmp_win->class);
X    if (tmp_win->auto_raise) Scr->NumAutoRaises++;
X    tmp_win->iconify_by_unmapping = Scr->IconifyByUnmapping;
X    if (Scr->IconifyByUnmapping)
X    {
X	tmp_win->iconify_by_unmapping = iconm ? FALSE :
X	    !(short)LookInList(Scr->DontIconify, tmp_win->full_name,
X		&tmp_win->class);
X    }
X    tmp_win->iconify_by_unmapping |= 
X	(short)LookInList(Scr->IconifyByUn, tmp_win->full_name,
X	    &tmp_win->class);
X
X    if (LookInList(Scr->WindowRingL, tmp_win->full_name, &tmp_win->class)) {
X	if (Scr->Ring) {
X	    tmp_win->ring.next = Scr->Ring->ring.next;
X	    if (Scr->Ring->ring.next->ring.prev)
X	      Scr->Ring->ring.next->ring.prev = tmp_win;
X	    Scr->Ring->ring.next = tmp_win;
X	    tmp_win->ring.prev = Scr->Ring;
X	} else {
X	    tmp_win->ring.next = tmp_win->ring.prev = Scr->Ring = tmp_win;
X	}
X    } else
X      tmp_win->ring.next = tmp_win->ring.prev = NULL;
X    tmp_win->ring.cursor_valid = False;
X
X    tmp_win->squeeze_info = NULL;
X#ifdef SHAPE
X    /*
X     * get the squeeze information; note that this does not have to be freed
X     * since it is coming from the screen list
X     */
X    if (HasShape) {
X	if (!LookInList (Scr->DontSqueezeTitleL, tmp_win->full_name, 
X			 &tmp_win->class)) {
X	    tmp_win->squeeze_info = (SqueezeInfo *)
X	      LookInList (Scr->SqueezeTitleL, tmp_win->full_name,
X			  &tmp_win->class);
X	    if (!tmp_win->squeeze_info) {
X		static SqueezeInfo default_squeeze = { J_LEFT, 0, 0 };
X		if (Scr->SqueezeTitle)
X		  tmp_win->squeeze_info = &default_squeeze;
X	    }
X	}
X      }
X#endif
X
X    tmp_win->old_bw = tmp_win->attr.border_width;
X
X    if (Scr->ClientBorderWidth) {
X    	tmp_win->frame_bw = tmp_win->old_bw;
X    } else {
X    	tmp_win->frame_bw = Scr->BorderWidth;
X    }
X    bw2 = tmp_win->frame_bw * 2;
X
X    tmp_win->title_height = Scr->TitleHeight + tmp_win->frame_bw;
X    if (Scr->NoTitlebar)
X        tmp_win->title_height = 0;
X    if (LookInList(Scr->MakeTitle, tmp_win->full_name, &tmp_win->class))
X        tmp_win->title_height = Scr->TitleHeight + tmp_win->frame_bw;
X    if (LookInList(Scr->NoTitle, tmp_win->full_name, &tmp_win->class))
X        tmp_win->title_height = 0;
X
X    /* if it is a transient window, don't put a title on it */
X    if (tmp_win->transient && !Scr->DecorateTransients)
X	tmp_win->title_height = 0;
X
X    if (LookInList(Scr->StartIconified, tmp_win->full_name, &tmp_win->class))
X    {
X	if (!tmp_win->wmhints)
X	{
X	    tmp_win->wmhints = (XWMHints *)malloc(sizeof(XWMHints));
X	    tmp_win->wmhints->flags = 0;
X	}
X	tmp_win->wmhints->initial_state = IconicState;
X	tmp_win->wmhints->flags |= StateHint;
X    }
X
X    if (!(supplied & PWinGravity)) SimulateWinGravity (tmp_win);
X    GetGravityOffsets (tmp_win, &gravx, &gravy);
X
X
X#ifdef DEBUG
X	fprintf(stderr, "  position window  %d, %d  %dx%d\n", 
X	    tmp_win->attr.x,
X	    tmp_win->attr.y,
X	    tmp_win->attr.width,
X	    tmp_win->attr.height);
X#endif
X
X    if (!Scr->ClientBorderWidth) {	/* need to adjust for twm borders */
X	int delta = tmp_win->attr.border_width - tmp_win->frame_bw;
X	tmp_win->attr.x += gravx * delta;
X	tmp_win->attr.y += gravy * delta;
X    }
X
X    tmp_win->title_width = tmp_win->attr.width;
X
X    if (tmp_win->old_bw) XSetWindowBorderWidth (dpy, tmp_win->w, 0);
X
X    tmp_win->name_width = XTextWidth(Scr->TitleBarFont.font, tmp_win->name,
X				     namelen);
X
X    if (XGetWindowProperty (dpy, tmp_win->w, XA_WM_ICON_NAME, 0L, 200L, False,
X			    XA_STRING, &actual_type, &actual_format, &nitems,
X			    &bytesafter,(unsigned char **)&tmp_win->icon_name))
X	tmp_win->icon_name = tmp_win->name;
X
X    if (tmp_win->icon_name == NULL)
X	tmp_win->icon_name = tmp_win->name;
X
X    tmp_win->iconified = FALSE;
X    tmp_win->icon = FALSE;
X    tmp_win->icon_on = FALSE;
X
X    XGrabServer(dpy);
X
X    /*
X     * Make sure the client window still exists.  We don't want to leave an
X     * orphan frame window if it doesn't.  Since we now have the server 
X     * grabbed, the window can't disappear later without having been 
X     * reparented, so we'll get a DestroyNotify for it.  We won't have 
X     * gotten one for anything up to here, however.
X     */
X    if (XGetGeometry(dpy, tmp_win->w, &JunkRoot, &JunkX, &JunkY,
X		     &JunkWidth, &JunkHeight, &JunkBW, &JunkDepth) == 0)
X    {
X	free((char *)tmp_win);
X	XUngrabServer(dpy);
X	return(NULL);
X    }
X
X    /* add the window into the twm list */
X    tmp_win->next = Scr->TwmRoot.next;
X    if (Scr->TwmRoot.next != NULL)
X	Scr->TwmRoot.next->prev = tmp_win;
X    tmp_win->prev = &Scr->TwmRoot;
X    Scr->TwmRoot.next = tmp_win;
X
X    /* get all the colors for the window */
X
X    tmp_win->border = Scr->BorderColor;
X    tmp_win->icon_border = Scr->IconBorderColor;
X    tmp_win->border_tile.fore = Scr->BorderTileC.fore;
X    tmp_win->border_tile.back = Scr->BorderTileC.back;
X    tmp_win->title.fore = Scr->TitleC.fore;
X    tmp_win->title.back = Scr->TitleC.back;
X    tmp_win->iconc.fore = Scr->IconC.fore;
X    tmp_win->iconc.back = Scr->IconC.back;
X
X    GetColorFromList(Scr->BorderColorL, tmp_win->full_name, &tmp_win->class,
X	&tmp_win->border);
X    GetColorFromList(Scr->IconBorderColorL, tmp_win->full_name, &tmp_win->class,
X	&tmp_win->icon_border);
X    GetColorFromList(Scr->BorderTileForegroundL, tmp_win->full_name,
X	&tmp_win->class, &tmp_win->border_tile.fore);
X    GetColorFromList(Scr->BorderTileBackgroundL, tmp_win->full_name,
X	&tmp_win->class, &tmp_win->border_tile.back);
X    GetColorFromList(Scr->TitleForegroundL, tmp_win->full_name, &tmp_win->class,
X	&tmp_win->title.fore);
X    GetColorFromList(Scr->TitleBackgroundL, tmp_win->full_name, &tmp_win->class,
X	&tmp_win->title.back);
X    GetColorFromList(Scr->IconForegroundL, tmp_win->full_name, &tmp_win->class,
X	&tmp_win->iconc.fore);
X    GetColorFromList(Scr->IconBackgroundL, tmp_win->full_name, &tmp_win->class,
X	&tmp_win->iconc.back);
X
X
X    /* create windows */
X
X    tmp_win->frame_width = tmp_win->attr.width;
X    tmp_win->frame_height = tmp_win->attr.height + tmp_win->title_height;
X
X    valuemask = CWBackPixmap | CWBorderPixel | CWCursor | CWEventMask;
X    attributes.background_pixmap = None;
X    attributes.border_pixel = tmp_win->border;
X    attributes.cursor = Scr->FrameCursor;
X    attributes.event_mask = (SubstructureRedirectMask | 
X			     ButtonPressMask | ButtonReleaseMask |
X			     EnterWindowMask | LeaveWindowMask);
X    if (tmp_win->attr.save_under) {
X	attributes.save_under = True;
X	valuemask |= CWSaveUnder;
X    }
X
X    if (Scr->VirtualDesktop) {
X	if (tmp_win->sticky)
X	    tmp_win->root = Scr->Root;
X	else
X	    tmp_win->root = Scr->VirtualDesktop;
X
X	tmp_win->virtualWindow = MakeVirtual(tmp_win,
X	    tmp_win->frame_x, tmp_win->frame_y,
X	    tmp_win->frame_width, tmp_win->frame_height,
X	    tmp_win->title.back, tmp_win->border);
X    }
X    else
X	tmp_win->root = Scr->Root;
X
X    tmp_win->frame = XCreateWindow (dpy, tmp_win->root, 0, 0,
X				    (unsigned int) tmp_win->frame_width,
X				    (unsigned int) tmp_win->frame_height,
X				    (unsigned int) tmp_win->frame_bw,
X				    Scr->d_depth,
X				    (unsigned int) CopyFromParent,
X				    Scr->d_visual, valuemask, &attributes);
X    if (tmp_win->title_height)
X    {
X	valuemask = (CWEventMask | CWBorderPixel | CWBackPixel);
X	attributes.event_mask = (KeyPressMask | ButtonPressMask |
X				 ButtonReleaseMask | ExposureMask);
X	attributes.border_pixel = tmp_win->border;
X	attributes.background_pixel = tmp_win->title.back;
X	tmp_win->title_w = XCreateWindow (dpy, tmp_win->frame, 
X					  -tmp_win->frame_bw,
X					  -tmp_win->frame_bw,
X					  (unsigned int) tmp_win->attr.width, 
X					  (unsigned int) Scr->TitleHeight,
X					  (unsigned int) tmp_win->frame_bw,
X					  Scr->d_depth,
X					  (unsigned int) CopyFromParent,
X					  Scr->d_visual, valuemask,
X					  &attributes);
X    }
X    else {
X	tmp_win->title_w = 0;
X	tmp_win->squeeze_info = NULL;
X    }
X
X    if (tmp_win->highlight)
X    {
X	tmp_win->gray = XCreatePixmapFromBitmapData(dpy, Scr->Root, 
X	    gray_bits, gray_width, gray_height, 
X	    tmp_win->border_tile.fore, tmp_win->border_tile.back,
X	    Scr->d_depth);
X
X	SetBorder (tmp_win, False);
X    }
X    else
X	tmp_win->gray = None;
X
X	
X    if (tmp_win->title_w) {
X	CreateWindowTitlebarButtons (tmp_win);
X	ComputeTitleLocation (tmp_win);
X	XMoveWindow (dpy, tmp_win->title_w,
X		     tmp_win->title_x, tmp_win->title_y);
X	XDefineCursor(dpy, tmp_win->title_w, Scr->TitleCursor);
X    }
X
X    valuemask = (CWEventMask | CWDontPropagate);
X    attributes.event_mask = (StructureNotifyMask | PropertyChangeMask |
X			     ColormapChangeMask | VisibilityChangeMask |
X			     EnterWindowMask | LeaveWindowMask);
X    if (tmp_win->w == Scr->Panner)
X	attributes.event_mask |= ExposureMask;
X    attributes.do_not_propagate_mask = ButtonPressMask | ButtonReleaseMask;
X    XChangeWindowAttributes (dpy, tmp_win->w, valuemask, &attributes);
X
X#ifdef SHAPE
X    if (HasShape)
X	XShapeSelectInput (dpy, tmp_win->w, ShapeNotifyMask);
X#endif
X	
X    if (tmp_win->title_w) {
X	XMapWindow (dpy, tmp_win->title_w);
X    }
X
X#ifdef SHAPE
X    if (HasShape) {
X	int xws, yws, xbs, ybs;
X	unsigned wws, hws, wbs, hbs;
X	int boundingShaped, clipShaped;
X
X	XShapeSelectInput (dpy, tmp_win->w, ShapeNotifyMask);
X	XShapeQueryExtents (dpy, tmp_win->w,
X			    &boundingShaped, &xws, &yws, &wws, &hws,
X			    &clipShaped, &xbs, &ybs, &wbs, &hbs);
X	tmp_win->wShaped = boundingShaped;
X    }
X#endif
X
X    if (!tmp_win->iconmgr)
X	XAddToSaveSet(dpy, tmp_win->w);
X	
X    XReparentWindow(dpy, tmp_win->w, tmp_win->frame, 0, tmp_win->title_height);
X    /*
X     * Reparenting generates an UnmapNotify event, followed by a MapNotify.
X     * Set the map state to FALSE to prevent a transition back to
X     * WithdrawnState in HandleUnmapNotify.  Map state gets set correctly
X     * again in HandleMapNotify.
X     */
X    tmp_win->mapped = FALSE;
X
X    /*
X     * do any prompting for position
X     */
X    if (HandlingEvents && ask_user) {
X      if (Scr->RandomPlacement) {	/* just stick it somewhere */
X	if ((PlaceX + tmp_win->attr.width) > Scr->MyDisplayWidth)
X	    PlaceX = 50;
X	if ((PlaceY + tmp_win->attr.height) > Scr->MyDisplayHeight)
X	    PlaceY = 50;
X
X	tmp_win->attr.x = PlaceX;
X	tmp_win->attr.y = PlaceY;
X	PlaceX += 30;
X	PlaceY += 30;
X	if (tmp_win->root == Scr->VirtualDesktop) {
X	    tmp_win->attr.x += Scr->vdtPositionX;
X	    tmp_win->attr.y += Scr->vdtPositionY;
X	}
X      } else {				/* else prompt */
X	if (!(tmp_win->wmhints && tmp_win->wmhints->flags & StateHint &&
X	      tmp_win->wmhints->initial_state == IconicState))
X	{
X	    Bool firsttime = True;
X
X	    /* better wait until all the mouse buttons have been 
X	     * released.
X	     */
X	    while (TRUE)
X	    {
X		XUngrabServer(dpy);
X		XSync(dpy, 0);
X		XGrabServer(dpy);
X
X		JunkMask = 0;
X		if (!XQueryPointer (dpy, Scr->Root, &JunkRoot, 
X				    &JunkChild, &JunkX, &JunkY,
X				    &AddingX, &AddingY, &JunkMask))
X		  JunkMask = 0;
X
X		JunkMask &= (Button1Mask | Button2Mask | Button3Mask |
X			     Button4Mask | Button5Mask);
X
X		/*
X		 * watch out for changing screens
X		 */
X		if (firsttime) {
X		    if (JunkRoot != Scr->Root) {
X			register int scrnum;
X
X			for (scrnum = 0; scrnum < NumScreens; scrnum++) {
X			    if (JunkRoot == RootWindow (dpy, scrnum)) break;
X			}
X
X			if (scrnum != NumScreens) PreviousScreen = scrnum;
X		    }
X		    firsttime = False;
X		}
X
X		/*
X		 * wait for buttons to come up; yuck
X		 */
X		if (JunkMask != 0) continue;
X
X		/* 
X		 * this will cause a warp to the indicated root
X		 */
X		stat = XGrabPointer(dpy, Scr->Root, True,
X		    PointerMotionMask | ButtonPressMask | ButtonReleaseMask |
X		    EnterWindowMask | LeaveWindowMask,
X		    GrabModeAsync, GrabModeAsync,
X		    Scr->Root, UpperLeftCursor, CurrentTime);
X
X		if (stat == GrabSuccess)
X		    break;
X	    }
X
X	    width = (SIZE_HINDENT + XTextWidth (Scr->SizeFont.font,
X						tmp_win->name, namelen));
X	    height = Scr->SizeFont.height + SIZE_VINDENT * 2;
X	    
X	    XResizeWindow (dpy, Scr->SizeWindow, width + SIZE_HINDENT, height);
X	    XMapRaised(dpy, Scr->SizeWindow);
X	    InstallRootColormap();
X
X	    FBF(Scr->DefaultC.fore, Scr->DefaultC.back,
X		Scr->SizeFont.font->fid);
X	    XDrawImageString (dpy, Scr->SizeWindow, Scr->NormalGC,
X			      SIZE_HINDENT,
X			      SIZE_VINDENT + Scr->SizeFont.font->ascent,
X			      tmp_win->name, namelen);
X
X	    AddingW = tmp_win->attr.width + bw2;
X	    AddingH = tmp_win->attr.height + tmp_win->title_height + bw2;
X
X	    XQueryPointer(dpy, Scr->Root, &JunkRoot, &JunkChild,
X		&AddingX, &AddingY, &JunkX, &JunkY, &JunkMask);
X	    if (tmp_win->root == Scr->VirtualDesktop)
X		XMoveWindow(dpy, tmp_win->frame, AddingX+Scr->vdtPositionX,
X		    AddingY+Scr->vdtPositionY);
X	    else
X		XMoveWindow(dpy, tmp_win->frame, AddingX, AddingY);
X
X	    saveDelta = Scr->MoveDelta;
X	    Scr->MoveDelta = 0;
X	    StartMove(tmp_win, tmp_win->frame, tmp_win->title_height,
X		&AddingX, &AddingY, &cancel, OUT_PANNER, 1, 0, 0, True, False);
X	    Scr->MoveDelta = saveDelta;
X
X	    if (cancel == Button2) {
X		int lastx, lasty;
X
X		Scr->SizeStringOffset = width +
X		  XTextWidth(Scr->SizeFont.font, ": ", 2);
X		XResizeWindow (dpy, Scr->SizeWindow, Scr->SizeStringOffset +
X			       Scr->SizeStringWidth, height);
X		XDrawImageString (dpy, Scr->SizeWindow, Scr->NormalGC, width,
X				  SIZE_VINDENT + Scr->SizeFont.font->ascent,
X				  ": ", 2);
X		if (Scr->AutoRelativeResize) {
X		    int dx = (tmp_win->attr.width / 4);
X		    int dy = (tmp_win->attr.height / 4);
X		    
X#define HALF_AVE_CURSOR_SIZE 8		/* so that it is visible */
X		    if (dx < HALF_AVE_CURSOR_SIZE) dx = HALF_AVE_CURSOR_SIZE;
X		    if (dy < HALF_AVE_CURSOR_SIZE) dy = HALF_AVE_CURSOR_SIZE;
X#undef HALF_AVE_CURSOR_SIZE
X		    dx += (tmp_win->frame_bw + 1);
X		    dy += (bw2 + tmp_win->title_height + 1);
X		    if (AddingX + dx >= Scr->MyDisplayWidth)
X		      dx = Scr->MyDisplayWidth - AddingX - 1;
X		    if (AddingY + dy >= Scr->MyDisplayHeight)
X		      dy = Scr->MyDisplayHeight - AddingY - 1;
X		    if (dx > 0 && dy > 0)
X		      XWarpPointer (dpy, None, None, 0, 0, 0, 0, dx, dy);
X		} else {
X		    XWarpPointer (dpy, None, Scr->Root, 0, 0, 0, 0,
X				  AddingX + AddingW/2, AddingY + AddingH/2);
X		}
X		AddStartResize(tmp_win, AddingX, AddingY, AddingW, AddingH);
X
X		lastx = -10000;
X		lasty = -10000;
X		while (TRUE)
X		{
X		    /*
X		     * XXX - if we are going to do a loop, we ought to consider
X		     * using multiple GXxor lines so that we don't need to 
X		     * grab the server.
X		     */
X		    XQueryPointer(dpy, Scr->Root, &JunkRoot, &JunkChild,
X			&JunkX, &JunkY, &AddingX, &AddingY, &JunkMask);
X
X		    if (lastx != AddingX || lasty != AddingY)
X		    {
X			DoResize(AddingX, AddingY, tmp_win);
X
X			lastx = AddingX;
X			lasty = AddingY;
X		    }
X
X		    if (XCheckMaskEvent(dpy, ButtonReleaseMask, &event))
X		    {
X			AddEndResize(tmp_win);
X			break;
X		    }
X		}
X	    } 
X	    else if (cancel == Button3)
X	    {
X		int maxw = Scr->MyDisplayWidth - AddingX - bw2;
X		int maxh = Scr->MyDisplayHeight - AddingY - bw2;
X
X		/*
X		 * Make window go to bottom of screen, and clip to right edge.
X		 * This is useful when popping up large windows and fixed
X		 * column text windows.
X		 */
X		if (AddingW > maxw) AddingW = maxw;
X		AddingH = maxh;
X
X		ConstrainSize (tmp_win, &AddingW, &AddingH);  /* w/o borders */
X		AddingW += bw2;
X		AddingH += bw2;
X	    }
X	    else
X	    {
X		XMaskEvent(dpy, ButtonReleaseMask, &event);
X	    }
X
X	    MoveOutline(Scr->Root, 0, 0, 0, 0, 0, 0);
X	    XUnmapWindow(dpy, Scr->SizeWindow);
X	    UninstallRootColormap();
X	    XUngrabPointer(dpy, CurrentTime);
X
X	    tmp_win->attr.x = AddingX;
X	    tmp_win->attr.y = AddingY + tmp_win->title_height;
X	    tmp_win->attr.width = AddingW - bw2;
X	    tmp_win->attr.height = AddingH - tmp_win->title_height - bw2;
X
X	    XUngrabServer(dpy);
X	}
X      }
X    } else {				/* put it where asked, mod title bar */
X	/* if the gravity is towards the top, move it by the title height */
X	if (gravy < 0) tmp_win->attr.y -= gravy * tmp_win->title_height;
X    }
X
X    tmp_win->frame_x = tmp_win->attr.x + tmp_win->old_bw - tmp_win->frame_bw;
X    tmp_win->frame_y = tmp_win->attr.y - tmp_win->title_height +
X	tmp_win->old_bw - tmp_win->frame_bw;
X    tmp_win->frame_width = tmp_win->attr.width;
X    tmp_win->frame_height = tmp_win->attr.height + tmp_win->title_height;
X
X    /* Possibly adjust the position of the window if PPosition is
X     * being used.  In our case, if PPosition is set, we will translate
X     * the coordinates of the window into virtual desktop coordinates
X     */
X    if (tmp_win->root == Scr->VirtualDesktop &&
X	(!FromVirtualDesktop && tmp_win->transient) ||
X    	(ask_user == FALSE && (tmp_win->hints.flags & PPosition)))
X    {
X	tmp_win->frame_x += Scr->vdtPositionX;
X	tmp_win->frame_y += Scr->vdtPositionY;
X    }
X
X    /* tell the window what his root window id is */
X    /* this MUST com before SetupFrame so the synthetic ConfigureNotify
X     * event follows this property
X     */
X    SetSWM_ROOT(tmp_win);
X
X    tmpX = tmp_win->frame_x;
X    tmp_win->frame_x = -tmpX;	/* this will case a synthetice ConfigureNotify event */
X    SetupFrame (tmp_win, tmpX, tmp_win->frame_y,
X		tmp_win->frame_width, tmp_win->frame_height, -1, True);
X
X    /* wait until the window is iconified and the icon window is mapped
X     * before creating the icon window 
X     */
X    tmp_win->icon_w = NULL;
X
X    if (!tmp_win->iconmgr)
X    {
X	GrabButtons(tmp_win);
X	GrabKeys(tmp_win);
X    }
X
X    (void) AddIconManager(tmp_win);
X
X    XSaveContext(dpy, tmp_win->w, TwmContext, (caddr_t) tmp_win);
X    XSaveContext(dpy, tmp_win->w, ScreenContext, (caddr_t) Scr);
X    XSaveContext(dpy, tmp_win->frame, TwmContext, (caddr_t) tmp_win);
X    XSaveContext(dpy, tmp_win->frame, ScreenContext, (caddr_t) Scr);
X    if (tmp_win->title_height)
X    {
X	int i;
X	int nb = Scr->TBInfo.nleft + Scr->TBInfo.nright;
X
X	XSaveContext(dpy, tmp_win->title_w, TwmContext, (caddr_t) tmp_win);
X	XSaveContext(dpy, tmp_win->title_w, ScreenContext, (caddr_t) Scr);
X	for (i = 0; i < nb; i++) {
X	    XSaveContext(dpy, tmp_win->titlebuttons[i].window, TwmContext,
X			 (caddr_t) tmp_win);
X	    XSaveContext(dpy, tmp_win->titlebuttons[i].window, ScreenContext,
X			 (caddr_t) Scr);
X	}
X	if (tmp_win->hilite_w)
X	{
X	    XSaveContext(dpy, tmp_win->hilite_w, TwmContext, (caddr_t)tmp_win);
X	    XSaveContext(dpy, tmp_win->hilite_w, ScreenContext, (caddr_t)Scr);
X	}
X    }
X
X    XUngrabServer(dpy);
X
X    /* if we were in the middle of a menu activated function, regrab
X     * the pointer 
X     */
X    if (RootFunction)
X	ReGrab();
X
X    return (tmp_win);
X}
X
X
X/***********************************************************************
X *
X *  Procedure:
X *	MappedNotOverride - checks to see if we should really
X *		put a twm frame on the window
X *
X *  Returned Value:
X *	TRUE	- go ahead and frame the window
X *	FALSE	- don't frame the window
X *
X *  Inputs:
X *	w	- the window to check
X *
X ***********************************************************************
X */
X
Xint
XMappedNotOverride(w)
X    Window w;
X{
X    XWindowAttributes wa;
X
X    XGetWindowAttributes(dpy, w, &wa);
X    return ((wa.map_state != IsUnmapped) && (wa.override_redirect != True));
X}
X
X
X/***********************************************************************
X * 
X *  Procedure:
X *      AddDefaultBindings - attach default bindings so that naive users
X *      don't get messed up if they provide a minimal twmrc.
X */
Xstatic void do_add_binding (button, context, modifier, func)
X    int button, context, modifier;
X    int func;
X{
X    MouseButton *mb = &Scr->Mouse[button][context][modifier];
X
X    if (mb->func) return;		/* already defined */
X
X    mb->func = func;
X    mb->item = NULL;
X}
X
XAddDefaultBindings ()
X{
X    /*
X     * The bindings are stored in Scr->Mouse, indexed by
X     * Mouse[button_number][C_context][modifier].
X     */
X
X#define NoModifierMask 0
X
X    do_add_binding (Button1, C_TITLE, NoModifierMask, F_MOVE);
X    do_add_binding (Button1, C_ICON, NoModifierMask, F_ICONIFY);
X    do_add_binding (Button1, C_ICONMGR, NoModifierMask, F_ICONIFY);
X
X    do_add_binding (Button2, C_TITLE, NoModifierMask, F_RAISELOWER);
X    do_add_binding (Button2, C_ICON, NoModifierMask, F_ICONIFY);
X    do_add_binding (Button2, C_ICONMGR, NoModifierMask, F_ICONIFY);
X
X#undef NoModifierMask
X}
X
X
X
X
X/***********************************************************************
X *
X *  Procedure:
X *	GrabButtons - grab needed buttons for the window
X *
X *  Inputs:
X *	tmp_win - the twm window structure to use
X *
X ***********************************************************************
X */
X
Xvoid
XGrabButtons(tmp_win)
XTwmWindow *tmp_win;
X{
X    int i, j;
X
X    for (i = 0; i < MAX_BUTTONS+1; i++)
X    {
X	for (j = 0; j < MOD_SIZE; j++)
X	{
X	    if (Scr->Mouse[i][C_WINDOW][j].func != NULL)
X	    {
X		XGrabButton(dpy, i, j, tmp_win->w,
X		    True, ButtonPressMask | ButtonReleaseMask,
X		    GrabModeAsync, GrabModeAsync, None, Scr->FrameCursor);
X	    }
X	}
X    }
X}
X
X/***********************************************************************
X *
X *  Procedure:
X *	GrabKeys - grab needed keys for the window
X *
X *  Inputs:
X *	tmp_win - the twm window structure to use
X *
X ***********************************************************************
X */
X
Xvoid
XGrabKeys(tmp_win)
XTwmWindow *tmp_win;
X{
X    FuncKey *tmp;
X    IconMgr *p;
X
X    for (tmp = Scr->FuncKeyRoot.next; tmp != NULL; tmp = tmp->next)
X    {
X	switch (tmp->cont)
X	{
X	case C_WINDOW:
X	    XGrabKey(dpy, tmp->keycode, tmp->mods, tmp_win->w, True,
X		GrabModeAsync, GrabModeAsync);
X	    break;
X
X	case C_ICON:
X	    if (tmp_win->icon_w)
X		XGrabKey(dpy, tmp->keycode, tmp->mods, tmp_win->icon_w, True,
X		    GrabModeAsync, GrabModeAsync);
X
X	case C_TITLE:
X	    if (tmp_win->title_w)
X		XGrabKey(dpy, tmp->keycode, tmp->mods, tmp_win->title_w, True,
X		    GrabModeAsync, GrabModeAsync);
X	    break;
X
X	case C_NAME:
X	    XGrabKey(dpy, tmp->keycode, tmp->mods, tmp_win->w, True,
X		GrabModeAsync, GrabModeAsync);
X	    if (tmp_win->icon_w)
X		XGrabKey(dpy, tmp->keycode, tmp->mods, tmp_win->icon_w, True,
X		    GrabModeAsync, GrabModeAsync);
X	    if (tmp_win->title_w)
X		XGrabKey(dpy, tmp->keycode, tmp->mods, tmp_win->title_w, True,
X		    GrabModeAsync, GrabModeAsync);
X	    break;
X	/*
X	case C_ROOT:
X	    XGrabKey(dpy, tmp->keycode, tmp->mods, Scr->Root, True,
X		GrabModeAsync, GrabModeAsync);
X	    break;
X	*/
X	}
X    }
X    for (tmp = Scr->FuncKeyRoot.next; tmp != NULL; tmp = tmp->next)
X    {
X	if (tmp->cont == C_ICONMGR && !Scr->NoIconManagers)
X	{
X	    for (p = &Scr->iconmgr; p != NULL; p = p->next)
X	    {
X		XUngrabKey(dpy, tmp->keycode, tmp->mods, p->twm_win->w);
X	    }
X	}
X    }
X}
X
Xstatic Window CreateHighlightWindow (tmp_win)
X    TwmWindow *tmp_win;
X{
X    XSetWindowAttributes attributes;	/* attributes for create windows */
X    Pixmap pm = None;
X    GC gc;
X    XGCValues gcv;
X    unsigned long valuemask;
X    int h = (Scr->TitleHeight - 2 * Scr->FramePadding);
X    Window w;
X
X
X    /*
X     * If a special highlight pixmap was given, use that.  Otherwise,
X     * use a nice, even gray pattern.  The old horizontal lines look really
X     * awful on interlaced monitors (as well as resembling other looks a
X     * little bit too closely), but can be used by putting
X     *
X     *                 Pixmaps { TitleHighlight "hline2" }
X     *
X     * (or whatever the horizontal line bitmap is named) in the startup
X     * file.  If all else fails, use the foreground color to look like a 
X     * solid line.
X     */
X    if (!Scr->hilitePm) {
X	Scr->hilitePm = XCreateBitmapFromData (dpy, tmp_win->title_w, 
X					       gray_bits, gray_width, 
X					       gray_height);
X	Scr->hilite_pm_width = gray_width;
X	Scr->hilite_pm_height = gray_height;
X    }
X    if (Scr->hilitePm) {
X	pm = XCreatePixmap (dpy, tmp_win->title_w,
X			    Scr->hilite_pm_width, Scr->hilite_pm_height,
X			    Scr->d_depth);
X	gcv.foreground = tmp_win->title.fore;
X	gcv.background = tmp_win->title.back;
X	gcv.graphics_exposures = False;
X	gc = XCreateGC (dpy, pm,
X			(GCForeground|GCBackground|GCGraphicsExposures),
X			&gcv);
X	if (gc) {
X	    XCopyPlane (dpy, Scr->hilitePm, pm, gc, 0, 0, 
X			Scr->hilite_pm_width, Scr->hilite_pm_height,
X			0, 0, 1);
X	    XFreeGC (dpy, gc);
X	} else {
X	    XFreePixmap (dpy, pm);
X	    pm = None;
X	}
X    }
X    if (pm) {
X	valuemask = CWBackPixmap;
X	attributes.background_pixmap = pm;
X    } else {
X	valuemask = CWBackPixel;
X	attributes.background_pixel = tmp_win->title.fore;
X    }
X
X    w = XCreateWindow (dpy, tmp_win->title_w, 0, Scr->FramePadding,
X		       (unsigned int) Scr->TBInfo.width, (unsigned int) h,
X		       (unsigned int) 0,
X		       Scr->d_depth, (unsigned int) CopyFromParent,
X		       Scr->d_visual, valuemask, &attributes);
X    if (pm) XFreePixmap (dpy, pm);
X    return w;
X}
X
X
Xvoid ComputeCommonTitleOffsets ()
X{
X    int buttonwidth = (Scr->TBInfo.width + Scr->TBInfo.pad);
X
X    Scr->TBInfo.leftx = Scr->TBInfo.rightoff = Scr->FramePadding;
X    if (Scr->TBInfo.nleft > 0)
X      Scr->TBInfo.leftx += Scr->ButtonIndent;
X    Scr->TBInfo.titlex = (Scr->TBInfo.leftx +
X			  (Scr->TBInfo.nleft * buttonwidth) - Scr->TBInfo.pad +
X			  Scr->TitlePadding);
X    if (Scr->TBInfo.nright > 0)
X      Scr->TBInfo.rightoff += (Scr->ButtonIndent +
X			       ((Scr->TBInfo.nright * buttonwidth) -
X				Scr->TBInfo.pad));
X    return;
X}
X
Xvoid ComputeWindowTitleOffsets (tmp_win, width, squeeze)
X    TwmWindow *tmp_win;
X    Bool squeeze;
X{
X    tmp_win->highlightx = (Scr->TBInfo.titlex + tmp_win->name_width);
X    if (tmp_win->hilite_w || Scr->TBInfo.nright > 0) 
X      tmp_win->highlightx += Scr->TitlePadding;
X    tmp_win->rightx = width - Scr->TBInfo.rightoff;
X    if (squeeze && tmp_win->squeeze_info) {
X	int rx = (tmp_win->highlightx + 
X		  (tmp_win->hilite_w
X		    ? Scr->TBInfo.width * 2 : 0) +
X		  (Scr->TBInfo.nright > 0 ? Scr->TitlePadding : 0) +
X		  Scr->FramePadding);
X	if (rx < tmp_win->rightx) tmp_win->rightx = rx;
X    }
X    return;
X}
X
X
X/*
X * ComputeTitleLocation - calculate the position of the title window; we need
X * to take the frame_bw into account since we want (0,0) of the title window
X * to line up with (0,0) of the frame window.
X */
Xvoid ComputeTitleLocation (tmp)
X    register TwmWindow *tmp;
X{
X    tmp->title_x = -tmp->frame_bw;
X    tmp->title_y = -tmp->frame_bw;
X
X#ifdef SHAPE
X    if (tmp->squeeze_info) {
X	register SqueezeInfo *si = tmp->squeeze_info;
X	int basex;
X	int maxwidth = tmp->frame_width;
X	int tw = tmp->title_width;
X
X	/*
X	 * figure label base from squeeze info (justification fraction)
X	 */
X	if (si->denom == 0) {	/* num is pixel based */
X	    if ((basex = si->num) == 0) {  /* look for special cases */
X		switch (si->justify) {
X		  case J_RIGHT:
X		    basex = maxwidth;
X		    break;
X		  case J_CENTER:
X		    basex = maxwidth / 2;
X		break;
X		}
X	    }
X	} else {			/* num/denom is fraction */
X	    basex = ((si->num * maxwidth) / si->denom);
X	    if (si->num < 0) basex += maxwidth;
X	}
X
X	/*
X	 * adjust for left (nop), center, right justify and clip
X	 */
X	switch (si->justify) {
X	  case J_CENTER:
X	    basex -= tw / 2;
X	    break;
X	  case J_RIGHT:
X	    basex -= tw - 1;
X	    break;
X	}
X	if (basex > maxwidth - tw + 1)
X	  basex = maxwidth - tw + 1;
X	if (basex < 0) basex = 0;
X
X	tmp->title_x = basex - tmp->frame_bw;
X    }
X#endif
X}
X
X
Xstatic void CreateWindowTitlebarButtons (tmp_win)
X    TwmWindow *tmp_win;
X{
X    unsigned long valuemask;		/* mask for create windows */
X    XSetWindowAttributes attributes;	/* attributes for create windows */
X    int leftx, rightx, y;
X    TitleButton *tb;
X    int nb;
X
X    if (tmp_win->title_height == 0)
X    {
X	tmp_win->hilite_w = 0;
X	return;
X    }
X
X
X    /*
X     * create the title bar windows; let the event handler deal with painting
X     * so that we don't have to spend two pixmaps (or deal with hashing)
X     */
X    ComputeWindowTitleOffsets (tmp_win, tmp_win->attr.width, False);
X
X    leftx = y = Scr->TBInfo.leftx;
X    rightx = tmp_win->rightx;
X
X    attributes.win_gravity = NorthWestGravity;
X    attributes.background_pixel = tmp_win->title.back;
X    attributes.border_pixel = tmp_win->title.fore;
X    attributes.event_mask = (ButtonPressMask | ButtonReleaseMask |
X			     ExposureMask);
X    attributes.cursor = Scr->ButtonCursor;
X    valuemask = (CWWinGravity | CWBackPixel | CWBorderPixel | CWEventMask |
X		 CWCursor);
X
X    tmp_win->titlebuttons = NULL;
X    nb = Scr->TBInfo.nleft + Scr->TBInfo.nright;
X    if (nb > 0) {
X	tmp_win->titlebuttons = (TBWindow *) malloc (nb * sizeof(TBWindow));
X	if (!tmp_win->titlebuttons) {
X	    fprintf (stderr, "%s:  unable to allocate %d titlebuttons\n", 
X		     ProgramName, nb);
X	} else {
X	    TBWindow *tbw;
X	    int boxwidth = (Scr->TBInfo.width + Scr->TBInfo.pad);
X	    unsigned int h = (Scr->TBInfo.width - Scr->TBInfo.border * 2);
X
X	    for (tb = Scr->TBInfo.head, tbw = tmp_win->titlebuttons; tb;
X		 tb = tb->next, tbw++) {
X		int x;
X		if (tb->rightside) {
X		    x = rightx;
X		    rightx += boxwidth;
X		    attributes.win_gravity = NorthEastGravity;
X		} else {
X		    x = leftx;
X		    leftx += boxwidth;
X		    attributes.win_gravity = NorthWestGravity;
X		}
X		tbw->window = XCreateWindow (dpy, tmp_win->title_w, x, y, h, h,
X					     (unsigned int) Scr->TBInfo.border,
X					     0, (unsigned int) CopyFromParent,
X					     (Visual *) CopyFromParent,
X					     valuemask, &attributes);
X		tbw->info = tb;
X	    }
X	}
X    }
X
X    tmp_win->hilite_w = (tmp_win->titlehighlight 
X			 ? CreateHighlightWindow (tmp_win) : None);
X
X    XMapSubwindows(dpy, tmp_win->title_w);
X    if (tmp_win->hilite_w)
X      XUnmapWindow(dpy, tmp_win->hilite_w);
X    return;
X}
X
X
XSetHighlightPixmap (filename)
X    char *filename;
X{
X    Pixmap pm = GetBitmap (filename);
X
X    if (pm) {
X	if (Scr->hilitePm) {
X	    XFreePixmap (dpy, Scr->hilitePm);
X	}
X	Scr->hilitePm = pm;
X	Scr->hilite_pm_width = JunkWidth;
X	Scr->hilite_pm_height = JunkHeight;
X    }
X}
X
X
XFetchWmProtocols (tmp)
X    TwmWindow *tmp;
X{
X    unsigned long flags = 0L;
X    Atom *protocols = NULL;
X    int n;
X
X    if (XGetWMProtocols (dpy, tmp->w, &protocols, &n)) {
X	register int i;
X	register Atom *ap;
X
X	for (i = 0, ap = protocols; i < n; i++, ap++) {
X	    if (*ap == _XA_WM_TAKE_FOCUS) flags |= DoesWmTakeFocus;
X	    if (*ap == _XA_WM_SAVE_YOURSELF) flags |= DoesWmSaveYourself;
X	    if (*ap == _XA_WM_DELETE_WINDOW) flags |= DoesWmDeleteWindow;
X	}
X	if (protocols) XFree ((char *) protocols);
X    }
X    tmp->protocols = flags;
X}
X
XTwmColormap *
XCreateTwmColormap(c)
X    Colormap c;
X{
X    TwmColormap *cmap;
X    cmap = (TwmColormap *) malloc(sizeof(TwmColormap));
X    if (!cmap ||
X	XSaveContext(dpy, c, ColormapContext, (caddr_t) cmap)) {
X	if (cmap) free((char *) cmap);
X	return (NULL);
X    }
X    cmap->c = c;
X    cmap->state = 0;
X    cmap->install_req = 0;
X    cmap->w = None;
X    cmap->refcnt = 1;
X    return (cmap);
X}
X
XColormapWindow *
XCreateColormapWindow(w, creating_parent, property_window)
X    Window w;
X    Bool creating_parent;
X    Bool property_window;
X{
X    ColormapWindow *cwin;
X    TwmColormap *cmap;
X    XWindowAttributes attributes;
X
X    cwin = (ColormapWindow *) malloc(sizeof(ColormapWindow));
X    if (cwin) {
X	if (!XGetWindowAttributes(dpy, w, &attributes) ||
X	    XSaveContext(dpy, w, ColormapContext, (caddr_t) cwin)) {
X	    free((char *) cwin);
X	    return (NULL);
X	}
X
X	if (XFindContext(dpy, attributes.colormap,  ColormapContext,
X		(caddr_t *)&cwin->colormap) == XCNOENT) {
X	    cwin->colormap = cmap = CreateTwmColormap(attributes.colormap);
X	    if (!cmap) {
X		XDeleteContext(dpy, w, ColormapContext);
X		free((char *) cwin);
X		return (NULL);
X	    }
X	} else {
X	    cwin->colormap->refcnt++;
X	}
X
X	cwin->w = w;
X	/*
X	 * Assume that windows in colormap list are
X	 * obscured if we are creating the parent window.
X	 * Otherwise, we assume they are unobscured.
X	 */
X	cwin->visibility = creating_parent ?
X	    VisibilityFullyObscured : VisibilityUnobscured;
X	cwin->refcnt = 1;
X
X	/*
X	 * If this is a ColormapWindow property window and we
X	 * are not monitoring ColormapNotify or VisibilityNotify
X	 * events, we need to.
X	 */
X	if (property_window &&
X	    (attributes.your_event_mask &
X		(ColormapChangeMask|VisibilityChangeMask)) !=
X		    (ColormapChangeMask|VisibilityChangeMask)) {
X	    XSelectInput(dpy, w, attributes.your_event_mask |
X		(ColormapChangeMask|VisibilityChangeMask));
X	}
X    }
X
X    return (cwin);
X}
X		
XFetchWmColormapWindows (tmp)
X    TwmWindow *tmp;
X{
X    register int i, j;
X    Window *cmap_windows = NULL;
X    Bool can_free_cmap_windows = False;
X    int number_cmap_windows = 0;
X    ColormapWindow **cwins = NULL;
X    int previously_installed;
X    extern void free_cwins();
X
X    number_cmap_windows = 0;
X
X    if (previously_installed = (Scr->cmapInfo.cmaps == &tmp->cmaps &&
X				tmp->cmaps.number_cwins)) {
X	cwins = tmp->cmaps.cwins;
X	for (i = 0; i < tmp->cmaps.number_cwins; i++)
X	    cwins[i]->colormap->state = 0;
X    }
X
X    if (XGetWMColormapWindows (dpy, tmp->w, &cmap_windows, 
X			       &number_cmap_windows) &&
X	number_cmap_windows > 0) {
X
X	can_free_cmap_windows = False;
X	/*
X	 * check if the top level is in the list, add to front if not
X	 */
X	for (i = 0; i < number_cmap_windows; i++) {
X	    if (cmap_windows[i] == tmp->w) break;
X	}
X	if (i == number_cmap_windows) {	 /* not in list */
X	    Window *new_cmap_windows =
X	      (Window *) malloc (sizeof(Window) * (number_cmap_windows + 1));
X
X	    if (!new_cmap_windows) {
X		fprintf (stderr, 
X			 "%s:  unable to allocate %d element colormap window array\n",
X			ProgramName, number_cmap_windows+1);
X		goto done;
X	    }
X	    new_cmap_windows[0] = tmp->w;  /* add to front */
X	    for (i = 0; i < number_cmap_windows; i++) {	 /* append rest */
X		new_cmap_windows[i+1] = cmap_windows[i];
X	    }
X	    XFree ((char *) cmap_windows);
X	    can_free_cmap_windows = True;  /* do not use XFree any more */
X	    cmap_windows = new_cmap_windows;
X	    number_cmap_windows++;
X	}
X
X	cwins = (ColormapWindow **) malloc(sizeof(ColormapWindow *) *
X		number_cmap_windows);
X	if (cwins) {
X	    for (i = 0; i < number_cmap_windows; i++) {
X
X		/*
X		 * Copy any existing entries into new list.
X		 */
X		for (j = 0; j < tmp->cmaps.number_cwins; j++) {
X		    if (tmp->cmaps.cwins[j]->w == cmap_windows[i]) {
X			cwins[i] = tmp->cmaps.cwins[j];
X			cwins[i]->refcnt++;
X			break;
X		    }
X		}
X
X		/*
X		 * If the colormap window is not being pointed by
X		 * some other applications colormap window list,
X		 * create a new entry.
X		 */
X		if (j == tmp->cmaps.number_cwins) {
X		    if (XFindContext(dpy, cmap_windows[i], ColormapContext,
X				     (caddr_t *)&cwins[i]) == XCNOENT) {
X			if ((cwins[i] = CreateColormapWindow(cmap_windows[i],
X				    (Bool) tmp->cmaps.number_cwins == 0,
X				    True)) == NULL) {
X			    int k;
X			    for (k = i + 1; k < number_cmap_windows; k++)
X				cmap_windows[k-1] = cmap_windows[k];
X			    i--;
X			    number_cmap_windows--;
X			}
X		    } else
X			cwins[i]->refcnt++;
X		}
X	    }
X	}
X    }
X
X    /* No else here, in case we bailed out of clause above.
X     */
X    if (number_cmap_windows == 0) {
X
X	number_cmap_windows = 1;
X
X	cwins = (ColormapWindow **) malloc(sizeof(ColormapWindow *));
X	if (XFindContext(dpy, tmp->w, ColormapContext, (caddr_t *)&cwins[0]) ==
X		XCNOENT)
X	    cwins[0] = CreateColormapWindow(tmp->w,
X			    (Bool) tmp->cmaps.number_cwins == 0, False);
X	else
X	    cwins[0]->refcnt++;
X    }
X
X    if (tmp->cmaps.number_cwins)
X	free_cwins(tmp);
X
X    tmp->cmaps.cwins = cwins;
X    tmp->cmaps.number_cwins = number_cmap_windows;
X    if (number_cmap_windows > 1)
X	tmp->cmaps.scoreboard = 
X	  (char *) calloc(1, ColormapsScoreboardLength(&tmp->cmaps));
X		
X    if (previously_installed)
X	InstallWindowColormaps(PropertyNotify, (TwmWindow *) NULL);
X
X  done:
X    if (cmap_windows) {
X	if (can_free_cmap_windows)
X	  free ((char *) cmap_windows);
X	else
X	  XFree ((char *) cmap_windows);
X    }
X
X    return;
X}
X
X
XSimulateWinGravity (tmp)
X    TwmWindow *tmp;
X{
X    if (tmp->hints.flags & USPosition) {
X	static int gravs[] = { SouthEastGravity, SouthWestGravity,
X			       NorthEastGravity, NorthWestGravity };
X	int right =  tmp->attr.x + tmp->attr.width + 2 * tmp->old_bw;
X	int bottom = tmp->attr.y + tmp->attr.height + 2 * tmp->old_bw;
X	tmp->hints.win_gravity = 
X	  gravs[((Scr->MyDisplayHeight - bottom < tmp->title_height) ? 0 : 2) |
X		((Scr->MyDisplayWidth - right   < tmp->title_height) ? 0 : 1)];
X	tmp->hints.flags |= PWinGravity;
X    }
X}
X
Xstatic void
XgetTWM_FLAGS (w, flags)
X    Window w;
X    unsigned long *flags;
X{
X    Atom actual_type;
X    int actual_format;
X    unsigned long nitems, bytesafter;
X    unsigned long *datap = NULL;
X    Bool retval = False;
X
X    if (XGetWindowProperty (dpy, w, _XA_TWM_FLAGS, 0L, 1L, False, _XA_TWM_FLAGS,
X			    &actual_type, &actual_format, &nitems, &bytesafter,
X			    (unsigned char **) &datap) != Success || !datap)
X    {
X	*flags = 0;
X	return;
X    }
X    *flags = *datap;
X    XFree ((char *) datap);
X    return;
X}
X
Xvoid
XSetTWM_FLAGS(tmp_win)
XTwmWindow *tmp_win;
X{
X    unsigned long data;
X  
X    data = 0;
X
X    if (tmp_win->sticky)
X	data |= TWM_FLAGS_STICKY;
X
X
X    XChangeProperty (dpy, tmp_win->w, _XA_TWM_FLAGS, _XA_TWM_FLAGS, 32, 
X		 PropModeReplace, (unsigned char *) &data, 1);
X}
X
SHAR_EOF
if test 45413 -ne "`wc -c < add_window.c`"
then
    echo shar: error transmitting "add_window.c" '(should have been 45413 characters)'
fi
fi
if test -f 'add_window.h'
then
    echo shar: will not over-write existing file "add_window.h"
else
echo extracting "add_window.h"
sed 's/^X//' >add_window.h <<'SHAR_EOF'
X/*****************************************************************************/
X/**       Copyright 1988 by Evans & Sutherland Computer Corporation,        **/
X/**                          Salt Lake City, Utah                           **/
X/**  Portions Copyright 1989 by the Massachusetts Institute of Technology   **/
X/**                        Cambridge, Massachusetts                         **/
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/**    names of Evans & Sutherland and M.I.T. not be used in advertising    **/
X/**    in publicity pertaining to distribution of the  software  without    **/
X/**    specific, written prior permission.                                  **/
X/**                                                                         **/
X/**    EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD    **/
X/**    TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES  OF  MERCHANT-    **/
X/**    ABILITY  AND  FITNESS,  IN  NO  EVENT SHALL EVANS & SUTHERLAND OR    **/
X/**    M.I.T. 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/*****************************************************************************/
X
X
X/**********************************************************************
X *
X * $XConsortium: add_window.h,v 1.6 89/12/10 17:46:32 jim Exp $
X *
X * AddWindow include file
X *
X * 31-Mar-88 Tom LaStrange        Initial Version.
X *
X **********************************************************************/
X
X#ifndef _ADD_WINDOW_
X#define _ADD_WINDOW_
X
Xextern char NoName[];
X
Xextern TwmWindow *AddWindow();
Xextern int MappedNotOverride();
Xextern void GrabButtons();
Xextern void GrabKeys();
Xextern void UngrabButtons();
Xextern void UngrabKeys();
Xextern void SetTWM_FLAGS();
Xextern int AddingX;	
Xextern int AddingY;
Xextern int AddingW;
Xextern int AddingH;
X
X#endif /* _ADD_WINDOW_ */
X
SHAR_EOF
if test 2753 -ne "`wc -c < add_window.h`"
then
    echo shar: error transmitting "add_window.h" '(should have been 2753 characters)'
fi
fi
if test -f 'cursor.c'
then
    echo shar: will not over-write existing file "cursor.c"
else
echo extracting "cursor.c"
sed 's/^X//' >cursor.c <<'SHAR_EOF'
X/*
X * Copyright 1989 Massachusetts Institute of Technology
X *
X * Permission to use, copy, modify, and distribute this software and its
X * documentation for any purpose and without fee is hereby granted, provided
X * that the above copyright notice appear in all copies and that both that
X * copyright notice and this permission notice appear in supporting
X * documentation, and that the name of M.I.T. not be used in advertising
X * or publicity pertaining to distribution of the software without specific,
X * written prior permission.  M.I.T. makes no representations about the
X * suitability of this software for any purpose.  It is provided "as is"
X * without express or implied warranty.
X *
X * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
X * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
X * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
X * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
X */
X
X/***********************************************************************
X *
X * $XConsortium: cursor.c,v 1.10 89/12/14 14:52:23 jim Exp $
X *
X * cursor creation code
X *
X * 05-Apr-89 Thomas E. LaStrange	File created
X *
X ***********************************************************************/
X
X#include <stdio.h>
X#include "twm.h"
X#include <X11/Xos.h>
X#include "screen.h"
X#include "util.h"
X
Xstatic struct _CursorName {
X    char		*name;
X    unsigned int	shape;
X    Cursor		cursor;
X} cursor_names[] = {
X
X{"X_cursor",		XC_X_cursor,		None},
X{"arrow",		XC_arrow,		None},
X{"based_arrow_down",	XC_based_arrow_down,    None},
X{"based_arrow_up",	XC_based_arrow_up,      None},
X{"boat",		XC_boat,		None},
X{"bogosity",		XC_bogosity,		None},
X{"bottom_left_corner",	XC_bottom_left_corner,  None},
X{"bottom_right_corner",	XC_bottom_right_corner, None},
X{"bottom_side",		XC_bottom_side,		None},
X{"bottom_tee",		XC_bottom_tee,		None},
X{"box_spiral",		XC_box_spiral,		None},
X{"center_ptr",		XC_center_ptr,		None},
X{"circle",		XC_circle,		None},
X{"clock",		XC_clock,		None},
X{"coffee_mug",		XC_coffee_mug,		None},
X{"cross",		XC_cross,		None},
X{"cross_reverse",	XC_cross_reverse,       None},
X{"crosshair",		XC_crosshair,		None},
X{"diamond_cross",	XC_diamond_cross,       None},
X{"dot",			XC_dot,			None},
X{"dotbox",		XC_dotbox,		None},
X{"double_arrow",	XC_double_arrow,	None},
X{"draft_large",		XC_draft_large,		None},
X{"draft_small",		XC_draft_small,		None},
X{"draped_box",		XC_draped_box,		None},
X{"exchange",		XC_exchange,		None},
X{"fleur",		XC_fleur,		None},
X{"gobbler",		XC_gobbler,		None},
X{"gumby",		XC_gumby,		None},
X{"hand1",		XC_hand1,		None},
X{"hand2",		XC_hand2,		None},
X{"heart",		XC_heart,		None},
X{"icon",		XC_icon,		None},
X{"iron_cross",		XC_iron_cross,		None},
X{"left_ptr",		XC_left_ptr,		None},
X{"left_side",		XC_left_side,		None},
X{"left_tee",		XC_left_tee,		None},
X{"leftbutton",		XC_leftbutton,		None},
X{"ll_angle",		XC_ll_angle,		None},
X{"lr_angle",		XC_lr_angle,		None},
X{"man",			XC_man,			None},
X{"middlebutton",	XC_middlebutton,	None},
X{"mouse",		XC_mouse,		None},
X{"pencil",		XC_pencil,		None},
X{"pirate",		XC_pirate,		None},
X{"plus",		XC_plus,		None},
X{"question_arrow",	XC_question_arrow,	None},
X{"right_ptr",		XC_right_ptr,		None},
X{"right_side",		XC_right_side,		None},
X{"right_tee",		XC_right_tee,		None},
X{"rightbutton",		XC_rightbutton,		None},
X{"rtl_logo",		XC_rtl_logo,		None},
X{"sailboat",		XC_sailboat,		None},
X{"sb_down_arrow",	XC_sb_down_arrow,       None},
X{"sb_h_double_arrow",	XC_sb_h_double_arrow,   None},
X{"sb_left_arrow",	XC_sb_left_arrow,       None},
X{"sb_right_arrow",	XC_sb_right_arrow,      None},
X{"sb_up_arrow",		XC_sb_up_arrow,		None},
X{"sb_v_double_arrow",	XC_sb_v_double_arrow,   None},
X{"shuttle",		XC_shuttle,		None},
X{"sizing",		XC_sizing,		None},
X{"spider",		XC_spider,		None},
X{"spraycan",		XC_spraycan,		None},
X{"star",		XC_star,		None},
X{"target",		XC_target,		None},
X{"tcross",		XC_tcross,		None},
X{"top_left_arrow",	XC_top_left_arrow,      None},
X{"top_left_corner",	XC_top_left_corner,	None},
X{"top_right_corner",	XC_top_right_corner,    None},
X{"top_side",		XC_top_side,		None},
X{"top_tee",		XC_top_tee,		None},
X{"trek",		XC_trek,		None},
X{"ul_angle",		XC_ul_angle,		None},
X{"umbrella",		XC_umbrella,		None},
X{"ur_angle",		XC_ur_angle,		None},
X{"watch",		XC_watch,		None},
X{"xterm",		XC_xterm,		None},
X};
X
Xvoid NewFontCursor (cp, str)
X    Cursor *cp;
X    char *str;
X{
X    int i;
X
X    for (i = 0; i < sizeof(cursor_names)/sizeof(struct _CursorName); i++)
X    {
X	if (strcmp(str, cursor_names[i].name) == 0)
X	{
X	    if (cursor_names[i].cursor == None)
X		cursor_names[i].cursor = XCreateFontCursor(dpy,
X			cursor_names[i].shape);
X	    *cp = cursor_names[i].cursor;
X	    return;
X	}
X    }
X    fprintf (stderr, "%s:  unable to find font cursor \"%s\"\n", 
X	     ProgramName, str);
X}
X
XNewBitmapCursor(cp, source, mask)
XCursor *cp;
Xchar *source, *mask;
X{
X    XColor fore, back;
X    int hotx, hoty;
X    int sx, sy, mx, my;
X    unsigned int sw, sh, mw, mh;
X    Pixmap spm, mpm;
X    Colormap cmap = Scr->TwmRoot.cmaps.cwins[0]->colormap->c;
X
X    fore.pixel = Scr->Black;
X    XQueryColor(dpy, cmap, &fore);
X    back.pixel = Scr->White;
X    XQueryColor(dpy, cmap, &back);
X
X    spm = GetBitmap(source);
X    if ((hotx = HotX) < 0) hotx = 0;
X    if ((hoty = HotY) < 0) hoty = 0;
X    mpm = GetBitmap(mask);
X
X    /* make sure they are the same size */
X
X    XGetGeometry(dpy, spm, &JunkRoot, &sx, &sy, &sw, &sh, &JunkBW,&JunkDepth);
X    XGetGeometry(dpy, mpm, &JunkRoot, &mx, &my, &mw, &mh, &JunkBW,&JunkDepth);
X    if (sw != mw || sh != mh)
X    {
X	fprintf (stderr, 
X		 "%s:  cursor bitmaps \"%s\" and \"%s\" not the same size\n",
X		 ProgramName, source, mask);
X	return;
X    }
X    *cp = XCreatePixmapCursor(dpy, spm, mpm, &fore, &back, hotx,hoty);
X}
SHAR_EOF
if test 5925 -ne "`wc -c < cursor.c`"
then
    echo shar: error transmitting "cursor.c" '(should have been 5925 characters)'
fi
fi
if test -f 'patchlevel.h'
then
    echo shar: will not over-write existing file "patchlevel.h"
else
echo extracting "patchlevel.h"
sed 's/^X//' >patchlevel.h <<'SHAR_EOF'
X#define PATCHLEVEL 0
SHAR_EOF
if test 21 -ne "`wc -c < patchlevel.h`"
then
    echo shar: error transmitting "patchlevel.h" '(should have been 21 characters)'
fi
fi
if test -f 'siconify.bm'
then
    echo shar: will not over-write existing file "siconify.bm"
else
echo extracting "siconify.bm"
sed 's/^X//' >siconify.bm <<'SHAR_EOF'
X#define siconify_width 11
X#define siconify_height 11
Xstatic char siconify_bits[] = {
X   0xff, 0x07, 0x01, 0x04, 0x0d, 0x05, 0x9d, 0x05, 0xb9, 0x04, 0x51, 0x04,
X   0xe9, 0x04, 0xcd, 0x05, 0x85, 0x05, 0x01, 0x04, 0xff, 0x07};
SHAR_EOF
if test 224 -ne "`wc -c < siconify.bm`"
then
    echo shar: error transmitting "siconify.bm" '(should have been 224 characters)'
fi
fi
# end of shell archive
exit 0

dan
----------------------------------------------------
O'Reilly && Associates   argv@sun.com / argv@ora.com
Opinions expressed reflect those of the author only.