/* Program 3 -- Draw four graphs 
   Bert Nelson                  
   Copyright 1992 Bert Nelson

   Graph One   -- Line Graphs 
   Graph Two   -- bar graphs     
   Graph Three -- pie chart      
   Graph Four  -- sin/cos        

   Instructions:
   Press the key '1' to see Graph One
   Press the key '2' to see Graph Two
   Press the key '3' to see Graph Three
   Press the key '4' to see Graph Four

   Press the letter 'q' to quit the program


   Permission to use, copy, modify, and distribute this software and its
   documentation for any purpose and without fee is hereby granted,
   provided that the above copyright notice appear in all copies and that
   both that copyright notice and this permission notice appear in
   supporting documentation.  It is provided "as is" without any express or
   implied warranty.

   Bert Nelson DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
   Bert Nelson BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
   ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
   WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
   ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
   SOFTWARE.


*/


#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <math.h>


/* set up defines */


#define PI 3.141592654

char name[] = "Program Three - by Bert Nelson";
Font font;
static char *ncolors[9] = { 
	" ", "blue","red","green4",
	"magenta1","brown","chocolate",
	"gold1","DarkOrchid4"};

unsigned long fore,back;

Colormap color_map;
XColor colors[8];
XColor exact_colors[8];



main(argc,argv)
int argc;
char **argv;
{
	Display *mydisplay;
	Window  mywindow,child1,child2,child3,child4;
	GC mygc;
	XEvent myevent;
	KeySym mykey;
	XSizeHints myhint;

	int myscreen;
	unsigned long myforeground, mybackground;
	int i;
	char text[10];
	int done;

	/* open up a display and get the default screen */


	mydisplay = XOpenDisplay("");

	myscreen = DefaultScreen (mydisplay);


	/* extract black and white colors from color map */

	back = mybackground = WhitePixel (mydisplay, myscreen);
	fore = myforeground = BlackPixel (mydisplay, myscreen);


	/* set up attributes for the window */

	myhint.x = 0;
	myhint.y = 0;
	myhint.width =  1005;
	myhint.height = 705;
	myhint.flags = PPosition | PSize;

	/* create a basic generic window with the above attributes */


	mywindow = XCreateSimpleWindow (mydisplay,
	    DefaultRootWindow (mydisplay),
	    myhint.x, myhint.y, myhint.width, myhint.height,
	    2, myforeground, mybackground);

	child1 = XCreateSimpleWindow (mydisplay,
            mywindow,
            0, 0, 500, 350,
            2, myforeground, mybackground);

        child2 = XCreateSimpleWindow (mydisplay,
            mywindow,
            500, 0, 498, 350, 
            2, myforeground, mybackground);
 
        child3 = XCreateSimpleWindow (mydisplay,
            mywindow,
            0, 350, 500, 350,
            2, myforeground, mybackground);
 
        child4 = XCreateSimpleWindow (mydisplay,
            mywindow,
            500, 350, 498, 350,
            2, myforeground, mybackground);
 
	

	/* Set up the title of the window and set up   
	   background and foreground colors */


	XSetStandardProperties (mydisplay, mywindow, name, name,
	    None, argv, argc, &myhint);

	mygc = XCreateGC (mydisplay, mywindow, 0, 0);


	XSetBackground (mydisplay, mygc, mybackground);
	XSetForeground (mydisplay, mygc, myforeground);


	/* ask for input from the keyboard */

	XSelectInput (mydisplay, mywindow,
	    ButtonPressMask | KeyPressMask | ExposureMask);


	/* Map the window the the screen */


	XMapRaised (mydisplay, mywindow);

	XMapRaised  (mydisplay,child1);

        XMapRaised  (mydisplay,child2);
        XMapRaised  (mydisplay,child3);
        XMapRaised  (mydisplay,child4);



	/* set up named colors, so they can be easily used */

	color_set_up(mydisplay);

	/* This loop drives the program */


	done = 0;


	while (done == 0)
	{
		XNextEvent (mydisplay, &myevent );
		switch (myevent.type)

		{

		case Expose:
			if (myevent.xexpose.count == 0)
				break;

		case MappingNotify:
			XRefreshKeyboardMapping (&myevent);
			break;

			/* if a key is pressed then branch to the
	                   corresponding subroutine */

		case KeyPress:
		case ButtonPress:

			i = XLookupString (&myevent, text, 10, &mykey, 0);

			if (i == 1)
			{
				switch(text[0])
				{
				case '1' :
					line_graph(mydisplay,child1,mygc);
					break;

				case '2' :
					bar_graph(mydisplay,child2,mygc);
					break;


				case '3' :

					pie_graph(mydisplay,child3,mygc);
					break;

				case '4' :

					sin_cos(mydisplay,child4,mygc);
					break;

				case 'q' :

					done = 1;
					break;




				} /* switch text */



			}  /* if i */


		} /* switch */


	} /* while (done == 0) */

	/* Free up all the resources and shutdown gracefully */

	XFreeGC (mydisplay, mygc);
	XDestroyWindow (mydisplay, mywindow);
	XCloseDisplay (mydisplay);

	exit(0);

} /* end main */



