/*****************************************************************************
COLOURDEMO

	AUTHOR:		Renae BATINA

	FILE:		TUTORIALS.DIR/DEMOS.DIR/COLOURDEMO.C

	INSTITUTION:	Curtin University of Technology
			Bentley, Western Australia

	TO COMPILE:	cc -o colourdemo colourdemo.c -lX11

			Must have header file called colourheader.h

	DESCRIPTION:	This program takes a header file which contains
			colours avaliable on the system in use.  It then draws
			all the colours in a grid.  When the mouse button is
			clicked on one of these colours, the name of the
			colour will appear and the position of the colour
			in the header file.
******************************************************************************/

/*
 *	INCLUDE FILES
 */
#include <X11/Xlib.h>
#include <stdio.h>
#include <X11/Xutil.h>
#if 1
#include "colourheader.h"	/* header file for colour */
#else
#include "greyheader.h"		/* header file for grey */
#endif

/*
 *	CONSTANT DECLARATIONS
 */
#define FALSE	0
#define	TRUE	1

#define	INVALID	-1		/* invalid position */
#define BORDER	50		/* width of the border */
#define START   BORDER*2        /* start position away from the boarder */
#define INCR	BORDER          /* how big the shaded grid lines are apart */
#define NUMACROSS 12		/* number of colours across the grid */

#define QUITXPOS BORDER		/* x position of quit box */
#define QUITYPOS BORDER		/* y position of quit box */
#define	QUITWIDTH BORDER+BORDER/2 /* width of the quit box */
#define QUITHEIGHT BORDER/2	/* height of quit box */
#define QUITXSTR BORDER + 10	/* x position of quit string */
#define	QUITYSTR 70		/* y position of quit string */

#define NUMXPOS  290            /* x position where to write array pos */
#define NUMYPOS  75		/* y position of all information */
#define COLXPOS	 340		/* x position of colour name */

/******************************************************************************
		WINDOW  OPENWINDOW
******************************************************************************

DESCRIPTION:	Creates a window with particular attributes and then maps
		this window onto the screen.  In addition to this,
		open_window also creates a graphics context for the window
		which allows the window to be drawn to.

Xlib ROUTINES USED:
	XCreateWindow		Creates a window given particular attributes.
	XDestroyWindow		Unmaps a window and destroys it.
	XFlush			Flushes the buffer.
	XMapWindow		Draws a window to the screen.
	XSetStandardProperties	Sets the minimum set of properties for the
				window manager.

OTHER ROUTINES USED:
	createGC		Function which return a graphics context for
				a window.
******************************************************************************/
Window
OpenWindow(myDisplay,myScreen,myDepth,x, y, width, height, myGC,myWhitePixel,myBlackPixel)
Display         *myDisplay;             /* pointer to the display */
int             myScreen;               /* screen we are using */
int             myDepth;                /* colour plane depth */
int		x, y;			/* coords of top left corner of window */
unsigned int	width, height;		/* dimensions of the window */
GC		*myGC;			/* graphics context for the window */
unsigned long		myWhitePixel;		/* pixel value for white */
unsigned long		myBlackPixel;		/* pixel value for black */

