/*
* 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. 1993, 1994, 1995
* Copyright (c) 88open Consortium, Ltd. 1990, 1991, 1992, 1993
* All Rights Reserved.
* 
*/
/*
 * SYNOPSIS:
 *   void
 *   XmbSetWMProperties()
 */


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

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <locale.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
#include <X11/cursorfont.h>
#include <X11/Xresource.h>
#include <X11/Xproto.h>
#include <X11/Xcms.h>
#include <xtestlib.h>
#include <tet_api.h>
#include <r5structs.h>
#include <r5decl.h>
/*error messages created here*/
char	ebuf[4096];

#define T_XmbSetWMProperties	1
char    *TestName = "XmbSetWMProperties";





Display	   *display_good;
Window	window_id_good;

long supplied ;

static XClassHint chints = {
        "Resource",
        "Class",
        } ;

        XClassHint *class_hints = &chints ;

static XWMHints wmhints = {
        AllHints,
        False,
        IconicState,
        12200,
        100,
        10,
        10,
        1200,
        800,
        } ;

XWMHints *wm_hints = &wmhints ;
              
char *window_name_good = "window" ;

char *icon_name_good = "icon" ;
 
static char *argv_good[]={
			"CommandName",
			"This",
			"is", 
			"an", 
			"argument", 
			"list",
                    	"used",
			"to",
			"verify",
			"argument",
			"vector",
			"passing",
			 };	



static int num_args_good = 12;

static XSizeHints sizehints ={

  (PPosition|PSize|PMinSize|PMaxSize|PResizeInc|PAspect|PBaseSize|PWinGravity),  /* flags */
	 90,               /* x */
       	 80,               /* y */
	200,               /* width */
	100,               /* height */
	 10,               /* min_width */
       	 10,               /* min_height */
       1200,               /* max_width */
	800,               /* max_height */
         20,               /* width_inc */
         10,               /* height_inc */
        {5 , 5},           /* min_aspect numerator & denominator */        
	{10, 10},           /* max_aspect numerator & denominator */
        10,                /* base width */
        10,                /* base height */
        NorthWestGravity   /* win gravity */
        };                                                         

	XSizeHints	*hints_good = &sizehints;


char *exec_file_name;
int x_init,
    y_init,
    h_init,
    w_init;