/* Draw a line graph */


line_graph(the_display,the_window,the_gc)

Display *the_display;
Window the_window;
GC the_gc;

{

	XPoint male_line[5];
	XPoint female_line[5];
	XPoint total_line[5];


	total_line[0].x = 110;
	total_line[0].y = 229;
	total_line[1].x = 184;
	total_line[1].y = 198;
	total_line[2].x = 257;
	total_line[2].y = 166;
	total_line[3].x = 330;
	total_line[3].y = 96;
	total_line[4].x = 396;
	total_line[4].y = 25;

	male_line[0].x = 110;
	male_line[0].y = 253;
	male_line[1].x = 184;
	male_line[1].y = 237;
	male_line[2].x = 257;
	male_line[2].y = 214;
	male_line[3].x = 330;
	male_line[3].y = 206;
	male_line[4].x = 396;
	male_line[4].y = 182;


	female_line[0].x = 110;
	female_line[0].y = 278;
	female_line[1].x = 184;
	female_line[1].y = 261;
	female_line[2].x = 257;
	female_line[2].y = 214;
	female_line[3].x = 330;
	female_line[3].y = 164;
	female_line[4].x = 396;
	female_line[4].y = 148;

	/* Draw X and Y axis */

	XDrawLine(the_display,the_window,the_gc,45,20,45,326);

	XDrawLine(the_display,the_window,the_gc,20,300,420,300);

	XDrawLine(the_display,the_window,the_gc,41,25,49,25);

	/* Draw lines through the x axis */

	XDrawLine(the_display,the_window,the_gc,110,295,110,305);

	XDrawLine(the_display,the_window,the_gc,184,295,184,305);

	XDrawLine(the_display,the_window,the_gc,257,295,257,305);

	XDrawLine(the_display,the_window,the_gc,330,295,330,305);

	XDrawLine(the_display,the_window,the_gc,396,295,396,305);


	/* Change color for the line */

	XSetForeground(the_display,the_gc,colors[8].pixel);


	/* Draw the total line */

	XSetLineAttributes(the_display,the_gc,1,LineSolid,
	    CapRound,JoinRound);

	XDrawLine(the_display,the_window,the_gc,60,75,90,75);

	XDrawImageString(the_display,the_window,the_gc,95,75,
	    "Total",strlen("Total"));

	XDrawLines(the_display,the_window,the_gc,total_line,5,
	    CoordModeOrigin);



	/* Change the color */

	XSetForeground(the_display,the_gc,colors[2].pixel);

	/* Draw the male line */

	XSetLineAttributes(the_display,the_gc,LineOnOffDash,
	    CapRound,JoinRound);

	XDrawLine(the_display,the_window,the_gc,60,35,90,35);

	XDrawImageString(the_display,the_window,the_gc,95,35,
	    "Male",strlen("Male"));

	XDrawLines(the_display,the_window,the_gc,male_line,5,
	    CoordModeOrigin);




	/* Change the color */

	XSetForeground(the_display,the_gc,colors[1].pixel);

	/* Draw the female line */

	XSetLineAttributes(the_display,the_gc,LineDoubleDash,
	    CapRound,JoinRound);

	XDrawLine(the_display,the_window,the_gc,60,55,90,55);

	XDrawImageString(the_display,the_window,the_gc,95,55,
	    "Female",strlen("Female"));

	XDrawLines(the_display,the_window,the_gc,female_line,5,
	    CoordModeOrigin);

	reset_colors(the_display,the_gc);



	/* Draw graph title, source and numbers */

	XDrawImageString(the_display,the_window,the_gc,
	    11,28,"4730",strlen("4730"));

	XDrawImageString(the_display,the_window,the_gc,
	    60,15,"Two Year College Enrollments (in thousands)",
	    strlen("Two Year College Enrollments (in thousands)"));


	XDrawImageString(the_display,the_window,the_gc,
	    11,345,"Source: Statistical Abstract of the United States",
	    strlen("Source: Statistical Abstract of the United States"));

	XDrawImageString(the_display,the_window,the_gc,
	    105,320,"65 ",3);

	XDrawImageString(the_display,the_window,the_gc,
	    179,320,"70 ",3);

	XDrawImageString(the_display,the_window,the_gc,
	    252,320,"75 ",3);

	XDrawImageString(the_display,the_window,the_gc,
	    325,320,"80 ",3);

	XDrawImageString(the_display,the_window,the_gc,
	    391,320,"85 ",3);


	XSetLineAttributes(the_display,the_gc,1,LineSolid,
	    CapRound,JoinRound);


}