{
int 		border_width = 20;	/* border width of the window */
char		*HEADING = "XColours";
XSetWindowAttributes    myWindowAttributes;     /* structure of window attibutes */
unsigned long           myWindowMask;           /* mask for window attributes */
XSizeHints              theSizeHints;           /* window hints for window manger */
static Window           myWindow;               /* window structure */

/*
 *	SET WINDOW ATTRIBUTES
 */
	/* border colour */
	myWindowAttributes.border_pixel = BlackPixel (myDisplay, myScreen);

	/* background colour */
	myWindowAttributes.background_pixel = WhitePixel (myDisplay, myScreen);

	/* if window manager intervene or not */
	myWindowAttributes.override_redirect = True;

	/* create mask for attributes */
	myWindowMask = CWBackPixel | CWBorderPixel | CWOverrideRedirect;

/*
 *	CREATE THE WINDOW
 */
	myWindow = XCreateWindow (myDisplay, RootWindow (myDisplay, myScreen),
					x, y, width, height, border_width,
					myDepth, InputOutput, CopyFromParent,
					myWindowMask, &myWindowAttributes);

/*
 *	SETUP HINTS FOR WINDOW MANAGER
 */
	theSizeHints.flags      = PPosition | PSize;    /* set mask for the hints */
	theSizeHints.x          = x;                    /* x position */
	theSizeHints.y          = y;                    /* y position */
	theSizeHints.width      = width;                /* width of the window */
	theSizeHints.height     = height;               /* height of the window */

/*
 *	PASS HINTS TO WINDOW MANAGER
 */
	XSetStandardProperties (myDisplay, myWindow, HEADING, HEADING, None,
			NULL, 0, &theSizeHints);
/*
 *	SET GRAPHICS CONTEXT FOR THE WINDOW
 */
	if (CreateGC (myDisplay,myWindow, myGC,myWhitePixel,myBlackPixel) == 0)
	{
		XDestroyWindow(myDisplay, myScreen);
		return ((Window)0);
	}

/*
 *	MAP WINDOW ONTO THE SCREEN
 */
	XMapWindow (myDisplay, myWindow);
	
	XFlush (myDisplay);

	return(myWindow);

}

/*****************************************************************************
		INT  CREATEGC
****************************************************************************

DESCRIPTION:    Creates a graphics context for a given window.  It sets the
		forground colour to black and the background colour to white.
		If a GC cannot be created, then 0 is returned to the calling
		routine, otherwise 1 is returned as well as the GC.

Xlib ROUTINES USED:
	XCreateGC       	Create a new graphics context for a given
				display with the depth of the specified
				window.
	XSetForeground		Sets the forground colour in a graphics
				context.
	XSetBackground		Sets the background colour in a graphics
				context.

OTHER ROUTINES USED:		None

*****************************************************************************/
int
CreateGC (myDisplay,myWindow, myGC,myBlackPixel,myWhitePixel)

/* This function creates a given graphic context for a given window */
Display         *myDisplay;             /* pointer to the display */
Window		myWindow;
GC		*myGC;
unsigned long		myWhitePixel;		/* pixel value for white */
unsigned long		myBlackPixel;		/* pixel value for black */

{
XGCValues	myGCValues;

/*
 *	CREATE THE GRAPHICS CONTEXT
 */
	*myGC = XCreateGC (myDisplay, myWindow,
		   (unsigned long) 0,
		   &myGCValues);

/*
 *	CHECK IF CREATED OK
 */
	if (*myGC == 0)
		return (0);
	else
	/* set forground and background defaults */
	{
		XSetForeground (myDisplay, *myGC, myBlackPixel);
		XSetBackground (myDisplay, *myGC, myWhitePixel);
		return (1);
	}
}
/*****************************************************************************
		VOID  RECTANGLE
******************************************************************************

DESCRIPTION:	Draws a rectangle with its top left corner at position x, y
		and has dimensions of width and height.

		To draw a box, width and height are the same.

Xlib ROUTINES USED:
	XDrawRectangle		Draws an outline of a rectangle.

******************************************************************************/
void
Rectangle (myDisplay,myWindow, myGC, x, y, width, height)
Display         *myDisplay;             /* pointer to the display */
Window		myWindow; 		/* drawable window */
GC		myGC;			/* graphics context for the window */
int		x, y;			/* top left corner of the rectangle */
unsigned int	width, height;		/* dimensions of the rectangle */

{
	XDrawRectangle (myDisplay, myWindow, myGC,
		x, y, width, height);
}

/*****************************************************************************
		VOID  FILLRECTANGLE
*****************************************************************************

DESCRIPTION:	Draws a filled rectangle with its top left corner at postion
		x, y and with dimensions of width and height.

Xlib ROUTINES USED:
	XFillRectangle		Draws a filled rectangle.

*****************************************************************************/
void
FillRectangle (myDisplay,myWindow, myGC, x, y, width, height)
Display         *myDisplay;             /* pointer to the display */
Window          myWindow;		/* drawable window */
GC              myGC;			/* graphics context for the window */
int             x, y;			/* top left corner of the rectangle */
unsigned int    width, height;		/* dimensions of the rectangle */

{
        XFillRectangle (myDisplay, myWindow, myGC,
                x, y, width, height);
}

