/*

  Program One 
  Bert Nelson
  Copyright 1992 Bert Nelson

  Purpose:  Draw a triangle
            Draw a Rectangle
            Draw a Octagon
	    Draw a Circle
            Draw a Pie Chart with a different sizes of slices 
	    Draw a series of arcs


  Compile Instructions:  cc file.c -lX11 -lm -o file

  Run Instructions:  type 'file' after compiling and click a button
                     on the mouse to draw (or redraw) the figures


   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>

#define PI 3.141592654    /* set up PI defintion */


/* set strings as global */

char hello[] = "Program One - by Bert Nelson";
char tri_str[] = "Triangle";
char rect_str[] = "Rectangle";
char oct_str[] = "Octagon";
char circ_str[] = "Circle";
char sect_str[] = "Sectors";
char arcs_str[] = "Arcs";
Font font;

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

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

	/* set up display and foreground/background */

	mydisplay = XOpenDisplay("");

	myscreen = DefaultScreen (mydisplay);
	mybackground = WhitePixel (mydisplay, myscreen);
	myforeground = BlackPixel (mydisplay, myscreen);

	/* create a window with a width of 630 x 425 */

	myhint.x = 0;
	myhint.y = 0;
	myhint.width = 630;
	myhint.height = 425;
	myhint.flags = PPosition | PSize;
	mywindow = XCreateSimpleWindow (mydisplay,
	    DefaultRootWindow (mydisplay),
	    myhint.x, myhint.y, myhint.width, myhint.height,
	    5, myforeground, mybackground);

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

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

	/* Load a font called 8x16 */

	font = XLoadFont(mydisplay,"8x16");
	XSetFont(mydisplay,mygc,font);


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

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

	/* map window to the screen */

	XMapRaised (mydisplay, mywindow);


	/* Loop through until a q is press when the cursor is in
           the window, which will cause the application to quit */

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


		switch (myevent.type) {

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

				break;


		case MappingNotify:
			XRefreshKeyboardMapping (&myevent);
			break;


	/* When there is a mouse click fire up the graphics subroutines */

		case ButtonPress:

			triangle(mydisplay,mywindow,mygc);
			rect(mydisplay,mywindow,mygc);
			oct(mydisplay,mywindow,mygc);
			circ(mydisplay,mywindow,mygc);
			sectors(mydisplay,mywindow,mygc);
			arcs(mydisplay,mywindow,mygc);
			break;

			/* If a 'q' was pressed while the cursor is within
           the window set done to 1, which causes the loop
           to be broken and the program finishes */


		case KeyPress:
			i = XLookupString (&myevent, text, 10, &mykey, 0);
			if (i == 1 && text[0] == 'q')
				done = 1;
			break;


		} /* switch */


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


	/* Free up and clean up the window created */


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

	exit(0);

} /* main */


/* Draw a Triangle */

triangle(the_display,the_window,the_gc)
Display *the_display;
Drawable the_window;
GC the_gc;

{

	XPoint points[4] ;


	points[0].x = 100;
	points[0].y = 100;
	points[1].x = 50;
	points[1].y = 200;
	points[2].x = 150;
	points[2].y = 200;
	points[3].x = 100;
	points[3].y = 100;

	XDrawLines(the_display,the_window,the_gc,points,4,CoordModeOrigin);

	XDrawImageString(the_display,the_window,the_gc,75,85,
	    tri_str,strlen(tri_str));

}


/* Draw a rectangle */


rect(the_display,the_window,the_gc)
Display *the_display;
Drawable the_window;
GC the_gc;
{

	XDrawRectangle(the_display,the_window,the_gc,225,100,150,100);

	XDrawImageString(the_display,the_window,the_gc,265,85,                
	    rect_str,strlen(rect_str));
}




/* Draw an octagon */


oct(the_display,the_window,the_gc)


Display *the_display;
Drawable the_window;
GC the_gc;

{

	XPoint points[9];

	points[0].x = 516;
	points[0].y = 100;
	points[1].x = 550;
	points[1].y = 133;
	points[2].x = 550;
	points[2].y = 166;
	points[3].x = 516;
	points[3].y = 200;
	points[4].x = 483;
	points[4].y = 200;
	points[5].x = 450;
	points[5].y = 166;
	points[6].x = 450;
	points[6].y = 133;
	points[7].x = 483;
	points[7].y = 100;
	points[8].x = 516;
	points[8].y = 100;


	XDrawLines(the_display,the_window,the_gc,points,9,CoordModeOrigin);

	XDrawImageString(the_display,the_window,the_gc,470,85,
	    oct_str,strlen(oct_str));


}



/* Draw a circle */

circ(the_display,the_window,the_gc)

Display *the_display;
Drawable the_window;
GC the_gc;

{

	XDrawArc(the_display,the_window,the_gc,50,300,100,100,0,360*64);

	XDrawImageString(the_display,the_window,the_gc,75,285,
	    circ_str,strlen(circ_str));


}

/* Draw sectors according to the degrees wanted */

sectors(the_display,the_window,the_gc)

Display *the_display;
Drawable the_window;
GC the_gc;

{

	int i;
	double x;
	double y;
	int degrees[13];
	int degrees2[13];
	XPoint points[2];

	degrees[0] = 0;
	degrees[1] = 20;
	degrees[2] = 25;
	degrees[3] = 85;
	degrees[4] = 90;
	degrees[5] = 175;
	degrees[6] = 180;
	degrees[7] = 215;
	degrees[8] = 220;
	degrees[9] = 295;
	degrees[10] = 300;
	degrees[11] = 355;
	degrees[12] = 0;

	points[0].x = 300;
	points[0].y = 350;



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

	{

	/* convert to radians and find the cos/sin and multiply by 50, which
   will give us the absolute points from the origin */


		x = cos(degrees[i] * (PI/180)) * 50;
		y = sin(degrees[i] * (PI/180)) * 50;


		/* get the sign changed */

		y = -1.0 * y;


		points[1].x = x + 300;
		points[1].y = y + 350;

/* Draw the arc when you only need to, which is every other degree[i] */


		if (i == 0 || (i%2) == 0)
		{
			XDrawArc(the_display,the_window,the_gc,
			    250,300,100,100,degrees[i] * 64,
			    (degrees[i+1] - degrees[i])*64);
		}

	/* Draw the lines from the center to the end points of the arc */


		XDrawLines(the_display,the_window,the_gc,
			points,2,CoordModeOrigin);

	} /* end for loop */


	XDrawImageString(the_display,the_window,the_gc,275,285,sect_str,
	    strlen(sect_str));


}


/* Draw four arcs spanning 180 degrees */


arcs(the_display,the_window,the_gc)

Display *the_display;
Drawable the_window;
GC the_gc;

{

	XDrawArc(the_display,the_window,the_gc,460,350,100,100,0,180*64);

	XDrawArc(the_display,the_window,the_gc,470,360,80,80,0,180*64);

	XDrawArc(the_display,the_window,the_gc,480,370,60,60,0,180*64);

	XDrawArc(the_display,the_window,the_gc,490,380,40,40,0,180*64);

	XDrawImageString(the_display,the_window,the_gc,
	    490,340,arcs_str,strlen(arcs_str)+1);

}
