Jeremy Winston's  (TA Fall 1997) State Variables for HW2
--------------------------------------------------------

Polygon_list_node *head, *curr, *tail;	/* Ptrs to head, current, tail nodes */

int MainMenu,				/* Menu hierarchy */
     CreateMenu,
     ColorMenu,
      RedMenu,
      BlueMenu,
      GreenMenu;

GLdouble rgbDefault[3] = {0.3,0.3,0.3};	/* Default RGB values for new polys */

int action = NONE,			/* SELECT, CREATE */
    button = NOBUTTON,			/* mouse button pressed */
    width = 500,			/* window width */
    height = 500,			/* window height */
    xOrig,				/* x coord at beginning of drawing */
    yOrig;				/* y coord "      "           "    */


Pseudocode for Jeremy's HW2 Routines
------------------------------------

void createPoly(int value) {

    Polygon_list_node *pn;

    if action is not already CREATE
         /*
          * Allocate memory for a shape:
          */
          pn = (Polygon_list_node *)malloc(sizeof(Polygon_list_node));
          if (pn == NULL) {
                perror("createPoly: cannot malloc() Polygon_list_node\n");
                exit(1);
          }

          listInsertAfter(pn, tail);

          Set curr to pn;

    Set action to CREATE;

   /*
    * Initialize shape:
    */
    Set curr's type to value;
    Set curr's vertex count to ...;
    Set curr's (etc.)
    ...
}

void mainMenu(int value) {

    switch (value)

      case DELETE:

        if curr points to a shape

            if action is CREATE, curr's type is POLY and numVerts > 0

                  Remove the last of curr's vertices;

            else 

                  Remove curr from list;
                  Free curr's memory space;
                  Set curr to point to "none";
                  Set action to SELECT;
                  Set button to "none";

            glutPostRedisplay();

      case QUIT:
        exit;
}

void setColor(int value) {

    if curr doesn't point to a shape

          Set the default color based on value;

    else
          Set curr's color based on value;

          glutPostRedisplay();            /* Calls display() */

}



void display(void) {

    Clear drawing buffer;

    for each shape, p, in the list (from "back" to "front")

            Set GL's current color to p's color;

            Set the MODELVIEW matrix to the Identity matrix;

            Translate to p's center (x,y);

            Rotate by p's rotation angle;

            Draw p;

    Draw a white border around the "frontmost" shape;

    glutSwapBuffers();
}


void keybd(unsigned char key, int x, int y) {

    switch (key)

        case 'D' or 'd':

            mainMenu(DELETE);

            break;

        case 'Q' or 'q':

            exit(0);

        default:
}



Polygon_list_node *whichPoly(double x, double y) {
   /*
    * Return a ptr to the "frontmost" poly which contains the point (x,y)
    */
    for each shape, p, in the list (from "front" to "back")

          if pointInPoly(x, y, p)

                return a pointer to p;

    return NULL;
}


void mouse(int button, int state, int x, int y) {

    y = height - y; /* Question to students: Why do I do this? */

    if action is CREATE
        switch (curr's type) {
          case SQUARE or RECT:
            if state is DOWN			/* Start */
                Set curr's 1st vertex to (x,y);
            else state is UP			/* Finish */
                if curr's type is SQUARE
                    Set curr's 3rd vertex appropriately;
                    Set curr's 2nd & 4th vertices appropriately;
                else curr's type is RECT
                    Set curr's 3rd vertex to (x,y);
                    Set curr's 2nd & 4th vertices appropriately;
                Set curr's center to the average of its vertices;
                Adjust curr's vertices to a local reference frame
                    centered about curr's center;
                Set action to SELECT;
          case POLY:
            if state is DOWN
                if left button was pressed
                    if this is the 1st vertex
                        Set curr's 1st vertex to (x,y)
                        Incr. curr's numVerts;
                else if middle button was pressed
                    if curr has fewer than 3 vertices
                        listRemoveItem(curr);
                        free(curr);
                        curr = NULL;
                        action = SELECT;
                        button = NOBUTTON;
                    else /* Finish POLY */
                        Set curr's last vertex to (x,y);
                        Set curr's center to the avg of its vertices;
                        Adjust curr's vertices to a local reference frame
                            centered about curr's center;
                        Set action to SELECT;
            else state is UP
                if left button was pressed
                    Set curr's last vertex to (x,y);
        }
    else if action is SELECT
        if state is DOWN
            Set curr to whichPoly(x,y);
            if curr points to a shape (i.e., is not NULL)
                Move curr to the "front" of the list;
                Set button;

    glutPostRedisplay();
}

void motion(int x, int y) {

    y = height - y;

    if action is CREATE

        switch (curr's type)

            case SQUARE:

                Set curr's 3rd vertex appropriately;

            case RECT:

                Set curr's 3rd vertex to (x,y);

            case POLY:

                Set curr's last vertex to (x,y);

    else if action is SELECT

        if curr points to a shape

            if left button was pressed

                Translate curr's center appropriately;

            else if middle button was pressed

                Adjust curr's rotation angle appropriately;

    glutPostRedisplay();
}


void reshape(int w, int h) {

    width = w;		/* Question to students: What does this routine do? */
                        /*   What other approaches are there?               */
    height = h;

    glViewport(0, 0, w, h);

    glMatrixMode(GL_PROJECTION);

    glLoadIdentity();

    gluOrtho2D(0.0, width, 0.0, height);

    glMatrixMode(GL_MODELVIEW);

}