/* draw the pie graph with a legend */


pie_graph(the_display,the_window,the_gc)

Display *the_display;
Drawable the_window;
GC the_gc;

{

	int i;
	int index=0;
	int degrees[13];

	degrees[0] = 0;
	degrees[1] = 25;
	degrees[2] = 25;
	degrees[3] = 65;
	degrees[4] = 65;
	degrees[4] = 120;
	degrees[5] = 120;
	degrees[6] = 192;
	degrees[7] = 192;
	degrees[8] = 360;
	degrees[9] = 0;


	for( i=0; i<9; i++)

	{



		if (degrees[i] != degrees[i+1] )

		{
			index++;

			if (index == 6)
				break;

			XSetForeground(the_display,the_gc,colors[index].pixel);

			XFillArc(the_display,the_window,the_gc,
			    	75,50,200,200,degrees[i] * 64, 
				(degrees[i+1] - degrees[i])*64);

			display_legend(the_display,the_window,the_gc,index);

		} /* end if */




	} /* end for loop */

	reset_colors(the_display,the_gc);

	/* Display title and credit */



	XDrawImageString(the_display,the_window,the_gc,
	    	50,30,
		"Computer Use Among Elementary and Secondary School Students",
		59);

	XDrawImageString(the_display,the_window,the_gc,
	    	40,315,
	    	"Source: The Second National U.S. School Uses of Microcomputers Survey",69);


}





/* display the legend for the pie chart one at time */

display_legend(the_display,the_window,the_gc,idx)