/******************************************************************************
		VOID  INIT
****************************************************************************

DESCRIPTION:	First of all, this procedure establishes a connection
		between the client and the X server.  It then finds out
		information about the display that the program is running on.
		For example, it determines if the screen is colour or
		monochrome.

Xlib ROUTINES USED:
	BlackPixel		Returns the black pixel value in the default
				colour map
	DefaultColormap		Returns the default colour map for the
				specified screen.
	DefaultScreen		Returns the integer specified by XOpenDisplay.
	WhitePixel		Returns the white pixel value in the default
				colour map
	XDisplayName		Reports the display name.
	XOpenDisplay		Connects a client program with the server.
*******************************************************************************/
void init(myDisplay,myScreen,myDepth,myColourmap,myWhitePixel,myBlackPixel)
Display                 **myDisplay;             /* pointer to the display */
int                     *myScreen;               /* screen we are using */
int                     *myDepth;                /* colour plane depth */
Colormap		*myColourmap;		/* systems default colour map */
unsigned long		*myWhitePixel;		/* pixel value for white */
unsigned long		*myBlackPixel;		/* pixel value for black */
{
/*
 *	MAKE CONNECTION WITH THE SERVER
 */
	*myDisplay = XOpenDisplay ("");
	if (*myDisplay == NULL)
	{
		fprintf (stderr,
			"ERROR: Could not open a connection to X on display %s\n",
		XDisplayName (NULL));
		exit (0);
	}

/*
 *	INFORMATION ABOUT THE SCREEN
 */
	*myScreen = DefaultScreen (*myDisplay);

/*
 *	FINDING THE NUMBER OF COLOUR PLANES AND GET THE DEFAULT COLOUR MAP
 */
	*myDepth 	= DefaultDepth (*myDisplay, *myScreen);
	*myColourmap 	= DefaultColormap (*myDisplay, *myScreen);

/*
 *	GET INFO FOR THE GRAPHICS CONTEXT
 */
	*myWhitePixel = WhitePixel (*myDisplay, *myScreen);
	*myBlackPixel = BlackPixel (*myDisplay, *myScreen);
}

/******************************************************************************
		FONTSTRUCT  *INITFONT
****************************************************************************

DESCRIPTION:    Obtains information about a certian font and then stores
		this information into a font structure for later use.

Xlib ROUTINES USED:
	XLoadQueryFont		Load a font and fill the font structure.
	XSetFont                Set the font into the given graphics context.

******************************************************************************/
XFontStruct *
InitFont (myDisplay,myGC, fontName)
Display                 *myDisplay;             /* pointer to the display */
GC		myGC;			/* gc in which to set the font */
char		fontName[];		/* name of the font to set */

