/*
* Copyright (c) 2005 X.Org Foundation L.L.C.
* 
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
* 
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
* 
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
* 
* Copyright (c) Applied Testing and Technology, Inc. 1995
* All Rights Reserved.
* 
* 
* Portions of this software are based on Xlib and X Protocol Test Suite.
* We have used this material under the terms of its copyright, which grants
* free use, subject to the conditions below.  Note however that those
* portions of this software that are based on the original Test Suite have
* been significantly revised and that all such revisions are copyright (c)
* 1995 Applied Testing and Technology, Inc.  Insomuch as the proprietary
* revisions cannot be separated from the freely copyable material, the net
* result is that use of this software is governed by the ApTest copyright.
* 
* Copyright (c) 1990, 1991  X Consortium
* 
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* 
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* 
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
* X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* 
* Except as contained in this notice, the name of the X Consortium shall not be
* used in advertising or otherwise to promote the sale, use or other dealings
* in this Software without prior written authorization from the X Consortium.
* 
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of UniSoft not be
* used in advertising or publicity pertaining to distribution of the
* software without specific, written prior permission.  UniSoft
* makes no representations about the suitability of this software for any
* purpose.  It is provided "as is" without express or implied warranty.
* 
* Copyright (c) 2005 X.Org Foundation LLC
* 
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
* 
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
* 
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
* 
* Copyright (c) Applied Testing and Technology, Inc. 1995
* All Rights Reserved.
* 
* 
* Portions of this software are based on Xlib and X Protocol Test Suite.
* We have used this material under the terms of its copyright, which grants
* free use, subject to the conditions below.  Note however that those
* portions of this software that are based on the original Test Suite have
* been significantly revised and that all such revisions are copyright (c)
* 1995 Applied Testing and Technology, Inc.  Insomuch as the proprietary
* revisions cannot be separated from the freely copyable material, the net
* result is that use of this software is governed by the ApTest copyright.
* 
* Copyright (c) 1990, 1991  X Consortium
* 
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* 
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* 
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
* X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* 
* Except as contained in this notice, the name of the X Consortium shall not be
* used in advertising or otherwise to promote the sale, use or other dealings
* in this Software without prior written authorization from the X Consortium.
* 
* Copyright 1990, 1991 by UniSoft Group Limited.
* 
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of UniSoft not be
* used in advertising or publicity pertaining to distribution of the
* software without specific, written prior permission.  UniSoft
* makes no representations about the suitability of this software for any
* purpose.  It is provided "as is" without express or implied warranty.
* 
*/
/*
 * SYNOPSIS:
 *   void
 *   XResizeWindow(display, w, width, height)
 *   Display	*display;
 *   Window	w;
 *   unsigned int	width;
 *   unsigned int	height;
 */


#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include	<stdlib.h>
#include	<stdio.h>
#include	<string.h>
#include	"xtest.h"
#include	"X11/Xlib.h"
#include	"X11/Xutil.h"
#include	"X11/Xresource.h"
#include	"X11/keysym.h"
#include	"tet_api.h"
#include	"xtestlib.h"
#include	"pixval.h"
#ifdef INPUTEXTENSION
#include        "X11/extensions/XInput.h"
#include        "XItest.h"
#endif

extern	Display	*Dsp;
extern	Window	Win;

extern	Window	ErrdefWindow;
extern	Drawable ErrdefDrawable;
extern	GC		ErrdefGC;
extern	Colormap ErrdefColormap;
extern	Pixmap	ErrdefPixmap;
extern	Atom	ErrdefAtom;
extern	Cursor	ErrdefCursor;
extern	Font	ErrdefFont;


#define T_XResizeWindow	1
char    *TestName = "XResizeWindow";

/*
 * Defines for different argument types
 */
#define A_DISPLAY display
#define A_WINDOW w
#define A_DRAWABLE w


/*
 * Arguments to the XResizeWindow function
 */
static Display	*display;
static Window	w;
static unsigned int	width;
static unsigned int	height;



/*
 * Convenience routine that sets the 'w' argument to be simple window
 * with a background of W_FG at position (10,8) and * size 23x9.
 * The border width is 0.
 */
#define	OW_X	10
#define	OW_Y	8
#define	OW_WIDTH	23
#define	OW_HEIGHT	9

static	Window
onewin()
{
Window	base;
struct	area	area;

	base = defwin(display);
	setarea(&area, OW_X, OW_Y, OW_WIDTH, OW_HEIGHT);

	w = crechild(display, base, &area);
	XSetWindowBackground(display, w, W_FG);
	XClearWindow(display, w);

	return(base);
}

/*
 * A window with subwindows.
 */
static	char	*Tsub[] = {
	".",
	"top . (5, 5) 40x40",
	"sub1 top (1,3) 4x6",
	"sub2 top (8,3) 7x6",
	"sub3 top (3,14) 12x9",
	"sub4 top (28,10) 7x20",
	"sub5 top (14,25) 11x12",
};
#define	NTsub	(NELEM(Tsub))
#define	NTsubInf	(NTsub-1)	/* Number of inferiors excluding base */



extern	struct valname S_wingravity[];
extern	int 	NS_wingravity;

/* Values to resize onewin to (odd and even) */
#define	NEW_WIDTH	70
#define	NEW_HEIGHT	61

#define	BORDERW	1



/*
 * Flags to say that we received particular events.
 */
#define	WIN_CONFIG	001
#define	WIN_GRAVITY	002
#define	PAR_CONFIG	004
#define	PAR_GRAVITY	010