Display *the_display;
Window the_window;
GC the_gc;
int idx;
{

        /* display the legend one line at a time */
  

	if (idx == 5)

	{



		XFillRectangle(the_display,the_window,the_gc,
		    325,120,13,13);

		reset_colors(the_display,the_gc);

		XDrawImageString(the_display,the_window,the_gc,
		    168,185,"47%",3);


		XDrawImageString(the_display,the_window,the_gc,
		    345,130,"Instruction",11);

	}


	if (idx == 4)


	{
		XFillRectangle(the_display,the_window,the_gc,
		    325,140,13,13);

		reset_colors(the_display,the_gc);

		XDrawImageString(the_display,the_window,the_gc,
		    100,120,"20%",3);

		XDrawImageString(the_display,the_window,the_gc,
		    345,150,"Programming",11);
	}



	if (idx == 3)

	{

		XFillRectangle(the_display,the_window,the_gc,
		    325,160,13,13);

		reset_colors(the_display,the_gc);

		XDrawImageString(the_display,the_window,the_gc,
		    165,75,"15%",3);


		XDrawImageString(the_display,the_window,the_gc,
		    345,170,"Problem Solving",15);

	}


	if (idx == 2)

	{
		XFillRectangle(the_display,the_window,the_gc,
		    325,180,13,13);

		reset_colors(the_display,the_gc);

		XDrawImageString(the_display,the_window,the_gc,
		    220,95,"11%",3);

		XDrawImageString(the_display,the_window,the_gc,
		    345,190,"Word Processing",15);
	}



	if (idx == 1)


	{
		XFillRectangle(the_display,the_window,the_gc,
		    325,200,13,13);

		reset_colors(the_display,the_gc);

		XDrawImageString(the_display,the_window,the_gc,
		    240,135,"7%",2);

		XDrawImageString(the_display,the_window,the_gc,
		    345,210,"Other",5);

	}


}




/* get color values of named colors  */

color_set_up(the_display)

Display *the_display;

{

	int i;

	color_map = DefaultColormap(the_display,0);

	/* get the colors from the color map for the colors named */ 

	for (i=1; i<9; i++)
	{

		XAllocNamedColor(the_display,color_map,ncolors[i],
			&exact_colors[i],&colors[i]);

	}

}


/* change foreground color back to black */

reset_colors(display,gc)

Display *display;
GC gc;


{
	XSetForeground(display,gc,fore);
}


/* draw a bar graph of college population based on sex */


bar_graph(the_display,the_window,the_gc)

Display *the_display;
Window the_window;
GC the_gc;