{
XFontStruct	*fontstruct;		/* structure to fill with font info */

/*
 *	LOAD FONT
 */
	fontstruct = XLoadQueryFont (myDisplay, fontName);

/*
 *	IF FONT OK, LOAD INFO INTO THE FONT STRUCTURE
 */
	if (fontstruct != 0)
		XSetFont (myDisplay, myGC, fontstruct->fid);

/*
 *	RETURN THE FONT STUCTURE
 */
	return(fontstruct);
}
/*****************************************************************************
		VOID  INITCOLOURS
*****************************************************************************

DESCRIPTION:	Initializes a series of colours and finds the hardware pixel
		value for them.  This value is stored in an array which can
		be accessed at anytime.  This saves the program time as it
		does not need to continually look up the same colour.

Xlib ROUTINES USED:
	XAllocColor		Allocate a read only colourmap cell with
				the closest hardware supported colour.
	XLookupColor		Get database RGB values and closest hardware
				supported RGB values from the colour name
				specified.

*****************************************************************************/
void
InitColours(myDisplay, myColourmap,myDepth,colourpixels,myWhitePixel,myBlackPixel)
Display                 *myDisplay;             /* pointer to the display */
Colormap		myColourmap;		/* systems default colour map */
int                     myDepth;                /* colour plane depth */
unsigned long   	colourpixels[NUMCOLOURS];/* stores pixel values */
unsigned long		myWhitePixel;		/* pixel value for white */
unsigned long		myBlackPixel;		/* pixel value for black */
{
	int		col,loop;		/* loop counter */
        XColor          hwarecolour;    /* closest rgb colour for the hardware */
        int             status;         /* determines if function ok */

/*
 *	COLOUR SCREEN
 */
	if (myDepth > 1)
	{
 		for (col=0,loop=0; loop<NUMCOLOURS;loop++ )
		{
			/* find a match for the english colour */
			status = XParseColor (myDisplay, myColourmap,
					greynames[loop], 
					&hwarecolour);
			if (status != 0)
			/* allocate colour to colour map */
			{
				status = XAllocColor(myDisplay, myColourmap,
						&hwarecolour);
				if (status != 0)
				{
				/* set array of colours */
					colourpixels[col] = hwarecolour.pixel;
					col++;
				}
				else
				{
#if 0
					colourpixels[col] = myBlackPixel; /**/
					greynames[col] = "Invalid colour";
					col++;
#endif
					fprintf(stderr, "Couldn't allocate %s\n",
							greynames[loop]);
				}
			}
			else
			{
#if 0
				colourpixels[col] = myBlackPixel; /**/
				greynames[col] = "Invalid colour";
				col++;
#endif
				fprintf(stderr, "Couldn't lookup %s\n",
							greynames[loop]);
			}
		}
	}

/*
 *	MONOCHROME SCREEN
 */
	else
	{
		for (loop = 0; loop < NUMCOLOURS-1; loop ++)
		{
			if (strcmp ("white", greynames[loop]) == 0)
				colourpixels[loop] = myWhitePixel;
			else
				colourpixels[loop] = myBlackPixel;
		}
	}
}
/******************************************************************************
		VOID  SETCOLOUR
*****************************************************************************

DESCRIPTION:	Sets the current drawing colour to the one specifed by number.
		Number of the index into the array of the colour lookup
		table.

Xlib ROUTINES USED:
	XSetForeground		Sets the forground colour in the graphics
				context to the one specified.

******************************************************************************/
void
SetColour (myDisplay,myGC, colourpixels,number)

Display                 *myDisplay;             /* pointer to the display */
GC		myGC;			/* the graphics context */
int		number;			/* index into the colour array */
unsigned long   	colourpixels[NUMCOLOURS];/* stores pixel values */

{
	/* check if a valid number was given */
	if ((number >= 0) && (number < NUMCOLOURS))
		/* set the drawing colour */
		XSetForeground (myDisplay, myGC, colourpixels[number]);
}

/*****************************************************************************
		VOID  CALCULATEWHERE
****************************************************************************

DESCRIPTION:	Calculates the square which is the closest to where the
		mouse click was made.

******************************************************************************/
void
CalculateWhere (oldx, oldy, newx, newy )

int             oldx, oldy;             /* position at where mouse is */
int             *newx, *newy;           /* position of closest top corner */

{
int             tmp;           		/* temporary variables */

/*
 *	CALCULATE CLOSEST X COORDINATE
 */

	tmp = BORDER;
	while (tmp <= oldx)
	{
		tmp += INCR;
	}
	*newx = tmp - INCR;

/*
 *	CALCULATE CLOSEST Y COORDINATE
 */

	tmp = BORDER;
	while (tmp <= oldy)
	{
		tmp += INCR;
	}
 	*newy = tmp - INCR;
}

/****************************************************************************
		INT  CALCULATECOLOUR
 ****************************************************************************

   DESCRIPTION:	Determines what colour square the mouse click was made on.

 ****************************************************************************/
int
CalculateColour(x, y)
int 	x, y;
{
int 	tmpx, tmpy, pos;

/*
 *	DONT INCLUDE THE BORDER
 */
	tmpx = x - BORDER; tmpy = y - START;

/*
 *	CALCULATE NUMBER OF INCREMENTS IN FOR X
 */
	if (tmpx != 0)  x = tmpx/INCR;
	else  		x = 0;

/*
 *	CALCULATE NUMBER OF INCREMENTS IN FOR Y
 */
	if (tmpy != 0)  y = tmpy/INCR;
	else   		y = 0;

/*  	DETERMINE POSITION IN ARRAY   */
	pos = NUMACROSS*y + x;

/*
 *	DETERMINE IF VALID
 */
	if (pos >= NUMCOLOURS) pos = INVALID;

	return (pos);
}

