home *** CD-ROM | disk | FTP | other *** search
- /* PROJ1.C
- *
- * Scott R. Houck
- * Written in Turbo C 2.0
- *
- * Add egavga.bgi to graphics.lib. Then compile with:
- *
- * tcc proj1 graphics.lib
- *
- * This is a simple interactive graphics program. Two symbols exist:
- * a square and a triangle. Operations are:
- *
- * create a symbol
- * rotate a symbol
- * move a symbol
- * delete a symbol
- * delete all symbols
- * print data structure
- * terminate program
- *
- * Assume that your "room" is square, 15 feet on each side. The symbol
- * called "square" is one foot on each side, while the triangle is one
- * foot on a side.
- *
- * The following Turbo C graphics functions are used in this program:
- *
- * cleardevice Clears the screen (active page)
- * clearviewport Clears the current viewport
- * closegraph Shuts down the graphics system
- * drawpoly Draws the outline of a polygon
- * floodfill Flood-fills a bounded region
- * getcolor Returns the current drawing color
- * getfillsettings Returns information about the current fill settings
- * getimage Saves a bit image of the specified region to memory
- * getmaxx Returns the current x resolution
- * getmaxy Returns the current y resolution
- * getviewsettings Returns information about the current viewport
- * grapherrormsg Returns an error message for specified error code
- * graphresult Returns an error code for last error
- * imagesize Retuns number of bytes needed to store an image
- * initgraph Initializes the graphics system
- * lineto Draws a line from the current position to (x,y)
- * moveto Moves the current position to (x,y)
- * outtext Sends a string to the screen at the current position
- * putimage Puts a previously saved bit image onto the screen
- * rectangle Draws a rectangle
- * registerbgidriver Registers a driver file for inclusion at link time
- * setactivepage Sets the active page for graphics output
- * setcolor Sets the current drawing color
- * setfillstyle Sets the fill pattern and fill color
- * settextjustify Set text justification values used by outtext
- * setviewport Sets the current output viewport for graphics output
- * setvisualpage Sets the visual graphics page number
- */
-
- #include <stdio.h>
- #include <math.h>
- #include <dos.h>
- #include <mem.h>
- #include <alloc.h>
- #include <graphics.h>
-
-
- /* Mouse buttons */
-
- #define LEFTBUTTON 1
- #define RIGHTBUTTON 2
-
- /* Clipping */
-
- #define CLIPPING_ON 1
- #define CLIPPING_OFF 0
-
- /* Boolean values */
-
- #define TRUE 1
- #define FALSE 0
-
- /* Dialog box options */
-
- #define YES 1
- #define NO 0
-
- /* Symbols */
-
- #define TRIANGLE 0
- #define SQUARE 1
-
- /* Menu options */
-
- #define IGNORE -1
- #define CREATE 0
- #define DELETE 1
- #define MOVE 2
- #define ROTATE 3
- #define DELETE_ALL 4
- #define PRINT_DATA 5
- #define CANCEL 6
- #define QUIT 7
-
-
- /* Some useful typedefs */
-
- typedef struct {
- double x, y;
- } DPOINT; /* A point with x and y as doubles */
-
- typedef struct pointtype POINT; /* A point with x and y as ints */
- typedef POINT EXTENT [2]; /* Rectangular extent */
- typedef double MATRIX [3][3]; /* A 3x3 matrix */
- typedef double VECTOR [3]; /* A 1x3 matrix */
-
-
- /* Menu Box structure */
-
- struct {
- EXTENT extent;
- char *text;
- } menuBox[8];
-
-
- /* Object structure */
-
- typedef struct {
- int numverts; /* Number of vertices */
- DPOINT vertex[4]; /* At most 4 vertices */
- } OBJECT;
-
-
- /* For linked list of objects */
-
- typedef struct node NODE, *NODEPTR;
-
- struct node {
- OBJECT object;
- NODEPTR next;
- };
-
-
- /* Function prototypes */
-
- void InitializeGraphics(void);
- void DrawScreen(void);
- void Beep(void);
- int MouseReset(int *);
- void MouseOn(void);
- void MouseOff(void);
- int MouseStatus(POINT *);
- void MouseWaitForPress(int, POINT *);
- void MouseWaitForRelease(int, POINT *);
- void MouseSetHorizPos(int, int);
- void MouseSetVertPos(int, int);
- void MouseRestrict(void);
- void MouseFree(void);
- void MMmult(MATRIX, MATRIX, MATRIX);
- void VMmult(VECTOR, MATRIX, VECTOR);
- void CalcW2Vmatrix(double, double, double, double,
- int, int, int, int, MATRIX);
- void CalcV2Wmatrix(int, int, int, int,
- double, double, double, double, MATRIX);
- void DrawObject(OBJECT);
- void Translate(VECTOR, double, double, VECTOR);
- void TranslateObject(OBJECT *, double, double);
- void Rotate(VECTOR, double, DPOINT, VECTOR);
- void RotateObject(OBJECT *, double);
- int PointInExtent(POINT, EXTENT);
- int PickCorrInMenu(POINT);
- int HandlePickInMenu(POINT);
- void Message(char *);
- void HighlightMenu(int, int, int);
- void HighlightSymbol(int, int, int);
- int DialogBox(void);
- NODEPTR AddList(OBJECT);
- void DeleteList(NODEPTR);
- NODEPTR SearchList(POINT);
- void DoCreateObject(void);
- void DoDeleteObject(void);
- void DoMoveObject(void);
- void DoRotateObject(void);
- void DoDeleteAll(void);
- void DoPrintData(void);
- void DoCancel(void);
- int DoQuit(void);
-
-
- /* Global variables */
-
- MATRIX W2V; /* Window to Viewport matrix */
- MATRIX V2W; /* Viewport to Window matrix */
- int maxx, maxy; /* Maximum pixel values */
- int mminx, mminy, mmaxx, mmaxy; /* Message area coordinates */
- int vminx, vminy, vmaxx, vmaxy; /* "Room" (viewport) coords */
- int dminx, dminy, dmaxx, dmaxy; /* Dialog box coordinates */
- int triangleSymbol[8]; /* Triangle symbol */
- int squareSymbol[10]; /* Square symbol */
- EXTENT triangleExtent; /* Extent of the triangle symbol */
- EXTENT squareExtent; /* Extent of the square symbol */
- EXTENT roomExtent; /* Extent of the room */
- EXTENT yesExtent, noExtent; /* Extent of the YES/NO buttons */
- POINT triangleCenter, squareCenter; /* Centers of the symbols */
- NODEPTR list = NULL; /* Pointer to the linked list */
- NODEPTR listtail = NULL; /* Pointer to the end of the list */
- unsigned dialogSize; /* Dialog box image size */
- void *dialogBuffer, *saveBuffer; /* Dialog box and screen buffers */
-
-
- main()
- {
- POINT position;
- int choice;
-
- InitializeGraphics();
- DrawScreen();
- MouseOn();
-
- do
- {
- Message("Choose a menu box with the left mouse button");
- MouseWaitForPress(LEFTBUTTON, &position);
- MouseWaitForRelease(LEFTBUTTON, &position);
- choice = HandlePickInMenu(position);
- }
- while (choice != QUIT);
-
- MouseOff();
- closegraph();
- }
-
-
- /* InitializeGraphics() initializes the graphics package and mouse driver.
- * If there is an error, the program aborts with an appropriate error
- * message.
- */
- void InitializeGraphics()
- {
- int graphDriver, graphMode, errorCode;
- int numberOfButtons;
-
- if (MouseReset(&numberOfButtons) == 0)
- {
- printf("Mouse driver is not installed\n");
- exit(1);
- }
-
- if (numberOfButtons < 2)
- {
- printf("This program requires a mouse with at least two buttons\n");
- exit(2);
- }
-
- if (registerbgidriver(EGAVGA_driver) < 0)
- exit(1);
-
- graphDriver = DETECT;
- initgraph(&graphDriver, &graphMode, "");
- errorCode = graphresult();
- if (errorCode != grOk)
- {
- printf("Graphics System Error: %s\n", grapherrormsg(errorCode));
- exit(1);
- }
- }
-
-
- /* DrawScreen() draws the screen. Coordinates are calculated based on
- * the current screen resolution so that the program will run on either
- * a VGA or EGA system without modification.
- */
- void DrawScreen()
- {
- int vwidth, vheight; /* Viewport */
- int bminx, bminy, bmaxx, bmaxy; /* Menu buttons */
- int bwidth, bheight, bgap, bstart; /* Menu buttons */
- int dwidth, dheight; /* Dialog box */
- int yminx, yminy, ymaxx, ymaxy; /* YES button */
- int nminx, nminy, nmaxx, nmaxy; /* NO button */
- int i;
- static char *boxText[] = { "CREATE", "DELETE", "MOVE", "ROTATE",
- "DELETE ALL", "PRINT DATA", "CANCEL", "QUIT" };
-
- /* Set the pages to draw the screen in the background */
-
- setactivepage(0);
- setvisualpage(1);
-
- /* Get maximum x and y screen coordinates */
-
- maxx = getmaxx();
- maxy = getmaxy();
-
- /* Calculate the coordinates of the room */
-
- roomExtent[0].x = vminx = (int)(0.30 * maxx);
- roomExtent[0].y = vminy = (int)(0.05 * maxy);
- roomExtent[1].x = vmaxx = (int)(0.95 * maxx);
- roomExtent[1].y = vmaxy = (int)(0.80 * maxy);
-
- vwidth = vmaxx - vminx;
- vheight = vmaxy - vminy;
-
- /* Calculate the coordinates of the message area */
-
- mminx = vminx;
- mminy = (int)(0.85 * maxy);
- mmaxx = vmaxx;
- mmaxy = (int)(0.95 * maxy);
-
- /* Draw the dialog box */
-
- dwidth = (int)(0.35 * vwidth);
- dheight = (int)(0.25 * vheight);
- dminx = vminx + (vwidth - dwidth) / 2;
- dminy = vminy + (vheight - dheight) / 2;
- dmaxx = dminx + dwidth;
- dmaxy = dminy + dheight;
- rectangle(dminx, dminy, dmaxx, dmaxy); /* The outline */
-
- yesExtent[0].x = yminx = dminx + (int)(0.10 * dwidth);
- yesExtent[0].y = yminy = dminy + (int)(0.60 * dheight);
- yesExtent[1].x = ymaxx = dminx + (int)(0.40 * dwidth);
- yesExtent[1].y = ymaxy = dminy + (int)(0.90 * dheight);
- rectangle(yminx, yminy, ymaxx, ymaxy);
- setfillstyle(SOLID_FILL, RED);
- floodfill(yminx+1, yminy+1, WHITE); /* YES button */
-
- noExtent[0].x = nminx = dminx + (int)(0.60 * dwidth);
- noExtent[0].y = nminy = yminy;
- noExtent[1].x = nmaxx = dminx + (int)(0.90 * dwidth);
- noExtent[1].y = nmaxy = ymaxy;
- rectangle(nminx, nminy, nmaxx, nmaxy);
- floodfill(nminx+1, nminy+1, WHITE); /* NO button */
-
- setfillstyle(SOLID_FILL, LIGHTGRAY);
- floodfill(dminx+1, dminy+1, WHITE); /* The interior */
-
- settextjustify(CENTER_TEXT, CENTER_TEXT);
- moveto(dminx+dwidth/2, dminy+(yminy-dminy)/2);
- setcolor(BLACK);
- outtext("Are you sure?");
- setcolor(WHITE);
- moveto((yminx+ymaxx)/2, (yminy+ymaxy)/2);
- outtext("YES");
- moveto((nminx+nmaxx)/2, (nminy+nmaxy)/2);
- outtext("NO");
- setcolor(WHITE);
-
- /* Save dialog box in memory */
-
- dialogSize = imagesize(dminx, dminy, dmaxx, dmaxy);
- dialogBuffer = malloc(dialogSize);
- getimage(dminx, dminy, dmaxx, dmaxy, dialogBuffer);
- cleardevice(); /* Clear the screen */
-
- /* Draw the menu buttons */
-
- bheight = (int)(0.06 * maxy);
- bwidth = (int)(0.15 * maxx);
- bgap = (int)(0.03 * maxy);
- bstart = (int)(0.05 * maxy);
- setfillstyle(SOLID_FILL, RED);
- bminx = (int)(0.05 * maxx);
- for (i = 0; i < 8; i++)
- {
- bminy = (int)(i * (bheight + bgap)) + bstart;
- bmaxx = bminx + bwidth;
- bmaxy = bminy + bheight;
- rectangle(bminx, bminy, bmaxx, bmaxy);
- floodfill(bminx+1, bminy+1, WHITE);
- moveto(bminx+bwidth/2, bminy+bheight/2);
- outtext(boxText[i]);
-
- /* Initialize the menuBox info */
-
- menuBox[i].extent[0].x = bminx;
- menuBox[i].extent[0].y = bminy;
- menuBox[i].extent[1].x = bmaxx;
- menuBox[i].extent[1].y = bmaxy;
- menuBox[i].text = boxText[i];
- }
-
- /* Draw the triangle symbol */
-
- bminx = (int)(0.03 * maxx);
- bminy = (int)(0.85 * maxy);
- bmaxy = (int)(0.95 * maxy);
- bwidth = (int)(0.07 * maxx);
- bheight = bmaxy - bminy;
-
- triangleSymbol[0] = bminx;
- triangleSymbol[1] = bmaxy;
- triangleSymbol[2] = bminx + bwidth;
- triangleSymbol[3] = bmaxy;
- triangleSymbol[4] = bminx + bwidth/2;
- triangleSymbol[5] = bminy;
- triangleSymbol[6] = bminx;
- triangleSymbol[7] = bmaxy;
- triangleCenter.x = bminx + bwidth/2;
- triangleCenter.y = bminy + bheight/2;
- drawpoly(4, triangleSymbol);
- setfillstyle(SOLID_FILL, MAGENTA);
- floodfill(bminx + bwidth/2, bminy + bheight/2, WHITE);
-
- /* Initialize the triangle symbol's extent */
-
- triangleExtent[0].x = bminx;
- triangleExtent[0].y = bminy;
- triangleExtent[1].x = bminx + bwidth;
- triangleExtent[1].y = bmaxy;
-
- /* Draw the square symbol */
-
- bgap = (int)(0.05 * maxx);
- bminx += bwidth + bgap;
-
- squareSymbol[0] = bminx;
- squareSymbol[1] = bmaxy;
- squareSymbol[2] = bminx + bwidth;
- squareSymbol[3] = bmaxy;
- squareSymbol[4] = bminx + bwidth;
- squareSymbol[5] = bminy;
- squareSymbol[6] = bminx;
- squareSymbol[7] = bminy;
- squareSymbol[8] = bminx;
- squareSymbol[9] = bmaxy;
- squareCenter.x = bminx + bwidth/2;
- squareCenter.y = bminy + bheight/2;
- drawpoly(5, squareSymbol);
- setfillstyle(SOLID_FILL, GREEN);
- floodfill(bminx + bwidth/2, bminy + bheight/2, WHITE);
-
- /* Initialize the square symbol's extent */
-
- squareExtent[0].x = bminx;
- squareExtent[0].y = bminy;
- squareExtent[1].x = bminx + bwidth;
- squareExtent[1].y = bmaxy;
-
- /* Calculate window-to-viewport and viewport-to-window matrices */
-
- CalcW2Vmatrix(0.0, 0.0, 15.0, 15.0, vminx, vminy, vmaxx, vmaxy, W2V);
- CalcV2Wmatrix(vminx, vminy, vmaxx, vmaxy, 0.0, 0.0, 15.0, 15.0, V2W);
-
- /* Draw the message area */
-
- setfillstyle(SOLID_FILL, CYAN);
- rectangle(mminx, mminy, mmaxx, mmaxy);
- floodfill(mminx+1, mminy+1, WHITE);
-
- /* Draw the room */
-
- setfillstyle(SOLID_FILL, BLUE);
- rectangle(vminx-1, vminy-1, vmaxx+1, vmaxy+1);
- floodfill(vminx, vminy, WHITE);
-
- /* Set viewport to the room */
-
- setviewport(vminx, vminy, vmaxx, vmaxy, CLIPPING_ON);
-
- /* Display screen */
-
- setvisualpage(0);
- }
-
-
- /* Beep() sounds a beep to indicate an error. */
-
- void Beep()
- {
- sound(150);
- delay(75);
- nosound();
- }
-
-
- /* MouseReset() returns the current status of the mouse hardware and
- * software. The mouse status is 0 if the mouse hardware and software
- * are not installed or -1 if the hardware and software are installed.
- *
- * This function also resets the mouse driver to the default values.
- * The number of buttons is returned in numberOfButtons.
- */
- int MouseReset(int *numberOfButtons)
- {
- union REGS inregs, outregs;
-
- inregs.x.ax = 0; /* Mouse Function 0 -- Mouse Reset and Status */
- int86(0x33, &inregs, &outregs);
- *numberOfButtons = outregs.x.bx;
- return outregs.x.ax;
- }
-
-
- /* MouseOn() shows the mouse cursor. */
-
- void MouseOn()
- {
- union REGS inregs, outregs;
-
- inregs.x.ax = 1; /* Mouse Function 1 -- Show Cursor */
- int86(0x33, &inregs, &outregs);
- }
-
-
- /* MouseOff() hides the mouse cursor. */
-
- void MouseOff()
- {
- union REGS inregs, outregs;
-
- inregs.x.ax = 2; /* Mouse function 2 -- Hide Cursor */
- int86(0x33, &inregs, &outregs);
- }
-
-
- /* MouseStatus() returns the state of the left and right mouse buttons
- * and the horizontal and vertical coordinates of the cursor.
- *
- * The button status is a single integer value. Bit 0 represents the
- * left button; bit 1 represents the right button. These bits are 1
- * if the corresponding button is down, and 0 if it is up.
- */
- int MouseStatus(POINT *position)
- {
- union REGS inregs, outregs;
-
- inregs.x.ax = 3; /* Mouse function 3 --
- Get Button Status and Mouse Position */
- int86(0x33, &inregs, &outregs);
- position->x = outregs.x.cx;
- position->y = outregs.x.dx;
- return outregs.x.bx; /* Button status */
- }
-
-
- /* MouseWaitForPress() puts the program in a wait state until the
- * user presses the specified mouse button.
- */
- void MouseWaitForPress(int button, POINT *posptr)
- {
- int buttonPressed;
-
- do
- buttonPressed = MouseStatus(posptr);
- while (!(buttonPressed & button));
- }
-
-
- /* MouseWaitForRelease() puts the program in a wait state until the
- * user releases the specified mouse button.
- */
- void MouseWaitForRelease(int button, POINT *posptr)
- {
- int buttonPressed;
-
- do
- buttonPressed = MouseStatus(posptr);
- while (buttonPressed & button);
- }
-
-
- /* MouseSetHorizPos() sets the minimum and maximum horizontal cursor
- * coordinates on the screen. All cursor movement after the call
- * is restricted to the specified area.
- */
- void MouseSetHorizPos(int minpos, int maxpos)
- {
- union REGS inregs, outregs;
-
- inregs.x.ax = 7; /* Mouse function 7 -- Set Minimum and Maximum
- Horizontal Cursor Position */
- inregs.x.cx = minpos;
- inregs.x.dx = maxpos;
- int86(0x33, &inregs, &outregs);
- }
-
-
- /* MouseSetVertPos() sets the minimum and maximum vertical cursor
- * coordinates on the screen. All cursor movement after the call
- * is restricted to the specified area.
- */
- void MouseSetVertPos(int minpos, int maxpos)
- {
- union REGS inregs, outregs;
-
- inregs.x.ax = 8; /* Mouse function 8 -- Set Minimum and Maximum
- Vertical Cursor Position */
- inregs.x.cx = minpos;
- inregs.x.dx = maxpos;
- int86(0x33, &inregs, &outregs);
- }
-
-
- /* MouseRestrict() restricts the cursor to the viewport. */
-
- void MouseRestrict()
- {
- MouseSetHorizPos(vminx, vmaxx);
- MouseSetVertPos(vminy, vmaxy);
- }
-
-
- /* MouseFree() frees the cursor to move about the entire screen. */
-
- void MouseFree()
- {
- MouseSetHorizPos(0, maxx);
- MouseSetVertPos(0, maxy);
- }
-
-
- /* MMmult() performs Matrix-Matrix multiplication.
- *
- * _ _ _ _ _ _
- * | | | | | |
- * | a a a | | b b b | | c c c |
- * | 00 01 02 | | 00 01 02 | | 00 01 02 |
- * | | | | | |
- * | a a a | | b b b | | c c c |
- * | 10 11 12 | x | 10 11 12 | = | 10 11 12 |
- * | | | | | |
- * | a a a | | b b b | | c c c |
- * | 20 21 22 | | 20 21 22 | | 20 21 22 |
- * |_ _| |_ _| |_ _|
- *
- *
- */
- void MMmult(MATRIX a, MATRIX b, MATRIX c)
- {
- int i, j, k;
-
- for (i = 0; i < 3; i++) /* Row i */
- for (j = 0; j < 3; j++) /* Column j */
- for (c[i][j] = 0.0, k = 0; k < 3; k++)
- c[i][j] += a[i][k] * b[k][j];
- }
-
-
- /* VMmult() performs Vector-Matrix multiplication.
- *
- * _ _
- * | |
- * | b b b |
- * _ _ | 00 01 02 | _ _
- * | | | | | |
- * | a a a | | b b b | | c c c |
- * | 0 1 2 | x | 10 11 12 | = | 0 1 2 |
- * |_ _| | | |_ _|
- * | b b b |
- * | 20 21 22 |
- * |_ _|
- *
- *
- */
- void VMmult(VECTOR a, MATRIX b, VECTOR c)
- {
- int i, j;
-
- for (i = 0; i < 3; i++)
- for (c[i] = 0.0, j = 0; j < 3; j++)
- c[i] += a[j] * b[j][i];
- }
-
-
- /* CalcW2Vmatrix() calculates the Window to Viewport matrix.
- *
- * Window coordinates: (xmin,ymin) and (xmax,ymax)
- * Viewport coordinates: (umin,vmin) and (umax,vmax)
- *
- * _ _ _ _ _ _
- * | || || |
- * | || umax-umin || |
- * | 1 0 0 || --------- 0 0 || 1 0 0 |
- * | || xmax-xmin || |
- * | || vmax-vmin || |
- * | 0 1 0 || 0 - --------- 0 || 0 1 0 |
- * | || ymax-ymin || |
- * | || || |
- * | -xmin -ymin 1 || 0 0 1 || 0 vmax-vmin 1 |
- * | || || |
- * |_ _||_ _||_ _|
- *
- *
- * trans to origin scale window to viewport trans to viewport
- *
- *
- *
- * Note that these matrices are somewhat different from the normal
- * matrices used because the Turbo C graphics package considers the
- * origin to be at the upper left corner of the screen (rather than
- * the lower left) and also because the setviewport() function changes
- * the logical coordinates of the viewport to (0,0).
- */
-
- void CalcW2Vmatrix(xmin, ymin, xmax, ymax, umin, vmin, umax, vmax, m)
- double xmin, ymin, xmax, ymax; /* Window coordinates */
- int umin, vmin, umax, vmax; /* Viewport coordinates */
- MATRIX m; /* Resulting Window to Viewport matrix */
- {
- MATRIX a, b;
-
- /* Translate window to origin */
-
- a[0][0] = a[1][1] = a[2][2] = 1.0;
- a[0][1] = a[0][2] = a[1][0] = a[1][2] = 0.0;
- a[2][0] = -xmin;
- a[2][1] = -ymin;
-
- /* Scale window into viewport */
-
- m[0][1] = m[0][2] = m[1][0] = m[1][2] = m[2][0] = m[2][1] = 0.0;
- m[2][2] = 1.0;
- m[0][0] = (double)(umax - umin) / (xmax - xmin);
- m[1][1] = -(double)(vmax - vmin) / (ymax - ymin);
-
- MMmult(a, m, b);
-
- /* Translate to viewport position
- *
- * Normally, you would translate back to (umin,vmin), but Turbo C's
- * setviewport() function treats the upper left corner of the viewport
- * as (0,0). We want the origin to be in the lower left corner, so we
- * still have to translate to viewport_height - y. We scaled by -1
- * above (to get the -y), so all we have to do is translate by the
- * viewport height (vmax-vmin).
- */
-
- a[2][0] = 0.0;
- a[2][1] = (double)(vmax - vmin);
-
- MMmult(b, a, m);
- }
-
-
- /* CalcV2Wmatrix() calculates the Viewport to Window matrix.
- *
- * Viewport coordinates: (umin,vmin) and (umax,vmax)
- * Window coordinates: (xmin,ymin) and (xmax,ymax)
- *
- * _ _ _ _ _ _
- * | || || |
- * | || xmax-xmin || |
- * | 1 0 0 || --------- 0 0 || 1 0 0 |
- * | || umax-umin || |
- * | || ymax-ymin || |
- * | 0 1 0 || 0 - --------- 0 || 0 1 0 |
- * | || vmax-vmin || |
- * | || || |
- * | 0 -(vmax-vmin) 1 || 0 0 1 || xmin ymin 1 |
- * | || || |
- * |_ _||_ _||_ _|
- *
- *
- * trans to origin scale viewport to window trans to window
- *
- *
- *
- * Note that these matrices are somewhat different from the normal
- * matrices used because the Turbo C graphics package considers the
- * origin to be at the upper left corner of the screen (rather than
- * the lower left) and also because the setviewport() function changes
- * the logical coordinates of the viewport to (0,0).
- */
-
- void CalcV2Wmatrix(umin, vmin, umax, vmax, xmin, ymin, xmax, ymax, m)
- int umin, vmin, umax, vmax; /* Viewport coordinates */
- double xmin, ymin, xmax, ymax; /* Window coordinates */
- MATRIX m; /* Resulting Viewport to Window matrix */
- {
- MATRIX a, b;
-
- /* Translate viewport to origin */
-
- a[0][0] = a[1][1] = a[2][2] = 1.0;
- a[0][1] = a[0][2] = a[1][0] = a[1][2] = a[2][0] = 0.0;
- a[2][1] = -(double)(vmax - vmin);
-
- /* Scale viewport to window */
-
- m[0][1] = m[0][2] = m[1][0] = m[1][2] = m[2][0] = m[2][1] = 0.0;
- m[2][2] = 1.0;
- m[0][0] = (xmax - xmin) / (double)(umax - umin);
- m[1][1] = -(ymax - ymin) / (double)(vmax - vmin);
-
- MMmult(a, m, b);
-
- /* Translate to window position */
-
- a[2][0] = xmin;
- a[2][1] = ymin;
-
- MMmult(b, a, m);
- }
-
-
- /* DrawObject() draws the specified object on the screen. */
-
- void DrawObject(OBJECT object)
- {
- VECTOR p, q;
- int i;
-
- p[2] = 1.0;
-
- /* We will loop one more than the number of vertices in order
- * to draw a line from the last vertex to the first vertex.
- */
- for (i = 0; i < object.numverts + 1; i++)
- {
- p[0] = object.vertex[i % object.numverts].x;
- p[1] = object.vertex[i % object.numverts].y;
- VMmult(p, W2V, q); /* Transform to viewport coords */
- if (i == 0)
- moveto((int)q[0], (int)q[1]);
- else
- lineto((int)q[0], (int)q[1]);
- }
- }
-
-
- /* Translate() translates a point contained in VECTOR p by the amounts
- * Dx and Dy. The new point is contained in VECTOR q.
- *
- * _ _
- * | |
- * | 1 0 0 |
- * _ _ | | _ _
- * | | | | | |
- * | p p p | | 0 1 0 | | q q q |
- * | 0 1 2 | x | | = | 0 1 2 |
- * |_ _| | | |_ _|
- * | Dx Dy 1 |
- * | |
- * |_ _|
- *
- *
- */
-
- void Translate(VECTOR p, double Dx, double Dy, VECTOR q)
- {
- MATRIX t;
-
- t[0][0] = t[1][1] = t[2][2] = 1.0;
- t[0][1] = t[0][2] = t[1][0] = t[1][2] = 0.0;
- t[2][0] = Dx;
- t[2][1] = Dy;
-
- VMmult(p, t, q);
- }
-
-
- /* TranslateObject() calls Translate() to translate all the vertices of
- * the specified object by the amounts Dx and Dy.
- */
- void TranslateObject(OBJECT *object, double Dx, double Dy)
- {
- int i;
- VECTOR p, q;
-
- p[2] = 1.0;
- for (i = 0; i < object->numverts; i++)
- {
- p[0] = object->vertex[i].x;
- p[1] = object->vertex[i].y;
- Translate(p, Dx, Dy, q);
- object->vertex[i].x = q[0];
- object->vertex[i].y = q[1];
- }
- }
-
-
- /* Rotate() rotates a point contained in VECTOR p about the point pt.
- * The new point is contained in VECTOR q.
- *
- * _ _ _ _ _ _
- * | || || |
- * | || || |
- * | 1 0 0 || cos(angle) sin(angle) 0 || 1 0 0 |
- * | || || |
- * | || || |
- * | 0 1 0 || -sin(angle) cos(angle) 0 || 0 1 0 |
- * | || || |
- * | || || |
- * | -pt.x -pt.y 1 || 0 0 1 || pt.x pt.y 1 |
- * | || || |
- * |_ _||_ _||_ _|
- *
- *
- * trans pt to origin rotate trans back to pt
- *
- */
-
- void Rotate(VECTOR p, double angle, DPOINT pt, VECTOR q)
- {
- MATRIX r, t, u;
-
- /* Translate point to origin */
-
- t[0][0] = t[1][1] = t[2][2] = 1.0;
- t[0][1] = t[0][2] = t[1][0] = t[1][2] = 0.0;
- t[2][0] = -pt.x;
- t[2][1] = -pt.y;
-
- /* Define the rotation matrix. Note that angle is in radians. */
-
- r[0][2] = r[1][2] = r[2][0] = r[2][1] = 0.0;
- r[2][2] = 1.0;
- r[0][0] = r[1][1] = cos(angle);
- r[0][1] = sin(angle);
- r[1][0] = -r[0][1];
-
- MMmult(t, r, u);
-
- /* Translate back to point */
-
- t[2][0] = pt.x;
- t[2][1] = pt.y;
-
- MMmult(u, t, r);
-
- /* r now contains the accumulated matrix for the rotation */
-
- VMmult(p, r, q);
- }
-
-
- /* RotateObject() calls Translate() to translate all the vertices of
- * the specified object by the amounts Dx and Dy.
- */
- void RotateObject(OBJECT *object, double degrees)
- {
- int i;
- VECTOR p, q;
- DPOINT center;
- double radians = degrees * (M_PI / 180.0);
-
- /* Calculate the center of the object */
-
- center.x = center.y = 0.0;
- for (i = 0; i < object->numverts; i++)
- {
- center.x += object->vertex[i].x;
- center.y += object->vertex[i].y;
- }
- center.x /= object->numverts;
- center.y /= object->numverts;
-
- p[2] = 1.0;
- for (i = 0; i < object->numverts; i++)
- {
- p[0] = object->vertex[i].x;
- p[1] = object->vertex[i].y;
- Rotate(p, radians, center, q);
- object->vertex[i].x = q[0];
- object->vertex[i].y = q[1];
- }
- }
-
-
- /* PointInExtent() returns a boolean value specifying whether a point
- * is in a certain extent.
- */
- int PointInExtent(POINT pt, EXTENT ext)
- {
- return ext[0].x <= pt.x && pt.x <= ext[1].x &&
- ext[0].y <= pt.y && pt.y <= ext[1].y;
- }
-
-
- /* PickCorrInMenu() performs pick correlation within the menu box area. */
-
- int PickCorrInMenu(POINT pt)
- {
- int i;
-
- for (i = 0; i < 8; i++)
- if (PointInExtent(pt, menuBox[i].extent))
- return i;
-
- return IGNORE;
- }
-
-
- /* HandlePickInMenu() calls the appropriate function to handle a menu
- * option chosen by the user.
- */
- int HandlePickInMenu(POINT pt)
- {
- int choice;
-
- switch (choice = PickCorrInMenu(pt))
- {
- case IGNORE:
- Beep();
- break;
-
- case CREATE:
- DoCreateObject();
- break;
-
- case DELETE:
- DoDeleteObject();
- break;
-
- case MOVE:
- DoMoveObject();
- break;
-
- case ROTATE:
- DoRotateObject();
- break;
-
- case DELETE_ALL:
- DoDeleteAll();
- break;
-
- case PRINT_DATA:
- DoPrintData();
- break;
-
- case CANCEL:
- DoCancel();
- break;
-
- case QUIT:
- choice = DoQuit();
- break;
- }
-
- return choice;
- }
-
-
- /* Message() prints a message in the message area of screen. */
-
- void Message(char *msg)
- {
- struct viewporttype view;
- int color;
- int msgx = mminx + 15;
- int msgy = (mminy + mmaxy) / 2;
- char temp[50];
-
- MouseOff();
-
- /* Get attributes */
-
- getviewsettings(&view);
- color = getcolor();
-
- setviewport(0, 0, maxx, maxy, CLIPPING_OFF); /* Entire screen */
- settextjustify(LEFT_TEXT, CENTER_TEXT);
-
- memset(temp, 219, 49); /* Character 219 is a block */
- temp[49] = '\0';
- setcolor(CYAN);
- moveto(msgx, msgy);
- outtext(temp); /* Blank out existing message */
-
- setcolor(BLACK);
- moveto(msgx, msgy);
- outtext(msg); /* Print message */
-
- /* Reset attributes */
-
- setviewport(view.left, view.top, view.right, view.bottom, view.clip);
- setcolor(color);
-
- MouseOn();
- }
-
-
- /* HighlightMenu() highlights the specified menu box. */
-
- void HighlightMenu(int box, int background, int foreground)
- {
- struct viewporttype view;
- struct fillsettingstype fill;
- int color;
- int bminx = menuBox[box].extent[0].x;
- int bminy = menuBox[box].extent[0].y;
- int bmaxx = menuBox[box].extent[1].x;
- int bmaxy = menuBox[box].extent[1].y;
-
- MouseOff();
-
- /* Get attributes */
-
- getviewsettings(&view);
- getfillsettings(&fill);
- color = getcolor();
-
- setviewport(bminx, bminy, bmaxx, bmaxy, CLIPPING_OFF);
- clearviewport();
-
- setviewport(0, 0, maxx, maxy, CLIPPING_OFF);
- rectangle(bminx, bminy, bmaxx, bmaxy);
-
- setfillstyle(SOLID_FILL, background);
- floodfill(bminx+1, bminy+1, WHITE);
-
- settextjustify(CENTER_TEXT, CENTER_TEXT);
- setcolor(foreground);
- moveto((bminx + bmaxx) / 2, (bminy + bmaxy) / 2);
- outtext(menuBox[box].text);
-
- /* Reset attributes */
-
- setviewport(view.left, view.top, view.right, view.bottom, view.clip);
- setfillstyle(fill.pattern, fill.color);
- setcolor(color);
-
- MouseOn();
- }
-
-
- /* HighlightSymbol() highlights the specified symbol chosen by the user
- * during the CREATE process.
- */
- void HighlightSymbol(int symbol, int fillstyle, int color)
- {
- struct viewporttype view;
- struct fillsettingstype fill;
-
- MouseOff();
- getviewsettings(&view);
- getfillsettings(&fill);
-
- setviewport(0, 0, maxx, maxy, CLIPPING_OFF);
- setfillstyle(fillstyle, color);
- if (symbol == TRIANGLE)
- floodfill(triangleCenter.x, triangleCenter.y, WHITE);
- else /* SQUARE */
- floodfill(squareCenter.x, squareCenter.y, WHITE);
-
- setviewport(view.left, view.top, view.right, view.bottom, view.clip);
- setfillstyle(fill.pattern, fill.color);
- MouseOn();
- }
-
-
- /* DialogBox() displays a YES/NO dialog box, receives the input from
- * the user, restores the screen, and returns either YES or NO to the
- * caller.
- */
- int DialogBox()
- {
- POINT position;
- int choice, done = FALSE;
- struct viewporttype view;
-
- MouseOff();
-
- getviewsettings(&view);
- setviewport(0, 0, maxx, maxy, CLIPPING_OFF); /* Entire screen */
-
- /* Save the screen area under where the dialog box will display */
- saveBuffer = malloc(dialogSize);
- getimage(dminx, dminy, dmaxx, dmaxy, saveBuffer);
-
- /* Display the dialog box */
- putimage(dminx, dminy, dialogBuffer, COPY_PUT);
-
- MouseOn();
-
- Message("Choose YES or NO using left mouse button");
-
- do
- {
- MouseWaitForPress(LEFTBUTTON, &position);
- MouseWaitForRelease(LEFTBUTTON, &position);
- if (PointInExtent(position, yesExtent))
- {
- choice = YES;
- done = TRUE;
- }
- else if (PointInExtent(position, noExtent))
- {
- choice = NO;
- done = TRUE;
- }
- }
- while (!done);
-
- /* Restore the screen area and free the buffer */
-
- MouseOff();
- putimage(dminx, dminy, saveBuffer, COPY_PUT);
- free(saveBuffer);
- MouseOn();
-
- setviewport(view.left, view.top, view.right, view.bottom, view.clip);
- return choice;
- }
-
-
- /* AddList() adds an object to the linked list. */
-
- NODEPTR AddList(OBJECT object)
- {
- NODEPTR newnode;
-
- newnode = (NODEPTR) malloc(sizeof(NODE));
- if (newnode)
- {
- newnode->object = object;
- newnode->next = NULL;
- if (!list)
- list = listtail = newnode;
- else
- listtail = listtail->next = newnode;
- }
- return newnode;
- }
-
-
- /* DeleteList() deletes an object from the linked list. */
-
- void DeleteList(NODEPTR ptr)
- {
- NODEPTR p;
-
- if (ptr == list)
- list = ptr->next;
- else if (ptr == listtail)
- {
- for (p = list; p->next != listtail; p = p->next)
- ;
- p->next = NULL;
- listtail = p;
- }
- else
- {
- for (p = list; p->next != ptr; p = p->next)
- ;
- p->next = ptr->next;
- }
- free(ptr);
- }
-
-
- /* SearchList() searches the list and returns a pointer to the object
- * in the list if the point lies in the extent of the object. If no
- * object is found, NULL is returned.
- */
- NODEPTR SearchList(POINT pt)
- {
- NODEPTR p;
- VECTOR vcoords[4], wcoords[4];
- EXTENT extent;
- int i, x, y;
-
- for (p = list; p; p = p->next)
- {
- /* Transform the object's vertices into physical device
- * coordinates and calculate its extent.
- */
- extent[0].x = maxx;
- extent[0].y = maxy;
- extent[1].x = 0;
- extent[1].y = 0;
- for (i = 0; i < p->object.numverts; i++)
- {
- wcoords[i][0] = p->object.vertex[i].x;
- wcoords[i][1] = p->object.vertex[i].y;
- wcoords[i][2] = 1.0;
- VMmult(wcoords[i], W2V, vcoords[i]);
- vcoords[i][0] += vminx;
- vcoords[i][1] += vminy;
- if ((x = (int) vcoords[i][0]) < extent[0].x) extent[0].x = x;
- if ((y = (int) vcoords[i][1]) < extent[0].y) extent[0].y = y;
- if ((x = (int) vcoords[i][0]) > extent[1].x) extent[1].x = x;
- if ((y = (int) vcoords[i][1]) > extent[1].y) extent[1].y = y;
- }
- if (PointInExtent(pt, extent))
- return p; /* Object was found */
- }
-
- return NULL; /* Object was not found at that position */
- }
-
-
- /* DoCreateObject() handles the CREATE menu option. */
-
- void DoCreateObject()
- {
- POINT position;
- VECTOR vcoords, wcoords;
- OBJECT object;
- int symbol, normalColor;
-
- HighlightMenu(CREATE, LIGHTGRAY, BLACK);
- Message("Choose a TRIANGLE or SQUARE with left button");
-
- while (1)
- {
- MouseWaitForPress(LEFTBUTTON, &position);
- MouseWaitForRelease(LEFTBUTTON, &position);
- if (PointInExtent(position, menuBox[CANCEL].extent))
- {
- HighlightMenu(CANCEL, LIGHTGRAY, BLACK);
- HighlightMenu(CREATE, RED, WHITE);
- HighlightMenu(CANCEL, RED, WHITE);
- return;
- }
- if (PointInExtent(position, triangleExtent))
- {
- symbol = TRIANGLE;
- break;
- }
- else if (PointInExtent(position, squareExtent))
- {
- symbol = SQUARE;
- break;
- }
- else
- Beep(); /* Invalid click */
- }
-
- normalColor = (symbol == TRIANGLE) ? MAGENTA : GREEN;
- HighlightSymbol(symbol, INTERLEAVE_FILL, LIGHTGRAY);
- Message("Choose location in \"room\" with left button");
-
- while (1)
- {
- MouseWaitForPress(LEFTBUTTON, &position);
- MouseWaitForRelease(LEFTBUTTON, &position);
- if (PointInExtent(position, menuBox[CANCEL].extent))
- {
- HighlightMenu(CANCEL, LIGHTGRAY, BLACK);
- HighlightSymbol(symbol, SOLID_FILL, normalColor);
- HighlightMenu(CREATE, RED, WHITE);
- HighlightMenu(CANCEL, RED, WHITE);
- return;
- }
- if (PointInExtent(position, roomExtent))
- break;
- else
- Beep(); /* Invalid click */
- }
-
- vcoords[0] = position.x - vminx;
- vcoords[1] = position.y - vminy;
- vcoords[2] = 1.0;
- VMmult(vcoords, V2W, wcoords);
-
- /* wcoords is the bottom left corner of the object */
-
- object.vertex[0].x = wcoords[0];
- object.vertex[0].y = wcoords[1];
- object.vertex[1].x = wcoords[0] + 1.0;
- object.vertex[1].y = wcoords[1];
-
- if (symbol == TRIANGLE)
- {
- object.vertex[2].x = wcoords[0] + 0.5;
- object.vertex[2].y = wcoords[1] + 1.0;
- object.numverts = 3;
- }
- else /* SQUARE */
- {
- object.vertex[2].x = wcoords[0] + 1.0;
- object.vertex[2].y = wcoords[1] + 1.0;
- object.vertex[3].x = wcoords[0];
- object.vertex[3].y = wcoords[1] + 1.0;
- object.numverts = 4;
- }
-
- AddList(object);
-
- MouseOff();
- DrawObject(object);
- MouseOn();
-
- HighlightSymbol(symbol, SOLID_FILL, normalColor);
- HighlightMenu(CREATE, RED, WHITE);
- }
-
-
- /* DoDeleteObject() handles the DELETE menu option. */
-
- void DoDeleteObject()
- {
- POINT position;
- NODEPTR p, ptr;
- char *mainMessage = "Select the object to be deleted using left button";
-
- HighlightMenu(DELETE, LIGHTGRAY, BLACK);
-
- if (!list) /* No objects to be deleted */
- {
- Beep();
- Message("No objects to be deleted");
- sleep(1);
- HighlightMenu(DELETE, RED, WHITE);
- return;
- }
-
- Message(mainMessage);
-
- while (1)
- {
- MouseWaitForPress(LEFTBUTTON, &position);
- MouseWaitForRelease(LEFTBUTTON, &position);
- if (PointInExtent(position, menuBox[CANCEL].extent))
- {
- HighlightMenu(CANCEL, LIGHTGRAY, BLACK);
- HighlightMenu(DELETE, RED, WHITE);
- HighlightMenu(CANCEL, RED, WHITE);
- return;
- }
- if ((ptr = SearchList(position)) == NULL)
- {
- Beep();
- Message("No object found there");
- sleep(1);
- Message(mainMessage);
- }
- else
- break; /* Object found */
- }
-
- /* Erase the object */
- MouseOff();
- setcolor(BLUE);
- DrawObject(ptr->object);
- setcolor(WHITE);
-
- /* Delete it from the list */
- DeleteList(ptr);
-
- /* Redraw all objects in case there was an overlap */
- for (p = list; p; p = p->next)
- DrawObject(p->object);
- MouseOn();
-
- HighlightMenu(DELETE, RED, WHITE);
- }
-
-
- /* DoMoveObject() handles the MOVE menu option. */
-
- void DoMoveObject()
- {
- POINT position;
- NODEPTR p, ptr;
- VECTOR vcoords, wcoords;
- int i, valid;
- double Dx, Dy, deltaX, deltaY;
- int buttonPressed;
- char *mainMessage = "Drag an object with left button, then release";
-
- HighlightMenu(MOVE, LIGHTGRAY, BLACK);
-
- if (!list) /* No objects to be deleted */
- {
- Beep();
- Message("No objects to be moved");
- sleep(1);
- HighlightMenu(MOVE, RED, WHITE);
- return;
- }
-
- Message(mainMessage);
-
- while (1)
- {
- MouseWaitForPress(LEFTBUTTON, &position);
- if (PointInExtent(position, menuBox[CANCEL].extent))
- {
- MouseWaitForRelease(LEFTBUTTON, &position);
- HighlightMenu(CANCEL, LIGHTGRAY, BLACK);
- HighlightMenu(MOVE, RED, WHITE);
- HighlightMenu(CANCEL, RED, WHITE);
- return;
- }
- if ((ptr = SearchList(position)) == NULL)
- {
- Beep();
- Message("No object found there");
- sleep(1);
- Message(mainMessage);
- MouseWaitForRelease(LEFTBUTTON, &position);
- }
- else
- break; /* Object found */
- }
-
- /* Determine x and y distance from clicked position to the bottom
- * left corner of the object (deltaX and deltaY). This will be used
- * below so that when dragging the object, the cursor will remain on
- * the object at the same place.
- */
- vcoords[0] = position.x - vminx;
- vcoords[1] = position.y - vminy;
- vcoords[2] = 1.0;
- VMmult(vcoords, V2W, wcoords);
- deltaX = wcoords[0] - ptr->object.vertex[0].x;
- deltaY = wcoords[1] - ptr->object.vertex[0].y;
-
- /* Restrict the mouse to the "room" */
-
- MouseRestrict();
-
- do
- {
- buttonPressed = MouseStatus(&position);
-
- /* Convert the clicked position to world coordinates */
- vcoords[0] = position.x - vminx;
- vcoords[1] = position.y - vminy;
- vcoords[2] = 1.0;
- VMmult(vcoords, V2W, wcoords);
-
- /* Determine Dx and Dy for the translation */
- Dx = wcoords[0] - ptr->object.vertex[0].x - deltaX;
- Dy = wcoords[1] - ptr->object.vertex[0].y - deltaY;
-
- /* Erase old position */
- MouseOff();
- setcolor(BLUE);
- DrawObject(ptr->object);
- setcolor(WHITE);
-
- /* Translate the object and redraw all objects */
- TranslateObject(&ptr->object, Dx, Dy);
- for (p = list; p; p = p->next)
- DrawObject(p->object);
- MouseOn();
- }
- while (buttonPressed & LEFTBUTTON); /* Wait for release */
-
- MouseFree();
-
- HighlightMenu(MOVE, RED, WHITE);
- }
-
-
- /* DoRotateObject() handles the ROTATE menu option. */
-
- void DoRotateObject()
- {
- POINT position;
- NODEPTR p, ptr;
- int buttonPressed;
- double degrees;
- char *mainMessage = "Select an object to be rotated using left button";
-
- HighlightMenu(ROTATE, LIGHTGRAY, BLACK);
-
- if (!list) /* No objects to be rotated */
- {
- Beep();
- Message("No objects to be rotated");
- sleep(1);
- HighlightMenu(ROTATE, RED, WHITE);
- return;
- }
-
- Message(mainMessage);
-
- while (1)
- {
- MouseWaitForPress(LEFTBUTTON, &position);
- MouseWaitForRelease(LEFTBUTTON, &position);
- if (PointInExtent(position, menuBox[CANCEL].extent))
- {
- HighlightMenu(CANCEL, LIGHTGRAY, BLACK);
- HighlightMenu(ROTATE, RED, WHITE);
- HighlightMenu(CANCEL, RED, WHITE);
- return;
- }
- if ((ptr = SearchList(position)) == NULL)
- {
- Beep();
- Message("No object found there");
- sleep(1);
- Message(mainMessage);
- }
- else
- break;
- }
-
- Message("Use left/right buttons to rotate, QUIT to end");
-
- while (1)
- {
- buttonPressed = MouseStatus(&position);
- if (buttonPressed)
- {
- if (PointInExtent(position, menuBox[QUIT].extent))
- {
- HighlightMenu(QUIT, LIGHTGRAY, BLACK);
- HighlightMenu(ROTATE, RED, WHITE);
- HighlightMenu(QUIT, RED, WHITE);
- MouseWaitForRelease(LEFTBUTTON, &position);
- return;
- }
-
- if (buttonPressed & LEFTBUTTON)
- degrees = 2.0;
- else
- degrees = -2.0;
-
- /* Erase old position */
-
- MouseOff();
- setcolor(BLUE);
- DrawObject(ptr->object);
- setcolor(WHITE);
-
- /* Rotate the object and redraw all objects */
-
- RotateObject(&ptr->object, degrees);
- for (p = list; p; p = p->next)
- DrawObject(p->object);
- MouseOn();
- }
- }
- }
-
-
- /* DoDeleteAll() handles the DELETE ALL menu option. */
-
- void DoDeleteAll()
- {
- NODEPTR p, q;
-
- HighlightMenu(DELETE_ALL, LIGHTGRAY, BLACK);
-
- if (!list) /* No objects to be deleted */
- {
- Beep();
- Message("No objects to be deleted");
- sleep(1);
- HighlightMenu(DELETE_ALL, RED, WHITE);
- return;
- }
-
- /* After obtaining confirmation through the dialog box, erase
- * all objects, free the memory, and make the list null.
- */
-
- if (DialogBox() == YES)
- {
- MouseOff();
- setcolor(BLUE);
- p = list;
- while (p)
- {
- q = p;
- DrawObject(p->object);
- p = p->next;
- free(q);
- }
- list = listtail = NULL;
- setcolor(WHITE);
- MouseOn();
- }
-
- HighlightMenu(DELETE_ALL, RED, WHITE);
- }
-
-
- /* DoPrintData() handles the PRINT DATA menu option. */
-
- void DoPrintData()
- {
- FILE *outfile;
- NODEPTR p;
- int i;
-
- HighlightMenu(PRINT_DATA, LIGHTGRAY, BLACK);
-
- if ((outfile = fopen("proj1.dat", "w")) == NULL)
- {
- Message("Cannot create file PROJ1.DAT");
- HighlightMenu(PRINT_DATA, RED, WHITE);
- return;
- }
-
- if (!list)
- fprintf(outfile, "No objects found");
- else
- for (p = list; p; p = p->next)
- {
- fprintf(outfile, "Object Type: %s\n",
- p->object.numverts == 4 ? "SQUARE" : "TRIANGLE");
- fprintf(outfile, "Vertices:\n");
- for (i = 0; i < p->object.numverts; i++)
- fprintf(outfile, " (%2.2f, %2.2f)\n",
- p->object.vertex[i].x, p->object.vertex[i].y);
- fprintf(outfile, "\n");
- }
-
- fclose(outfile);
-
- Message("File PROJ1.DAT successfully created");
- sleep(1);
-
- HighlightMenu(PRINT_DATA, RED, WHITE);
- }
-
-
- /* DoCancel() handles the CANCEL menu option. Note that since CANCEL
- * must be used in conjunction with another menu option, this option
- * chosen as a standalone function just beeps and returns an error message.
- */
- void DoCancel()
- {
- HighlightMenu(CANCEL, LIGHTGRAY, BLACK);
- Beep();
- Message("Nothing to cancel!");
- sleep(1);
- HighlightMenu(CANCEL, RED, WHITE);
- }
-
-
- /* DoQuit() handles the QUIT menu option. */
-
- int DoQuit()
- {
- int choice;
-
- HighlightMenu(QUIT, LIGHTGRAY, BLACK);
- choice = DialogBox();
- HighlightMenu(QUIT, RED, WHITE);
- return (choice == YES) ? QUIT : IGNORE;
- }
-