{

	int xoff;

	/* Draw x and y axis */

	XDrawLine(the_display,the_window,the_gc,   
	    45,20,45,330);

	XDrawLine(the_display,the_window,the_gc,
	    20,300,480,300);

	XDrawLine(the_display,the_window,the_gc,
	    41,50,49,50);


	/* Draw rectangles and alternate the foreground colors */

	xoff = 26;

	XSetForeground(the_display,the_gc,colors[2].pixel);

	XFillRectangle(the_display,the_window,the_gc,
	    xoff*3,250,xoff,50);


	XSetForeground(the_display,the_gc,colors[1].pixel);

	XFillRectangle(the_display,the_window,the_gc,
	    xoff*4,275,xoff,25);


	XSetForeground(the_display,the_gc,colors[2].pixel);

	XFillRectangle(the_display,the_window,the_gc,
	    xoff*6,205,xoff,95);


	XSetForeground(the_display,the_gc,colors[1].pixel);

	XFillRectangle(the_display,the_window,the_gc,
	    xoff*7,225,xoff,75);


	XSetForeground(the_display,the_gc,colors[2].pixel);

	XFillRectangle(the_display,the_window,the_gc,
	    xoff*9,155,xoff,145);


	XSetForeground(the_display,the_gc,colors[1].pixel);

	XFillRectangle(the_display,the_window,the_gc,
	    xoff*10,180,xoff,120);


	XSetForeground(the_display,the_gc,colors[2].pixel);

	XFillRectangle(the_display,the_window,the_gc,
	    xoff*12,105,xoff,195);


	XSetForeground(the_display,the_gc,colors[1].pixel);

	XFillRectangle(the_display,the_window,the_gc,
	    xoff*13,60,xoff,240);


	XSetForeground(the_display,the_gc,colors[2].pixel);

	XFillRectangle(the_display,the_window,the_gc,
	    xoff*15,75,xoff,225);


	XSetForeground(the_display,the_gc,colors[1].pixel);

	XFillRectangle(the_display,the_window,the_gc,
	    xoff*16,50,xoff,250);


	/* draw legend */

	XSetForeground(the_display,the_gc,colors[2].pixel);

	XFillRectangle(the_display,the_window,the_gc,
	    xoff*3,30,xoff+5,10);


	XSetForeground(the_display,the_gc,colors[1].pixel);

	XFillRectangle(the_display,the_window,the_gc,
	    xoff*3,50,xoff+5,10);


	reset_colors(the_display,the_gc);


	XDrawImageString(the_display,the_window,the_gc,
	    xoff*4+15,37,"Male",4);

	XDrawImageString(the_display,the_window,the_gc,
	    xoff*4+15,58,"Female",6);



	XDrawImageString(the_display,the_window,the_gc,
	    10,58,"2507",4);

	XDrawImageString(the_display,the_window,the_gc,
	    xoff*2,13,"Two-Year College Enrollments (in thousands)",
	    43);


	/* Display years and source along the bottom */


	XDrawImageString(the_display,the_window,the_gc,
	    xoff-5,345,"Source: Statistical Abstract of the United States",
	    49);

	XDrawImageString(the_display,the_window,the_gc,
	    xoff*4-12,315,"1965",4);

	XDrawImageString(the_display,the_window,the_gc,
	    xoff*6+13,315,"1970",4);

	XDrawImageString(the_display,the_window,the_gc,
	    xoff*9+13,315,"1975",4);

	XDrawImageString(the_display,the_window,the_gc,
	    xoff*12+13,315,"1980",4);

	XDrawImageString(the_display,the_window,the_gc,
	    xoff*15+14,315,"1985",4);


}

/* draw a sine and cosine wave from -2 PI to +2 PI */

sin_cos(the_display,the_window,the_gc)

Display *the_display;
Window the_window;
GC the_gc;

{
	int idx;
	float i;
	int cosx,cosy,x1,y1;
	float x = 0;
	float tempx;
	float tempy;
	int y = 0;
	int xoff = 254;
	int yoff = 200;


	/* draw x and y axis */


	XDrawLine(the_display,the_window,the_gc,80,200,430,200);

	XDrawLine(the_display,the_window,the_gc,254,150,254,250);


	XDrawLine(the_display,the_window,the_gc,102,194,102,206);

	XDrawLine(the_display,the_window,the_gc,179,194,179,206);


	XDrawLine(the_display,the_window,the_gc,330,194,330,206);

	XDrawLine(the_display,the_window,the_gc,404,194,404,206);


	XDrawImageString(the_display,the_window,the_gc,95,215,
	    "x axis",6);

	XDrawImageString(the_display,the_window,the_gc,260,245,
	    "y axis",6);

	XDrawImageString(the_display,the_window,the_gc,125,158,
	    "sin(x)",6);

	XDrawImageString(the_display,the_window,the_gc,153,250,
	    "cos(x)",6);

	for (i = -2*PI; i<2*PI; i= i + PI/100)

	{

		/* calculate sine points */

		x = i ;
		y = yoff - sin(x) * 35 ;

		x1 = x * 24 + xoff;
		y1 =  y;


		/* calculate cosine points */

		tempx = i;
		tempy = yoff - cos(x) * 35 ;

		cosx = tempx * 24 + xoff;
		cosy = tempy;

		/* plot sine wave */

		XSetForeground(the_display,the_gc,colors[1].pixel);

		XDrawPoint(the_display,the_window,the_gc,x1,y1);

		/* plot cosine wave */

		XSetForeground(the_display,the_gc,colors[2].pixel);

		XDrawPoint(the_display,the_window,the_gc,cosx,cosy);


	}

	reset_colors(the_display,the_gc);

}