/******************************************************************************
		VOID  WRITECOLOURDETAILS
 *****************************************************************************

DESCRIPTION:	Writes to the screen the name of the colour which has been
		selected from the colour chart.  It also writes the position
		in the array the colour is located at.

Xlib ROUTINES USED:
	XDrawImageString	Draws an 8-bit image text characters.

OTHER ROUTINES USED:
	InitFont		Initializes the font with which to display
				the text.
	SetColour		Sets the current drawing colour.

 ******************************************************************************/
void
WriteColourDetails (myDisplay, myWindow,myGC,pos)

Display			*myDisplay;		/* connection to X server */
Window			myWindow;		/* window ID */
GC		myGC;			/* the graphics context */
int		pos;		/* position in the array of colours */

{
XFontStruct		*initfont();    /* function to get the font details */
char			*font = "zapfchancery-mediumitalic.24";
char			*blanks = "                                                  ";
char			*invalid = "Invalid Choice";
char			ch[3];

/*
 *	SET THE DRAWING COLOUR AND THE FONT TYPE
 */
	(void)InitFont (myDisplay,myGC, font);

/*
 *	BLANK OUT THE PREVIOUS COLOUR
 */
	XDrawImageString (myDisplay, myWindow, myGC, NUMXPOS-2, NUMYPOS,
			blanks, strlen(blanks));

/*
 * 	IF A VALID POSITION, WRITE THE NAME AND POSITION OF THE COLOUR
 */
	if (pos != INVALID)
	{
	/* convert the integer position to a character */
		sprintf (ch, "%d", pos);
		XDrawImageString (myDisplay, myWindow, myGC, NUMXPOS, NUMYPOS,
				ch, strlen(ch));
		XDrawImageString (myDisplay, myWindow, myGC, COLXPOS, NUMYPOS,
				greynames[pos], strlen(greynames[pos]));
	}

/*
 *	ELSE, INFORM USER THAT AN INVALID CHOICE WAS MADE
 */
	else
		XDrawImageString (myDisplay, myWindow, myGC, COLXPOS, NUMYPOS,
				invalid, strlen(invalid));
}

/*****************************************************************************
		VOID  DRAWDISPLAY
 *****************************************************************************

DESCRIPTION:	Draws the colour chart in  the window with the appropriate
		title and heading.

Xlib ROUTINES USED:
	XDrawImageString	Draws an 8-bit image text string.
	XFlush			Flush the contents of the buffer.

OTHER ROUTINES USED:
	FillRectangle		Draws a filled rectangle with the current
				colour set.
	InitFont		Sets the font to write with.
	Rectangle		Draws the outline of a rectangle.
	SetColour		Sets the drawing colour.

 ******************************************************************************/
void
DrawDisplay (myDisplay,myWindow, myGC,myWhitePixel,myBlackPixel,colourpixels)

Display		*myDisplay;		/* connection to X server */
Window		myWindow;
GC		myGC;
unsigned long		myWhitePixel;		/* pixel value for white */
unsigned long		myBlackPixel;		/* pixel value for black */
unsigned long   	colourpixels[NUMCOLOURS];/* stores pixel values */

{
int	loop, count;                        /* loop counter */
int	ypost;                              /* y position in the grid */
char	*headingfont	= "times-bold.32";  /* font for the heading */
char	*heading 	= "X COLOURS";      /* heading of the window */
char 	*quitfont 	= "times-bold.17";  /* font for the quit box */
char	*quit 		= "Quit";           /* inside quit box */

/* 	INITIALIZE VARIABLES   */
	ypost = START;
	count = 0;

/*
 *	LOOP TO DRAW ALL THE COLOURS
 */
	for (loop=0; loop<NUMCOLOURS; loop++)
	{
	   SetColour (myDisplay,myGC,colourpixels,loop);
	   FillRectangle (myDisplay,myWindow, myGC, BORDER+count*INCR, ypost, INCR, INCR);

	   if (count == NUMACROSS-1)	 /* start new line */
           {
			count = 0; ypost += INCR;
	   }
	   else
			count++;
	}

/*  	WRITE THE HEADING
 */
	XSetBackground (myDisplay, myGC, myWhitePixel);
	XSetForeground (myDisplay, myGC, myBlackPixel);

	(void) InitFont (myDisplay,myGC, headingfont);
	XDrawImageString (myDisplay, myWindow, myGC, 230, 35,
				heading, strlen(heading));

/*  	DRAW THE QUIT BOX
 */
	Rectangle (myDisplay,myWindow, myGC, QUITXPOS, QUITYPOS, QUITWIDTH, QUITHEIGHT);
	(void)InitFont (myDisplay,myGC, quitfont);
	XDrawImageString (myDisplay, myWindow, myGC, QUITXSTR, QUITYSTR,
			quit, strlen(quit));

/*  	FLUSH THE BUFFER
 */
	XFlush (myDisplay);
}