static void
calcxy(top, evtype, x, y)
struct	buildtree	*top;
int 	evtype;
int 	*x;
int 	*y;
{
int 	dx = NEW_WIDTH-top->width;
int 	dy = NEW_HEIGHT-top->height;

	switch (evtype) {
	case NorthWestGravity:
		break;
	case NorthGravity:
		*x += dx/2;
		break;
	case NorthEastGravity:
		*x += dx;
		break;
	case WestGravity:
		*y += dy/2;
		break;
	case CenterGravity:
		*x += dx/2;
		*y += dy/2;
		break;
	case EastGravity:
		*x += dx;
		*y += dy/2;
		break;
	case SouthWestGravity:
		*y += dy;
		break;
	case SouthGravity:
		*x += dx/2;
		*y += dy;
		break;
	case SouthEastGravity:
		*x += dx;
		*y += dy;
		break;
	case StaticGravity:
		break;
	default:
		delete("Internal error -- Unknown gravity in calcxy");
	}
}
/*
 * Routine that does the event checking for the gravity notify
 * test.
 */
static
wingravevents(display, bt, evtype)
Display	*display;
struct	buildtree	*bt;
int 	evtype;
{
XEvent	ev;
XConfigureEvent	confgood;
XGravityEvent	gravgood;
XConfigureEvent	*cnp;
XGravityEvent	*gnp;
struct	buildtree	*btp;
struct	buildtree	*top;
int 	gotgrav = 0;
int 	i;
int 	pass = 0, fail = 0;

	top = btntobtp(bt, "top");

	/* Set up events */
	confgood.type = ConfigureNotify;
	confgood.serial = 0L;
	confgood.send_event = False;
	confgood.display = display;
	confgood.above = None;	/* XXX */
	confgood.override_redirect = False;

	confgood.x = top->x;
	confgood.y = top->y;
	confgood.width = NEW_WIDTH;
	confgood.height = NEW_HEIGHT;
	confgood.border_width = 0;

	gravgood.type = GravityNotify;
	gravgood.serial = 0L;
	gravgood.send_event = False;
	gravgood.display = display;

	while (getevent(display, &ev) > 0) {

		switch (ev.type) {
		case ConfigureNotify:
			cnp = (XConfigureEvent*)&ev;

			btp = btwtobtp(bt, cnp->window);
			if (btp == NULL) {
				report("Event received on unknown window");
				FAIL;
				continue;
			}
			trace("Event received for window '%s'", btp->name);

			if (gotgrav) {
				report("Configure event received after gravity event");
				FAIL;
			} else
				CHECK;

			/*
			 * Work out if this event occurred on the parent or the window.
			 */
			if (cnp->window != cnp->event) {
				if (!btp->parent || btp->parent->wid != cnp->event) {
					report("Event received on other than the parent window");
					FAIL;
				} else
					btp->uflags |= PAR_CONFIG;
			} else {
				btp->uflags |= WIN_CONFIG;
			}

			confgood.event = cnp->event;
			confgood.window = cnp->window;

			if (checkevent((XEvent*)&confgood, &ev) == 0)
				CHECK;
			else
				FAIL;

			break;
		case GravityNotify:
			gnp = (XGravityEvent*)&ev;
			gotgrav = 1;

			btp = btwtobtp(bt, gnp->window);
			if (btp == NULL) {
				report("Event received on unknown window");
				FAIL;
				continue;
			}
			trace("Event received for window '%s'", btp->name);

			/*
			 * Work out if this event occurred on the parent or the window.
			 */
			if (gnp->window != gnp->event) {
				if (!btp->parent || btp->parent->wid != gnp->event) {
					report("Event received on other than the parent window");
					FAIL;
				} else
					btp->uflags |= PAR_GRAVITY;
			} else {
				btp->uflags |= WIN_GRAVITY;
			}

			gravgood.event = gnp->event;
			gravgood.window = gnp->window;
			gravgood.x = btp->x;
			gravgood.y = btp->y;
			calcxy(top, evtype, &gravgood.x, &gravgood.y);

			if (checkevent((XEvent*)&gravgood, &ev) == 0)
				CHECK;
			else
				FAIL;

			break;
		default:
			report("Unexpected event type %s", eventname(ev.type));
			FAIL;
		}
	}

	/*
	 * Since the previous loop is executed a variable number of times
	 * check that it was executed at least once and reset the pass count.
	 */
	if (pass > 0)
		pass = 1;
	else
		delete("No CHECK marks in wingravevents() loop");

	/*
	 * Check correct events on the top (resized) window.
	 */
	if (top->uflags & WIN_CONFIG)
		CHECK;
	else {
		report("Configure event not received on window 'top'");
		FAIL;
	}
	if (top->uflags & PAR_CONFIG)
		CHECK;
	else {
		report("Configure event not received on parent of window 'top'");
		FAIL;
	}
	if (top->uflags & (PAR_GRAVITY|WIN_GRAVITY)) {
		report("Gravity events unexpectedly received on window 'top'");
		FAIL;
	} else
		CHECK;

	for (i = 2; i < NTsub; i++) {
		if (evtype == NorthWestGravity || evtype == StaticGravity) {
			if (bt[i].uflags & WIN_GRAVITY) {
				report("Gravity event unexpectedly received on window '%s'", bt[i].name);
				FAIL;
			} else
				CHECK;
			if (bt[i].uflags & PAR_GRAVITY) {
				report("Gravity event unexpectedly received on parent of window '%s'", bt[i].name);
				FAIL;
			} else
				CHECK;

		} else {

			if (bt[i].uflags & WIN_GRAVITY)
				CHECK;
			else {
				report("Gravity event not received on window '%s'", bt[i].name);
				FAIL;
			}
			if (bt[i].uflags & PAR_GRAVITY)
				CHECK;
			else {
				report("Gravity event not received on parent of window '%s'", bt[i].name);
				FAIL;
			}
		}
		if (bt[i].uflags & (PAR_CONFIG|WIN_CONFIG)) {
			report("Configure event unexpectedly received on window '%s'", bt[i].name);
			FAIL;
		}
	}
	if (fail == 0 && pass != 14)
		delete("Path check error in wingravevents got %d, expecting 14", pass);

	if (fail == 0)
		return(True);
	else
		return(False);
}