svcmbSetWMProperties(display, window_id, window_name, 
icon_name, argv, num_args, hints, wmh_good, classh_good) 
Display              *display;
Window               window_id;
char                 *window_name;
char                 *icon_name;
char                 **argv;
int                  num_args;
XSizeHints           *hints;
XWMHints		 *wmh_good;
XClassHint		 *classh_good ;
{
        extern int  errcnt;
        extern int  errflg;
        extern int  chkflg;
	extern int  signal_status();
	extern int  unexp_err();
	extern char *strcpy();

	int
		ss_status,		/* save stat return status */	
  		setup_status,
		stat_status;		/* check stat return status */


/*
 * The following definitions are used in the checking code to verify
 * that all the events occur as expected. They are used to
 * index into an array of integers used to tally the occurrances of
 * each event atom of our expected event type.
 */

#define NAME    	0
#define ICON_NAME 	1 
#define WM_HINTS     	2
#define COMMAND	    	3
#define NORMAL_HINTS 	4
#define ONCE		1

static char *window_name_return, *icon_name_return;
static XSizeHints hints_return;
static XWMHints  *wmhints_return;
static XClassHint class_hints_return;
static int NULL_SPOT = 1;
static unsigned char *data = NULL, *dptr;
static Atom actual_type;
static int actual_format, idx, i;
static unsigned long nitems, fitems;
static unsigned long leftover;

	/******
 	* Turn on buffering and buffer parameter information
 	* in case an error occurs
 	******/
	regr_args.l_flags.bufrout = 1;

	/* buffer display struct info for error checking */
	bufrdisp(display);
                                                    
	drawable_id = window_id;

	if (regr_args.iter == 0)   
	    regr_args.iter = 1;	/* set number of iterations to 1.	*/ 

	if (regr_args.l_flags.setup) 
		setup_status = REGR_NORMAL;
	XSync(display_arg, 0);

	if (regr_args.l_flags.chksta  == 1)
		ss_status = save_stat(dpy_msk | win_msk ,
		       gc_id, display_arg, drawable_id);
				

	first_error = 0;	/* no errors encountered yet */

	errflg = 0;
	XSetErrorHandler(signal_status);
	XmbSetWMProperties( display, window_id, window_name, 
		icon_name, argv, num_args, 
		hints, wmh_good, classh_good);
	XSync(display_arg, 0);
	XSetErrorHandler(unexp_err);          
	/* no colormap by default */
	r_wait(display_arg, window_arg, time_delay, None);	
					   
	if (regr_args.l_flags.chksta  == 1) 
		stat_status = chek_stat (dpy_msk | win_msk ,
			 		gc_id, display_arg,
			 		drawable_id, ss_status);
	else                              
		stat_status = REGR_NORMAL;

	if ((!errflg) && (!chkflg)) 
		if ((badstat(display_arg, estatus, Success)) != REGR_NORMAL)
			errflg = 1;

	if ((regr_args.l_flags.check) && 
	    (errflg == 0) && 
	    (stat_status == REGR_NORMAL)) 
	{
		/* 
		 * check that window_name is what we set (if anything)
		 * in service invocation 
		 */
 		(void)XFetchName(display, window_id, &window_name_return);

		check_str("window", window_name_return, "window_name");
                                                                        
		/* check that icon_name is what we set(if anything)in service invocation */
		(void)XGetIconName(display, window_id, &icon_name_return);             
		check_str("icon", icon_name_return, "icon_name");
                                                                           
		wmhints_return =  XGetWMHints(display, window_id);

		/* 
		 * check the icon_pixmap id is what we set (if anything)
		 * in service invocation
   		 * and that the .flags field is set to IconPixmapHint 
		 */
		check_dec((long)AllHints, (long)wmhints_return->flags, 
			  "WMHints .flags field");
                   

		/* check XSetCommand's argv array */

		(void)XGetWindowProperty(display, 	 /* Display */
	 	         window_id, 	 /* Window  */
		         XA_WM_COMMAND,	 /* property atom */
		         0L, 		 /* long offset */
		         (long)BUFSIZ, 	 /* long length */
		         False, 	 /* delete Bool */
		         XA_STRING, 	 /* atom identifier */
	 	         &actual_type,	 /* atom identifier */
	                 &actual_format, /* format of property(8 bits) */
		         &nitems, 	 /* number of 8 bit chars */
		         &leftover, 	 /* bytes remaining on partial read */
                         &data);	 /* pointer to the data is spec format*/

		/* 
		 * check that the command property data returned 
		 * matches all expected criteria 
		 */	

                check_uns (XA_STRING, actual_type, 
			   "command property actual_type=XA_STRING");
                check_dec ((long)8, (long)actual_format, 
			   "command property actual_format");
                check_dec ((long)0, leftover, 
			   "command property leftover bytes");

		/* Get actual length of argv list */
                fitems=0;
                for (i=0; i < num_args; i++) 
			fitems += strlen( argv[i]) + NULL_SPOT;

		/* 
		 * Walk thru the data buffer and verify that the 
		 * argv arguments are intact 
		 */

		dptr = data;
		for(idx = 0, i = 0; *dptr;  i++, dptr = &data[idx])
                {  
			/* do some calc's */
			idx = strlen((char *)dptr) + NULL_SPOT + idx;
                	check_str (argv[i], (char *)dptr, 
				"command property data string");                  
                }
                check_uns (fitems, nitems, "command property data length");
                check_dec ((long)num_args, (long)i, "number of argv strings");
	
		/* 
		 * check the sizehints are what we set (if anything)
		 * in the service invocation 
		 */ 
                    
		XGetWMNormalHints(display, window_id, &hints_return, &supplied);

		check_dec((long)hints->flags, (long)hints_return.flags , "XSizeHints->flags");
		check_dec((long)hints->x, (long)hints_return.x , "XSizeHints->x");
		check_dec((long)hints->y, (long)hints_return.y , "XSizeHints->y");
		check_dec((long)hints->width, (long)hints_return.width , "XSizeHints->width");
		check_dec((long)hints->height, (long)hints_return.height , "XSizeHints->height");
		check_dec((long)hints->min_width, (long)hints_return.min_width , "XSizeHints->min_width");
		check_dec((long)hints->min_height, (long)hints_return.min_height , "XSizeHints->min_height");
		check_dec((long)hints->max_width, (long)hints_return.max_width , "XSizeHints->max_width");
		check_dec((long)hints->max_height, (long)hints_return.max_height , "XSizeHints->max_height");
		check_dec((long)hints->width_inc, (long)hints_return.width_inc , "XSizeHints->width_inc");
		check_dec((long)hints->height_inc, (long)hints_return.height_inc , "XSizeHints->height_inc");
		check_dec((long)hints->min_aspect.x, (long)hints_return.min_aspect.x , "XSizeHints->min_aspect.x");
		check_dec((long)hints->min_aspect.y, (long)hints_return.min_aspect.y , "XSizeHints->min_aspect.y");
		check_dec((long)hints->max_aspect.x, (long)hints_return.max_aspect.x , "XSizeHints->max_aspect.x");
		check_dec((long)hints->max_aspect.y, (long)hints_return.max_aspect.y , "XSizeHints->max_aspect.y");
		check_dec((long)hints->base_width, (long)hints_return.base_width , "XSizeHints->base_width");
		check_dec((long)hints->base_height, (long)hints_return.base_height , "XSizeHints->base_height");
		check_dec((long)hints->win_gravity, (long)hints_return.win_gravity , "XSizeHints->win_gravity");

		check_dec((long)wm_hints->flags, (long)wmhints_return->flags , "XWMHints->flags")
		;
		check_dec((long)wm_hints->input, (long)wmhints_return->input , "XWMHints->input")
		;
		check_dec((long)wm_hints->initial_state, (long)wmhints_return->initial_state , "XWMHints->initial_state");
		check_dec((long)wm_hints->icon_window, (long)wmhints_return->icon_window , "XWMHints->icon_window");
		check_dec((long)wm_hints->icon_x, (long)wmhints_return->icon_x , "XWMHints->icon_x");
		check_dec((long)wm_hints->icon_y, (long)wmhints_return->icon_y , "XWMHints->icon_y");
		check_dec((long)wm_hints->icon_mask, (long)wmhints_return->icon_mask , "XWMHints->icon_mask");
		check_dec((long)wm_hints->window_group, (long)wmhints_return->window_group , "XWMHints->window_group");

		(void)XGetClassHint(display_arg, window_arg, &class_hints_return);

		/* check the class_hints structure */
		check_str(class_hints->res_name, class_hints_return.res_name , "XClassHints->res_name");
		check_str(class_hints->res_class, class_hints_return.res_class , "XClassHints->res_class");


	} /* end of checking code */
                              
	XSync(display_arg, 0);


	/*   Free storage allocated by XGetWindowProperty & XGetWMHints */

	if (regr_args.l_flags.cleanup)
	{
		if (data != NULL)
			XFree ((char *)data);

		if (wmhints_return != NULL)
          		XFree ((char *)wmhints_return);     

		if (class_hints_return.res_name != NULL)
			(void)XFree(class_hints_return.res_name);
		if (class_hints_return.res_class != NULL)
			(void)XFree(class_hints_return.res_class);

		XSync (display, 1);   /* Discard leftover events */
	}
	XSync(display_arg, 0);
	if (errflg) 
	{ 	
		errcnt++;   /* ...increment the error count  */
		tet_result(TET_FAIL);
        }
	/*****
 	* clear all flags
 	*****/
	chkflg = 0;
  	regr_args.l_flags.bufrout = 0;

        dumpbuf();
}