/***************************************************************************
		INT  INQUITBOX
 ****************************************************************************

  DESCRIPTION:	Determines if the mouse button has been moved into the
		rectangular 'QUIT' box.
 ***************************************************************************/
int
InQuitBox (xpos, ypos)
int	xpos, ypos;          /* current position of the mouse pointer */
{
	if ( (xpos >= QUITXPOS) && (xpos <= QUITWIDTH+QUITXPOS) &&
   	     (ypos >= QUITYPOS) && (ypos <= QUITHEIGHT+QUITYPOS) )
		return (TRUE);	 /* inside the box */
	else
		return (FALSE);	 /* not inside the box */
}

/***************************************************************************
		INT  INGRID
 ****************************************************************************

  DESCRIPTION:	Determines if the mouse button was clicked inside the colour
		grid or in the white space surrounding the colour grid.
 ***************************************************************************/
int InGrid (width,height,xpos, ypos)
int	xpos, ypos;		/* position the mouse button was clicked on */
unsigned int    width, height;          /* dimensions of the window */
{
	if ( (xpos >= BORDER) && (xpos < width-BORDER) &&
   	     (ypos >= START ) && (ypos < height-BORDER) )
		return (TRUE);	 /* inside grid */
	else
		return (FALSE);		 /* in white space */
}
/****************************************************************************
		VOID  POLLEVENTS
 ****************************************************************************

DESCRIPTION:	This procedure loops around until the user indicates to stop.
		On each pass of the loop, if an event has occured, then
		the correct action for that event will be carried out.

		The user finishes the program by placing the mouse pointer
		over the 'Quit' rectangle and presses any of the mouse
		buttons.

		The events that the procedure recognises is any movement of
		the mouse pointer and any button press of the mouse.

		If the mouse is moved and motion is detected, then it is
		determined if the mouse is over the 'Quit' box.  If it is, then
		the quit text enlargens to indicate that it has detected where
		the mouse is.  If it is not inside this box, the text is
		returned to normal size.

		If a mouse button is pressed, then once again, the program
		determines if it was inside the 'Quit' box.  If it is, then
		this indicates that the user wishes to finish.  However, if
		it isn't and it is inside the colour grid, then the colour of
		the square the pointer is in is determined and the colour and
		position written to the screen.  If the pointer is in 'white'
		space, then an error message of 'Invalid Choice' is given.

Xlib ROUTINES USED:
	XDrawImageString	Draws an 8-bit image text character.
	XNextEvent		Gets the next event of any type or window.
	XSelectInput		Sets up the input types to be sent to a window

OTHER ROUTINES USED:
	CalculateColour		Determines the positon number in the array
				the colour selected is.
	CalculateWhere		Determines the position of the mouse pointer
				in relation to the grid of colours.
	InitFont		Initializes the font to use.
	InGrid			Determines if the position selected by the
				mouse button is a valid position in the grid.
	InQuitBox		Function which determines if mouse pointer in
				the quit box or not.
	WriteColourDetails	Writes to the screen in the correct position
				the name of the colour selected and the postion
				number it is in the array.

 *****************************************************************************/
void
PollEvents (myDisplay,myWindow, myGC,width,height)