#define	ON_PARENT	0x01
#define	ON_WINDOW	0x02


int 	tet_thistest;

/*
 * Called at the beginning of each test purpose to reset the
 * arguments to their initial values
 */
static void
setargs()
{
	display = Dsp;
	w = 0;
	width = 0;
	height = 0;
}

/*
 * Set the arguments to default values for error tests
 */
static void
seterrdef()
{
	w = ErrdefWindow;
}

static void t001(){

Window	base;
struct	area	area;
int 	pass = 0, fail = 0;

 	report_purpose(1);

	report_assertion("Assertion XResizeWindow-1.(A)");
	report_assertion("A call to XResizeWindow changes the inside size of the");
	report_assertion("specified window to width and height.");

	report_strategy("Create test window with background of W_FG.");
	report_strategy("Set width and height.");
	report_strategy("Call XResizeWindow.");
	report_strategy("Verify new size on screen with checkarea().");

	tpstartup();
	setargs();
	base = onewin();

	setarea(&area, OW_X, OW_Y, 23, 47);
	width = area.width;
	height = area.height;

	startcall(display);
	if (isdeleted())
		return;
	XResizeWindow(display, w, width, height);
	endcall(display);
	if (geterr() != Success) {
		report("Got %s, Expecting Success", errorname(geterr()));
		FAIL;
	}

	if (checkarea(display, base, &area, W_FG, W_BG, CHECK_ALL))
		CHECK;
	else {
		report("Error in resizing window");
		FAIL;
	}

	CHECKPASS(1);
	tpcleanup();
	pfcount(pass, fail);
}

static void t002(){

Window	base;
struct	buildtree	*bt;
struct	buildtree	*topbtp;
struct	valname 	*wgrav;
XSetWindowAttributes	setatts;
int 	i;
int 	pass = 0, fail = 0;

 	report_purpose(2);

	report_assertion("Assertion XResizeWindow-2.(A)");
	report_assertion("When a call to XResizeWindow actually changes the size of");
	report_assertion("the window, then the subwindows of the window are");
	report_assertion("repositioned according to their win-gravity attribute and a");
	report_assertion("GravityNotify event is generated for each repositioned");
	report_assertion("subwindow after the ConfigureNotify event.");

	report_strategy("For each win-gravity attribute (apart from UnmapGravity)");
	report_strategy("  Create window with subwindows.");
	report_strategy("  Enable SubstructureNotify|StructureNotify events on all windows.");
	report_strategy("  Set win-gravity on window.");
	report_strategy("  Call XResizeWindow to resize window.");
	report_strategy("  Verify window positions by pixel check.");
	report_strategy("  Verify ConfigureNotify on resized window.");
	report_strategy("  Verify ConfigureNotify on parent of resized window.");
	report_strategy("  If NorthWestGravity || StaticGravity");
	report_strategy("    Verify that no gravity events are received.");
	report_strategy("  else");
	report_strategy("    Verify GravityNotify events received on each repositioned subwindow.");
	report_strategy("    Verify gravity events are received on the parent of each subwindow.");
	report_strategy("  Verify that configure events arrive before gravity events.");

	tpstartup();
	setargs();
	width = NEW_WIDTH;
	height = NEW_HEIGHT;

	for (wgrav = S_wingravity; wgrav < S_wingravity+NS_wingravity; wgrav++) {

		if (wgrav->val == UnmapGravity)
			continue;

		trace("-- Testing win-gravity %s", wgrav->name);

		base = defwin(display);
		bt = buildtree(display, base, Tsub, NTsub);

		topbtp = btntobtp(bt, "top");

		/* Select for all structure events on all windows */
		for (i = 0; i < NTsub; i++) {
			XSelectInput(display, bt[i].wid,
			 	SubstructureNotifyMask|StructureNotifyMask);
		}

		/*
		 * Set the win_gravity on windows below 'top'.  Also set the
		 * borderwidths to make things more interesting, esp on mono
		 * displays.
		 */
		setatts.win_gravity = wgrav->val;
		for (i = 2; i < NTsub; i++) {
			XChangeWindowAttributes(display, bt[i].wid, CWWinGravity, &setatts);
			XSetWindowBorderWidth(display, bt[i].wid, BORDERW);
			XSetWindowBorder(display, bt[i].wid, W_BG);	/* to show up */
		}

		w = topbtp->wid;
		startcall(display);
		if (isdeleted())
			return;
		XResizeWindow(display, w, width, height);
		endcall(display);
		if (geterr() != Success) {
			report("Got %s, Expecting Success", errorname(geterr()));
			FAIL;
		}

		PIXCHECK(display, base);

#ifndef GENERATE_PIXMAPS
		if (wingravevents(display, bt, wgrav->val))
			CHECK;
#endif
	}

	/*
	 * In the GENERATE_PIXMAPS case there will be a path-check error here,
	 * this is intentional. (To prove that wingravevents() is used in
	 * the verification case)
	 */
	CHECKPASS(2*(NS_wingravity-1));	/* -1 for UnmapGravity */
	tpcleanup();
	pfcount(pass, fail);
}