int 	tet_thistest;

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

static void t001(){


 	report_purpose(1);

	report_assertion("Assertion XmbSetWMProperties-1.(C)");
	report_assertion("If the implementation is X11R5 or later: If the value for a");
	report_assertion("window argument does not name a defined window a call to");
	report_assertion("XmbSetWMProperties shall return the BadWindow error code.");
#if XT_X_RELEASE > 4
	display_arg = Dsp;
/*
 * Create a GC to save environmental data in
 */
	gc_save = XCreateGC(display_arg,
		XRootWindow(display_arg,XDefaultScreen(display_arg)),(unsigned long)0,(XGCValues *)0);


	BorderPixel = XBlackPixel(display_arg,XDefaultScreen(display_arg));
	BackgroundPixel = XWhitePixel(display_arg,XDefaultScreen(display_arg));
	colormap_arg = XDefaultColormap(display_arg, XDefaultScreen(display_arg));
	PixPerCM = XDisplayWidth(display_arg, 
		XDefaultScreen(display_arg))*10/XDisplayWidthMM(display_arg,
		XDefaultScreen(display_arg));
	MaxDisplayWidth  = XDisplayWidth(display_arg, XDefaultScreen(display_arg));
	MaxDisplayHeight = XDisplayHeight(display_arg, XDefaultScreen(display_arg));
	DisplayCenterX   = (MaxDisplayWidth / 2) - PixPerCM;
	DisplayCenterY   = (MaxDisplayHeight / 2) - PixPerCM;
	x_init = -1;
	y_init = -1;
	h_init = -1;
	w_init = -1;
          
	if (w_init == -1) w_init = (MaxDisplayWidth - (2 * PixPerCM));
	if (h_init == -1) h_init = (MaxDisplayHeight - (2 * PixPerCM));
	if (x_init == -1) x_init = PixPerCM - 5;
	if (y_init == -1) y_init = PixPerCM - 5;
	if ((window_arg = XCreateSimpleWindow(display_arg, 
	    (Window)XRootWindow(display_arg, XDefaultScreen(display_arg)),
	    x_init, y_init, (unsigned int)w_init, (unsigned int)h_init,    
		BorderWidth, BorderPixel, BackgroundPixel)) == NULL)
	{            
		tet_infoline("ERROR: Window creation failed.");
		tet_infoline("       Check x y w h values in change test");
		tet_result(TET_FAIL);
		return;
	}
	XMapWindow (display_arg, window_arg);
	XSync (display_arg, 0);	
	
	regr_args.l_flags.check = 0;
	regr_args.l_flags.nostat = 0;
	regr_args.l_flags.perf = 0;
	regr_args.l_flags.setup = 0;
	regr_args.l_flags.cleanup = 0;
	regr_args.l_flags.chksta = 0;
	regr_args.l_flags.chkdpy = 0;
	regr_args.l_flags.verbose = 0;
	regr_args.iter = 1;	/* execute service once	*/
	estatus[0] = 1;

        setlocale(LC_ALL, "C") ;
	display_good = display_arg;
	window_id_good = window_arg;

	XSelectInput(display_arg, window_arg, PropertyChangeMask);

	estatus[0] = 1;
	estatus[1] = BadWindow;

	if ((regr_args.l_flags.good == 0) || (estatus[1] == Success)) 
	{
		regr_args.l_flags.setup = 0;
		regr_args.l_flags.cleanup = 0;
		regr_args.l_flags.check = 0;
		regr_args.l_flags.chksta = 1;
		regr_args.l_flags.chkdpy = 0;

		{
		/*
 		* Create and destroy a window to make sure 
		* we have a bad window id or a bad drawable id
 		*/
		Window bad_window;

		tet_infoline("PREP: Create a window.");
		bad_window = XCreateSimpleWindow(display_arg, 
		XRootWindow(display_arg, XDefaultScreen(display_arg)),
		0, 0, (unsigned int)10, (unsigned int)10, (unsigned int)0, 
  		XWhitePixel(display_arg, XDefaultScreen(display_arg)),
		XWhitePixel(display_arg, XDefaultScreen(display_arg)));
		tet_infoline("PREP: Destroy the window.");
		XDestroyWindow(display_arg, bad_window);
		XSync(display_arg, 0);
		tet_infoline("TEST: Catt to XmbSetWMProperties with a non-existant window id returns BadWindow error");
		svcmbSetWMProperties( display_good,
                         bad_window, window_name_good,
                         icon_name_good, argv_good,
                         num_args_good, hints_good,
                         wm_hints, class_hints);
                }
	    } /* end if */
	tet_result(TET_PASS);
#else
	tet_infoline("INFO: Implementation not X11R5 or greater");
	tet_result(TET_UNSUPPORTED);
#endif

}