unsigned int    width, height;          /* dimensions of the window */
Display		*myDisplay;		/* connection to X server */
Window		myWindow;
GC		myGC;
{

int		finished;		/* if user wishes to quit */
XEvent		myEvent;		/* event which has occured */
int		newx, newy;		/* position of mouse pointer */
int		pos;

/* font information */
char		*bigquitfont 	= "times-bold.18";
char		*smallquitfont 	= "times-bold.17";

/*
 * 	SELECT WHICH EVENTS YOU WANT TO WATCH
 */

	XSelectInput (myDisplay, myWindow,
	      ButtonPressMask | KeyPressMask | PointerMotionMask);

	finished = FALSE;			/* initialize loop control */

/*
 * 	START POLLING FOR EVENTS
 */

	while (!finished)
	{

	/* read next event in the queue */
		XNextEvent (myDisplay, &myEvent);

		switch (myEvent.type)
		{
		/* 	 mouse was moved */
		case MotionNotify :
			CalculateWhere (myEvent.xmotion.x, myEvent.xmotion.y,
					&newx, &newy);

			if (InQuitBox(newx, newy))	 /* inside quitbox*/
			{
				(void) InitFont (myDisplay,myGC, bigquitfont);
				XDrawImageString (myDisplay, myWindow,
						  myGC, QUITXSTR, QUITYSTR,
						  "Quit", strlen("Quit"));
			}
			else				 /* not inside quitbox*/
			{
				(void) InitFont (myDisplay,myGC, smallquitfont);
				XDrawImageString (myDisplay, myWindow,
						  myGC, QUITXSTR, QUITYSTR,
						  "Quit", strlen("Quit"));
			}
			break;

		/* 	mouse button was pressed */
		case ButtonPress:
			CalculateWhere (myEvent.xbutton.x, myEvent.xbutton.y,
					&newx, &newy);

			/* user wishes to finish program */
			if (InQuitBox(newx, newy)) finished = TRUE;
			/* determine if valid position on the grid */
			else if (InGrid(width,height,newx, newy))
			{
				pos = CalculateColour(newx, newy);
				WriteColourDetails (myDisplay, myWindow,myGC,pos);
			}
			else			 /* in white space */
			{
				pos = INVALID;
				WriteColourDetails (myDisplay, myWindow,myGC,pos);
			}
			break;
		}
	}
}
/*****************************************************************************
                MAINLINE
 ******************************************************************************/
main (argc, argv)
int argc;
char **argv;
{

/*
 *	DECLARATIIONS
 */

int                     x 	= 250;		/* x top left corner of window */
int                     y 	= 25;		/* y top left corner of window */
unsigned int 		width, height;		/* dimensions of the box */
Display                 *myDisplay;             /* pointer to the display */
int                     myScreen;               /* screen we are using */
int                     myDepth;                /* colour plane depth */
Window                  myWindow;               /* Window to display */
Colormap		myColourmap;		/* systems default colour map */
GC			myGC;
unsigned long		myWhitePixel;		/* pixel value for white */
unsigned long		myBlackPixel;		/* pixel value for black */
unsigned long   	colourpixels[NUMCOLOURS];/* stores pixel values */

/*
 *	SET THE DIMENSIONS OF THE BOX
 */

	width = NUMACROSS*INCR+START;
	height = NUMCOLOURS/NUMACROSS*INCR+2*START;

/*
 * 	INITIALIZE VARIABLES
 */

	init(&myDisplay,&myScreen,&myDepth,&myColourmap,&myWhitePixel,&myBlackPixel);

	InitColours(myDisplay,myColourmap,myDepth,colourpixels,myWhitePixel,myBlackPixel);

/*
 *	OPEN UP A WINDOW
 */

	myWindow = OpenWindow(myDisplay,myScreen,myDepth,x, y, width, height, &myGC,myWhitePixel,myBlackPixel);

/*
 *	DO SOME DRAWING IN COLOUR
 */

	DrawDisplay (myDisplay,myWindow, myGC,myWhitePixel,myBlackPixel,colourpixels);

/*
 *	POLL FOR EVENTS
 */

	PollEvents (myDisplay,myWindow, myGC,width,height);

/*
 *	DRAW VIA FLUSHING THE BUFFERS
 */

	XFlush (myDisplay);

/*
 *	DESTROY ALL WINDOWS
 */

	XDestroyWindow (myDisplay, myWindow);
	XCloseDisplay (myDisplay);

/*
 *	EXIT
 */

	exit (0);

}

/*****************************************************************************
	END OF FILE COLOURDEMO.C
 *****************************************************************************/