static void t003(){

Window	base;
struct	buildtree	*bt;
struct	buildtree	*topbtp;
struct	buildtree	*btp;
XEvent	ev;
XUnmapEvent	good;
XUnmapEvent	*ump;
XSetWindowAttributes	setatts;
XWindowAttributes	atts;
int 	i;
int 	pass = 0, fail = 0;

 	report_purpose(3);

	report_assertion("Assertion XResizeWindow-3.(A)");
	report_assertion("When a call to XResizeWindow actually changes the size of");
	report_assertion("the window and the win-gravity of a subwindow is");
	report_assertion("UnmapGravity and the subwindow is already mapped, then the");
	report_assertion("subwindow is unmapped without being moved and an UnmapNotify");
	report_assertion("event is generated.");

	report_strategy("Create window with subwindows.");
	report_strategy("Enable events on all subwindows.");
	report_strategy("Enable events on window.");
	report_strategy("Set win-gravity to UnmapGravity.");
	report_strategy("Call XResizeWindow to resize window.");
	report_strategy("Verify windows are removed from screen.");
	report_strategy("Verify window positions are unchanged.");
	report_strategy("Verify that UnmapNotify events received on each subwindow.");
	report_strategy("Verify that UnmapNotify events received on parent of each subwindow.");

	tpstartup();
	setargs();
	/* Set up good unmap event struct */
	good.type = UnmapNotify;
	good.serial = 0L;
	good.send_event = False;
	good.display = display;
	good.from_configure = True;

	width = NEW_WIDTH;
	height = NEW_HEIGHT;

	base = defwin(display);
	bt = buildtree(display, base, Tsub, NTsub);

	topbtp = btntobtp(bt, "top");

	/* Select for all structure events on all windows */
	for (i = 0; i < NTsub; i++) {
		XSelectInput(display, bt[i].wid,
			SubstructureNotifyMask|StructureNotifyMask);
	}

	/*
	 * Set the win_gravity on windows below 'top'.  Also set the
	 * borderwidths to make things more interesting, esp on mono
	 * displays.
	 */
	setatts.win_gravity = UnmapGravity;
	for (i = 2; i < NTsub; i++) {
		XChangeWindowAttributes(display, bt[i].wid, CWWinGravity, &setatts);
		XSetWindowBorderWidth(display, bt[i].wid, BORDERW);
	}

	w = topbtp->wid;
	startcall(display);
	if (isdeleted())
		return;
	XResizeWindow(display, w, width, height);
	endcall(display);
	if (geterr() != Success) {
		report("Got %s, Expecting Success", errorname(geterr()));
		FAIL;
	}

	if (checkarea(display, w, (struct area *)0, W_FG, W_FG, CHECK_ALL))
		CHECK;
	else {
		report("UnmapGravity did not appear to remove subwindows");
		FAIL;
	}

	while (getevent(display, &ev) > 0) {

		if (ev.type != UnmapNotify)
			continue;

		ump = (XUnmapEvent*)&ev;

		btp = btwtobtp(bt, ump->window);
		if (btp == NULL) {
			report("Event received on unknown window");
			FAIL;
			continue;
		}
		trace("Event received for window '%s'", btp->name);

		/*
		 * Work out if this event occurred on the parent or the window.
		 */
		if (ump->window != ump->event) {
			if (!btp->parent || btp->parent->wid != ump->event) {
				report("Event received on other than the parent window");
				FAIL;
			} else
				btp->uflags |= ON_PARENT;
		} else {
			btp->uflags |= ON_WINDOW;
		}

		good.event = ump->event;
		good.window = ump->window;

		if (checkevent((XEvent*)&good, &ev) == 0)
			CHECK;
		else
			FAIL;
	}

	/*
	 * Go through the subwindows below top and check for events received
	 * and map_state and position unchanged.
	 */
	for (i = 2; i < NTsub; i++) {
		if (bt[i].uflags & ON_WINDOW)
			CHECK;
		else {
			report("Unmap event not received on window '%s'", bt[i].name);
			FAIL;
		}
		if (bt[i].uflags & ON_PARENT)
			CHECK;
		else {
			report("Unmap event not received on parent of window '%s'", bt[i].name);
			FAIL;
		}

		XGetWindowAttributes(display, bt[i].wid, &atts);
		if (atts.map_state != IsUnmapped) {
			report("map_state was %s, expecting IsUnmapped",
				mapstatename(atts.map_state));
			FAIL;
		} else
			CHECK;

		if (atts.x != bt[i].x || atts.y != bt[i].y) {
			report("Subwindow was moved after UnmapGravity used");
			FAIL;
		} else
			CHECK;
	}

	CHECKPASS(1+6*(NTsub-2));
	tpcleanup();
	pfcount(pass, fail);
}