/* Including from file Mdefcode.tmc.4008 */
/* End of included file Mdefcode.tmc.4008 */

static void t002(){


 	report_purpose(2);

	report_assertion("Assertion XmbSetWMProperties-2.(C)");
	report_assertion("If the implementation is X11R5 or later: A call to");
	report_assertion("XmbSetWMProperties shall set a window's standard window");
	report_assertion("manager properties. If the window_name argument is non-null,");
	report_assertion("it shall set WM_NAME property. If the icon_name argument is");
	report_assertion("non-null, it shall set WM_ICON_NAME property. If the argv");
	report_assertion("argument is non-null, it shall set WM_COMMAND property. If");
	report_assertion("the argc argument is zero, it shall set WM_CLIENT_MACHINE");
	report_assertion("property. If the normal_hints argument in non-null, it shall");
	report_assertion("set WM_NORMAL_HINTS property. If the wm_hints argument is");
	report_assertion("non-null, it shall set WM_HINTS property. If the class_hints");
	report_assertion("argument is non-null, it shall set WM_CLASS property.");
#if XT_X_RELEASE > 4
	display_arg = Dsp;
/*
 * Create a GC to save environmental data in
 */
	gc_save = XCreateGC(display_arg,XRootWindow(display_arg,XDefaultScreen(display_arg)),(unsigned long)0,(XGCValues *)0);


	BorderPixel = XBlackPixel(display_arg,XDefaultScreen(display_arg));
	BackgroundPixel = XWhitePixel(display_arg,XDefaultScreen(display_arg));
	colormap_arg = XDefaultColormap(display_arg, XDefaultScreen(display_arg));
	PixPerCM = XDisplayWidth(display_arg, 
		  XDefaultScreen(display_arg))*10/XDisplayWidthMM(display_arg,
		  XDefaultScreen(display_arg));
	MaxDisplayWidth  = XDisplayWidth(display_arg, XDefaultScreen(display_arg));
	MaxDisplayHeight = XDisplayHeight(display_arg, XDefaultScreen(display_arg));
	DisplayCenterX   = (MaxDisplayWidth / 2) - PixPerCM;
	DisplayCenterY   = (MaxDisplayHeight / 2) - PixPerCM;
	x_init = -1;
	y_init = -1;
	h_init = -1;
	w_init = -1;
          
	tet_infoline("PREP: Create a window.");
	if (w_init == -1) w_init = (MaxDisplayWidth - (2 * PixPerCM));
	if (h_init == -1) h_init = (MaxDisplayHeight - (2 * PixPerCM));
	if (x_init == -1) x_init = PixPerCM - 5;
	if (y_init == -1) y_init = PixPerCM - 5;
	if ((window_arg = XCreateSimpleWindow(display_arg, 
		(Window)XRootWindow(display_arg, XDefaultScreen(display_arg)),
		x_init, y_init,
		(unsigned int)w_init, 
		(unsigned int)h_init,    
		BorderWidth,
		BorderPixel, 
		BackgroundPixel)) == NULL)
	{            
		tet_infoline("ERROR: Window creation failed.");
		tet_infoline("       Check x y w h values in change test");
		tet_result(TET_FAIL);
		return;
	}
	XMapWindow (display_arg, window_arg);
	XSync (display_arg, 0);	
	
	regr_args.l_flags.check = 0;
	regr_args.l_flags.nostat = 0;
	regr_args.l_flags.perf = 0;
	regr_args.l_flags.setup = 0;
	regr_args.l_flags.cleanup = 0;
	regr_args.l_flags.chksta = 0;
	regr_args.l_flags.chkdpy = 0;
	regr_args.l_flags.verbose = 0;
	regr_args.iter = 1;	/* execute service once	*/
	estatus[0] = 1;

        setlocale(LC_ALL, "C") ;
	display_good = display_arg;
	window_id_good = window_arg;

	XSelectInput(display_arg, window_arg, PropertyChangeMask);

	estatus[0] = 1;
	estatus[1] = Success;

	if ((regr_args.l_flags.good == 0) || (estatus[1] == Success)) 
	{
		tet_infoline("TEST: XmbSetWMProperties sets all the specified window properties");
		regr_args.l_flags.setup = 0;
		regr_args.l_flags.cleanup = 1;
		regr_args.l_flags.chkdpy = 0;
		regr_args.l_flags.chksta = 1;
		regr_args.l_flags.check = 1;
		
		{
    		svcmbSetWMProperties(display_good, window_id_good,
	 			window_name_good, icon_name_good,
	 			argv_good, num_args_good, hints_good,
	 			wm_hints, class_hints);

		}
	} /* end if */
	tet_result(TET_PASS);
#else
	tet_infoline("INFO: Implementation not X11R5 or greater");
	tet_result(TET_UNSUPPORTED);
#endif
}

/* Including from file Mdefcode.tmc.4008 */
/* End of included file Mdefcode.tmc.4008 */

/* End of Test Cases */


struct tet_testlist tet_testlist[] = {
	{ t001, 1 },
	{ t002, 2 },
	{ NULL, 0 }
};

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

void	(*tet_startup)() = r5_startup;
void	(*tet_cleanup)() = r5_cleanup;
