#include <string.h>
#include <stdio.h>
#include <stdarg.h>

#include <GL/glut.h>

#define initial_width 800
#define initial_height 400

int main_window, sub_window1, sub_window2;

// The following two functions will be active if a key is pressed.
// It will have access to the key value, as well as the position of the
//   cursor (x,y) within the window.  There is a different function for
//   each sub-window.

void key_pressed1(unsigned char key, int x, int y)  // Sub-Window 1
{
 if (isprint(key)) {
    printf("First Subwindow   key: `%c' %d,%d\n", key, x, y);

  } else {
    printf("First Subwindow   key: 0x%x %d,%d\n", key, x, y);
  }
}

void key_pressed2(unsigned char key, int x, int y)  // Sub-Window 2
{
  if (isprint(key)) {
    printf("Second Subwindow   key: `%c' %d,%d\n", key, x, y);

  } else {
    printf("Second Subwindow   key: 0x%x %d,%d\n", key, x, y);
  }
}

// The following two functions relate to Mouse Routines.  The function will
//   have access to which of the three mouse buttons was pressed (0, 1, or 2).
// It will also identify whether that button was pushed DOWN, or let UP.
// The functions will have access to the coordinates (x,y) within the window.

void mouse1(int button, int state, int x, int y)  // Sub-Window 1
{
  printf("WINDOW 1:   button: %d %s %d,%d\n", button, state == GLUT_UP ? "UP" : "down", x, y);
}

void mouse2(int button, int state, int x, int y)  // Sub-Window 2
{
  printf("WINDOW 2:   button: %d %s %d,%d\n", button, state == GLUT_UP ? "UP" : "down", x, y);
}


// This routine deals with writing raster graphics to the screen.

void bitmap_output(int x, int y, int z, char *string, void *font)
{
  int len, i;

  glRasterPos3f(x, y, 0);
  len = (int) strlen(string);
  for (i = 0; i < len; i++) {
    glutBitmapCharacter(font, string[i]);
  }
}


// Draws a graph of a simple line.

DrawGraph()
{
  float x;
  glBegin(GL_POINTS);  			// Start drawing points
    glColor3f(0.0,0.0,0.0);		// Set drawing color to black
    for (x=-0.9; x<0.9; x+=0.01) 	// Step through x values
     {glVertex3f(x,x,0.0);		// Put a point at (x,x)
     }
  glEnd();
} 

// Draws a set of labeled axes

DrawAxes()
{
  glBegin(GL_LINES);
    glColor3f(1.0, 1.0, 0.0);
    glVertex3f(-0.9,0.0, 0.0);
    glVertex3f(0.9, 0.0, 0.0);
    glVertex3f(0.0, -0.9,0.0);
    glVertex3f(0.0, 0.9, 0.0);
  glEnd();
  glPushMatrix();
    glTranslatef(0.05, 0.85, 0);
    bitmap_output(0,0,0, "y", GLUT_BITMAP_TIMES_ROMAN_24);
  glPopMatrix();

  glPushMatrix();
    glTranslatef(0.8, -0.1, 0);
    bitmap_output(0,0,0, "x", GLUT_BITMAP_TIMES_ROMAN_24);
  glPopMatrix();
 
}

//Draws some titles on the screen in available Times Roman fonts

void DrawTitles()
{
  glColor3f(0.0, 0.0, 0.0);
  glPushMatrix();
  glTranslatef(-0.9, 0.8, 0);
  bitmap_output(0,0,0, "Example #1", GLUT_BITMAP_TIMES_ROMAN_24);
  glPopMatrix();

  glPushMatrix();
  glTranslatef(-0.5, -0.95, 0);
  bitmap_output(0,0,0, "The above graph is for the linear equation   y = x", 
                GLUT_BITMAP_TIMES_ROMAN_10);
  glPopMatrix();
} 
  
// Inner display window 

void display1(void)
{
  glClear(GL_COLOR_BUFFER_BIT);
  glFlush();
  DrawAxes();
  DrawGraph();
  DrawTitles();
}
  				
void display2(void)
{
glPixelZoom(0.5,0.5);
display1();
}

// Main display loop

void display(void)
{
  glClear(GL_COLOR_BUFFER_BIT);
  glFlush();
}


// 
void reshape(int w, int h)
{
  int width = initial_width;
  int height = initial_height;
  glViewport(0, 0, w, h);


  // Give border, and take care of tiny image problems

  if (w > 50) {
      width = w - 30 ; // maximum width would be three gaps wide
      } 
  else {
      width = 20;
      }
  if (h > 50) {
      height = h - 20; // height would remain two gaps wide
      } 
  else {
      height = 20;
      }

  glutSetWindow(sub_window1);          // Stuff for window #1
  glutPositionWindow(10,10);
  glutReshapeWindow(width/2, height);

 // glOrtho sets "clipping planes" for the viewing volume
 // Those planes are (left, right, top, bottom, front, back)

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho( -1.0, 1.0, -1.0, 1.0, -1.0, 1.0 ); // The default is 1.0
  glMatrixMode(GL_MODELVIEW);


  glutSetWindow(sub_window2);	      // Stuff for window #2
  glutPositionWindow(width/2 + 20,10);
  glutReshapeWindow(width/2, height);
  glMatrixMode(GL_PROJECTION);

  glLoadIdentity();  // Identity matrix is needed to keep recalls to
                     // the reshape routine from shrinking the image.

// THis will establish a drawing volume that ranges from -3 to +3 in both
// the x-direction and y-direction

  glOrtho( -3.0, 3.0, -3.0, 3.0, -1.0, 1.0 ); // "Shrinks" image
  glMatrixMode(GL_MODELVIEW);
}

int main(int argc, char **argv)
{ float r,g,b = 0.0;
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGB);
  glutInitWindowSize(initial_width, initial_height);
  main_window = glutCreateWindow("My First Window ");
  glutDisplayFunc(display);
  glutReshapeFunc(reshape);
  glClearColor(1.0, 1.0, 1.0, 1.0);

  // Create First subwindow

  sub_window1 = glutCreateSubWindow(main_window, 10, 10, 
                                  initial_width, initial_height);
  glutDisplayFunc(display1);
  r = 1.0;
  glClearColor(r, 0.0, 0.0, 1.0);  // Background is red
  glutKeyboardFunc(key_pressed1);  // Points to first keyboard function
  glutMouseFunc(mouse1);           // Points to first mouse function

  // First subwindow definition ends here


  // Create second subwindow

  sub_window2 = glutCreateSubWindow(main_window, 10, 10, 
                                   initial_width, initial_height);
  glutDisplayFunc(display2);
  b = 1.0;
  glClearColor(0.0, 0.0, b, 1.0);  // Background is blue
  glutKeyboardFunc(key_pressed2);  // Points to second keyboard function
  glutMouseFunc(mouse2);           // Points to second mouse function

  // Second subwindow definition ends here
  glutMainLoop();
  return 0;             /* ANSI C requires main to return int. */
}