static void t004(){

struct	valname	*bitgrav;
Window	base;
XSetWindowAttributes	setatts;
struct	area	area;
extern	struct	valname	S_bitgravity[];
extern	int 	NS_bitgravity;
int 	pass = 0, fail = 0;

 	report_purpose(4);

	report_assertion("Assertion XResizeWindow-4.(A)");
	report_assertion("If the server uses the window's bit-gravity attribute: When");
	report_assertion("a call to XResizeWindow actually changes the size of the");
	report_assertion("window, then the contents of the window are repositioned or");
	report_assertion("discarded according to the bit-gravity attribute. Otherwise:");
	report_assertion("When a call to XResizeWindow actually changes the size of");
	report_assertion("the window, then the contents of the window are discarded.");

	report_strategy("For each value of bit-gravity.");
	report_strategy("  Create window.");
	report_strategy("  Draw into window.");
	report_strategy("  Call XResizeWindow to resize window.");
	report_strategy("  Verify that either:");
	report_strategy("	Window is clear.");
	report_strategy("  else");
	report_strategy("	Contents have been repositioned correctly.");

	tpstartup();
	setargs();

	for (bitgrav = S_bitgravity; bitgrav < S_bitgravity+NS_bitgravity; bitgrav++) {

		trace("-- Trying bitgravity of %s", bitgrav->name);
		setarea(&area, OW_X, OW_Y, OW_WIDTH, OW_HEIGHT);

		base = onewin();
		XSetWindowBackground(display, w, W_BG);
		dset(display, w, W_FG);

		setatts.bit_gravity = bitgrav->val;
		XChangeWindowAttributes(display, w, CWBitGravity, &setatts);

		width = NEW_WIDTH;
		height = NEW_HEIGHT;

		startcall(display);
		if (isdeleted())
			return;
		XResizeWindow(display, w, width, height);
		endcall(display);
		if (geterr() != Success) {
			report("Got %s, Expecting Success", errorname(geterr()));
			FAIL;
		}

		switch (bitgrav->val) {
		case NorthGravity: case CenterGravity: case SouthGravity:
			area.x += (NEW_WIDTH-OW_WIDTH)/2;
			break;
		case NorthEastGravity: case EastGravity: case SouthEastGravity:
			area.x += (NEW_WIDTH-OW_WIDTH);
			break;
		}
		switch (bitgrav->val) {
		case CenterGravity: case WestGravity: case EastGravity:
			area.y += (NEW_HEIGHT-OW_HEIGHT)/2;
			break;
		case SouthGravity: case SouthEastGravity: case SouthWestGravity:
			area.y += (NEW_HEIGHT-OW_HEIGHT);
			break;
		}

		if (checkarea(display, base, (struct area *)0, W_BG, W_BG, CHECK_ALL|CHECK_DIFFER)) {

			/*
			 * The whole base window was clear, the server is not using
			 * bit-gravity, or else we are trying ForgetGravity.
			 */
			if (bitgrav->val != ForgetGravity)
				trace("server not using bit-gravity");
			CHECK;
		} else {
			/*
			 * For ForgetGravity then we must not get here.
			 */
			if (bitgrav->val == ForgetGravity) {
				report("Contents were not discarded with ForgetGravity");
				FAIL;
			} else if (checkarea(display, base, &area, W_FG, W_BG, CHECK_ALL)) {
				CHECK;
			} else {
				report("bits positioned incorrectly for bit-gravity of %s",
					bitgrav->name);
				FAIL;
			}
		}
	}

	CHECKPASS(NS_bitgravity);

	tpcleanup();
	pfcount(pass, fail);
}

static void t005(){

int 	pass = 0, fail = 0;

 	report_purpose(5);

	report_assertion("Assertion XResizeWindow-5.(A)");
	report_assertion("When the window is a root window, then a call to");
	report_assertion("XResizeWindow has no effect.");

	report_strategy("Call XResizeWindow on root window.");
	report_strategy("Touch test only.");

	tpstartup();
	setargs();
	w = DefaultRootWindow(display);
	width = NEW_WIDTH;
	height = NEW_HEIGHT;

	startcall(display);
	if (isdeleted())
		return;
	XResizeWindow(display, w, width, height);
	endcall(display);
	if (geterr() != Success) {
		report("Got %s, Expecting Success", errorname(geterr()));
		FAIL;
	}

	if (fail == 0)
		PASS;
	tpcleanup();
	pfcount(pass, fail);
}

static void t006(){

Window	base;
XConfigureRequestEvent	good;
XSetWindowAttributes	setatts;
Display	*client2;
XEvent	ev;
XImage	*imp;
int 	n;
int 	pass = 0, fail = 0;

 	report_purpose(6);

	report_assertion("Assertion XResizeWindow-6.(A)");
	report_assertion("When the override-redirect attribute of the window is False");
	report_assertion("and some other client has selected SubstructureRedirectMask");
	report_assertion("on the parent window, then a ConfigureRequest event is");
	report_assertion("generated, and the window size is not changed.");

	report_strategy("Create windows.");
	report_strategy("Set override-redirect to False.");
	report_strategy("Create second client.");
	report_strategy("Select SubstructureRedirectMask for second client on parent of window.");
	report_strategy("Call XResizeWindow.");
	report_strategy("Verify that a ConfigureRequest event is generated.");
	report_strategy("Verify that window configuration has not changed on the screen.");

	tpstartup();
	setargs();
	base = onewin();

	setatts.override_redirect = False;
	XChangeWindowAttributes(display, w, CWOverrideRedirect, &setatts);

	client2 = opendisplay();
	XSelectInput(client2, base, SubstructureRedirectMask);
	XSync(client2, False);

	width = NEW_WIDTH;
	height = NEW_HEIGHT;

	good.type = ConfigureRequest;
	good.serial = 0L;
	good.send_event = False;
	good.display = client2;
	good.parent = base;
	good.window = w;
	good.x = OW_X;
	good.y = OW_Y;
	good.width = NEW_WIDTH;
	good.height = NEW_HEIGHT;
	good.border_width = 0;
	good.above = None;
	good.detail = Above;
	good.value_mask = CWWidth | CWHeight;

	imp = savimage(display, base);

	startcall(display);
	if (isdeleted())
		return;
	XResizeWindow(display, w, width, height);
	endcall(display);
	if (geterr() != Success) {
		report("Got %s, Expecting Success", errorname(geterr()));
		FAIL;
	}
	XSync(client2, False);

	n = getevent(client2, &ev);
	if (n != 1) {
		report("Expecting 1 event");
		FAIL;
	} else
		CHECK;

	if (n > 0 && checkevent((XEvent*)&good, &ev) == 0)
		CHECK;
	else
		FAIL;

	if (compsavimage(display, base, imp))
		CHECK;
	else {
		report("Screen contents changed");
		FAIL;
	}

	CHECKPASS(3);

	tpcleanup();
	pfcount(pass, fail);
}

static void t007(){

Window	base;
XResizeRequestEvent	good;
XSetWindowAttributes	setatts;
Display	*client2;
XEvent	ev;
struct	area	area;
int 	n;
int 	pass = 0, fail = 0;

 	report_purpose(7);

	report_assertion("Assertion XResizeWindow-7.(A)");
	report_assertion("When another client has selected ResizeRedirectMask on the");
	report_assertion("window and the size would be changed, then a ResizeRequest");
	report_assertion("event is generated and the size is not changed.");

	report_strategy("Create windows.");
	report_strategy("Set override-redirect to False.");
	report_strategy("Create second client.");
	report_strategy("Select ResizeRedirectMask for second client on window.");
	report_strategy("Set parameters to move and resize window.");
	report_strategy("Call XResizeWindow.");
	report_strategy("Verify that a ResizeRequest event is generated.");
	report_strategy("Verify that window has not changed size but that other changes have occurred.");

	tpstartup();
	setargs();
	base = onewin();

	setatts.override_redirect = False;
	XChangeWindowAttributes(display, w, CWOverrideRedirect, &setatts);

	client2 = opendisplay();
	XSelectInput(client2, w, ResizeRedirectMask);
	XSync(client2, False);

	width = NEW_WIDTH;
	height = NEW_HEIGHT;

	good.type = ResizeRequest;
	good.serial = 0L;
	good.send_event = False;
	good.display = client2;
	good.window = w;
	good.width = NEW_WIDTH;
	good.height = NEW_HEIGHT;

	startcall(display);
	if (isdeleted())
		return;
	XResizeWindow(display, w, width, height);
	endcall(display);
	if (geterr() != Success) {
		report("Got %s, Expecting Success", errorname(geterr()));
		FAIL;
	}
	XSync(client2, False);

	n = getevent(client2, &ev);
	if (n != 1) {
		report("Expecting 1 event");
		report("Received %d", n);
		FAIL;
	} else
		CHECK;

	if (n > 0 && checkevent((XEvent*)&good, &ev) == 0)
		CHECK;
	else
		FAIL;

	/* Window does not change size */
	setarea(&area, OW_X, OW_Y, OW_WIDTH, OW_HEIGHT);
	if (checkarea(display, base, &area, W_FG, W_BG, CHECK_ALL))
		CHECK;
	else {
		report("Size of window not as expected");
		FAIL;
	}

	CHECKPASS(3);

	tpcleanup();
	pfcount(pass, fail);
}

static void t008(){

Window	base;
XConfigureRequestEvent	good;
XSetWindowAttributes	setatts;
Display	*client2;
Display	*client3;
XEvent	ev;
XImage	*imp;
int 	n;
int 	pass = 0, fail = 0;

 	report_purpose(8);

	report_assertion("Assertion XResizeWindow-8.(A)");
	report_assertion("When another client has selected ResizeRedirectMask on the");
	report_assertion("window and another client has selected");
	report_assertion("SubstructureRedirectMask on the parent window and the");
	report_assertion("override-redirect attribute of the window is False, then a");
	report_assertion("ConfigureRequest event is generated, and the window size is");
	report_assertion("not changed.");

	report_strategy("Create windows.");
	report_strategy("Set override-redirect to False.");
	report_strategy("Create second client.");
	report_strategy("Select ResizeRedirectMask for second client on window.");
	report_strategy("Create third client.");
	report_strategy("Select SubstructureRedirectMask for third client on parent of window.");
	report_strategy("Call XResizeWindow.");
	report_strategy("Verify that a ConfigureRequest event is generated for client 3.");
	report_strategy("Verify that no ResizeRequest event is generated for client 2.");
	report_strategy("Verify that window configuration is not changed.");

	tpstartup();
	setargs();
	base = onewin();

	setatts.override_redirect = False;
	XChangeWindowAttributes(display, w, CWOverrideRedirect, &setatts);

	client2 = opendisplay();
	XSelectInput(client2, w, ResizeRedirectMask);
	XSync(client2, False);

	client3 = opendisplay();
	XSelectInput(client3, base, SubstructureRedirectMask);
	XSync(client3, False);

	width = NEW_WIDTH;
	height = NEW_HEIGHT;

	imp = savimage(display, base);

	startcall(display);
	if (isdeleted())
		return;
	XResizeWindow(display, w, width, height);
	endcall(display);
	if (geterr() != Success) {
		report("Got %s, Expecting Success", errorname(geterr()));
		FAIL;
	}
	XSync(client2, False);
	XSync(client3, False);

	n = getevent(client2, &ev);
	if (n != 0) {
		report("Got an event unexpectedly for client selecting ResizeRedirect");
		report("  Event type was %s", eventname(ev.type));
		FAIL;
	} else
		CHECK;

	good.type = ConfigureRequest;
	good.serial = 0L;
	good.send_event = False;
	good.display = client3;
	good.parent = base;
	good.window = w;
	good.x = OW_X;
	good.y = OW_Y;
	good.width = NEW_WIDTH;
	good.height = NEW_HEIGHT;
	good.border_width = 0;
	good.above = None;
	good.detail = Above;
	good.value_mask = CWWidth | CWHeight;

	n = getevent(client3, &ev);
	if (n != 1) {
		report("Expecting one configure events");
		FAIL;
	} else
		CHECK;
	if (n > 0 && checkevent((XEvent*)&good, &ev) == 0)
		CHECK;
	else
		FAIL;

	if (compsavimage(display, base, imp))
		CHECK;
	else {
		report("Window changed when client was selecting SubstructureRedirect");
		FAIL;
	}
	CHECKPASS(4);

	tpcleanup();
	pfcount(pass, fail);
}

static void t009(){

XConfigureEvent	good;
XEvent	ev;
int 	n;
int 	pass = 0, fail = 0;

 	report_purpose(9);

	report_assertion("Assertion XResizeWindow-9.(A)");
	report_assertion("When the size actually changes, then a ConfigureNotify");
	report_assertion("event is generated.");

	report_strategy("Create windows.");
	report_strategy("Enable SubstructureNotify events.");
	report_strategy("Call XResizeWindow such that the window configuration changes.");
	report_strategy("Verify that a ConfigureNotify event is generated.");
	report_strategy("Call XResizeWindow again with the same parameters.");
	report_strategy("Verify that no ConfigureNotify event is generated.");

	tpstartup();
	setargs();
	onewin();

	XSelectInput(display, w, StructureNotifyMask);

	width = NEW_WIDTH;
	height = NEW_HEIGHT;


	startcall(display);
	if (isdeleted())
		return;
	XResizeWindow(display, w, width, height);
	endcall(display);
	if (geterr() != Success) {
		report("Got %s, Expecting Success", errorname(geterr()));
		FAIL;
	}

	good.type = ConfigureNotify;
	good.serial = 0L;
	good.send_event = False;
	good.display = display;
	good.event = w;
	good.window = w;
	good.x = OW_X;
	good.y = OW_Y;
	good.width = NEW_WIDTH;
	good.height = NEW_HEIGHT;
	good.border_width = 0;
	good.above = None;
	good.override_redirect = False;

	n = getevent(display, &ev);
	if (n != 1) {
		report("Expecting 1 event, got %d", n);
		FAIL;
	} else
		CHECK;
	if (n > 0 && checkevent((XEvent*)&good, &ev) == 0)
		CHECK;
	else
		FAIL;

	/* Call again */
	startcall(display);
	if (isdeleted())
		return;
	XResizeWindow(display, w, width, height);
	endcall(display);
	if (geterr() != Success) {
		report("Got %s, Expecting Success", errorname(geterr()));
		FAIL;
	}
	if ((n = XPending(display)) == 0)
		CHECK;
	else {
		report("Received event when configuration was not changed");
		FAIL;
	}

	CHECKPASS(3);

	tpcleanup();
	pfcount(pass, fail);
}

static void t010(){

int 	pass = 0, fail = 0;

 	report_purpose(10);

	report_assertion("Assertion XResizeWindow-10.(A)");
	report_assertion("When a call to XResizeWindow actually changes the size of");
	report_assertion("the window, then Expose events are generated for regions");
	report_assertion("that are newly visible or for which the contents have been");
	report_assertion("lost.");

	report_strategy("Create windows.");
	report_strategy("Set test window background to W_BG.");
	report_strategy("Set up window with setforexpose().");
	report_strategy("Enable expose events.");
	report_strategy("Resize window with XResizeWindow.");
	report_strategy("Verify that correct expose events were received with exposecheck().");

	tpstartup();
	setargs();
	onewin();

	XSetWindowBackground(display, w, W_BG);
	XClearWindow(display, w);
	setforexpose(display, w);

	XSelectInput(display, w, ExposureMask);

	width = NEW_WIDTH;
	height = NEW_HEIGHT;

	startcall(display);
	if (isdeleted())
		return;
	XResizeWindow(display, w, width, height);
	endcall(display);
	if (geterr() != Success) {
		report("Got %s, Expecting Success", errorname(geterr()));
		FAIL;
	}

	if (exposecheck(display, w))
		CHECK;
	else {
		report("Correct expose events not received after resize");
		FAIL;
	}

	CHECKPASS(1);
	tpcleanup();
	pfcount(pass, fail);
}

static void t011(){

Window	base, one , two;
struct	area	area;
Display	*client2;
int 	pass = 0, fail = 0;

 	report_purpose(11);

	report_assertion("Assertion XResizeWindow-11.(A)");
	report_assertion("When a call to XResizeWindow uncovers part of any window");
	report_assertion("that was formerly obscured, then either Expose events are");
	report_assertion("generated or the contents are restored from backing store.");

	report_strategy("Create window.");
	report_strategy("Call setforexpose() on unobscured window.");
	report_strategy("Create second window to partially obscure this window.");
	report_strategy("Create second client to receive events on.");
	report_strategy("Resize window with XResizeWindow, ensuring that first window is now unobscured.");
	report_strategy("Verify for correct expose or backing store behaviour with exposecheck().");

	tpstartup();
	setargs();
/* Create windows. */
	base = defwin(display);

	setarea(&area, OW_X+5, OW_Y+5, OW_WIDTH, OW_HEIGHT);
	one = crechild(display, base, &area);
	setforexpose(display, one);

	setarea(&area, OW_X, OW_Y, OW_WIDTH, OW_HEIGHT);
	two = crechild(display, base, &area);
	
	client2 = opendisplay();
	XSelectInput(client2, one, ExposureMask);
	XSync(client2, False);

	w = two;
	width = 3;
	height = 3;
	startcall(display);
	if (isdeleted())
		return;
	XResizeWindow(display, w, width, height);
	endcall(display);
	if (geterr() != Success) {
		report("Got %s, Expecting Success", errorname(geterr()));
		FAIL;
	}
	XSync(client2, False);

	if (exposecheck(client2, one))
		CHECK;
	else {
		report("Neither Expose events or backing store processing");
		report("  could correctly restore the window contents.");
		FAIL;
	}
	CHECKPASS(1);
	tpcleanup();
	pfcount(pass, fail);
}

static void t012(){

int 	pass = 0, fail = 0;

 	report_purpose(12);

	report_assertion("Assertion XResizeWindow-12.(A)");
	report_assertion("When width or height is zero, then a BadValue error occurs.");

	report_strategy("Create a test window.");
	report_strategy("Call XResizeWindow with width of zero.");
	report_strategy("Verify a BadValue error occurred.");
	report_strategy("Call XResizeWindow with height of zero.");
	report_strategy("Verify a BadValue error occurred.");
	report_strategy("Call XResizeWindow with height and width of zero.");
	report_strategy("Verify a BadValue error occurred.");

	tpstartup();
	setargs();
/* Create a test window. */
	w = defwin(display);

/* Call xname with width of zero. */
	width = 0;
	height =  OW_HEIGHT;
	startcall(display);
	if (isdeleted())
		return;
	XResizeWindow(display, w, width, height);
	endcall(display);
	if (geterr() != BadValue) {
		report("Got %s, Expecting BadValue", errorname(geterr()));
		FAIL;
	}

/* Verify a BadValue error occurred. */
	if (geterr() != BadValue)
		FAIL;
	else
		CHECK;

/* Call xname with height of zero. */
	width = OW_WIDTH;
	height =  0;
	startcall(display);
	if (isdeleted())
		return;
	XResizeWindow(display, w, width, height);
	endcall(display);
	if (geterr() != BadValue) {
		report("Got %s, Expecting BadValue", errorname(geterr()));
		FAIL;
	}

/* Verify a BadValue error occurred. */
	if (geterr() != BadValue)
		FAIL;
	else
		CHECK;

/* Call xname with height and width of zero. */
	width = 0;
	height =  0;
	startcall(display);
	if (isdeleted())
		return;
	XResizeWindow(display, w, width, height);
	endcall(display);
	if (geterr() != BadValue) {
		report("Got %s, Expecting BadValue", errorname(geterr()));
		FAIL;
	}

/* Verify a BadValue error occurred. */
	if (geterr() != BadValue)
		FAIL;
	else
		CHECK;
	CHECKPASS(3);

	tpcleanup();
	pfcount(pass, fail);
}

/* Including from file error/EWin.mc */
/* End of included file error/EWin.mc */

/* Including from file error/EWin.mc */
static void t013(){

int 	pass = 0, fail = 0;

 	report_purpose(13);

	report_assertion("Assertion XResizeWindow-13.(A)");
	report_assertion("When a window argument does not name a valid Window, then a");
	report_assertion("BadWindow error occurs.");

	report_strategy("Create a bad window by creating and destroying a window.");
	report_strategy("Call test function using bad window as the window argument.");
	report_strategy("Verify that a BadWindow error occurs.");

	tpstartup();
	setargs();
	seterrdef();

	A_WINDOW = badwin(A_DISPLAY);

	startcall(display);
	if (isdeleted())
		return;
	XResizeWindow(display, w, width, height);
	endcall(display);
	if (geterr() != BadWindow) {
		report("Got %s, Expecting BadWindow", errorname(geterr()));
		FAIL;
	}

	if (geterr() == BadWindow)
		PASS;
	else
		FAIL;

	tpcleanup();
	pfcount(pass, fail);
}

/* End of included file error/EWin.mc */

/* End of Test Cases */


struct tet_testlist tet_testlist[] = {
	{ t001, 1 },
	{ t002, 2 },
	{ t003, 3 },
	{ t004, 4 },
	{ t005, 5 },
	{ t006, 6 },
	{ t007, 7 },
	{ t008, 8 },
	{ t009, 9 },
	{ t010, 10 },
	{ t011, 11 },
	{ t012, 12 },
	{ t013, 13 },
	{ NULL, 0 }
};

int 	ntests = sizeof(tet_testlist)/sizeof(struct tet_testlist)-1;

void	(*tet_startup)() = startup;
void	(*tet_cleanup)() = cleanup;
